%{ open Ast open Getters open AstUtils let rec MyFold ee acc = match ee with | [] -> acc | x::rest -> BinaryAnd x (MyFold rest acc) %} // The start token becomes a parser function in the compiled code: %start start // These are the terminal tokens of the grammar along with the types of // the data carried by each token: %token ID %token INTEGER %token DOT %token NOT %token STAR DIV MOD %token PLUS MINUS %token OLD %token DOTDOT DOTDOTDOT %token EQ NEQ LESS ATMOST ATLEAST GREATER IN NOTIN %token AND OR %token IMPLIES %token IFF %token LPAREN RPAREN LBRACKET RBRACKET LCURLY RCURLY VERTBAR %token GETS COLON COLONCOLON COMMA QMARK %token INTERFACE DATAMODEL CODE %token VAR CONSTRUCTOR METHOD FRAME INVARIANT RETURNS REQUIRES ENSURES FORALL %token INTTYPE BOOLTYPE SEQTYPE SETTYPE %token EOF // This is the type of the data produced by a successful reduction of the 'start' // symbol: %type < Ast.SyntacticProgram > start %% // These are the rules of the grammar along with the F# code of the // actions executed as rules are reduced. In this case the actions // produce data using F# data construction terms. start: TopLevelDecls EOF { SProgram($1) } TopLevelDecls: | { [] } | TopLevelDecl TopLevelDecls { $1 :: $2 } TopLevelDecl: | INTERFACE ID TypeParams LCURLY Members RCURLY { Interface($2, $3, $5) } | DATAMODEL ID TypeParams LCURLY FrameMembers RCURLY { match $5 with (vv,fr,inv) -> DataModel($2, $3, vv, fr, inv) } | CODE ID TypeParams LCURLY RCURLY { Code($2, $3) } TypeParams: | { [] } | LBRACKET IdList RBRACKET { $2 } IdList: | ID { [$1] } | ID IdList { $1 :: $2 } Members: | { [] } | Member Members { $1 :: $2 } Signature: | LPAREN VarDeclList RPAREN { Sig($2, []) } | LPAREN VarDeclList RPAREN RETURNS LPAREN VarDeclList RPAREN { Sig($2, $6) } Pre: | { TrueLiteral } | REQUIRES Expr Pre { BinaryAnd $2 $3 } Post: | { TrueLiteral } | ENSURES Expr Post { BinaryAnd $2 $3 } | ID GETS Expr Post { BinaryAnd (BinaryExpr(40,"=",IdLiteral($1),$3)) $4 } StmtList: | { [] } | Stmt StmtList { $1 :: $2 } Stmt: | BlockStmt { $1 } | Expr GETS Expr { Assign($1, $3) } BlockStmt: | LCURLY StmtList RCURLY { Block $2 } Member: | VAR VarDecl { Field($2) } | CONSTRUCTOR ID Signature Pre Post { Method($2, $3, RewriteVars (GetSigVars $3) $4, RewriteVars (GetSigVars $3) $5, true) } | METHOD ID Signature Pre Post { Method($2, $3, RewriteVars (GetSigVars $3) $4, RewriteVars (GetSigVars $3) $5, false) } | INVARIANT ExprList { Invariant($2) } FrameMembers: | { [], [], TrueLiteral } | VAR VarDecl FrameMembers { match $3 with (vv,fr,inv) -> $2 :: vv, fr, inv } | FRAME FrameMembers { $2 } | FRAME FramePartitionList FrameMembers { match $3 with (vv,fr,inv) -> vv, List.append $2 fr, inv } | INVARIANT ExprList FrameMembers { match $3 with (vv,fr,inv) -> vv, fr, MyFold $2 inv } FramePartitionList: | FramePartition { $1 } | FramePartition FramePartitionList { List.append $1 $2 } VarDeclList: | { [] } | VarDecl { [$1] } | VarDecl COMMA VarDeclList { $1 :: $3 } VarDecl: | ID { Var($1,None, false) } | ID COLON Type { Var($1,Some($3), false) } Type: | INTTYPE { IntType } | BOOLTYPE { BoolType } | ID { NamedType($1, []) } | SEQTYPE LBRACKET Type RBRACKET { SeqType($3) } | SETTYPE LBRACKET Type RBRACKET { SetType($3) } | ID LBRACKET Type RBRACKET { InstantiatedType($1, [$3]) } ExprList: | { [] } | Expr { [$1] } | Expr ExprList { $1 :: $2 } Expr: | Expr10 { $1 } Expr10: | Expr20 { $1 } | Expr10 IFF Expr20 { BinaryExpr(10,"<==>",$1,$3) } Expr20: | Expr25 { $1 } | Expr25 IMPLIES Expr20 { BinaryExpr(20,"==>",$1,$3) } Expr25: | Expr30 { $1 } | Expr30 QMARK Expr25 COLON Expr25 { IteExpr($1,$3,$5) } Expr30: | Expr40 { $1 } | Expr40 AND Expr30and { BinaryAnd $1 $3 } | Expr40 OR Expr30or { BinaryOr $1 $3 } Expr30and: | Expr40 { $1 } | Expr40 AND Expr30and { BinaryAnd $1 $3 } Expr30or: | Expr40 { $1 } | Expr40 AND Expr30or { BinaryOr $1 $3 } Expr40: | Expr50 { $1 } | Expr50 EQ Expr50 { BinaryExpr(40,"=",$1,$3) } | Expr50 NEQ Expr50 { BinaryExpr(40,"!=",$1,$3) } | Expr50 LESS Expr50 { BinaryExpr(40,"<",$1,$3) } | Expr50 ATMOST Expr50 { BinaryExpr(40,"<=",$1,$3) } | Expr50 ATLEAST Expr50 { BinaryExpr(40,">=",$1,$3) } | Expr50 GREATER Expr50 { BinaryExpr(40,">",$1,$3) } | Expr50 IN Expr50 { BinaryExpr(40,"in",$1,$3) } | Expr50 NOTIN Expr50 { BinaryExpr(40,"!in",$1,$3) } Expr50: | Expr55 { $1 } | Expr55 DOTDOTDOT Expr55 { BinaryExpr(50,"...",$1,$3) } Expr55: | Expr60 { $1 } | Expr55 PLUS Expr60 { BinaryExpr(55,"+",$1,$3) } | Expr55 MINUS Expr60 { BinaryExpr(55,"-",$1,$3) } Expr60: | Expr90 { $1 } | Expr60 STAR Expr90 { BinaryExpr(60,"*",$1,$3) } | Expr60 DIV Expr90 { BinaryExpr(60,"div",$1,$3) } | Expr60 MOD Expr90 { BinaryExpr(60,"mod",$1,$3) } Expr90: | Expr100 { $1 } | OLD LPAREN Expr90 RPAREN { OldExpr($3) } | NOT Expr90 { UnaryExpr("!", $2) } | MINUS Expr90 { UnaryExpr("-", $2) } | Expr90 DOTDOT { LCIntervalExpr($1) } Expr100: | INTEGER { IntLiteral($1) } | ID { if $1 = "this" then ObjLiteral("this") elif $1 = "null" then ObjLiteral("null") else IdLiteral($1) } | Expr100 DOT ID { Dot($1, $3) } | Expr100 LBRACKET StarExpr RBRACKET { SelectExpr($1, $3) } | Expr100 LBRACKET Expr GETS Expr RBRACKET { UpdateExpr($1, $3, $5) } | LPAREN Expr RPAREN { $2 } | LBRACKET ExprList RBRACKET { SequenceExpr($2) } | LCURLY ExprList RCURLY { SetExpr($2) } | VERTBAR Expr VERTBAR { SeqLength($2) } | FORALL VarDeclList COLONCOLON Expr { ForallExpr($2, RewriteVars $2 $4) } StarExpr: | STAR { Star } | Expr { $1 } FramePartition: | Expr100 { [$1] } | Expr100 STAR FramePartition { $1 :: $3 }