using System.Collections.Generic;
using System.Numerics;
using Microsoft.Boogie;
using System.IO;
using System.Text;
using System;
using System.Diagnostics.Contracts;
namespace Microsoft.Dafny {
public class Parser {
public const int _EOF = 0;
public const int _ident = 1;
public const int _digits = 2;
public const int _arrayToken = 3;
public const int _string = 4;
public const int _colon = 5;
public const int _lbrace = 6;
public const int _rbrace = 7;
public const int _notIn = 8;
public const int maxT = 120;
const bool T = true;
const bool x = false;
const int minErrDist = 2;
public Scanner/*!*/ scanner;
public Errors/*!*/ errors;
public Token/*!*/ t; // last recognized token
public Token/*!*/ la; // lookahead token
int errDist = minErrDist;
readonly Expression/*!*/ dummyExpr;
readonly AssignmentRhs/*!*/ dummyRhs;
readonly FrameExpression/*!*/ dummyFrameExpr;
readonly Statement/*!*/ dummyStmt;
readonly Attributes.Argument/*!*/ dummyAttrArg;
readonly ModuleDecl theModule;
readonly BuiltIns theBuiltIns;
int anonymousIds = 0;
struct MemberModifiers {
public bool IsGhost;
public bool IsStatic;
}
///
/// Parses top-level things (modules, classes, datatypes, class members) from "filename"
/// and appends them in appropriate form to "module".
/// Returns the number of parsing errors encountered.
/// Note: first initialize the Scanner.
///
public static int Parse (string/*!*/ filename, ModuleDecl module, BuiltIns builtIns) /* throws System.IO.IOException */ {
Contract.Requires(filename != null);
Contract.Requires(module != null);
string s;
if (filename == "stdin.dfy") {
s = Microsoft.Boogie.ParserHelper.Fill(System.Console.In, new List());
return Parse(s, filename, module, builtIns);
} else {
using (System.IO.StreamReader reader = new System.IO.StreamReader(filename)) {
s = Microsoft.Boogie.ParserHelper.Fill(reader, new List());
return Parse(s, filename, module, builtIns);
}
}
}
///
/// Parses top-level things (modules, classes, datatypes, class members)
/// and appends them in appropriate form to "module".
/// Returns the number of parsing errors encountered.
/// Note: first initialize the Scanner.
///
public static int Parse (string/*!*/ s, string/*!*/ filename, ModuleDecl module, BuiltIns builtIns) {
Contract.Requires(s != null);
Contract.Requires(filename != null);
Contract.Requires(module != null);
Errors errors = new Errors();
return Parse(s, filename, module, builtIns, errors);
}
///
/// Parses top-level things (modules, classes, datatypes, class members)
/// and appends them in appropriate form to "module".
/// Returns the number of parsing errors encountered.
/// Note: first initialize the Scanner with the given Errors sink.
///
public static int Parse (string/*!*/ s, string/*!*/ filename, ModuleDecl module, BuiltIns builtIns,
Errors/*!*/ errors) {
Contract.Requires(s != null);
Contract.Requires(filename != null);
Contract.Requires(module != null);
Contract.Requires(errors != null);
byte[]/*!*/ buffer = cce.NonNull( UTF8Encoding.Default.GetBytes(s));
MemoryStream ms = new MemoryStream(buffer,false);
Scanner scanner = new Scanner(ms, errors, filename);
Parser parser = new Parser(scanner, errors, module, builtIns);
parser.Parse();
return parser.errors.count;
}
public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors, ModuleDecl module, BuiltIns builtIns)
: this(scanner, errors) // the real work
{
// initialize readonly fields
dummyExpr = new LiteralExpr(Token.NoToken);
dummyRhs = new ExprRhs(dummyExpr, null);
dummyFrameExpr = new FrameExpression(dummyExpr.tok, dummyExpr, null);
dummyStmt = new ReturnStmt(Token.NoToken, null);
dummyAttrArg = new Attributes.Argument(Token.NoToken, "dummyAttrArg");
theModule = module;
theBuiltIns = builtIns;
}
bool IsAttribute() {
Token x = scanner.Peek();
return la.kind == _lbrace && x.kind == _colon;
}
bool IsAlternative() {
Token x = scanner.Peek();
return la.kind == _lbrace && x.val == "case";
}
bool IsLoopSpec() {
return la.val == "invariant" | la.val == "decreases" | la.val == "modifies";
}
bool IsLoopSpecOrAlternative() {
Token x = scanner.Peek();
return IsLoopSpec() || (la.kind == _lbrace && x.val == "case");
}
/*--------------------------------------------------------------------------*/
public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors) {
this.scanner = scanner;
this.errors = errors;
Token/*!*/ tok = new Token();
tok.val = "";
this.la = tok;
this.t = new Token(); // just to satisfy its non-null constraint
}
void SynErr (int n) {
if (errDist >= minErrDist) errors.SynErr(la.filename, la.line, la.col, n);
errDist = 0;
}
public void SemErr (string/*!*/ msg) {
Contract.Requires(msg != null);
if (errDist >= minErrDist) errors.SemErr(t, msg);
errDist = 0;
}
public void SemErr(IToken/*!*/ tok, string/*!*/ msg) {
Contract.Requires(tok != null);
Contract.Requires(msg != null);
errors.SemErr(tok, msg);
}
void Get () {
for (;;) {
t = la;
la = scanner.Scan();
if (la.kind <= maxT) { ++errDist; break; }
la = t;
}
}
void Expect (int n) {
if (la.kind==n) Get(); else { SynErr(n); }
}
bool StartOf (int s) {
return set[s, la.kind];
}
void ExpectWeak (int n, int follow) {
if (la.kind == n) Get();
else {
SynErr(n);
while (!StartOf(follow)) Get();
}
}
bool WeakSeparator(int n, int syFol, int repFol) {
int kind = la.kind;
if (kind == n) {Get(); return true;}
else if (StartOf(repFol)) {return false;}
else {
SynErr(n);
while (!(set[syFol, kind] || set[repFol, kind] || set[0, kind])) {
Get();
kind = la.kind;
}
return StartOf(syFol);
}
}
void Dafny() {
ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; ArbitraryTypeDecl at; IteratorDecl iter;
List membersDefaultClass = new List();
ModuleDecl submodule;
// to support multiple files, create a default module only if theModule is null
DefaultModuleDecl defaultModule = (DefaultModuleDecl)((LiteralModuleDecl)theModule).ModuleDef;
// theModule should be a DefaultModuleDecl (actually, the singular DefaultModuleDecl)
Contract.Assert(defaultModule != null);
while (StartOf(1)) {
switch (la.kind) {
case 9: case 10: case 12: {
SubModuleDecl(defaultModule, out submodule);
defaultModule.TopLevelDecls.Add(submodule);
break;
}
case 19: {
ClassDecl(defaultModule, out c);
defaultModule.TopLevelDecls.Add(c);
break;
}
case 22: case 23: {
DatatypeDecl(defaultModule, out dt);
defaultModule.TopLevelDecls.Add(dt);
break;
}
case 27: {
ArbitraryTypeDecl(defaultModule, out at);
defaultModule.TopLevelDecls.Add(at);
break;
}
case 31: {
IteratorDecl(defaultModule, out iter);
defaultModule.TopLevelDecls.Add(iter);
break;
}
case 20: case 21: case 25: case 37: case 38: case 39: case 55: case 56: case 57: {
ClassMemberDecl(membersDefaultClass, false);
break;
}
}
}
DefaultClassDecl defaultClass = null;
foreach (TopLevelDecl topleveldecl in defaultModule.TopLevelDecls) {
defaultClass = topleveldecl as DefaultClassDecl;
if (defaultClass != null) {
defaultClass.Members.AddRange(membersDefaultClass);
break;
}
}
if (defaultClass == null) { // create the default class here, because it wasn't found
defaultClass = new DefaultClassDecl(defaultModule, membersDefaultClass);
defaultModule.TopLevelDecls.Add(defaultClass);
}
Expect(0);
}
void SubModuleDecl(ModuleDefinition parent, out ModuleDecl submodule) {
ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; ArbitraryTypeDecl at; IteratorDecl iter;
Attributes attrs = null; IToken/*!*/ id;
List namedModuleDefaultClassMembers = new List();;
List idRefined = null, idPath = null, idAssignment = null;
ModuleDefinition module;
ModuleDecl sm;
submodule = null; // appease compiler
bool isAbstract = false;
bool opened = false;
if (la.kind == 9 || la.kind == 10) {
if (la.kind == 9) {
Get();
isAbstract = true;
}
Expect(10);
while (la.kind == 6) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 11) {
Get();
QualifiedName(out idRefined);
}
module = new ModuleDefinition(id, id.val, isAbstract, false, idRefined == null ? null : idRefined, attrs, false);
Expect(6);
module.BodyStartTok = t;
while (StartOf(1)) {
switch (la.kind) {
case 9: case 10: case 12: {
SubModuleDecl(module, out sm);
module.TopLevelDecls.Add(sm);
break;
}
case 19: {
ClassDecl(module, out c);
module.TopLevelDecls.Add(c);
break;
}
case 22: case 23: {
DatatypeDecl(module, out dt);
module.TopLevelDecls.Add(dt);
break;
}
case 27: {
ArbitraryTypeDecl(module, out at);
module.TopLevelDecls.Add(at);
break;
}
case 31: {
IteratorDecl(module, out iter);
module.TopLevelDecls.Add(iter);
break;
}
case 20: case 21: case 25: case 37: case 38: case 39: case 55: case 56: case 57: {
ClassMemberDecl(namedModuleDefaultClassMembers, false);
break;
}
}
}
Expect(7);
module.BodyEndTok = t;
module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers));
submodule = new LiteralModuleDecl(module, parent);
} else if (la.kind == 12) {
Get();
if (la.kind == 13) {
Get();
opened = true;
}
NoUSIdent(out id);
if (la.kind == 14) {
Get();
QualifiedName(out idPath);
Expect(15);
submodule = new AliasModuleDecl(idPath, id, parent, opened);
} else if (la.kind == 15) {
Get();
idPath = new List(); idPath.Add(id); submodule = new AliasModuleDecl(idPath, id, parent, opened);
} else if (la.kind == 16) {
Get();
QualifiedName(out idPath);
if (la.kind == 17) {
Get();
QualifiedName(out idAssignment);
}
Expect(15);
submodule = new ModuleFacadeDecl(idPath, id, parent, idAssignment, opened);
} else SynErr(121);
} else SynErr(122);
}
void ClassDecl(ModuleDefinition/*!*/ module, out ClassDecl/*!*/ c) {
Contract.Requires(module != null);
Contract.Ensures(Contract.ValueAtReturn(out c) != null);
IToken/*!*/ id;
Attributes attrs = null;
List typeArgs = new List();
List members = new List();
IToken bodyStart;
while (!(la.kind == 0 || la.kind == 19)) {SynErr(123); Get();}
Expect(19);
while (la.kind == 6) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 35) {
GenericParameters(typeArgs);
}
Expect(6);
bodyStart = t;
while (StartOf(2)) {
ClassMemberDecl(members, true);
}
Expect(7);
c = new ClassDecl(id, id.val, module, typeArgs, members, attrs);
c.BodyStartTok = bodyStart;
c.BodyEndTok = t;
}
void DatatypeDecl(ModuleDefinition/*!*/ module, out DatatypeDecl/*!*/ dt) {
Contract.Requires(module != null);
Contract.Ensures(Contract.ValueAtReturn(out dt)!=null);
IToken/*!*/ id;
Attributes attrs = null;
List typeArgs = new List();
List ctors = new List();
IToken bodyStart = Token.NoToken; // dummy assignment
bool co = false;
while (!(la.kind == 0 || la.kind == 22 || la.kind == 23)) {SynErr(124); Get();}
if (la.kind == 22) {
Get();
} else if (la.kind == 23) {
Get();
co = true;
} else SynErr(125);
while (la.kind == 6) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 35) {
GenericParameters(typeArgs);
}
Expect(14);
bodyStart = t;
DatatypeMemberDecl(ctors);
while (la.kind == 24) {
Get();
DatatypeMemberDecl(ctors);
}
while (!(la.kind == 0 || la.kind == 15)) {SynErr(126); Get();}
Expect(15);
if (co) {
dt = new CoDatatypeDecl(id, id.val, module, typeArgs, ctors, attrs);
} else {
dt = new IndDatatypeDecl(id, id.val, module, typeArgs, ctors, attrs);
}
dt.BodyStartTok = bodyStart;
dt.BodyEndTok = t;
}
void ArbitraryTypeDecl(ModuleDefinition/*!*/ module, out ArbitraryTypeDecl at) {
IToken/*!*/ id;
Attributes attrs = null;
var eqSupport = TypeParameter.EqualitySupportValue.Unspecified;
Expect(27);
while (la.kind == 6) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 28) {
Get();
Expect(29);
Expect(30);
eqSupport = TypeParameter.EqualitySupportValue.Required;
}
at = new ArbitraryTypeDecl(id, id.val, module, eqSupport, attrs);
while (!(la.kind == 0 || la.kind == 15)) {SynErr(127); Get();}
Expect(15);
}
void IteratorDecl(ModuleDefinition module, out IteratorDecl/*!*/ iter) {
Contract.Ensures(Contract.ValueAtReturn(out iter) != null);
IToken/*!*/ id;
Attributes attrs = null;
List/*!*/ typeArgs = new List();
IToken openParen;
List ins = new List();
List outs = new List();
List reads = new List();
List mod = new List();
List decreases = new List();
List req = new List();
List ens = new List();
List yieldReq = new List();
List yieldEns = new List();
List dec = new List();
Attributes readsAttrs = null;
Attributes modAttrs = null;
Attributes decrAttrs = null;
BlockStmt body = null;
bool signatureOmitted = false;
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
while (!(la.kind == 0 || la.kind == 31)) {SynErr(128); Get();}
Expect(31);
while (la.kind == 6) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 28 || la.kind == 35) {
if (la.kind == 35) {
GenericParameters(typeArgs);
}
Formals(true, true, ins, out openParen);
if (la.kind == 32 || la.kind == 33) {
if (la.kind == 32) {
Get();
} else {
Get();
SemErr(t, "iterators don't have a 'returns' clause; did you mean 'yields'?");
}
Formals(false, true, outs, out openParen);
}
} else if (la.kind == 34) {
Get();
signatureOmitted = true; openParen = Token.NoToken;
} else SynErr(129);
while (StartOf(3)) {
IteratorSpec(reads, mod, decreases, req, ens, yieldReq, yieldEns, ref readsAttrs, ref modAttrs, ref decrAttrs);
}
if (la.kind == 6) {
BlockStmt(out body, out bodyStart, out bodyEnd);
}
iter = new IteratorDecl(id, id.val, module, typeArgs, ins, outs,
new Specification(reads, readsAttrs),
new Specification(mod, modAttrs),
new Specification(decreases, decrAttrs),
req, ens, yieldReq, yieldEns,
body, attrs, signatureOmitted);
iter.BodyStartTok = bodyStart;
iter.BodyEndTok = bodyEnd;
}
void ClassMemberDecl(List/*!*/ mm, bool allowConstructors) {
Contract.Requires(cce.NonNullElements(mm));
Method/*!*/ m;
Function/*!*/ f;
MemberModifiers mmod = new MemberModifiers();
while (la.kind == 20 || la.kind == 21) {
if (la.kind == 20) {
Get();
mmod.IsGhost = true;
} else {
Get();
mmod.IsStatic = true;
}
}
if (la.kind == 25) {
FieldDecl(mmod, mm);
} else if (la.kind == 55 || la.kind == 56 || la.kind == 57) {
FunctionDecl(mmod, out f);
mm.Add(f);
} else if (la.kind == 37 || la.kind == 38 || la.kind == 39) {
MethodDecl(mmod, allowConstructors, out m);
mm.Add(m);
} else SynErr(130);
}
void Attribute(ref Attributes attrs) {
Expect(6);
AttributeBody(ref attrs);
Expect(7);
}
void NoUSIdent(out IToken/*!*/ x) {
Contract.Ensures(Contract.ValueAtReturn(out x) != null);
Expect(1);
x = t;
if (x.val.StartsWith("_")) {
SemErr("cannot declare identifier beginning with underscore");
}
}
void QualifiedName(out List ids) {
IToken id; ids = new List();
Ident(out id);
ids.Add(id);
while (la.kind == 18) {
Get();
Ident(out id);
ids.Add(id);
}
}
void Ident(out IToken/*!*/ x) {
Contract.Ensures(Contract.ValueAtReturn(out x) != null);
Expect(1);
x = t;
}
void GenericParameters(List/*!*/ typeArgs) {
Contract.Requires(cce.NonNullElements(typeArgs));
IToken/*!*/ id;
TypeParameter.EqualitySupportValue eqSupport;
Expect(35);
NoUSIdent(out id);
eqSupport = TypeParameter.EqualitySupportValue.Unspecified;
if (la.kind == 28) {
Get();
Expect(29);
Expect(30);
eqSupport = TypeParameter.EqualitySupportValue.Required;
}
typeArgs.Add(new TypeParameter(id, id.val, eqSupport));
while (la.kind == 26) {
Get();
NoUSIdent(out id);
eqSupport = TypeParameter.EqualitySupportValue.Unspecified;
if (la.kind == 28) {
Get();
Expect(29);
Expect(30);
eqSupport = TypeParameter.EqualitySupportValue.Required;
}
typeArgs.Add(new TypeParameter(id, id.val, eqSupport));
}
Expect(36);
}
void FieldDecl(MemberModifiers mmod, List/*!*/ mm) {
Contract.Requires(cce.NonNullElements(mm));
Attributes attrs = null;
IToken/*!*/ id; Type/*!*/ ty;
while (!(la.kind == 0 || la.kind == 25)) {SynErr(131); Get();}
Expect(25);
if (mmod.IsStatic) { SemErr(t, "fields cannot be declared 'static'"); }
while (la.kind == 6) {
Attribute(ref attrs);
}
IdentType(out id, out ty, false);
mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs));
while (la.kind == 26) {
Get();
IdentType(out id, out ty, false);
mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs));
}
while (!(la.kind == 0 || la.kind == 15)) {SynErr(132); Get();}
Expect(15);
}
void FunctionDecl(MemberModifiers mmod, out Function/*!*/ f) {
Contract.Ensures(Contract.ValueAtReturn(out f)!=null);
Attributes attrs = null;
IToken/*!*/ id = Token.NoToken; // to please compiler
List typeArgs = new List();
List formals = new List();
Type/*!*/ returnType = new BoolType();
List reqs = new List();
List ens = new List();
List reads = new List();
List decreases;
Expression body = null;
bool isPredicate = false; bool isCoPredicate = false;
bool isFunctionMethod = false;
IToken openParen = null;
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
bool signatureOmitted = false;
if (la.kind == 55) {
Get();
if (la.kind == 37) {
Get();
isFunctionMethod = true;
}
if (mmod.IsGhost) { SemErr(t, "functions cannot be declared 'ghost' (they are ghost by default)"); }
while (la.kind == 6) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 28 || la.kind == 35) {
if (la.kind == 35) {
GenericParameters(typeArgs);
}
Formals(true, isFunctionMethod, formals, out openParen);
Expect(5);
Type(out returnType);
} else if (la.kind == 34) {
Get();
signatureOmitted = true;
openParen = Token.NoToken;
} else SynErr(133);
} else if (la.kind == 56) {
Get();
isPredicate = true;
if (la.kind == 37) {
Get();
isFunctionMethod = true;
}
if (mmod.IsGhost) { SemErr(t, "predicates cannot be declared 'ghost' (they are ghost by default)"); }
while (la.kind == 6) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (StartOf(4)) {
if (la.kind == 35) {
GenericParameters(typeArgs);
}
if (la.kind == 28) {
Formals(true, isFunctionMethod, formals, out openParen);
if (la.kind == 5) {
Get();
SemErr(t, "predicates do not have an explicitly declared return type; it is always bool");
}
}
} else if (la.kind == 34) {
Get();
signatureOmitted = true;
openParen = Token.NoToken;
} else SynErr(134);
} else if (la.kind == 57) {
Get();
isCoPredicate = true;
if (mmod.IsGhost) { SemErr(t, "copredicates cannot be declared 'ghost' (they are ghost by default)"); }
while (la.kind == 6) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (StartOf(4)) {
if (la.kind == 35) {
GenericParameters(typeArgs);
}
if (la.kind == 28) {
Formals(true, isFunctionMethod, formals, out openParen);
if (la.kind == 5) {
Get();
SemErr(t, "copredicates do not have an explicitly declared return type; it is always bool");
}
}
} else if (la.kind == 34) {
Get();
signatureOmitted = true;
openParen = Token.NoToken;
} else SynErr(135);
} else SynErr(136);
decreases = isCoPredicate ? null : new List();
while (StartOf(5)) {
FunctionSpec(reqs, reads, ens, decreases);
}
if (la.kind == 6) {
FunctionBody(out body, out bodyStart, out bodyEnd);
}
if (isPredicate) {
f = new Predicate(id, id.val, mmod.IsStatic, !isFunctionMethod, typeArgs, openParen, formals,
reqs, reads, ens, new Specification(decreases, null), body, Predicate.BodyOriginKind.OriginalOrInherited, attrs, signatureOmitted);
} else if (isCoPredicate) {
f = new CoPredicate(id, id.val, mmod.IsStatic, typeArgs, openParen, formals,
reqs, reads, ens, body, attrs, signatureOmitted);
} else {
f = new Function(id, id.val, mmod.IsStatic, !isFunctionMethod, typeArgs, openParen, formals, returnType,
reqs, reads, ens, new Specification(decreases, null), body, attrs, signatureOmitted);
}
f.BodyStartTok = bodyStart;
f.BodyEndTok = bodyEnd;
}
void MethodDecl(MemberModifiers mmod, bool allowConstructor, out Method/*!*/ m) {
Contract.Ensures(Contract.ValueAtReturn(out m) !=null);
IToken/*!*/ id = Token.NoToken;
bool hasName = false; IToken keywordToken;
Attributes attrs = null;
List/*!*/ typeArgs = new List();
IToken openParen;
List ins = new List();
List outs = new List();
List req = new List();
List mod = new List();
List ens = new List();
List dec = new List();
Attributes decAttrs = null;
Attributes modAttrs = null;
BlockStmt body = null;
bool isConstructor = false;
bool isCoMethod = false;
bool signatureOmitted = false;
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
while (!(StartOf(6))) {SynErr(137); Get();}
if (la.kind == 37) {
Get();
} else if (la.kind == 38) {
Get();
isCoMethod = true;
} else if (la.kind == 39) {
Get();
if (allowConstructor) {
isConstructor = true;
} else {
SemErr(t, "constructors are only allowed in classes");
}
} else SynErr(138);
keywordToken = t;
if (isConstructor) {
if (mmod.IsGhost) {
SemErr(t, "constructors cannot be declared 'ghost'");
}
if (mmod.IsStatic) {
SemErr(t, "constructors cannot be declared 'static'");
}
} else if (isCoMethod) {
if (mmod.IsGhost) {
SemErr(t, "comethods cannot be declared 'ghost'");
}
}
while (la.kind == 6) {
Attribute(ref attrs);
}
if (la.kind == 1) {
NoUSIdent(out id);
hasName = true;
}
if (!hasName) {
id = keywordToken;
if (!isConstructor) {
SemErr(la, "a method must be given a name (expecting identifier)");
}
}
if (la.kind == 28 || la.kind == 35) {
if (la.kind == 35) {
GenericParameters(typeArgs);
}
Formals(true, !mmod.IsGhost, ins, out openParen);
if (la.kind == 33) {
Get();
if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); }
Formals(false, !mmod.IsGhost, outs, out openParen);
}
} else if (la.kind == 34) {
Get();
signatureOmitted = true; openParen = Token.NoToken;
} else SynErr(139);
while (StartOf(7)) {
MethodSpec(req, mod, ens, dec, ref decAttrs, ref modAttrs);
}
if (la.kind == 6) {
BlockStmt(out body, out bodyStart, out bodyEnd);
}
if (isConstructor) {
m = new Constructor(id, hasName ? id.val : "_ctor", typeArgs, ins,
req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureOmitted);
} else if (isCoMethod) {
m = new CoMethod(id, id.val, mmod.IsStatic, typeArgs, ins, outs,
req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureOmitted);
} else {
m = new Method(id, id.val, mmod.IsStatic, mmod.IsGhost, typeArgs, ins, outs,
req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureOmitted);
}
m.BodyStartTok = bodyStart;
m.BodyEndTok = bodyEnd;
}
void DatatypeMemberDecl(List/*!*/ ctors) {
Contract.Requires(cce.NonNullElements(ctors));
Attributes attrs = null;
IToken/*!*/ id;
List formals = new List();
while (la.kind == 6) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 28) {
FormalsOptionalIds(formals);
}
ctors.Add(new DatatypeCtor(id, id.val, formals, attrs));
}
void FormalsOptionalIds(List/*!*/ formals) {
Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; string/*!*/ name; bool isGhost;
Expect(28);
if (StartOf(8)) {
TypeIdentOptional(out id, out name, out ty, out isGhost);
formals.Add(new Formal(id, name, ty, true, isGhost));
while (la.kind == 26) {
Get();
TypeIdentOptional(out id, out name, out ty, out isGhost);
formals.Add(new Formal(id, name, ty, true, isGhost));
}
}
Expect(30);
}
void IdentType(out IToken/*!*/ id, out Type/*!*/ ty, bool allowWildcardId) {
Contract.Ensures(Contract.ValueAtReturn(out id) != null); Contract.Ensures(Contract.ValueAtReturn(out ty) != null);
WildIdent(out id, allowWildcardId);
Expect(5);
Type(out ty);
}
void GIdentType(bool allowGhostKeyword, out IToken/*!*/ id, out Type/*!*/ ty, out bool isGhost) {
Contract.Ensures(Contract.ValueAtReturn(out id)!=null);
Contract.Ensures(Contract.ValueAtReturn(out ty)!=null);
isGhost = false;
if (la.kind == 20) {
Get();
if (allowGhostKeyword) { isGhost = true; } else { SemErr(t, "formal cannot be declared 'ghost' in this context"); }
}
IdentType(out id, out ty, true);
}
void WildIdent(out IToken/*!*/ x, bool allowWildcardId) {
Contract.Ensures(Contract.ValueAtReturn(out x) != null);
Expect(1);
x = t;
if (x.val.StartsWith("_")) {
if (allowWildcardId && x.val.Length == 1) {
t.val = "_v" + anonymousIds++;
} else {
SemErr("cannot declare identifier beginning with underscore");
}
}
}
void Type(out Type/*!*/ ty) {
Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken/*!*/ tok;
TypeAndToken(out tok, out ty);
}
void LocalIdentTypeOptional(out VarDecl/*!*/ var, bool isGhost) {
IToken/*!*/ id; Type/*!*/ ty; Type optType = null;
WildIdent(out id, true);
if (la.kind == 5) {
Get();
Type(out ty);
optType = ty;
}
var = new VarDecl(id, id.val, optType == null ? new InferredTypeProxy() : optType, isGhost);
}
void IdentTypeOptional(out BoundVar/*!*/ var) {
Contract.Ensures(Contract.ValueAtReturn(out var)!=null); IToken/*!*/ id; Type/*!*/ ty; Type optType = null;
WildIdent(out id, true);
if (la.kind == 5) {
Get();
Type(out ty);
optType = ty;
}
var = new BoundVar(id, id.val, optType == null ? new InferredTypeProxy() : optType);
}
void TypeIdentOptional(out IToken/*!*/ id, out string/*!*/ identName, out Type/*!*/ ty, out bool isGhost) {
Contract.Ensures(Contract.ValueAtReturn(out id)!=null);
Contract.Ensures(Contract.ValueAtReturn(out ty)!=null);
Contract.Ensures(Contract.ValueAtReturn(out identName)!=null);
string name = null; isGhost = false;
if (la.kind == 20) {
Get();
isGhost = true;
}
TypeAndToken(out id, out ty);
if (la.kind == 5) {
Get();
UserDefinedType udt = ty as UserDefinedType;
if (udt != null && udt.TypeArgs.Count == 0) {
name = udt.Name;
} else {
SemErr(id, "invalid formal-parameter name in datatype constructor");
}
Type(out ty);
}
if (name != null) {
identName = name;
} else {
identName = "#" + anonymousIds++;
}
}
void TypeAndToken(out IToken/*!*/ tok, out Type/*!*/ ty) {
Contract.Ensures(Contract.ValueAtReturn(out tok)!=null); Contract.Ensures(Contract.ValueAtReturn(out ty) != null); tok = Token.NoToken; ty = new BoolType(); /*keep compiler happy*/
List/*!*/ gt;
switch (la.kind) {
case 47: {
Get();
tok = t;
break;
}
case 48: {
Get();
tok = t; ty = new NatType();
break;
}
case 49: {
Get();
tok = t; ty = new IntType();
break;
}
case 50: {
Get();
tok = t; gt = new List();
GenericInstantiation(gt);
if (gt.Count != 1) {
SemErr("set type expects exactly one type argument");
}
ty = new SetType(gt[0]);
break;
}
case 51: {
Get();
tok = t; gt = new List();
GenericInstantiation(gt);
if (gt.Count != 1) {
SemErr("multiset type expects exactly one type argument");
}
ty = new MultiSetType(gt[0]);
break;
}
case 52: {
Get();
tok = t; gt = new List();
GenericInstantiation(gt);
if (gt.Count != 1) {
SemErr("seq type expects exactly one type argument");
}
ty = new SeqType(gt[0]);
break;
}
case 53: {
Get();
tok = t; gt = new List();
GenericInstantiation(gt);
if (gt.Count != 2) {
SemErr("map type expects exactly two type arguments");
}
else { ty = new MapType(gt[0], gt[1]); }
break;
}
case 1: case 3: case 54: {
ReferenceType(out tok, out ty);
break;
}
default: SynErr(140); break;
}
}
void Formals(bool incoming, bool allowGhostKeyword, List/*!*/ formals, out IToken openParen) {
Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; bool isGhost;
Expect(28);
openParen = t;
if (la.kind == 1 || la.kind == 20) {
GIdentType(allowGhostKeyword, out id, out ty, out isGhost);
formals.Add(new Formal(id, id.val, ty, incoming, isGhost));
while (la.kind == 26) {
Get();
GIdentType(allowGhostKeyword, out id, out ty, out isGhost);
formals.Add(new Formal(id, id.val, ty, incoming, isGhost));
}
}
Expect(30);
}
void IteratorSpec(List/*!*/ reads, List/*!*/ mod, List decreases,
List/*!*/ req, List/*!*/ ens,
List/*!*/ yieldReq, List/*!*/ yieldEns,
ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) {
Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; bool isYield = false; Attributes ensAttrs = null;
while (!(StartOf(9))) {SynErr(141); Get();}
if (la.kind == 45) {
Get();
while (IsAttribute()) {
Attribute(ref readsAttrs);
}
if (StartOf(10)) {
FrameExpression(out fe);
reads.Add(fe);
while (la.kind == 26) {
Get();
FrameExpression(out fe);
reads.Add(fe);
}
}
while (!(la.kind == 0 || la.kind == 15)) {SynErr(142); Get();}
Expect(15);
} else if (la.kind == 40) {
Get();
while (IsAttribute()) {
Attribute(ref modAttrs);
}
if (StartOf(10)) {
FrameExpression(out fe);
mod.Add(fe);
while (la.kind == 26) {
Get();
FrameExpression(out fe);
mod.Add(fe);
}
}
while (!(la.kind == 0 || la.kind == 15)) {SynErr(143); Get();}
Expect(15);
} else if (StartOf(11)) {
if (la.kind == 41) {
Get();
isFree = true;
}
if (la.kind == 46) {
Get();
isYield = true;
}
if (la.kind == 42) {
Get();
Expression(out e);
while (!(la.kind == 0 || la.kind == 15)) {SynErr(144); Get();}
Expect(15);
if (isYield) {
yieldReq.Add(new MaybeFreeExpression(e, isFree));
} else {
req.Add(new MaybeFreeExpression(e, isFree));
}
} else if (la.kind == 43) {
Get();
while (IsAttribute()) {
Attribute(ref ensAttrs);
}
Expression(out e);
while (!(la.kind == 0 || la.kind == 15)) {SynErr(145); Get();}
Expect(15);
if (isYield) {
yieldEns.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
} else {
ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
}
} else SynErr(146);
} else if (la.kind == 44) {
Get();
while (IsAttribute()) {
Attribute(ref decrAttrs);
}
DecreasesList(decreases, false);
while (!(la.kind == 0 || la.kind == 15)) {SynErr(147); Get();}
Expect(15);
} else SynErr(148);
}
void BlockStmt(out BlockStmt/*!*/ block, out IToken bodyStart, out IToken bodyEnd) {
Contract.Ensures(Contract.ValueAtReturn(out block) != null);
List body = new List();
Expect(6);
bodyStart = t;
while (StartOf(12)) {
Stmt(body);
}
Expect(7);
bodyEnd = t;
block = new BlockStmt(bodyStart, body);
}
void MethodSpec(List/*!*/ req, List/*!*/ mod, List/*!*/ ens,
List/*!*/ decreases, ref Attributes decAttrs, ref Attributes modAttrs) {
Contract.Requires(cce.NonNullElements(req)); Contract.Requires(cce.NonNullElements(mod)); Contract.Requires(cce.NonNullElements(ens)); Contract.Requires(cce.NonNullElements(decreases));
Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; Attributes ensAttrs = null;
while (!(StartOf(13))) {SynErr(149); Get();}
if (la.kind == 40) {
Get();
while (IsAttribute()) {
Attribute(ref modAttrs);
}
if (StartOf(10)) {
FrameExpression(out fe);
mod.Add(fe);
while (la.kind == 26) {
Get();
FrameExpression(out fe);
mod.Add(fe);
}
}
while (!(la.kind == 0 || la.kind == 15)) {SynErr(150); Get();}
Expect(15);
} else if (la.kind == 41 || la.kind == 42 || la.kind == 43) {
if (la.kind == 41) {
Get();
isFree = true;
}
if (la.kind == 42) {
Get();
Expression(out e);
while (!(la.kind == 0 || la.kind == 15)) {SynErr(151); Get();}
Expect(15);
req.Add(new MaybeFreeExpression(e, isFree));
} else if (la.kind == 43) {
Get();
while (IsAttribute()) {
Attribute(ref ensAttrs);
}
Expression(out e);
while (!(la.kind == 0 || la.kind == 15)) {SynErr(152); Get();}
Expect(15);
ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
} else SynErr(153);
} else if (la.kind == 44) {
Get();
while (IsAttribute()) {
Attribute(ref decAttrs);
}
DecreasesList(decreases, true);
while (!(la.kind == 0 || la.kind == 15)) {SynErr(154); Get();}
Expect(15);
} else SynErr(155);
}
void FrameExpression(out FrameExpression/*!*/ fe) {
Contract.Ensures(Contract.ValueAtReturn(out fe) != null);
Expression/*!*/ e;
IToken/*!*/ id;
string fieldName = null; IToken feTok = null;
fe = null;
if (StartOf(14)) {
Expression(out e);
feTok = e.tok;
if (la.kind == 59) {
Get();
Ident(out id);
fieldName = id.val; feTok = id;
}
fe = new FrameExpression(feTok, e, fieldName);
} else if (la.kind == 59) {
Get();
Ident(out id);
fieldName = id.val;
fe = new FrameExpression(id, new ImplicitThisExpr(id), fieldName);
} else SynErr(156);
}
void Expression(out Expression/*!*/ e) {
EquivExpression(out e);
}
void DecreasesList(List decreases, bool allowWildcard) {
Expression/*!*/ e;
PossiblyWildExpression(out e);
if (!allowWildcard && e is WildcardExpr) {
SemErr(e.tok, "'decreases *' is only allowed on loops and tail-recursive methods");
} else {
decreases.Add(e);
}
while (la.kind == 26) {
Get();
PossiblyWildExpression(out e);
if (!allowWildcard && e is WildcardExpr) {
SemErr(e.tok, "'decreases *' is only allowed on loops and tail-recursive methods");
} else {
decreases.Add(e);
}
}
}
void GenericInstantiation(List/*!*/ gt) {
Contract.Requires(cce.NonNullElements(gt)); Type/*!*/ ty;
Expect(35);
Type(out ty);
gt.Add(ty);
while (la.kind == 26) {
Get();
Type(out ty);
gt.Add(ty);
}
Expect(36);
}
void ReferenceType(out IToken/*!*/ tok, out Type/*!*/ ty) {
Contract.Ensures(Contract.ValueAtReturn(out tok) != null); Contract.Ensures(Contract.ValueAtReturn(out ty) != null);
tok = Token.NoToken; ty = new BoolType(); /*keep compiler happy*/
List/*!*/ gt;
List path;
if (la.kind == 54) {
Get();
tok = t; ty = new ObjectType();
} else if (la.kind == 3) {
Get();
tok = t; gt = new List();
GenericInstantiation(gt);
if (gt.Count != 1) {
SemErr("array type expects exactly one type argument");
}
int dims = 1;
if (tok.val.Length != 5) {
dims = int.Parse(tok.val.Substring(5));
}
ty = theBuiltIns.ArrayType(tok, dims, gt[0], true);
} else if (la.kind == 1) {
Ident(out tok);
gt = new List();
path = new List();
while (la.kind == 18) {
path.Add(tok);
Get();
Ident(out tok);
}
if (la.kind == 35) {
GenericInstantiation(gt);
}
ty = new UserDefinedType(tok, tok.val, gt, path);
} else SynErr(157);
}
void FunctionSpec(List/*!*/ reqs, List/*!*/ reads, List/*!*/ ens, List decreases) {
Contract.Requires(cce.NonNullElements(reqs));
Contract.Requires(cce.NonNullElements(reads));
Contract.Requires(decreases == null || cce.NonNullElements(decreases));
Expression/*!*/ e; FrameExpression/*!*/ fe;
if (la.kind == 42) {
while (!(la.kind == 0 || la.kind == 42)) {SynErr(158); Get();}
Get();
Expression(out e);
while (!(la.kind == 0 || la.kind == 15)) {SynErr(159); Get();}
Expect(15);
reqs.Add(e);
} else if (la.kind == 45) {
Get();
if (StartOf(15)) {
PossiblyWildFrameExpression(out fe);
reads.Add(fe);
while (la.kind == 26) {
Get();
PossiblyWildFrameExpression(out fe);
reads.Add(fe);
}
}
while (!(la.kind == 0 || la.kind == 15)) {SynErr(160); Get();}
Expect(15);
} else if (la.kind == 43) {
Get();
Expression(out e);
while (!(la.kind == 0 || la.kind == 15)) {SynErr(161); Get();}
Expect(15);
ens.Add(e);
} else if (la.kind == 44) {
Get();
if (decreases == null) {
SemErr(t, "'decreases' clauses are meaningless for copredicates, so they are not allowed");
decreases = new List();
}
DecreasesList(decreases, false);
while (!(la.kind == 0 || la.kind == 15)) {SynErr(162); Get();}
Expect(15);
} else SynErr(163);
}
void FunctionBody(out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd) {
Contract.Ensures(Contract.ValueAtReturn(out e) != null); e = dummyExpr;
Expect(6);
bodyStart = t;
Expression(out e);
Expect(7);
bodyEnd = t;
}
void PossiblyWildFrameExpression(out FrameExpression/*!*/ fe) {
Contract.Ensures(Contract.ValueAtReturn(out fe) != null); fe = dummyFrameExpr;
if (la.kind == 58) {
Get();
fe = new FrameExpression(t, new WildcardExpr(t), null);
} else if (StartOf(10)) {
FrameExpression(out fe);
} else SynErr(164);
}
void PossiblyWildExpression(out Expression/*!*/ e) {
Contract.Ensures(Contract.ValueAtReturn(out e)!=null);
e = dummyExpr;
if (la.kind == 58) {
Get();
e = new WildcardExpr(t);
} else if (StartOf(14)) {
Expression(out e);
} else SynErr(165);
}
void Stmt(List/*!*/ ss) {
Statement/*!*/ s;
OneStmt(out s);
ss.Add(s);
}
void OneStmt(out Statement/*!*/ s) {
Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; IToken/*!*/ id; string label = null;
s = dummyStmt; /* to please the compiler */
BlockStmt bs;
IToken bodyStart, bodyEnd;
int breakCount;
while (!(StartOf(16))) {SynErr(166); Get();}
switch (la.kind) {
case 6: {
BlockStmt(out bs, out bodyStart, out bodyEnd);
s = bs;
break;
}
case 78: {
AssertStmt(out s);
break;
}
case 66: {
AssumeStmt(out s);
break;
}
case 79: {
PrintStmt(out s);
break;
}
case 1: case 2: case 24: case 28: case 107: case 108: case 109: case 110: case 111: case 112: {
UpdateStmt(out s);
break;
}
case 20: case 25: {
VarDeclStatement(out s);
break;
}
case 71: {
IfStmt(out s);
break;
}
case 75: {
WhileStmt(out s);
break;
}
case 77: {
MatchStmt(out s);
break;
}
case 80: case 81: {
ForallStmt(out s);
break;
}
case 82: {
CalcStmt(out s);
break;
}
case 60: {
Get();
x = t;
NoUSIdent(out id);
Expect(5);
OneStmt(out s);
s.Labels = new LList