Source

ocaml-lib / dcg / essai.ml


let _ = Dcg.trace := true

let skip = Str.regexp "[ \\\n\\\t\\\r]+"

let p_ident = dcg "identifier" [ s = match "[a-zA-Z_][a-zA-Z_0-9]*" as "ident" when "invalid ident" not (List.mem x ["and"; "or"; "not"]) -> s ]
let p_nat = dcg "natural" [ s = match "[0-9]+" -> int_of_string s ]
let p_float = dcg "float" [ s = match "[0-9]+\\.[0-9]*" -> float_of_string s ]
let p_string = dcg "string" [ s = match "\"[^\"]*\"" as "literal" -> String.escaped (String.sub s 1 (String.length s - 2)) ]


type t = Atom of string | Literal of string | Not of t | And of t * t | Or of t * t

let rec print = function
  | Atom s -> s
  | Literal s -> "\"" ^ s ^ "\""
  | Not f -> "not " ^ print f
  | And (f1,f2) -> "(" ^ print f1 ^ " and " ^ print f2 ^ ")"
  | Or (f1,f2) -> "(" ^ print f1 ^ " or " ^ print f2 ^ ")"

let p = dcg [
  x = p_ident;
  "and";
  y = p_ident
  -> And (Atom x, Atom y)
]

let rec parse = dcg "top" [
  p = parse_or;
  ( "and" then q = parse -> And (p,q)
  | -> p
  ) ]
and parse_or = dcg [
  p = parse_not;
  ( "or" then q = parse_or -> Or (p,q)
  | -> p
  ) ]
and parse_not = dcg [
  | "not" then p = parse_atom -> Not p
  | x = parse_atom -> x ]
and parse_atom = dcg [
  | "(" then p = parse; ")" -> p
  | s = p_string -> Literal s
  | x = p_ident -> Atom x ]

let _, f = Dcg.once (dcg [ x = parse; EOF -> x ]) [] (Matcher.cursor_of_string skip "x and (\"y\" or not z)") in
assert (f = And (Atom "x", Or (Literal "y", Not (Atom "z"))))

let _, _ = Dcg.once (dcg [ EOF -> "" ]) [] (Matcher.cursor_of_string (Str.regexp "") "");;

let rec parse_file = dcg "file"
  [ f = parse_line then l = parse_file -> f::l
  | EOF -> [] ]
and parse_line = dcg "line"
    [ f = parse; "." -> f ]

let _, l = Dcg.once parse_file [] (Matcher.cursor_of_channel skip (open_in "essai.txt")) in
List.iter (fun f -> print_endline (print f ^ ".")) l;;