Skip to content

Commit 9fc014e

Browse files
committed
Add support for no-associativity in Camlp5/gramlib.
This also includes removing the continuation-based fallback, as in: Notation "x !" := (S x) (at level 2). Check 0!%nat. which should not be accepted if not in recovery mode.
1 parent 728a90b commit 9fc014e

3 files changed

Lines changed: 32 additions & 19 deletions

File tree

gramlib/grammar.ml

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ module type ExtS = sig
136136
estate : EState.t;
137137
kwstate : keyword_state;
138138
recover : bool;
139+
has_non_assoc : bool;
139140
}
140141
end
141142

@@ -239,7 +240,7 @@ and ('self, 'trec, 'trecs, 'trecb, 'a, 'r) ty_node = {
239240
type ('t,'a) entry_data = {
240241
edesc : 'a ty_desc;
241242
estart : 't -> int -> 'a parser_t;
242-
econtinue : 't -> int -> int -> 'a -> 'a parser_t;
243+
econtinue : 't -> int option -> int -> int -> 'a -> 'a parser_t;
243244
}
244245

245246
module DMap = PolyMap.Make (struct type nonrec 'a tag = 'a tag = .. end)
@@ -253,12 +254,14 @@ and GState : sig
253254
estate : EState.t;
254255
kwstate : L.keyword_state;
255256
recover : bool;
257+
has_non_assoc : bool;
256258
}
257259
end = struct
258260
type t = {
259261
estate : EState.t;
260262
kwstate : L.keyword_state;
261263
recover : bool;
264+
has_non_assoc : bool;
262265
}
263266
end
264267
open GState
@@ -1163,8 +1166,8 @@ let empty_entry ename levn strm =
11631166
let start_parser_of_entry gstate entry levn (strm:_ LStream.t) =
11641167
(get_entry gstate.estate entry).estart gstate levn strm
11651168

1166-
let continue_parser_of_entry gstate entry levn bp a (strm:_ LStream.t) =
1167-
(get_entry gstate.estate entry).econtinue gstate levn bp a strm
1169+
let continue_parser_of_entry gstate entry levfrom levn bp a (strm:_ LStream.t) =
1170+
(get_entry gstate.estate entry).econtinue gstate levfrom levn bp a strm
11681171

11691172
(**
11701173
nlevn: level for Snext
@@ -1264,7 +1267,7 @@ and parser_cont : type s tr tr' a r.
12641267
have been expected according to the level. *)
12651268
if gstate.recover then
12661269
let p1 = parser_of_tree entry nlevn alevn son in
1267-
let a = continue_parser_of_entry gstate (entry_of_symb entry s) 0 bp a strm__ in
1270+
let a = continue_parser_of_entry gstate (entry_of_symb entry s) None 0 bp a strm__ in
12681271
let act =
12691272
try p1 gstate strm__ with
12701273
Stream.Failure -> raise (Stream.Error (tree_failed entry a s son))
@@ -1537,7 +1540,7 @@ let rec start_parser_of_levels entry clevn =
15371540
let act = p2 gstate strm__ in
15381541
let ep = LStream.count strm__ in
15391542
let a = act (LStream.interval_loc bp ep strm__) in
1540-
continue_parser_of_entry gstate entry levn bp a strm)
1543+
continue_parser_of_entry gstate entry (Some clevn) levn bp a strm)
15411544
| _ ->
15421545
fun gstate levn strm ->
15431546
if levn > clevn then
@@ -1550,7 +1553,7 @@ let rec start_parser_of_levels entry clevn =
15501553
Some act ->
15511554
let ep = LStream.count strm__ in
15521555
let a = act (LStream.interval_loc bp ep strm__) in
1553-
continue_parser_of_entry gstate entry levn bp a strm
1556+
continue_parser_of_entry gstate entry (Some clevn) levn bp a strm
15541557
| _ -> p1 gstate levn strm__
15551558

