11% {
22(*
3- Menhir reports the following warnings:
3+ This parser should be conflict-free (0 shift/reduce, 0 reduce/reduce).
44
5- Warning: 5 states have shift/reduce conflicts.
6- Warning: 6 shift/reduce conflicts were arbitrarily resolved.
7- Warning: 221 end-of-stream conflicts were arbitrarily resolved.
5+ Shift/reduce conflicts that naturally arise in an ML-style language
6+ (dangling BAR in match/function/try, FUN body extent, etc.) are
7+ resolved via precedence declarations: chain rules are annotated with
8+ %prec below_op so that binary operators and delimiters always shift
9+ into the body of the enclosing construct.
810
9- If you're editing this file, be sure to not increase the warnings,
10- except if you have a really good reason.
11-
12- The shift-reduce conflicts are natural in an ML-style language. E.g.,
13- there are S-R conflicts with dangling elses, with a non-delimited match where
14- the BAR is dangling etc.
11+ If you're editing this file, be sure to not introduce new conflicts.
1512
1613 Note: Some symbols are marked public, so that we can reuse this parser from
1714 the parser for the Pulse DSL in FStarLang/steel.
18-
15+
1916*)
2017(* (c) Microsoft Corporation. All rights reserved *)
2118open Prims
@@ -205,14 +202,32 @@ let rec pat_names (bs : pattern list) : ident list =
205202/* These are artificial */
206203% token EOF
207204
205+ (* Lowest precedence — used for chain rules that should always
206+ lose to any operator/delimiter, so that the body of FUN,
207+ quantifiers, match, function, and try extends as far right
208+ as possible (standard "maximal munch" for ML-like languages). *)
209+ % nonassoc below_op
210+
208211% nonassoc THEN
209212% nonassoc ELSE
210213
214+ % nonassoc SEMICOLON SEMICOLON_OP
215+
211216% nonassoc ASSERT
212217% nonassoc EQUALTYPE
213218% nonassoc SUBTYPE
214219% nonassoc BY
215220
221+ % nonassoc LBRACK
222+ % nonassoc BAR
223+
224+ % nonassoc IFF
225+ % nonassoc IMPLIES
226+ % nonassoc RARROW
227+ % nonassoc DISJUNCTION
228+ % nonassoc CONJUNCTION
229+ % nonassoc COMMA
230+
216231% right COLON_COLON
217232% right AMP
218233
@@ -721,7 +736,7 @@ letqualifier:
721736 *)
722737aqual:
723738 | HASH LBRACK t= thunk(term) RBRACK { mk_meta_tac t }
724- | HASH { Implicit }
739+ | HASH % prec below_op { Implicit }
725740 | DOLLAR { Equality }
726741
727742binderAttributes:
@@ -957,6 +972,7 @@ kind:
957972
958973term:
959974 | e= noSeqTerm
975+ % prec below_op
960976 { e }
961977 | e1= noSeqTerm SEMICOLON e2= term
962978 { mk_term (Seq (e1, e2)) (rr2 $ loc(e1) $ loc(e2)) Expr }
@@ -988,7 +1004,7 @@ localletqualifier:
9881004
9891005% public
9901006noSeqTerm:
991- | t= typ { t }
1007+ | t= typ % prec below_op { t }
9921008 | e= tmIff SUBTYPE t= tmIff
9931009 { mk_term (Ascribed (e,{t with level= Expr },None ,false )) (rr $ loc(e)) Expr }
9941010 | e= tmIff SUBTYPE t= tmIff BY tactic= thunk(typ)
@@ -1043,11 +1059,13 @@ noSeqTerm:
10431059 mk_term (If (e1, op, ret_opt, e2, e3)) (rr2 $ loc(op) $ loc(e2)) Expr
10441060 }
10451061 | TRY e1= term WITH pbs= left_flexible_nonempty_list(BAR , patternBranch)
1062+ % prec below_op
10461063 {
10471064 let branches = focusBranches (pbs) (rr2 $ loc($ 1 ) $ loc(pbs)) in
10481065 mk_term (TryWith (e1, branches)) (rr2 $ loc($ 1 ) $ loc(pbs)) Expr
10491066 }
10501067 | op= matchMaybeOp e= term ret_opt= option (match_returning) WITH pbs= left_flexible_list(BAR , pb= patternBranch {pb})
1068+ % prec below_op
10511069 {
10521070 let branches = focusBranches pbs (rr2 $ loc(op) $ loc(pbs)) in
10531071 mk_term (Match (e, op, ret_opt, branches)) (rr2 $ loc(op) $ loc(pbs)) Expr
@@ -1081,6 +1099,7 @@ noSeqTerm:
10811099 , e)) (rr2 $ loc(op) $ loc(e)) Expr
10821100 }
10831101 | FUNCTION pbs= left_flexible_nonempty_list(BAR , patternBranch)
1102+ % prec below_op
10841103 {
10851104 let branches = focusBranches pbs (rr2 $ loc($ 1 ) $ loc(pbs)) in
10861105 mk_function branches (rr $ loc) (rr2 $ loc($ 1 ) $ loc(pbs))
@@ -1131,7 +1150,7 @@ noSeqTerm:
11311150 else mk_term (IntroExists (bs, p, vs, e)) (rr2 $ loc($ 1 ) $ loc(e)) Expr
11321151 }
11331152
1134- | INTRO p= tmFormula IMPLIES q= tmFormula WITH y= singleBinder DOT e= noSeqTerm
1153+ | INTRO p= tmArrow( tmFormula) IMPLIES q= tmFormula WITH y= singleBinder DOT e= noSeqTerm
11351154 {
11361155 mk_term (IntroImplies (p, q, y, e)) (rr2 $ loc($ 1 ) $ loc(e)) Expr
11371156 }
@@ -1161,7 +1180,7 @@ noSeqTerm:
11611180 mk_term (ElimExists (bs, p, q, y, e)) (rr2 $ loc($ 1 ) $ loc(e)) Expr
11621181 }
11631182
1164- | ELIM p= tmFormula IMPLIES q= tmFormula WITH e= noSeqTerm
1183+ | ELIM p= tmArrow( tmFormula) IMPLIES q= tmFormula WITH e= noSeqTerm
11651184 {
11661185 mk_term (ElimImplies (p, q, e)) (rr2 $ loc($ 1 ) $ loc(e)) Expr
11671186 }
@@ -1221,8 +1240,9 @@ typ:
12211240 }
12221241
12231242% public
1243+ % inline
12241244trigger:
1225- | { [] }
1245+ | { [] }
12261246 | LBRACE_COLON_PATTERN pats= disjunctivePats RBRACE { pats }
12271247
12281248disjunctivePats:
@@ -1257,12 +1277,13 @@ patternBranch:
12571277tmIff:
12581278 | e1= tmImplies tok= IFF e2= tmIff
12591279 { mk_term (Op (mk_ident(" <==>" , rr $ loc(tok)), [e1; e2])) (rr2 $ loc(e1) $ loc(e2)) Formula }
1260- | e= tmImplies { e }
1280+ | e= tmImplies % prec below_op { e }
12611281
12621282tmImplies:
12631283 | e1= tmArrow(tmFormula) tok= IMPLIES e2= tmImplies
12641284 { mk_term (Op (mk_ident(" ==>" , rr $ loc(tok)), [e1; e2])) (rr2 $ loc(e1) $ loc(e2)) Formula }
12651285 | e= tmArrow(tmFormula)
1286+ % prec below_op
12661287 { e }
12671288
12681289
@@ -1277,7 +1298,7 @@ tmArrow(Tm):
12771298 in
12781299 mk_term (Product ([b], tgt)) (rr2 $ loc(dom) $ loc(tgt)) Un
12791300 }
1280- | e= Tm { e }
1301+ | e= Tm % prec below_op { e }
12811302
12821303simpleArrow:
12831304 | dom= simpleArrowDomain RARROW tgt= simpleArrow
@@ -1305,21 +1326,24 @@ simpleArrowDomain:
13051326tmFormula:
13061327 | e1= tmFormula tok= DISJUNCTION e2= tmConjunction
13071328 { mk_term (Op (mk_ident(" \\ /" , rr $ loc(tok)), [e1;e2])) (rr2 $ loc(e1) $ loc(e2)) Formula }
1308- | e= tmConjunction { e }
1329+ | e= tmConjunction % prec below_op { e }
13091330
13101331tmConjunction:
13111332 | e1= tmConjunction tok= CONJUNCTION e2= tmTuple
13121333 { mk_term (Op (mk_ident(" /\\ " , rr $ loc(tok)), [e1;e2])) (rr2 $ loc(e1) $ loc(e2)) Formula }
13131334 | e= tmTuple { e }
13141335
13151336tmTuple:
1316- | el= separated_nonempty_list(COMMA , tmEq)
1317- {
1318- match el with
1319- | [x] -> x
1320- | components -> mkTuple components (rr2 $ loc(el) $ loc(el))
1321- }
1337+ | e= tmEq % prec below_op
1338+ { e }
1339+ | e= tmEq COMMA rest= commaTmEqList
1340+ { mkTuple (e :: rest) (rr $ loc(e)) }
13221341
1342+ commaTmEqList:
1343+ | e= tmEq % prec below_op
1344+ { [e] }
1345+ | e= tmEq COMMA rest= commaTmEqList
1346+ { e :: rest }
13231347
13241348
13251349% public
@@ -1354,6 +1378,7 @@ tmEqWith(X):
13541378 | BACKTICK_HASH e= atomicTerm
13551379 { mk_term (Antiquote e) (rr $ loc) Un }
13561380 | e= tmNoEqWith(X )
1381+ % prec below_op
13571382 { e }
13581383
13591384% inline recordTerm:
@@ -1424,7 +1449,7 @@ tmEqNoRefinement:
14241449
14251450% public
14261451tmEq:
1427- | e= tmEqWith(tmRefinement) { e }
1452+ | e= tmEqWith(tmRefinement) % prec below_op { e }
14281453
14291454tmNoEq:
14301455 | e= tmNoEqWith(tmRefinement) { e }
@@ -1537,7 +1562,7 @@ atomicTermQUident:
15371562 }
15381563
15391564atomicTermNotQUident:
1540- | UNDERSCORE { mk_term Wild (rr $ loc) Un }
1565+ | UNDERSCORE % prec below_op { mk_term Wild (rr $ loc) Un }
15411566 | c= constant { mk_term (Const c) (rr $ loc) Expr }
15421567 | x= opPrefixTerm(atomicTermNotQUident)
15431568 { x }
@@ -1712,6 +1737,7 @@ right_flexible_nonempty_list(SEP, X):
17121737
17131738reverse_left_flexible_list(delim, X ):
17141739| (* nothing *)
1740+ % prec below_op
17151741 { [] }
17161742| x = X
17171743 { [x] }
0 commit comments