|
1 | 1 | open Util |
2 | 2 | open Core.Reporter |
| 3 | +open Core.Origin |
3 | 4 | open Fmlib_parse |
4 | 5 | open Notation |
5 | 6 | module TokMap = Map.Make (Token) |
|
21 | 22 |
|
22 | 23 | (* The functor that defines all the term-parsing combinators. *) |
23 | 24 | module Combinators (Final : Fmlib_std.Interfaces.ANY) = struct |
24 | | - module Basic = Token_parser.Make (Unit) (Lexer.Token_whitespace) (Final) (SemanticError) |
| 25 | + (* The "state" is an Origin. Normally the origin is stored globally with a State effect, but we sometimes need to change the origin temporarily during parsing (e.g. to go back in time and parse a term using the notations that were in scope in the past) and doing that with effects doesn't interact well with fmlib's continuation-based parser monad. So we store the origin used for parsing in fmlib's built-in state parameter instead, and initialize it with the overall current origin when beginning parsing. *) |
| 26 | + module Basic = Token_parser.Make (Origin) (Lexer.Token_whitespace) (Final) (SemanticError) |
25 | 27 | open Basic |
26 | 28 |
|
27 | 29 | (* We aren't using Fmlib's error reporting, so there's no point in supplying it nonempty "expect" strings. *) |
@@ -108,7 +110,8 @@ module Combinators (Final : Fmlib_std.Interfaces.ANY) = struct |
108 | 110 | (lt, ls) No.iinterval -> (rt, rs) tokmap -> (lt, ls) right_wrapped_parse t = |
109 | 111 | fun tight stop -> |
110 | 112 | let* res = |
111 | | - (let* inner_loc, (inner, notn) = located (entry (Scope.Situation.left_closeds ())) in |
| 113 | + (let* origin = get in |
| 114 | + let* inner_loc, (inner, notn) = located (entry (Scope.Situation.left_closeds_at origin)) in |
112 | 115 | match notn with |
113 | 116 | | Open_in_interval (lt, _) -> No.plusomega_nlt lt (* This case is impossible *) |
114 | 117 | | Closed_in_interval notn -> ( |
@@ -219,18 +222,20 @@ module Combinators (Final : Fmlib_std.Interfaces.ANY) = struct |
219 | 222 | | None -> succeed first_arg |
220 | 223 | | Some nontrivial -> |
221 | 224 | (* Now we start by looking ahead one token. If we see one of the specified ending ops, or the initial op of a left-open tree with looser tightness than the lower endpoint of the current interval (with strictness determined by the tree in question), we return the result argument without parsing any more. Note that the order matters, in case the next token could have more than one role. Ending ops are tested first, which means that if a certain operator could end an "inner term" in an outer containing notation, it always does, even if it could also be interpreted as some infix notation inside that inner term. If a certain token could be the initial op of more than one left-open, we stop here if *any* of those is looser; we don't backtrack and try other possibilities. So the rule is that if multiple notations start with the same token, the looser one is used preferentially in cases when it matters. (In cases where it doesn't matter, i.e. they would both be allowed at the same grouping relative to other notations, we can proceed to parse a merged tree containing both of them and decide later which one it is.) *) |
| 225 | + let* origin = get in |
222 | 226 | followed_by |
223 | 227 | (step (fun state _ (tok, _) -> |
224 | 228 | if TokMap.mem tok stop then Some (first_arg, state) |
225 | 229 | else |
226 | 230 | let open Monad.Ops (Monad.Maybe) in |
227 | | - let* (No.Interval ivl) = Scope.Situation.left_opens tok in |
| 231 | + let* (No.Interval ivl) = Scope.Situation.left_opens_at origin tok in |
228 | 232 | let t = tight.endpoint in |
229 | 233 | let* _ = No.Interval.contains ivl t in |
230 | 234 | return (first_arg, state))) |
231 | 235 | (* Otherwise, we parse either an arbitrary left-closed tree (applying the given result to it as a function) or an arbitrary left-open tree with tightness in the given interval (passing the given result as the starting open argument). Interior terms are treated as in "lclosed". *) |
232 | 236 | </> (let* res = |
233 | | - (let* inner_loc, (inner, notn) = located (entry (Scope.Situation.tighters tight)) in |
| 237 | + (let* inner_loc, (inner, notn) = |
| 238 | + located (entry (Scope.Situation.tighters_at origin tight)) in |
234 | 239 | match notn with |
235 | 240 | | Open_in_interval (left_ok, notn) -> ( |
236 | 241 | match (first_arg.get (interval_left notn), right notn) with |
@@ -397,7 +402,7 @@ module Combinators (Final : Fmlib_std.Interfaces.ANY) = struct |
397 | 402 | | Error e -> fatal (Anomaly ("Outer term failed: " ^ e)) |
398 | 403 |
|
399 | 404 | module Lex_and_parse = |
400 | | - Parse_with_lexer.Make_utf8 (Unit) (Lexer.Token_whitespace) (Final) (SemanticError) |
| 405 | + Parse_with_lexer.Make_utf8 (Origin) (Lexer.Token_whitespace) (Final) (SemanticError) |
401 | 406 | (Lexer.Parser) |
402 | 407 | (Basic.Parser) |
403 | 408 |
|
@@ -438,7 +443,9 @@ module Term = struct |
438 | 443 | ( { source = `File name; length = In_channel.length ic }, |
439 | 444 | fun p -> C.Lex_and_parse.run_on_channel ic p ) in |
440 | 445 | Range.run ~env @@ fun () -> |
441 | | - let p = C.Lex_and_parse.make Lexer.Parser.start (C.Basic.make () (C.term_only ?li ?ri ())) in |
| 446 | + let p = |
| 447 | + C.Lex_and_parse.make Lexer.Parser.start |
| 448 | + (C.Basic.make (Origin.current ()) (C.term_only ?li ?ri ())) in |
442 | 449 | let p = run p in |
443 | 450 | C.ensure_success p |
444 | 451 |
|
|
0 commit comments