15561559
(** [continue_parser_of_levels entry clevn levels levn bp a strm] goes
@@ -1566,7 +1569,7 @@ let rec start_parser_of_levels entry clevn =
15661569
*)
15671570
let rec continue_parser_of_levels entry clevn =
15681571
function
1569-
[] -> (fun _gstate levn bp a (strm__ : _ LStream.t) -> raise Stream.Failure)
1572+
[] -> (fun _gstate levfrom levn bp a (strm__ : _ LStream.t) -> raise Stream.Failure)
15701573
| Level lev :: levs ->
15711574
let p1 = continue_parser_of_levels entry (succ clevn) levs in
15721575
match lev.lsuffix with
@@ -1578,27 +1581,36 @@ let rec continue_parser_of_levels entry clevn =
15781581
| RightA -> clevn
15791582
in
15801583
let p2 = parser_of_tree entry (succ clevn) alevn tree in
1581-
fun gstate levn bp a strm ->
1584+
fun gstate levfrom levn bp a strm ->
1585+
(* Apply the lsuffix continuation if the level is in the interval [levn;levfrom] *)
15821586
if levn > clevn then
15831587
(* Skip rules before [levn] *)
1584-
p1 gstate levn bp a strm
1588+
p1 gstate levfrom levn bp a strm
1589+
else if (not gstate.recover && match levfrom with Some levfrom -> levfrom < clevn | None -> false) then
1590+
raise Stream.Failure
15851591
else
15861592
let (strm__ : _ LStream.t) = strm in
1587-
try p1 gstate levn bp a strm__ with
1593+
try p1 gstate levfrom levn bp a strm__ with
15881594
Stream.Failure ->
15891595
let act = p2 gstate strm__ in
15901596
let ep = LStream.count strm__ in
15911597
let a = act a (LStream.interval_loc bp ep strm__) in
1592-
continue_parser_of_entry gstate entry levn bp a strm
1598+
if gstate.has_non_assoc && lev.assoc = NonA then
1599+
if clevn = levn then
1600+
a
1601+
else
1602+
continue_parser_of_entry gstate entry (Some (clevn-1)) levn bp a strm
1603+
else
1604+
continue_parser_of_entry gstate entry (Some clevn) levn bp a strm
15931605

15941606
let make_continue_parser_of_entry entry desc =
15951607
match desc with
1596-
| Dlevels [] -> (fun _ _ _ _ (_ : _ LStream.t) -> raise Stream.Failure)
1608+
| Dlevels [] -> (fun _ _ _ _ _ (_ : _ LStream.t) -> raise Stream.Failure)
15971609
| Dlevels elev ->
15981610
let p = lazy (continue_parser_of_levels entry 0 elev) in
1599-
(fun gstate levn bp a (strm__ : _ LStream.t) ->
1600-
try Lazy.force p gstate levn bp a strm__ with Stream.Failure -> a)
1601-
| Dparser p -> fun gstate levn bp a (strm__ : _ LStream.t) -> raise Stream.Failure
1611+
(fun gstate levfrom levn bp a (strm__ : _ LStream.t) ->
1612+
try Lazy.force p gstate levfrom levn bp a strm__ with Stream.Failure -> a)
1613+
| Dparser p -> fun gstate levfrom levn bp a (strm__ : _ LStream.t) -> raise Stream.Failure
16021614

16031615
let make_start_parser_of_entry entry desc =
16041616
match desc with
@@ -1718,7 +1730,7 @@ module Entry = struct
17181730
let estate = add_entry otag estate e {
17191731
edesc = Dlevels [];
17201732
estart = empty_entry n;
1721-
econtinue = (fun _ _ _ _ (strm__ : _ LStream.t) -> raise Stream.Failure);
1733+
econtinue = (fun _ _ _ _ _ (strm__ : _ LStream.t) -> raise Stream.Failure);
17221734
}
17231735
in
17241736
estate, e
@@ -1733,7 +1745,7 @@ module Entry = struct
17331745
let e, otag = fresh n in
17341746
let estate = add_entry otag estate e {
17351747
estart = (fun gstate _ (strm:_ LStream.t) -> p gstate.kwstate strm);
1736-
econtinue = (fun _ _ _ _ (strm__ : _ LStream.t) -> raise Stream.Failure);
1748+
econtinue = (fun _ _ _ _ _ (strm__ : _ LStream.t) -> raise Stream.Failure);
17371749
edesc = Dparser p;
17381750
}
17391751
in
@@ -1883,7 +1895,7 @@ module Unsafe = struct
18831895
let clear_entry estate e =
18841896
modify_entry estate e (fun data -> {
18851897
estart = (fun _ _ (strm__ : _ LStream.t) -> raise Stream.Failure);
1886-
econtinue = (fun _ _ _ _ (strm__ : _ LStream.t) -> raise Stream.Failure);
1898+
econtinue = (fun _ _ _ _ _ (strm__ : _ LStream.t) -> raise Stream.Failure);
18871899
edesc = match data.edesc with
18881900
| Dlevels _ -> Dlevels []
18891901
| Dparser _ -> data.edesc;

gramlib/grammar.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ module type ExtS = sig
139139
estate : EState.t;
140140
kwstate : keyword_state;
141141
recover : bool;
142+
has_non_assoc : bool;
142143
}
143144
end
144145

parsing/pcoq.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ let set_keyword_state s = keyword_state := s
2323
(** Not marshallable! *)
2424
let estate = ref EState.empty
2525

26-
let gstate () = { GState.estate = !estate; kwstate = !keyword_state; recover = true }
26+
let gstate () = { GState.estate = !estate; kwstate = !keyword_state; recover = true; has_non_assoc = false }
2727

2828
module Parsable = struct
2929
include Parsable

0 commit comments

Comments
 (0)