Skip to content

Commit 2f53ef0

Browse files
authored
Merge pull request #4219 from mtzguido/pars
Parser(s): annotate precedences and remove (most) conflicts
2 parents 955fab1 + 43ec65d commit 2f53ef0

2 files changed

Lines changed: 64 additions & 44 deletions

File tree

pulse/src/ml/pulseparser.mly

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
11
%{
2-
(*
3-
Warning: 27 states have shift/reduce conflicts.
4-
Warning: one state has reduce/reduce conflicts.
5-
Warning: 342 shift/reduce conflicts were arbitrarily resolved.
6-
Warning: one reduce/reduce conflict was arbitrarily resolved.
7-
Warning: 234 end-of-stream conflicts were arbitrarily resolved.
8-
*)
92
(* (c) Microsoft Corporation. All rights reserved *)
103
open Fstarcompiler
114
open Prims
@@ -250,19 +243,14 @@ while_invariant1:
250243
while_invariant:
251244
| is=list(while_invariant1) { is }
252245

253-
pulseStmtAfterLabel:
254-
| { None }
255-
| SEMICOLON s=pulseStmtNonempty { Some s }
256-
257246
pulseStmtNoSeq:
258247
| OPEN i=quident
259248
{ PulseSyntaxExtension_Sugar.mk_open i }
260-
| tm=appTerm LARROW arr_elt=noSeqTerm
249+
| e1=indexingTerm LARROW e3=noSeqTerm
261250
{
262-
match tm.tm with
251+
match e1.tm with
263252
| Op(op, [arr;ix]) when FStarC_Ident.string_of_id op = ".()" ->
264-
PulseSyntaxExtension_Sugar.mk_array_assignment arr ix arr_elt
265-
253+
PulseSyntaxExtension_Sugar.mk_array_assignment arr ix e3
266254
| _ ->
267255
raise_error_text (rr $loc) Fatal_SyntaxError "Expected an array assignment of the form x.(i) <- v"
268256
}
@@ -284,9 +272,9 @@ pulseStmtNoSeq:
284272
{ PulseSyntaxExtension_Sugar.mk_proof_hint_with_binders (ASSERT p) bs }
285273
| bs=withBindersOpt ASSUME p=pulseSLProp
286274
{ PulseSyntaxExtension_Sugar.mk_proof_hint_with_binders (ASSUME p) bs }
287-
| bs=withBindersOpt UNFOLD ns=option(names) p=pulseSLProp
275+
| bs=withBindersOpt UNFOLD ns=optionalNames p=pulseSLProp
288276
{ PulseSyntaxExtension_Sugar.mk_proof_hint_with_binders (UNFOLD (ns,p)) bs }
289-
| bs=withBindersOpt FOLD ns=option(names) p=pulseSLProp
277+
| bs=withBindersOpt FOLD ns=optionalNames p=pulseSLProp
290278
{ PulseSyntaxExtension_Sugar.mk_proof_hint_with_binders (FOLD (ns,p)) bs }
291279
| bs=withBinders UNDERSCORE
292280
{ PulseSyntaxExtension_Sugar.mk_proof_hint_with_binders WILD bs }
@@ -302,6 +290,8 @@ pulseStmtNoSeq:
302290
{ PulseSyntaxExtension_Sugar.mk_block s }
303291
| LBRACE body=pulseStmt RBRACE post=option(ensuresSLProp) LABEL lbl=lident COLON
304292
{ PulseSyntaxExtension_Sugar.mk_forward_jump_label body lbl post }
293+
| LABEL lbl=lident COLON LBRACE body=pulseStmt RBRACE post=option(ensuresSLProp)
294+
{ PulseSyntaxExtension_Sugar.mk_forward_jump_label body lbl post }
305295
| p=matchStmt { p }
306296
| PRAGMA_SET_OPTIONS options=STRING LBRACE s=pulseStmt RBRACE
307297
{ PulseSyntaxExtension_Sugar.mk_pragma_set_options options s }
@@ -348,6 +338,10 @@ names:
348338
| LBRACK l=separated_nonempty_list(SEMICOLON, qlident) RBRACK
349339
{ l }
350340

341+
optionalNames:
342+
| ns=names { Some ns }
343+
| %prec below_op { None }
344+
351345
withBinders:
352346
| WITH bs=nonempty_list(multiBinder) DOT
353347
{ List.flatten bs }

src/ml/FStarC_Parser_Parse.mly

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
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 *)
2118
open 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
*)
722737
aqual:
723738
| HASH LBRACK t=thunk(term) RBRACK { mk_meta_tac t }
724-
| HASH { Implicit }
739+
| HASH %prec below_op { Implicit }
725740
| DOLLAR { Equality }
726741

727742
binderAttributes:
@@ -957,6 +972,7 @@ kind:
957972

958973
term:
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
9901006
noSeqTerm:
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
12241244
trigger:
1225-
| { [] }
1245+
| { [] }
12261246
| LBRACE_COLON_PATTERN pats=disjunctivePats RBRACE { pats }
12271247

12281248
disjunctivePats:
@@ -1257,12 +1277,13 @@ patternBranch:
12571277
tmIff:
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

12621282
tmImplies:
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

12821303
simpleArrow:
12831304
| dom=simpleArrowDomain RARROW tgt=simpleArrow
@@ -1305,21 +1326,24 @@ simpleArrowDomain:
13051326
tmFormula:
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

13101331
tmConjunction:
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

13151336
tmTuple:
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
14261451
tmEq:
1427-
| e=tmEqWith(tmRefinement) { e }
1452+
| e=tmEqWith(tmRefinement) %prec below_op { e }
14281453

14291454
tmNoEq:
14301455
| e=tmNoEqWith(tmRefinement) { e }
@@ -1537,7 +1562,7 @@ atomicTermQUident:
15371562
}
15381563

15391564
atomicTermNotQUident:
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

17131738
reverse_left_flexible_list(delim, X):
17141739
| (* nothing *)
1740+
%prec below_op
17151741
{ [] }
17161742
| x = X
17171743
{ [x] }

0 commit comments

Comments
 (0)