( ";"
{ Spec }
| { Spec }
ImplBody
(.
impl = new Implementation(x, x.val, typeParams,
Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, kv == null ? null : (QKeyValue)kv.Clone(), this.errors);
.)
)
(. proc = new Procedure(x, x.val, typeParams, ins, outs, pre, mods, post, kv); .)
.
Implementation
= (. Contract.Ensures(Contract.ValueAtReturn(out impl) != null); IToken/*!*/ x;
TypeVariableSeq/*!*/ typeParams;
List/*!*/ ins, outs;
List/*!*/ locals;
StmtList/*!*/ stmtList;
QKeyValue kv;
.)
"implementation"
ProcSignature
ImplBody
(. impl = new Implementation(x, x.val, typeParams, ins, outs, locals, stmtList, kv, this.errors); .)
.
ProcSignature/*!*/ ins, out List/*!*/ outs, out QKeyValue kv>
= (. Contract.Ensures(Contract.ValueAtReturn(out name) != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); Contract.Ensures(Contract.ValueAtReturn(out ins) != null); Contract.Ensures(Contract.ValueAtReturn(out outs) != null);
IToken/*!*/ typeParamTok; typeParams = new TypeVariableSeq();
outs = new List(); kv = null; .)
{ Attribute[ }
Ident
[ TypeParams ]
ProcFormals
[ "returns" ProcFormals ]
.
Spec]/*!*/ pre, List/*!*/ mods, List/*!*/ post>
= (.Contract.Requires(pre != null); Contract.Requires(mods != null); Contract.Requires(post != null); List/*!*/ ms; .)
( "modifies"
[ Idents (. foreach(IToken/*!*/ m in ms){
Contract.Assert(m != null);
mods.Add(new IdentifierExpr(m, m.val));
}
.)
] ";"
| "free" SpecPrePost
| SpecPrePost
)
.
SpecPrePost/*!*/ pre, List/*!*/ post>
= (. Contract.Requires(pre != null); Contract.Requires(post != null); Expr/*!*/ e; Token tok = null; QKeyValue kv = null; .)
( "requires" (. tok = t; .)
{ Attribute[ }
Proposition ";" (. pre.Add(new Requires(tok, free, e, null, kv)); .)
| "ensures" (. tok = t; .)
{ Attribute][ }
Proposition ";" (. post.Add(new Ensures(tok, free, e, null, kv)); .)
)
.
/*------------------------------------------------------------------------*/
ImplBody/*!*/ locals, out StmtList/*!*/ stmtList>
= (. Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); locals = new List(); .)
"{"
{ LocalVars }
StmtList
.
/* the StmtList also reads the final curly brace */
StmtList
= (. Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); List bigblocks = new List();
/* built-up state for the current BigBlock: */
IToken startToken = null; string currentLabel = null;
List cs = null; /* invariant: startToken != null ==> cs != null */
/* temporary variables: */
IToken label; Cmd c; BigBlock b;
StructuredCmd ec = null; StructuredCmd/*!*/ ecn;
TransferCmd tc = null; TransferCmd/*!*/ tcn;
.)
{
( LabelOrCmd
(. if (c != null) {
// LabelOrCmd read a Cmd
Contract.Assert(label == null);
if (startToken == null) { startToken = c.tok; cs = new List(); }
Contract.Assert(cs != null);
cs.Add(c);
} else {
// LabelOrCmd read a label
Contract.Assert(label != null);
if (startToken != null) {
Contract.Assert(cs != null);
// dump the built-up state into a BigBlock
b = new BigBlock(startToken, currentLabel, cs, null, null);
bigblocks.Add(b);
cs = null;
}
startToken = label;
currentLabel = label.val;
cs = new List();
}
.)
| StructuredCmd
(. ec = ecn;
if (startToken == null) { startToken = ec.tok; cs = new List(); }
Contract.Assert(cs != null);
b = new BigBlock(startToken, currentLabel, cs, ec, null);
bigblocks.Add(b);
startToken = null; currentLabel = null; cs = null;
.)
| TransferCmd
(. tc = tcn;
if (startToken == null) { startToken = tc.tok; cs = new List(); }
Contract.Assert(cs != null);
b = new BigBlock(startToken, currentLabel, cs, null, tc);
bigblocks.Add(b);
startToken = null; currentLabel = null; cs = null;
.)
)
}
"}"
(. IToken/*!*/ endCurly = t;
if (startToken == null && bigblocks.Count == 0) {
startToken = t; cs = new List();
}
if (startToken != null) {
Contract.Assert(cs != null);
b = new BigBlock(startToken, currentLabel, cs, null, null);
bigblocks.Add(b);
}
stmtList = new StmtList(bigblocks, endCurly);
.)
.
TransferCmd
= (. Contract.Ensures(Contract.ValueAtReturn(out tc) != null); tc = dummyTransferCmd;
Token y; List/*!*/ xs;
List ss = new List();
.)
( "goto" (. y = t; .)
Idents (. foreach(IToken/*!*/ s in xs){
Contract.Assert(s != null);
ss.Add(s.val); }
tc = new GotoCmd(y, ss);
.)
| "return" (. tc = new ReturnCmd(t); .)
) ";"
.
StructuredCmd
= (. Contract.Ensures(Contract.ValueAtReturn(out ec) != null); ec = dummyStructuredCmd; Contract.Assume(cce.IsPeerConsistent(ec));
IfCmd/*!*/ ifcmd; WhileCmd/*!*/ wcmd; BreakCmd/*!*/ bcmd;
.)
( IfCmd (. ec = ifcmd; .)
| WhileCmd (. ec = wcmd; .)
| BreakCmd (. ec = bcmd; .)
)
.
IfCmd
= (. Contract.Ensures(Contract.ValueAtReturn(out ifcmd) != null); IToken/*!*/ x;
Expr guard;
StmtList/*!*/ thn;
IfCmd/*!*/ elseIf; IfCmd elseIfOption = null;
StmtList/*!*/ els; StmtList elseOption = null;
.)
"if" (. x = t; .)
Guard
"{" StmtList
[ "else"
( IfCmd (. elseIfOption = elseIf; .)
| "{"
StmtList (. elseOption = els; .)
)
]
(. ifcmd = new IfCmd(x, guard, thn, elseIfOption, elseOption); .)
.
WhileCmd
= (. Contract.Ensures(Contract.ValueAtReturn(out wcmd) != null); IToken/*!*/ x; Token z;
Expr guard; Expr/*!*/ e; bool isFree;
List invariants = new List();
StmtList/*!*/ body;
QKeyValue kv = null;
.)
"while" (. x = t; .)
Guard (. Contract.Assume(guard == null || cce.Owner.None(guard)); .)
{ (. isFree = false; z = la/*lookahead token*/; .)
[ "free" (. isFree = true; .)
]
"invariant"
{ Attribute][ }
Expression (. if (isFree) {
invariants.Add(new AssumeCmd(z, e, kv));
} else {
invariants.Add(new AssertCmd(z, e, kv));
}
.)
";"
}
"{"
StmtList (. wcmd = new WhileCmd(x, guard, invariants, body); .)
.
Guard
= (. Expr/*!*/ ee; e = null; .)
"("
( "*" (. e = null; .)
| Expression (. e = ee; .)
)
")"
.
BreakCmd
= (.Contract.Ensures(Contract.ValueAtReturn(out bcmd) != null); IToken/*!*/ x; IToken/*!*/ y;
string breakLabel = null;
.)
"break" (. x = t; .)
[ Ident (. breakLabel = y.val; .)
] ";" (. bcmd = new BreakCmd(x, breakLabel); .)
.
/*------------------------------------------------------------------------*/
LabelOrCmd
/* ensures (c == null) != (label != null) */
= (. IToken/*!*/ x; Expr/*!*/ e;
List/*!*/ xs;
List ids;
c = dummyCmd; label = null;
Cmd/*!*/ cn;
QKeyValue kv = null;
.)
( LabelOrAssign
| "assert" (. x = t; .)
{ Attribute][ }
Proposition (. c = new AssertCmd(x, e, kv); .)
";"
| "assume" (. x = t; .)
{ Attribute][ }
Proposition (. c = new AssumeCmd(x, e, kv); .)
";"
| "havoc" (. x = t; .)
Idents ";" (. ids = new List();
foreach(IToken/*!*/ y in xs){
Contract.Assert(y != null);
ids.Add(new IdentifierExpr(y, y.val));
}
c = new HavocCmd(x,ids);
.)
| CallCmd ";" (. c = cn; .)
| "yield" (. x = t; .)
";" (. c = new YieldCmd(x); .)
)
.
/*------------------------------------------------------------------------*/
LabelOrAssign
/* ensures (c == null) != (label != null) */
= (. IToken/*!*/ id; IToken/*!*/ x, y; Expr/*!*/ e0;
c = dummyCmd; label = null;
AssignLhs/*!*/ lhs;
List/*!*/ lhss;
List/*!*/ rhss;
List/*!*/ indexes;
.)
Ident (. x = t; .)
( ":" (. c = null; label = x; .)
| (. lhss = new List(); .)
(. lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val)); .)
{ MapAssignIndex (. lhs = new MapAssignLhs(y, lhs, indexes); .) }
(. lhss.Add(lhs); .)
{ ","
Ident
(. lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val)); .)
{ MapAssignIndex (. lhs = new MapAssignLhs(y, lhs, indexes); .) }
(. lhss.Add(lhs); .)
}
":=" (. x = t; /* use location of := */ .)
Expression (. rhss = new List ();
rhss.Add(e0); .)
{ ","
Expression (. rhss.Add(e0); .)
}
";" (. c = new AssignCmd(x, lhss, rhss); .)
)
.
MapAssignIndex<.out IToken/*!*/ x, out List/*!*/ indexes.>
= (.Contract.Ensures(Contract.ValueAtReturn(out x) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out indexes))); indexes = new List ();
Expr/*!*/ e;
.)
"[" (. x = t; .)
[
Expression (. indexes.Add(e); .)
{ ","
Expression (. indexes.Add(e); .)
}
]
"]"
.
/*------------------------------------------------------------------------*/
CallCmd
= (. Contract.Ensures(Contract.ValueAtReturn(out c) != null);
IToken x;
bool isAsync = false;
bool isFree = false;
QKeyValue kv = null;
c = null;
.)
[ "async" (. isAsync = true; .)
]
[ "free" (. isFree = true; .)
]
"call" (. x = t; .)
{ Attribute][ }
CallParams (. .)
{ "|" CallParams (. .)
}
.
CallParams
= (.
List ids = new List();
List es = new List();
Expr en;
IToken first;
IToken p;
.)
Ident
( "("
[ Expression (. es.Add(en); .)
{ "," Expression (. es.Add(en); .)
}
]
")" (. c = new CallCmd(x, first.val, es, ids, kv, (CallCmd) c); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync; .)
|
(. ids.Add(new IdentifierExpr(first, first.val)); .)
[ "," Ident (. ids.Add(new IdentifierExpr(p, p.val)); .)
{ "," Ident (. ids.Add(new IdentifierExpr(p, p.val)); .)
}
] ":="
Ident "("
[ Expression (. es.Add(en); .)
{ "," Expression (. es.Add(en); .)
}
]
")" (. c = new CallCmd(x, first.val, es, ids, kv, (CallCmd) c); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync; .)
)
.
/*------------------------------------------------------------------------*/
Proposition
=(.Contract.Ensures(Contract.ValueAtReturn(out e) != null);.)
Expression
.
/*------------------------------------------------------------------------*/
Idents/*!*/ xs>
= (.Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new List(); .)
Ident (. xs.Add(id); .)
{ "," Ident (. xs.Add(id); .)
}
.
/*------------------------------------------------------------------------*/
WhiteSpaceIdents/*!*/ xs>
= (. Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new List(); .)
Ident (. xs.Add(id); .)
{ Ident (. xs.Add(id); .)
}
.
/*------------------------------------------------------------------------*/
Expressions
= (. Contract.Ensures(Contract.ValueAtReturn(out es) != null); Expr/*!*/ e; es = new ExprSeq(); .)
Expression (. es.Add(e); .)
{ "," Expression (. es.Add(e); .)
}
.
/*------------------------------------------------------------------------*/
Expression
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
ImpliesExpression
{ EquivOp (. x = t; .)
ImpliesExpression
(. e0 = Expr.Binary(x, BinaryOperator.Opcode.Iff, e0, e1); .)
}
.
EquivOp = "<==>" | '\u21d4'.
/*------------------------------------------------------------------------*/
ImpliesExpression
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
LogicalExpression
[
ImpliesOp (. x = t; .)
/* recurse because implication is right-associative */
ImpliesExpression
(. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e0, e1); .)
|
ExpliesOp (. if (noExplies)
this.SemErr("illegal mixture of ==> and <==, use parentheses to disambiguate");
x = t; .)
LogicalExpression
(. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0); .)
/* loop because explies is left-associative */
{
ExpliesOp (. x = t; .)
LogicalExpression
(. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0); .)
}
]
.
ImpliesOp = "==>" | '\u21d2'.
ExpliesOp = "<==" | '\u21d0'.
/*------------------------------------------------------------------------*/
LogicalExpression
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
RelationalExpression
[ AndOp (. x = t; .)
RelationalExpression
(. e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1); .)
{ AndOp (. x = t; .)
RelationalExpression
(. e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1); .)
}
| OrOp (. x = t; .)
RelationalExpression
(. e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1); .)
{ OrOp (. x = t; .)
RelationalExpression
(. e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1); .)
}
]
.
AndOp = "&&" | '\u2227'.
OrOp = "||" | '\u2228'.
/*------------------------------------------------------------------------*/
RelationalExpression
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op; .)
BvTerm
[ RelOp
BvTerm]