@@ -510,7 +510,7 @@ class FastParser {
510510 }
511511
512512 if (body != method.body) {
513- PMethod (method.idndef, method.formalArgs, method.formalReturns, method.pres, method.posts, body)(method.pos)
513+ PMethod (method.idndef, method.formalArgs, method.formalReturns, method.pres, method.posts, body)(method.pos, method.annotations )
514514 } else {
515515 method
516516 }
@@ -794,14 +794,23 @@ class FastParser {
794794
795795 // Note that `typedFapp` is before `"(" ~ exp ~ ")"` to ensure that the latter doesn't gobble up the brackets for the former
796796 // and then look like an `fapp` up untill the `: type` part, after which we need to backtrack all the way back (or error if cut)
797- def atom (implicit ctx : P [_]) : P [PExp ] = P (ParserExtension .newExpAtStart(ctx) | integer | booltrue | boolfalse | nul | old
797+ def atom (implicit ctx : P [_]) : P [PExp ] = P (ParserExtension .newExpAtStart(ctx) | annotatedAtom
798+ | integer | booltrue | boolfalse | nul | old
798799 | result | unExp | typedFapp
799800 | " (" ~ exp ~ " )" | accessPred | inhaleExhale | perm | let | quant | forperm | unfolding | applying
800801 | setTypedEmpty | explicitSetNonEmpty | multiSetTypedEmpty | explicitMultisetNonEmpty | seqTypedEmpty
801802 | size | explicitSeqNonEmpty | seqRange
802803 | mapTypedEmpty | explicitMapNonEmpty | mapDomain | mapRange
803804 | fapp | idnuse | ParserExtension .newExpAtEnd(ctx))
804805
806+ def stringLiteral [$ : P ]: P [String ] = P (" \" " ~ CharsWhile (_ != '\" ' ).! ~ " \" " )
807+
808+ def annotation [$ : P ]: P [(String , Seq [String ])] = P (" @" ~~ annotationIdentifier ~ parens(stringLiteral.rep(sep = " ," )))
809+
810+ def annotatedAtom [$ : P ]: P [PExp ] = FP (annotation ~ atom).map{
811+ case (pos, (key, value, exp)) => PAnnotatedExp (exp, (key, value))(pos)
812+ }
813+
805814 def result [$ : P ]: P [PResultLit ] = FP (keyword(" result" )).map { case (pos, _) => PResultLit ()(pos) }
806815
807816 def unExp [$ : P ]: P [PUnExp ] = FP (CharIn (" \\ -\\ !" ).! ~ suffixExpr).map { case (pos, (a, b)) => PUnExp (a, b)(pos) }
@@ -818,6 +827,8 @@ class FastParser {
818827
819828 def identifier [$ : P ]: P [Unit ] = CharIn (" A-Z" , " a-z" , " $_" ) ~~ CharIn (" 0-9" , " A-Z" , " a-z" , " $_" ).repX
820829
830+ def annotationIdentifier [$ : P ]: P [String ] = (CharIn (" A-Z" , " a-z" , " $_" ) ~~ CharIn (" 0-9" , " A-Z" , " a-z" , " $_." ).repX).!
831+
821832 def ident [$ : P ]: P [String ] = identifier.! .filter(a => ! keywords.contains(a)).opaque(" invalid identifier (could be a keyword)" )
822833
823834 def idnuse [$ : P ]: P [PIdnUse ] = FP (ident).map { case (pos, id) => PIdnUse (id)(pos) }
@@ -1094,11 +1105,16 @@ class FastParser {
10941105 case (pos, (func, args, typeGiven)) => PCall (func, args, Some (typeGiven))(pos)
10951106 }
10961107
1097- def stmt (implicit ctx : P [_]) : P [PStmt ] = P (ParserExtension .newStmtAtStart(ctx) | macroassign | fieldassign | localassign | fold | unfold | exhale | assertP |
1108+ def stmt (implicit ctx : P [_]) : P [PStmt ] = P (ParserExtension .newStmtAtStart(ctx) | annotatedStmt |
1109+ macroassign | fieldassign | localassign | fold | unfold | exhale | assertP |
10981110 inhale | assume | ifthnels | whle | varDecl | defineDecl | newstmt |
10991111 methodCall | goto | lbl | packageWand | applyWand | macroref | block |
11001112 quasihavoc | quasihavocall | ParserExtension .newStmtAtEnd(ctx))
11011113
1114+ def annotatedStmt (implicit ctx : P [_]): P [PStmt ] = (FP (annotation ~ stmt).map{
1115+ case (pos, (key, value, pStmt)) => PAnnotatedStmt (pStmt, (key, value))(pos)
1116+ })
1117+
11021118 def nodefinestmt (implicit ctx : P [_]) : P [PStmt ] = P (ParserExtension .newStmtAtStart(ctx) | fieldassign | localassign | fold | unfold | exhale | assertP |
11031119 inhale | assume | ifthnels | whle | varDecl | newstmt |
11041120 methodCall | goto | lbl | packageWand | applyWand | macroref | block |
@@ -1210,7 +1226,8 @@ class FastParser {
12101226
12111227 def applying [$ : P ]: P [PExp ] = FP (keyword(" applying" ) ~/ " (" ~ magicWandExp ~ " )" ~ " in" ~ exp).map { case (pos, (a, b)) => PApplying (a, b)(pos) }
12121228
1213- def programDecl (implicit ctx : P [_]) : P [PProgram ] = P (FP ((ParserExtension .newDeclAtStart(ctx) | preambleImport | defineDecl | domainDecl | fieldDecl | functionDecl | predicateDecl | methodDecl | ParserExtension .newDeclAtEnd(ctx)).rep).map {
1229+ def programDecl (implicit ctx : P [_]) : P [PProgram ] =
1230+ P (FP ((ParserExtension .newDeclAtStart(ctx) | preambleImport | defineDecl | fieldDecl | methodDecl | domainDecl | functionDecl | predicateDecl | ParserExtension .newDeclAtEnd(ctx)).rep).map {
12141231 case (pos, decls) => {
12151232 PProgram (
12161233 decls.collect { case i : PImport => i }, // Imports
@@ -1235,26 +1252,26 @@ class FastParser {
12351252
12361253 def anyString [$ : P ]: P [String ] = P (CharPred (c => c != '\" ' ).rep(1 ).! )
12371254
1238- def domainDecl [$ : P ]: P [PDomain ] = FP (" domain" ~/ idndef ~ typeParams ~ (" interpretation" ~ parens((ident ~ " :" ~ quoted(anyString.! )).rep(sep = " ," ))).? ~ " {" ~ (domainFunctionDecl | axiomDecl).rep ~
1255+ def domainDecl [$ : P ]: P [PDomain ] = FP (annotation.rep( 0 ) ~ " domain" ~/ idndef ~ typeParams ~ (" interpretation" ~ parens((ident ~ " :" ~ quoted(anyString.! )).rep(sep = " ," ))).? ~ " {" ~ (domainFunctionDecl | axiomDecl).rep ~
12391256 " }" ).map {
1240- case (pos, (name, typparams, interpretations, members)) =>
1257+ case (pos, (anns, name, typparams, interpretations, members)) =>
12411258 val funcs = members collect { case m : PDomainFunction1 => m }
12421259 val axioms = members collect { case m : PAxiom1 => m }
12431260 PDomain (
12441261 name,
12451262 typparams,
1246- funcs map (f => PDomainFunction (f.idndef, f.formalArgs, f.typ, f.unique, f.interpretation)(PIdnUse (name.name)(name.pos))(f.pos)),
1247- axioms map (a => PAxiom (a.idndef, a.exp)(PIdnUse (name.name)(name.pos))(a.pos)),
1248- interpretations.map(i => i.toMap))(pos)
1263+ funcs map (f => PDomainFunction (f.idndef, f.formalArgs, f.typ, f.unique, f.interpretation)(PIdnUse (name.name)(name.pos))(f.pos, f.annotations )),
1264+ axioms map (a => PAxiom (a.idndef, a.exp)(PIdnUse (name.name)(name.pos))(a.pos, a.annotations )),
1265+ interpretations.map(i => i.toMap))(pos, anns )
12491266 }
12501267
12511268 def domainTypeVarDecl [$ : P ]: P [PTypeVarDecl ] = FP (idndef).map{ case (pos, i) => PTypeVarDecl (i)(pos) }
12521269
12531270 def typeParams [$ : P ]: P [Seq [PTypeVarDecl ]] = P ((" [" ~ domainTypeVarDecl.rep(sep = " ," ) ~ " ]" ).? ).map(_.getOrElse(Nil ))
12541271
1255- def domainFunctionDecl [$ : P ]: P [PDomainFunction1 ] = FP (" unique" .! .? ~ domainFunctionSignature ~ (" interpretation" ~ quoted(anyString.! )).? ~~~ " ;" .lw.? ).map {
1256- case (pos, (unique, fdecl, interpretation)) => fdecl match {
1257- case (name, formalArgs, t) => PDomainFunction1 (name, formalArgs, t, unique.isDefined, interpretation)(pos)
1272+ def domainFunctionDecl [$ : P ]: P [PDomainFunction1 ] = FP (annotation.rep( 0 ) ~ " unique" .! .? ~ domainFunctionSignature ~ (" interpretation" ~ quoted(anyString.! )).? ~~~ " ;" .lw.? ).map {
1273+ case (pos, (anns, unique, fdecl, interpretation)) => fdecl match {
1274+ case (name, formalArgs, t) => PDomainFunction1 (name, formalArgs, t, unique.isDefined, interpretation)(pos, anns )
12581275 }
12591276 }
12601277
@@ -1268,15 +1285,15 @@ class FastParser {
12681285
12691286 def formalArgList [$ : P ]: P [Seq [PFormalArgDecl ]] = P (formalArg.rep(sep = " ," ))
12701287
1271- def axiomDecl [$ : P ]: P [PAxiom1 ] = FP (keyword(" axiom" ) ~ idndef.? ~ " {" ~ exp ~ " }" ~~~ " ;" .lw.? ).map { case (pos, (a, b)) => PAxiom1 (a, b)(pos) }
1288+ def axiomDecl [$ : P ]: P [PAxiom1 ] = FP (annotation.rep( 0 ) ~ keyword(" axiom" ) ~ idndef.? ~ " {" ~ exp ~ " }" ~~~ " ;" .lw.? ).map { case (pos, (anns, a, b)) => PAxiom1 (a, b)(pos, anns ) }
12721289
1273- def fieldDecl [$ : P ]: P [PField ] = FP (keyword(" field" ) ~/ idndef ~ " :" ~ typ ~~~ " ;" .lw.? ).map {
1274- case (pos, (a, b)) => PField (a, b)(pos)
1290+ def fieldDecl [$ : P ]: P [PField ] = FP (annotation.rep( 0 ) ~ keyword(" field" ) ~/ idndef ~ " :" ~ typ ~~~ " ;" .lw.? ).map {
1291+ case (pos, (anns, a, b)) => PField (a, b)(pos, anns )
12751292 }
12761293
1277- def functionDecl [$ : P ]: P [PFunction ] = FP (" function" ~/ idndef ~ " (" ~ formalArgList ~ " )" ~ " :" ~ typ ~~~ pre.lw.rep ~~~
1278- post.lw.rep ~~~ (" {" ~ exp ~ " }" ).lw.? ).map({ case (pos, (a, b, c, d, e, f)) =>
1279- PFunction (a, b, c, d, e, f)(pos)
1294+ def functionDecl [$ : P ]: P [PFunction ] = FP (annotation.rep( 0 ) ~ " function" ~/ idndef ~ " (" ~ formalArgList ~ " )" ~ " :" ~ typ ~~~ pre.lw.rep ~~~
1295+ post.lw.rep ~~~ (" {" ~ exp ~ " }" ).lw.? ).map({ case (pos, (anns, a, b, c, d, e, f)) =>
1296+ PFunction (a, b, c, d, e, f)(pos, anns )
12801297 })
12811298
12821299
@@ -1286,14 +1303,14 @@ class FastParser {
12861303
12871304 def decCl [$ : P ]: P [Seq [PExp ]] = P (exp.rep(sep = " ," ))
12881305
1289- def predicateDecl [$ : P ]: P [PPredicate ] = FP (keyword(" predicate" ) ~/ idndef ~ " (" ~ formalArgList ~ " )" ~~~ (" {" ~ exp ~ " }" ).lw.? ).map {
1290- case (pos, (a, b, c)) =>
1291- PPredicate (a, b, c)(pos)
1306+ def predicateDecl [$ : P ]: P [PPredicate ] = FP (annotation.rep( 0 ) ~ keyword(" predicate" ) ~/ idndef ~ " (" ~ formalArgList ~ " )" ~~~ (" {" ~ exp ~ " }" ).lw.? ).map {
1307+ case (pos, (anns, a, b, c)) =>
1308+ PPredicate (a, b, c)(pos, anns )
12921309 }
12931310
1294- def methodDecl [$ : P ]: P [PMethod ] = FP (methodSignature ~~~/ pre.lw.rep ~~~ post.lw.rep ~~~ block.lw.? ).map {
1295- case (pos, (name, args, rets, pres, posts, body)) =>
1296- PMethod (name, args, rets.getOrElse(Nil ), pres, posts, body)(pos)
1311+ def methodDecl [$ : P ]: P [PMethod ] = FP (annotation.rep( 0 ) ~ methodSignature ~~~/ pre.lw.rep ~~~ post.lw.rep ~~~ block.lw.? ).map {
1312+ case (pos, (anns, ( name, args, rets) , pres, posts, body)) =>
1313+ PMethod (name, args, rets.getOrElse(Nil ), pres, posts, body)(pos, anns )
12971314 }
12981315
12991316 def methodSignature [$ : P ] = P (" method" ~/ idndef ~ " (" ~ formalArgList ~ " )" ~~~ (" returns" ~ " (" ~ formalArgList ~ " )" ).lw.? )
0 commit comments