( ";"
{ Spec }
| { Spec }
ImplBody
(.
// here we attach kv only to the Procedure, not its implementation
impl = new Implementation(x, x.val, typeParams,
Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, null, 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;
VariableSeq/*!*/ ins, outs;
VariableSeq/*!*/ locals;
StmtList/*!*/ stmtList;
QKeyValue kv;
.)
"implementation"
ProcSignature
ImplBody
(. impl = new Implementation(x, x.val, typeParams, ins, outs, locals, stmtList, kv, this.errors); .)
.
ProcSignature
= (. 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 VariableSeq(); kv = null; .)
{ Attribute[ }
Ident
[ TypeParams ]
ProcFormals
[ "returns" ProcFormals ]
.
Spec
= (.Contract.Requires(pre != null); Contract.Requires(mods != null); Contract.Requires(post != null); TokenSeq/*!*/ ms; .)
( "modifies"
[ Idents (. foreach(IToken/*!*/ m in ms){
Contract.Assert(m != null);
mods.Add(new IdentifierExpr(m, m.val));
}
.)
] ";"
| "free" SpecPrePost
| SpecPrePost
)
.
SpecPrePost
= (. Contract.Requires(pre != null); Contract.Requires(post != null); Expr/*!*/ e; VariableSeq/*!*/ locals; BlockSeq/*!*/ blocks; 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
= (. Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); locals = new VariableSeq(); .)
"{"
{ 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;
CmdSeq 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 CmdSeq(); }
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 CmdSeq();
}
.)
| StructuredCmd
(. ec = ecn;
if (startToken == null) { startToken = ec.tok; cs = new CmdSeq(); }
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 CmdSeq(); }
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 CmdSeq();
}
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; TokenSeq/*!*/ xs;
StringSeq ss = new StringSeq();
.)
( "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;
.)
"while" (. x = t; .)
Guard (. Contract.Assume(guard == null || cce.Owner.None(guard)); .)
{ (. isFree = false; z = la/*lookahead token*/; .)
[ "free" (. isFree = true; .)
]
"invariant"
Expression (. if (isFree) {
invariants.Add(new AssumeCmd(z, e));
} else {
invariants.Add(new AssertCmd(z, e));
}
.)
";"
}
"{"
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;
TokenSeq/*!*/ xs;
IdentifierExprSeq 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; .)
Proposition (. c = new AssumeCmd(x,e); .)
";"
| "havoc" (. x = t; .)
Idents ";" (. ids = new IdentifierExprSeq();
foreach(IToken/*!*/ y in xs){
Contract.Assert(y != null);
ids.Add(new IdentifierExpr(y, y.val));
}
c = new HavocCmd(x,ids);
.)
| CallCmd ";" (. c = cn; .)
)
.
/*------------------------------------------------------------------------*/
LabelOrAssign
/* ensures (c == null) != (label != null) */
= (. IToken/*!*/ id; IToken/*!*/ x, y; Expr/*!*/ e, 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; IToken/*!*/ first; IToken p;
List/*!*/ ids = new List();
List/*!*/ es = new List();
QKeyValue kv = null;
Expr en; List args;
c = dummyCmd;
.)
"call" (. x = t; .)
{ Attribute][ }
( Ident
( "("
[ CallForallArg (. es.Add(en); .)
{ "," CallForallArg (. es.Add(en); .)
}
]
")" (. c = new CallCmd(x, first.val, es, ids, kv); .)
|
(. ids.Add(new IdentifierExpr(first, first.val)); .)
[ "," CallOutIdent (.
if (p==null) {
ids.Add(null);
} else {
ids.Add(new IdentifierExpr(p, p.val));
}
.)
{ "," CallOutIdent (.
if (p==null) {
ids.Add(null);
} else {
ids.Add(new IdentifierExpr(p, p.val));
}
.)
}
] ":="
Ident "("
[ CallForallArg (. es.Add(en); .)
{ "," CallForallArg (. es.Add(en); .)
}
]
")" (. c = new CallCmd(x, first.val, es, ids, kv); .)
)
| "forall"
Ident "(" (. args = new List(); .)
[ CallForallArg (. args.Add(en); .)
{ "," CallForallArg (. args.Add(en); .)
}
]
")" (. c = new CallForallCmd(x, first.val, args, kv); .)
| "*"
(. ids.Add(null); .)
[ "," CallOutIdent (.
if (p==null) {
ids.Add(null);
} else {
ids.Add(new IdentifierExpr(p, p.val));
}
.)
{ "," CallOutIdent (.
if (p==null) {
ids.Add(null);
} else {
ids.Add(new IdentifierExpr(p, p.val));
}
.)
}
] ":="
Ident "("
[ CallForallArg (. es.Add(en); .)
{ "," CallForallArg (. es.Add(en); .)
}
]
")" (. c = new CallCmd(x, first.val, es, ids, kv); .)
)
.
CallOutIdent
= (. id = null;
IToken/*!*/ p;
.)
( "*"
| Ident (. id = p; .)
)
.
CallForallArg
= (. exprOptional = null;
Expr/*!*/ e;
.)
( "*"
| Expression (. exprOptional = e; .)
)
.
/*------------------------------------------------------------------------*/
Proposition
=(.Contract.Ensures(Contract.ValueAtReturn(out e) != null);.)
Expression
.
/*------------------------------------------------------------------------*/
Idents
= (.Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new TokenSeq(); .)
Ident (. xs.Add(id); .)
{ "," Ident (. xs.Add(id); .)
}
.
/*------------------------------------------------------------------------*/
WhiteSpaceIdents
= (. Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new TokenSeq(); .)
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; BinaryOperator.Opcode op; .)
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 (. e0 = Expr.Binary(x, op, e0, e1); .)
]
.
RelOp
= (.Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; .)
( "==" (. x = t; op=BinaryOperator.Opcode.Eq; .)
| "<" (. x = t; op=BinaryOperator.Opcode.Lt; .)
| ">" (. x = t; op=BinaryOperator.Opcode.Gt; .)
| "<=" (. x = t; op=BinaryOperator.Opcode.Le; .)
| ">=" (. x = t; op=BinaryOperator.Opcode.Ge; .)
| "!=" (. x = t; op=BinaryOperator.Opcode.Neq; .)
| "<:" (. x = t; op=BinaryOperator.Opcode.Subtype; .)
| '\u2260' (. x = t; op=BinaryOperator.Opcode.Neq; .)
| '\u2264' (. x = t; op=BinaryOperator.Opcode.Le; .)
| '\u2265' (. x = t; op=BinaryOperator.Opcode.Ge; .)
)
.
/*------------------------------------------------------------------------*/
BvTerm
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; .)
Term
{ "++" (. x = t; .)
Term (. e0 = new BvConcatExpr(x, e0, e1); .)
}
.
/*------------------------------------------------------------------------*/
Term
= (.Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op; .)
Factor
{ AddOp
Factor (. e0 = Expr.Binary(x, op, e0, e1); .)
}
.
AddOp
= (.Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; .)
( "+" (. x = t; op=BinaryOperator.Opcode.Add; .)
| "-" (. x = t; op=BinaryOperator.Opcode.Sub; .)
)
.
/*------------------------------------------------------------------------*/
Factor
= (.Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op; .)
UnaryExpression
{ MulOp
UnaryExpression (. e0 = Expr.Binary(x, op, e0, e1); .)
}
.
MulOp
= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; .)
( "*" (. x = t; op=BinaryOperator.Opcode.Mul; .)
| "/" (. x = t; op=BinaryOperator.Opcode.Div; .)
| "%" (. x = t; op=BinaryOperator.Opcode.Mod; .)
)
.
/*------------------------------------------------------------------------*/
UnaryExpression
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
e = dummyExpr;
.)
( "-" (. x = t; .)
UnaryExpression (. e = Expr.Binary(x, BinaryOperator.Opcode.Sub, new LiteralExpr(x, BigNum.ZERO), e); .)
| NegOp (. x = t; .)
UnaryExpression (. e = Expr.Unary(x, UnaryOperator.Opcode.Not, e); .)
| CoercionExpression
)
.
NegOp = "!" | '\u00ac'.
/*------------------------------------------------------------------------*/
/* This production creates ambiguities, because types can start with "<"
(polymorphic map types), but can also be followed by "<" (inequalities).
Coco deals with these ambiguities in a reasonable way by preferring to read
further types (type arguments) over relational symbols. E.g., "5 : C < 0"
will cause a parse error because "<" is treated as the beginning of a
map type. */
CoercionExpression
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
Type/*!*/ coercedTo;
BigNum bn;
.)
ArrayExpression
{ ":" (. x = t; .)
(
Type (. e = Expr.CoerceType(x, e, coercedTo); .)
|
Nat /* This means that we really look at a bitvector
expression t[a:b] */
(. if (!(e is LiteralExpr) || !((LiteralExpr)e).isBigNum) {
this.SemErr("arguments of extract need to be integer literals");
e = new BvBounds(x, bn, BigNum.ZERO);
} else {
e = new BvBounds(x, bn, ((LiteralExpr)e).asBigNum);
}
.)
)
}
.
/*------------------------------------------------------------------------*/
ArrayExpression
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;
Expr/*!*/ index0 = dummyExpr; Expr/*!*/ e1;
bool store; bool bvExtract;
ExprSeq/*!*/ allArgs = dummyExprSeq;
.)
AtomExpression
{ "[" (. x = t; allArgs = new ExprSeq ();
allArgs.Add(e);
store = false; bvExtract = false; .)
[
Expression
(. if (index0 is BvBounds)
bvExtract = true;
else
allArgs.Add(index0);
.)
{ "," Expression
(. if (bvExtract || e1 is BvBounds)
this.SemErr("bitvectors only have one dimension");
allArgs.Add(e1);
.)
}
[ ":=" Expression
(. if (bvExtract || e1 is BvBounds)
this.SemErr("assignment to bitvectors is not possible");
allArgs.Add(e1); store = true;
.)
]
| ":=" Expression (. allArgs.Add(e1); store = true; .)
]
"]"
(. if (store)
e = new NAryExpr(x, new MapStore(x, allArgs.Length - 2), allArgs);
else if (bvExtract)
e = new BvExtractExpr(x, e,
((BvBounds)index0).Upper.ToIntSafe,
((BvBounds)index0).Lower.ToIntSafe);
else
e = new NAryExpr(x, new MapSelect(x, allArgs.Length - 1), allArgs);
.)
}
.
/*------------------------------------------------------------------------*/
AtomExpression
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn;
ExprSeq/*!*/ es; VariableSeq/*!*/ ds; Trigger trig;
TypeVariableSeq/*!*/ typeParams;
IdentifierExpr/*!*/ id;
Bpl.Type/*!*/ ty;
QKeyValue kv;
e = dummyExpr;
VariableSeq/*!*/ locals;
List/*!*/ blocks;
.)
( "false" (. e = new LiteralExpr(t, false); .)
| "true" (. e = new LiteralExpr(t, true); .)
| Nat (. e = new LiteralExpr(t, bn); .)
| BvLit (. e = new LiteralExpr(t, bn, n); .)
| Ident (. id = new IdentifierExpr(x, x.val); e = id; .)
[ "("
( Expressions (. e = new NAryExpr(x, new FunctionCall(id), es); .)
| /* empty */ (. e = new NAryExpr(x, new FunctionCall(id), new ExprSeq()); .)
)
")"
]
| "old" (. x = t; .)
"("
Expression
")" (. e = new OldExpr(x, e); .)
| "(" ( Expression (. if (e is BvBounds)
this.SemErr("parentheses around bitvector bounds " +
"are not allowed"); .)
| Forall (. x = t; .)
QuantifierBody
(. if (typeParams.Length + ds.Length > 0)
e = new ForallExpr(x, typeParams, ds, kv, trig, e); .)
| Exists (. x = t; .)
QuantifierBody
(. if (typeParams.Length + ds.Length > 0)
e = new ExistsExpr(x, typeParams, ds, kv, trig, e); .)
| Lambda (. x = t; .)
QuantifierBody
(. if (trig != null)
SemErr("triggers not allowed in lambda expressions");
if (typeParams.Length + ds.Length > 0)
e = new LambdaExpr(x, typeParams, ds, kv, e); .)
)
")"
| IfThenElseExpression
| CodeExpression (. e = new CodeExpr(locals, blocks); .)
)
.
CodeExpression<.out VariableSeq/*!*/ locals, out List/*!*/ blocks.>
= (. Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out blocks))); locals = new VariableSeq(); Block/*!*/ b;
blocks = new List();
.)
"|{"
{ LocalVars }
SpecBlock (. blocks.Add(b); .)
{ SpecBlock (. blocks.Add(b); .)
}
"}|"
.
SpecBlock
= (. Contract.Ensures(Contract.ValueAtReturn(out b) != null); IToken/*!*/ x; IToken/*!*/ y;
Cmd c; IToken label;
CmdSeq cs = new CmdSeq();
TokenSeq/*!*/ xs;
StringSeq ss = new StringSeq();
b = dummyBlock;
Expr/*!*/ e;
.)
Ident ":"
{ LabelOrCmd
(. if (c != null) {
Contract.Assert(label == null);
cs.Add(c);
} else {
Contract.Assert(label != null);
SemErr("SpecBlock's can only have one label");
}
.)
}
( "goto" (. y = t; .)
Idents (. foreach(IToken/*!*/ s in xs){
Contract.Assert(s != null);
ss.Add(s.val); }
b = new Block(x,x.val,cs,new GotoCmd(y,ss));
.)
| "return" Expression
(. b = new Block(x,x.val,cs,new ReturnExprCmd(t,e)); .)
)
";"
.
Attribute][
= (. Trigger trig = null; .)
AttributeOrTrigger][ (. if (trig != null) this.SemErr("only attributes, not triggers, allowed here"); .)
.
AttributeOrTrigger][
= (. IToken/*!*/ tok; Expr/*!*/ e; ExprSeq/*!*/ es;
string key; string value;
List parameters; object/*!*/ param;
.)
"{" (. tok = t; .)
(
":" ident (. key = t.val; parameters = new List(); .)
[ AttributeParameter (. parameters.Add(param); .)
{ "," AttributeParameter (. parameters.Add(param); .)
}
]
(. if (key == "nopats") {
if (parameters.Count == 1 && parameters[0] is Expr) {
e = (Expr)parameters[0];
if(trig==null){
trig = new Trigger(tok, false, new ExprSeq(e), null);
} else {
trig.AddLast(new Trigger(tok, false, new ExprSeq(e), null));
}
} else {
this.SemErr("the 'nopats' quantifier attribute expects a string-literal parameter");
}
} else {
if (kv==null) {
kv = new QKeyValue(tok, key, parameters, null);
} else {
kv.AddLast(new QKeyValue(tok, key, parameters, null));
}
}
.)
|
Expression]