Skip to content

Commit e598092

Browse files
authored
Merge pull request #291 from LPCIC/2.0.3
fix parsing of ==>
2 parents 8a27883 + 4a98f8d commit e598092

File tree

6 files changed

+68
-14
lines changed

6 files changed

+68
-14
lines changed

CHANGES.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
# v2.0.3 (November 2024)
2+
3+
Requires Menhir 20211230 and OCaml 4.13 or above.
4+
5+
- Parser:
6+
- Fix parsing of infix `==>` so that `A,B ==> C,D` means `A, (B => (C,D))`
7+
as it is intended to be.
8+
9+
110
# v2.0.2 (November 2024)
211

312
Requires Menhir 20211230 and OCaml 4.13 or above.

src/parser/ast.ml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ let mkSeq ?loc (l : t list) =
146146
let rec aux = function
147147
[] -> assert false
148148
| [e] -> e
149+
| { it = Parens it} :: tl -> aux (it :: tl)
149150
| hd::tl ->
150151
let tl = aux tl in
151152
{ loc = Loc.merge hd.loc tl.loc; it = App({ it = Const Func.consf; loc = hd.loc },[hd;tl]) }
@@ -170,10 +171,20 @@ let mkApp loc = function
170171
| [] -> anomaly ~loc "empty application"
171172
| x::_ -> raise (NotInProlog(loc,"syntax error: the head of an application must be a constant or a variable, got: " ^ best_effort_pp x.it))
172173

173-
let rec mkAppF loc (cloc, c) = function
174-
| [] -> anomaly ~loc "empty application"
175-
| { loc; it = App({it=Const ","; loc=cloc}, tl1)} ::tl when c="," -> mkAppF loc (cloc, ",") (tl1@tl)
176-
| args -> { loc; it = App( { it = Const c; loc = cloc },args) }
174+
let mkAppF loc (cloc, c) l =
175+
if l = [] then anomaly ~loc "empty application";
176+
if c = "," then
177+
{ loc; it =
178+
App({ it = Const c; loc = cloc },
179+
List.concat_map (function
180+
| { loc; it = Parens { it = App({it=Const ","}, l)}} -> l
181+
| { loc; it = App({it=Const ","}, l)} -> l
182+
| x -> [x]
183+
) l) }
184+
else
185+
{ loc; it = App({ it = Const c; loc = cloc },l) }
186+
187+
177188

178189
let last_warn_impl = ref (Loc.initial "(dummy)")
179190
let warn_impl { it; loc } =

src/parser/grammar.mly

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,36 @@ let desugar_macro loc lhs rhs =
6262
raise (ParseError(loc,"Illformed macro left hand side"))
6363
;;
6464

65-
let mkParens_if_impl loc t =
65+
let mkParens_if_impl_or_conj loc t =
6666
match t.it with
6767
| App({ it = Const c},_) when Func.(equal c implf) -> mkParens loc t
68+
| App({ it = Const c},_) when Func.(equal c andf) -> mkParens loc t
6869
| _ -> t
6970

7071
let mkApp loc = function
7172
| { it = Const c; loc = cloc } :: a :: { it = App ({ it = Const c1 }, args) } :: [] when Func.(equal c andf && equal c1 andf) ->
7273
mkAppF loc (cloc,c) (a :: args)
7374
| l -> mkApp loc l
7475

75-
let mkAppF loc (cloc,c) = function
76-
| a :: { it = App ({ it = Const c1 }, args) } :: [] when Func.(equal c andf && equal c1 andf) ->
77-
mkAppF loc (cloc,c) (a :: args)
78-
| l -> mkAppF loc (cloc,c) l
76+
let rec unparen = function
77+
| [] -> []
78+
| { it = Parens { it = App ({ it = Const c1 }, args) } } as x :: xs when Func.(equal c1 implf) -> x :: unparen xs
79+
| { it = Parens x} :: xs -> x :: unparen xs
80+
| x :: xs -> x :: unparen xs
81+
82+
let mkAppF loc (cloc,c) l =
83+
if Func.(equal c implf) then
84+
match l with
85+
| { it = App ({ it = Const j; loc = jloc }, args) } :: rhs when Func.(equal j andf) ->
86+
begin match List.rev args with
87+
| last :: ( { loc = dloc } :: _ as rest_rev) ->
88+
let jloc = List.fold_left (fun x { loc } -> Loc.merge x loc) dloc rest_rev in
89+
let iloc = List.fold_left (fun x { loc } -> Loc.merge x loc) last.loc rhs in
90+
{ it = App ({ it = Const j; loc = jloc },List.rev rest_rev @ [mkAppF iloc (cloc,c) (last :: rhs)]); loc = loc }
91+
| _ -> mkAppF loc (cloc,c) l
92+
end
93+
| _ -> mkAppF loc (cloc,c) (unparen l)
94+
else mkAppF loc (cloc,c) l
7995

8096
let binder l (loc,ty,b) =
8197
match List.rev l with
@@ -371,7 +387,7 @@ closed_term:
371387

372388
head_term:
373389
| t = constant { mkConst (loc $loc) t }
374-
| LPAREN; t = term; RPAREN { mkParens_if_impl (loc $loc) t }
390+
| LPAREN; t = term; RPAREN { mkParens_if_impl_or_conj (loc $loc) t }
375391
| LPAREN; t = term; COLON; ty = type_term RPAREN { mkCast (loc $loc) t ty }
376392

377393
list_items:
@@ -430,7 +446,7 @@ clause_hd_term:
430446

