@@ -750,20 +750,23 @@ class FastParser {
750750 val expander = StrategyBuilder .Ancestor [PNode ] {
751751
752752 // Handles macros on the left hand-side of assignments
753- case (PMacroAssign (call, exp), ctx) =>
754- if (! isMacro(call.opName))
755- throw ParseException (" The only calls that can be on the left-hand side of an assignment statement are calls to macros" , call.pos._1)
756-
757- val body = ExpandMacroIfValid (call, ctx)
758-
759- // Check if macro's body can be the left-hand side of an assignment and,
760- // if that's the case, add it in a corresponding assignment statement
761- body match {
762- case fa : PFieldAccess =>
763- val node = PFieldAssign (fa, exp)(fa.pos)
764- (node, ctx)
765- case _ => throw ParseException (" The body of this macro is not a suitable left-hand side for an assignment statement" , call.pos._1)
753+ case (assign@ PAssign (targets, rhs), ctx) =>
754+ val expandedTargets = targets map {
755+ case call : PCall => {
756+ if (! isMacro(call.opName))
757+ throw ParseException (" The only calls that can be on the left-hand side of an assignment statement are calls to macros" , call.pos._1)
758+ val body = ExpandMacroIfValid (call, ctx)
759+
760+ // Check if macro's body can be the left-hand side of an assignment and,
761+ // if that's the case, add it in a corresponding assignment statement
762+ body match {
763+ case target : PAssignTarget => target
764+ case _ => throw ParseException (" The body of this macro is not a suitable left-hand side for an assignment statement" , call.pos._1)
765+ }
766+ }
767+ case target => target
766768 }
769+ (PAssign (expandedTargets, rhs)(assign.pos), ctx)
767770
768771 // Handles all other calls to macros
769772 case (node, ctx) => (ExpandMacroIfValid (node, ctx), ctx)
@@ -800,7 +803,7 @@ class FastParser {
800803 | setTypedEmpty | explicitSetNonEmpty | multiSetTypedEmpty | explicitMultisetNonEmpty | seqTypedEmpty
801804 | size | explicitSeqNonEmpty | seqRange
802805 | mapTypedEmpty | explicitMapNonEmpty | mapDomain | mapRange
803- | fapp | idnuse | ParserExtension .newExpAtEnd(ctx))
806+ | newExp | fapp | idnuse | ParserExtension .newExpAtEnd(ctx))
804807
805808 def result [$ : P ]: P [PResultLit ] = FP (keyword(" result" )).map { case (pos, _) => PResultLit ()(pos) }
806809
@@ -1085,6 +1088,10 @@ class FastParser {
10851088 case (pos, e) => PMapRange (e)(pos)
10861089 })
10871090
1091+ def newExp [$ : P ]: P [PNewExp ] = FP (" new" ~ " (" ~ newExpFields ~ " )" ).map { case (pos, fields) => PNewExp (fields)(pos) }
1092+
1093+ def newExpFields [$ : P ]: P [Option [Seq [PIdnUse ]]] = P (idnuse.rep(sep = " ," )).map(Some (_)) | P (" *" ).map(_ => None )
1094+
10881095 def fapp [$ : P ]: P [PCall ] = FP (idnuse ~ parens(actualArgList)).map {
10891096 case (pos, (func, args)) =>
10901097 PCall (func, args, None )(pos)
@@ -1094,23 +1101,21 @@ class FastParser {
10941101 case (pos, (func, args, typeGiven)) => PCall (func, args, Some (typeGiven))(pos)
10951102 }
10961103
1097- def stmt (implicit ctx : P [_]) : P [PStmt ] = P (ParserExtension .newStmtAtStart(ctx) | macroassign | fieldassign | localassign | fold | unfold | exhale | assertP |
1098- inhale | assume | ifthnels | whle | varDecl | defineDecl | newstmt |
1099- methodCall | goto | lbl | packageWand | applyWand | macroref | block |
1104+ def stmt (implicit ctx : P [_]) : P [PStmt ] = P (ParserExtension .newStmtAtStart(ctx) | fold | unfold | exhale | assertP |
1105+ inhale | assume | ifthnels | whle | varDecl | defineDecl |
1106+ goto | lbl | packageWand | applyWand | assign | macroref | block |
11001107 quasihavoc | quasihavocall | ParserExtension .newStmtAtEnd(ctx))
11011108
1102- def nodefinestmt (implicit ctx : P [_]) : P [PStmt ] = P (ParserExtension .newStmtAtStart(ctx) | fieldassign | localassign | fold | unfold | exhale | assertP |
1103- inhale | assume | ifthnels | whle | varDecl | newstmt |
1104- methodCall | goto | lbl | packageWand | applyWand | macroref | block |
1109+ def nodefinestmt (implicit ctx : P [_]) : P [PStmt ] = P (ParserExtension .newStmtAtStart(ctx) | fold | unfold | exhale | assertP |
1110+ inhale | assume | ifthnels | whle | varDecl |
1111+ goto | lbl | packageWand | applyWand | assign | macroref | block |
11051112 quasihavoc | quasihavocall | ParserExtension .newStmtAtEnd(ctx))
11061113
11071114 def macroref [$ : P ]: P [PMacroRef ] = FP (idnuse).map { case (pos, a) => PMacroRef (a)(pos) }
11081115
1109- def fieldassign [$ : P ]: P [PFieldAssign ] = FP (fieldAcc ~ " :=" ~ exp).map { case (pos, (a, b)) => PFieldAssign (a, b)(pos) }
1110-
1111- def macroassign [$ : P ]: P [PMacroAssign ] = FP (NoCut (fapp) ~ " :=" ~ exp).map { case (pos, (call, exp)) => PMacroAssign (call, exp)(pos) }
1116+ def assignTarget [$ : P ]: P [PAssignTarget ] = fieldAcc | NoCut (fapp) | idnuse
11121117
1113- def localassign [$ : P ]: P [PVarAssign ] = FP (idnuse ~ " :=" ~ exp).map { case (pos, (a, b )) => PVarAssign (a, b )(pos) }
1118+ def assign [$ : P ]: P [PAssign ] = FP ((assignTarget.rep(min = 1 , sep = " , " ) ~ " :=" ). ? ~ exp).map { case (pos, (targets, rhs )) => PAssign (targets.getOrElse( Seq ()), rhs )(pos) }
11141119
11151120 def fold [$ : P ]: P [PFold ] = FP (" fold" ~ predicateAccessPred).map{ case (pos, e) => PFold (e)(pos)}
11161121
@@ -1170,7 +1175,9 @@ class FastParser {
11701175
11711176 def inv (implicit ctx : P [_]) : P [PExp ] = P ((keyword(" invariant" ) ~ exp ~~~ " ;" .lw.? ) | ParserExtension .invSpecification(ctx))
11721177
1173- def varDecl [$ : P ]: P [PLocalVarDecl ] = FP (keyword(" var" ) ~/ idndef ~ " :" ~ typ ~~~ (" :=" ~ exp).lw.? ).map { case (pos, (a, b, c)) => PLocalVarDecl (a, b, c)(pos) }
1178+ def varDecl [$ : P ]: P [PLocalVarDecl ] = FP (keyword(" var" ) ~/ nonEmptyFormalArgList ~~~ (" :=" ~ exp).lw.? ).map {
1179+ case (pos, (a, b)) => PLocalVarDecl (a, b.map(i => PAssign (a.map(v => PIdnUse (v.idndef.name)(v.idndef.pos)), i)(pos)))(pos)
1180+ }
11741181
11751182 def defineDecl [$ : P ]: P [PDefine ] = FP (keyword(" define" ) ~/ idndef ~ (" (" ~ idndef.rep(sep = " ," ) ~ " )" ).? ~ (exp | " {" ~ (nodefinestmt ~ " ;" .? ).rep ~ " }" )).map {
11761183 case (pos, (a, b, c)) => c match {
@@ -1179,19 +1186,6 @@ class FastParser {
11791186 }
11801187 }
11811188
1182- def newstmt [$ : P ]: P [PNewStmt ] = starredNewstmt | regularNewstmt
1183-
1184- def regularNewstmt [$ : P ]: P [PRegularNewStmt ] = FP (idnuse ~ " :=" ~ " new" ~ " (" ~ idnuse.rep(sep = " ," ) ~ " )" ).map { case (pos, (a, b)) => PRegularNewStmt (a, b)(pos) }
1185-
1186- def starredNewstmt [$ : P ]: P [PStarredNewStmt ] = FP (idnuse ~ " :=" ~ " new" ~ " (" ~ " *" ~ " )" ).map{ case (pos, e) => PStarredNewStmt (e)(pos) }
1187-
1188- def methodCall [$ : P ]: P [PMethodCall ] = FP ((idnuse.rep(sep = " ," ) ~ " :=" ).? ~ idnuse ~ parens(exp.rep(sep = " ," ))).map {
1189- case (pos, (None , method, args)) =>
1190- PMethodCall (Nil , method, args)(pos)
1191- case (pos, (Some (targets), method, args)) =>
1192- PMethodCall (targets, method, args)(pos)
1193- }
1194-
11951189 def goto [$ : P ]: P [PGoto ] = FP (" goto" ~/ idnuse).map{ case (pos, e) => PGoto (e)(pos) }
11961190
11971191 def lbl [$ : P ]: P [PLabel ] = FP (keyword(" label" ) ~/ idndef ~~~ (keyword(" invariant" ) ~/ exp).lw.rep).map {
@@ -1264,8 +1258,6 @@ class FastParser {
12641258
12651259 def unnamedFormalArg [$ : P ] = FP (typ).map{ case (pos, t) => PUnnamedFormalArgDecl (t)(pos) }
12661260
1267- def functionSignature [$ : P ] = P (" function" ~ idndef ~ " (" ~ formalArgList ~ " )" ~ " :" ~ typ)
1268-
12691261 def formalArgList [$ : P ]: P [Seq [PFormalArgDecl ]] = P (formalArg.rep(sep = " ," ))
12701262
12711263 def axiomDecl [$ : P ]: P [PAxiom1 ] = FP (keyword(" axiom" ) ~ idndef.? ~ " {" ~ exp ~ " }" ~~~ " ;" .lw.? ).map { case (pos, (a, b)) => PAxiom1 (a, b)(pos) }
0 commit comments