-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathambiguity.ml
86 lines (74 loc) · 2.91 KB
/
ambiguity.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
open Util
open Core
open Parser
open Notation
open Testutil
open Showparse
(* We raise an error if one notation is a prefix of another, since parsing such combinations would require too much backtracking. Here we test the generation of that error. *)
let ifthen = make "ifthen" (Prefixr No.zero)
let () =
set_tree ifthen
(Closed_entry (eop (Ident [ "if" ]) (term (Ident [ "then" ]) (Done_closed ifthen))))
let ifthenelse = make "ifthenelse" (Prefixr No.zero)
let () =
set_tree ifthenelse
(Closed_entry
(eop (Ident [ "if" ])
(term (Ident [ "then" ]) (term (Ident [ "else" ]) (Done_closed ifthenelse)))))
let () =
Parser.Lexer.Specials.run @@ fun () ->
Reporter.run ~emit:Reporter.display ~fatal:(fun d ->
Reporter.display d;
raise (Failure "Parse failure"))
@@ fun () ->
Situation.run_on Situation.empty @@ fun () ->
Situation.Current.add ifthen;
assert (parse "if x then y" = Notn ("ifthen", [ Term (Ident [ "x" ]); Term (Ident [ "y" ]) ]))
let () =
Parser.Lexer.Specials.run @@ fun () ->
Reporter.run ~emit:Reporter.display ~fatal:(fun d ->
Reporter.display d;
raise (Failure "Parse failure"))
@@ fun () ->
Situation.run_on Situation.empty @@ fun () ->
Situation.Current.add ifthenelse;
assert (
parse "if x then y else z"
= Notn ("ifthenelse", [ Term (Ident [ "x" ]); Term (Ident [ "y" ]); Term (Ident [ "z" ]) ]))
let () =
Parser.Lexer.Specials.run @@ fun () ->
Reporter.run ~emit:Reporter.display ~fatal:(fun d ->
if
d.message
= Parsing_ambiguity "One notation is a prefix of another: [ifthen] and [ifthenelse]"
then ()
else (
Reporter.display d;
raise (Failure "Unexpected error code")))
@@ fun () ->
Situation.run_on Situation.empty @@ fun () ->
Situation.Current.add ifthen;
Situation.Current.add ifthenelse;
assert (parse "if x then y" = Notn ("ifthen", [ Term (Ident [ "x" ]); Term (Ident [ "y" ]) ]))
(* However, it does work to have two distinct notations that share a common prefix, as long as both of them extend that prefix nontrivially. (This is the whole point of merging notation trees.) *)
let ifthenelif = make "ifthenelif" (Prefixr No.zero)
let () =
set_tree ifthenelif
(Closed_entry
(eop (Ident [ "if" ])
(term (Ident [ "then" ]) (term (Ident [ "elif" ]) (Done_closed ifthenelif)))))
let () =
Parser.Lexer.Specials.run @@ fun () ->
Reporter.run ~emit:Reporter.display ~fatal:(fun d ->
Reporter.display d;
raise (Failure "Parse failure"))
@@ fun () ->
Situation.run_on Situation.empty @@ fun () ->
Situation.Current.add ifthenelse;
Situation.Current.add ifthenelif;
assert (
parse "if x then y else z"
= Notn ("ifthenelse", [ Term (Ident [ "x" ]); Term (Ident [ "y" ]); Term (Ident [ "z" ]) ]));
assert (
parse "if x then y elif z"
= Notn ("ifthenelif", [ Term (Ident [ "x" ]); Term (Ident [ "y" ]); Term (Ident [ "z" ]) ]))