431447
clause_hd_closed_term:
432448
| t = constant { mkConst (loc $sloc) t }
433-
| LPAREN; t = term; RPAREN { mkParens_if_impl (loc $loc) t }
449+
| LPAREN; t = term; RPAREN { mkParens_if_impl_or_conj (loc $loc) t }
434450

435451
clause_hd_open_term:
436452
| hd = PI; args = nonempty_list(constant_w_loc); b = binder_body { desugar_multi_binder (loc $loc) @@ mkApp (loc $loc) (mkConst (loc $loc(hd)) (Func.from_string "pi") :: binder args b) }

src/parser/lexer_config.ml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ type fixed = {
3737
token : string;
3838
the_token : string;
3939
mk_token : Tokens.token;
40+
comment : (int * string) option;
4041
}
4142

4243
type mixfix_kind = Fixed of fixed | Extensible of extensible
@@ -46,18 +47,19 @@ type mixfix = {
4647
fixity : fixity;
4748
}
4849

49-
let mkFix token the_token mk_token = Fixed { token; the_token; mk_token }
50+
let mkFix ?comment token the_token mk_token = Fixed { token; the_token; mk_token; comment }
5051

5152
let mkExt token start ?(non_enclosed=false) ?(at_least_one_char=false) ?(fixed=[]) mk_token =
5253
Extensible { start; mk_token; token; non_enclosed; at_least_one_char; fixed }
5354

55+
let comment = 1, "The LHS of ==> binds stronger than conjunction, hence (a,b ==> c,d) reads a, (b ==> (c,d))"
5456
let mixfix_symbols : mixfix list = [
5557
{ tokens = [ mkFix "VDASH" ":-" VDASH;
5658
mkFix "QDASH" "?-" QDASH];
5759
fixity = Infix };
5860
{ tokens = [ mkFix "OR" ";" OR];
5961
fixity = Infixr };
60-
{ tokens = [ mkFix "DDARROW" "==>" DDARROW];
62+
{ tokens = [ mkFix ~comment "DDARROW" "==>" DDARROW];
6163
fixity = Infixr };
6264
{ tokens = [ mkFix "CONJ" "," CONJ;
6365
mkFix "CONJ2" "&" CONJ2];

src/parser/parser_config.ml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,18 @@ let pp_non_enclosed fmt = function
7171
let pp_tok_list fmt l =
7272
List.iter (function
7373
| Extensible { start; fixed; non_enclosed; _ } -> Format.fprintf fmt "%a%s..%a @ " pp_fixed fixed start pp_non_enclosed non_enclosed
74-
| Fixed { the_token; _ } -> Format.fprintf fmt "%s @ " the_token)
74+
| Fixed { the_token; comment = None; _ } -> Format.fprintf fmt "%s @ " the_token
75+
| Fixed { the_token; comment = Some (id,_); _ } -> Format.fprintf fmt "%s (* see note %d *) @ " the_token id)
7576
l
7677

78+
let pp_tok_list_comments fmt l =
79+
List.iter (function
80+
| Extensible _ -> ()
81+
| Fixed { comment = None; _ } -> ()
82+
| Fixed { comment = Some (id,txt); _ } -> Format.fprintf fmt "%d: %s@ " id txt)
83+
l
84+
85+
7786
let legacy_parser_compat_error =
7887
let open Format in
7988
let b = Buffer.create 80 in
@@ -140,6 +149,11 @@ let legacy_parser_compat_error =
140149
fprintf fmt "%s@;" "verify how the text was parsed. Eg:";
141150
fprintf fmt "%s@;" "";
142151
fprintf fmt "%s@;" "echo 'MyFormula = a || b ==> c && d' | elpi -parse-term";
152+
fprintf fmt "%s@;" "";
153+
fprintf fmt "%s@;" "Notes:";
154+
List.iter (fun { tokens; _ } ->
155+
fprintf fmt "%a" pp_tok_list_comments tokens;
156+
) mixfix_symbols;
143157
fprintf fmt "@]";
144158
pp_print_flush fmt ();
145159
Buffer.contents b

src/parser/test_parser.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ let _ =
179179
test "q && r x || s." 1 13 1 0 [] (app "||" 10 [app "&&" 3 [c 1 "q"; app "r" 6 [c 8 "x"]]; c 13 "s"]);
180180
(* 01234567890123456789012345 *)
181181
test "f x ==> y." 1 9 1 0 [] (app "=>" ~len:3 5 [app "f" 1 [c 3 "x"]; c 9 "y"]);
182+
test "x, y ==> z, a." 1 13 1 0 [] (app "," 1 [c 1 "x"; app "=>" ~len:3 6 [c 4 "y"; app "," ~bug 11 [c 10 "z";c 13 "a"]]]);
183+
test "(x, y) ==> z, a." 1 15 1 0 [] (app "=>" ~len:3 8 [app "," ~bug 3 [c ~bug 2 "x"; c 5 "y"]; app "," ~bug 13 [c 12 "z";c 15 "a"]]);
182184
test "x ==> y, z." 1 10 1 0 [] (app "=>" ~len:3 3 [c 1 "x"; app "," ~bug 8 [c 7 "y"; c 10 "z"]]);
183185
test "x => y, z." 1 9 1 0 [] ~warns:".*infix operator" (app "," ~bug 7 [app "=>" 3 [c 1 "x";c 6 "y"];c 9 "z"]);
184186
test "x => y, !." 1 9 1 0 [] (app "," ~bug 7 [app "=>" 3 [c 1 "x";c 6 "y"];c 9 "!"]);

0 commit comments

Comments
 (0)