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 maxT = 111; 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; } // helper routine for parsing call statements /// /// 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; } /*--------------------------------------------------------------------------*/ 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; 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); bool isGhost; while (StartOf(1)) { isGhost = false; if (la.kind == 8) { Get(); isGhost = true; } if (la.kind == 9 || la.kind == 11) { SubModuleDecl(defaultModule, isGhost, out submodule); defaultModule.TopLevelDecls.Add(submodule); } else if (la.kind == 18) { if (isGhost) { SemErr(t, "a class is not allowed to be declared as 'ghost'"); } ClassDecl(defaultModule, out c); defaultModule.TopLevelDecls.Add(c); } else if (la.kind == 20 || la.kind == 21) { if (isGhost) { SemErr(t, "a datatype/codatatype is not allowed to be declared as 'ghost'"); } DatatypeDecl(defaultModule, out dt); defaultModule.TopLevelDecls.Add(dt); } else if (la.kind == 25) { if (isGhost) { SemErr(t, "a type is not allowed to be declared as 'ghost'"); } ArbitraryTypeDecl(defaultModule, out at); defaultModule.TopLevelDecls.Add(at); } else if (StartOf(2)) { ClassMemberDecl(membersDefaultClass, isGhost, false); } else SynErr(112); } 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, bool isOverallModuleGhost, out ModuleDecl submodule) { ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; ArbitraryTypeDecl at; Attributes attrs = null; IToken/*!*/ id; List namedModuleDefaultClassMembers = new List();; List idRefined = null, idPath = null, idAssignment = null; bool isGhost = false; ModuleDefinition module; ModuleDecl sm; submodule = null; // appease compiler bool opened = false; if (la.kind == 9) { Get(); while (la.kind == 6) { Attribute(ref attrs); } NoUSIdent(out id); if (la.kind == 10) { Get(); QualifiedName(out idRefined); } module = new ModuleDefinition(id, id.val, isOverallModuleGhost, false, idRefined == null ? null : idRefined, attrs, false); Expect(6); module.BodyStartTok = t; while (StartOf(1)) { isGhost = false; if (la.kind == 8) { Get(); isGhost = true; } if (la.kind == 9 || la.kind == 11) { SubModuleDecl(module, isGhost, out sm); module.TopLevelDecls.Add(sm); } else if (la.kind == 18) { if (isGhost) { SemErr(t, "a class is not allowed to be declared as 'ghost'"); } ClassDecl(module, out c); module.TopLevelDecls.Add(c); } else if (la.kind == 20 || la.kind == 21) { if (isGhost) { SemErr(t, "a datatype/codatatype is not allowed to be declared as 'ghost'"); } DatatypeDecl(module, out dt); module.TopLevelDecls.Add(dt); } else if (la.kind == 25) { if (isGhost) { SemErr(t, "a type is not allowed to be declared as 'ghost'"); } ArbitraryTypeDecl(module, out at); module.TopLevelDecls.Add(at); } else if (StartOf(2)) { ClassMemberDecl(namedModuleDefaultClassMembers, isGhost, false); } else SynErr(113); } Expect(7); module.BodyEndTok = t; module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers)); submodule = new LiteralModuleDecl(module, parent); } else if (la.kind == 11) { Get(); if (la.kind == 12) { Get(); opened = true; } NoUSIdent(out id); if (la.kind == 13) { Get(); QualifiedName(out idPath); Expect(14); submodule = new AliasModuleDecl(idPath, id, parent, opened); } else if (la.kind == 14) { Get(); idPath = new List(); idPath.Add(id); submodule = new AliasModuleDecl(idPath, id, parent, opened); } else if (la.kind == 15) { Get(); QualifiedName(out idPath); if (la.kind == 16) { Get(); QualifiedName(out idAssignment); } Expect(14); submodule = new AbstractModuleDecl(idPath, id, parent, idAssignment, opened); } else SynErr(114); } else SynErr(115); } 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 == 18)) {SynErr(116); Get();} Expect(18); while (la.kind == 6) { Attribute(ref attrs); } NoUSIdent(out id); if (la.kind == 29) { GenericParameters(typeArgs); } Expect(6); bodyStart = t; while (StartOf(2)) { ClassMemberDecl(members, false, 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 == 20 || la.kind == 21)) {SynErr(117); Get();} if (la.kind == 20) { Get(); } else if (la.kind == 21) { Get(); co = true; } else SynErr(118); while (la.kind == 6) { Attribute(ref attrs); } NoUSIdent(out id); if (la.kind == 29) { GenericParameters(typeArgs); } Expect(13); bodyStart = t; DatatypeMemberDecl(ctors); while (la.kind == 22) { Get(); DatatypeMemberDecl(ctors); } while (!(la.kind == 0 || la.kind == 14)) {SynErr(119); Get();} Expect(14); 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(25); while (la.kind == 6) { Attribute(ref attrs); } NoUSIdent(out id); if (la.kind == 26) { Get(); Expect(27); Expect(28); eqSupport = TypeParameter.EqualitySupportValue.Required; } at = new ArbitraryTypeDecl(id, id.val, module, eqSupport, attrs); while (!(la.kind == 0 || la.kind == 14)) {SynErr(120); Get();} Expect(14); } void ClassMemberDecl(List/*!*/ mm, bool isAlreadyGhost, bool allowConstructors) { Contract.Requires(cce.NonNullElements(mm)); Method/*!*/ m; Function/*!*/ f; MemberModifiers mmod = new MemberModifiers(); mmod.IsGhost = isAlreadyGhost; while (la.kind == 8 || la.kind == 19) { if (la.kind == 8) { Get(); mmod.IsGhost = true; } else { Get(); mmod.IsStatic = true; } } if (la.kind == 23) { FieldDecl(mmod, mm); } else if (la.kind == 48 || la.kind == 49 || la.kind == 50) { FunctionDecl(mmod, out f); mm.Add(f); } else if (la.kind == 31 || la.kind == 32) { MethodDecl(mmod, allowConstructors, out m); mm.Add(m); } else SynErr(121); } 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 == 17) { 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(29); NoUSIdent(out id); eqSupport = TypeParameter.EqualitySupportValue.Unspecified; if (la.kind == 26) { Get(); Expect(27); Expect(28); eqSupport = TypeParameter.EqualitySupportValue.Required; } typeArgs.Add(new TypeParameter(id, id.val, eqSupport)); while (la.kind == 24) { Get(); NoUSIdent(out id); eqSupport = TypeParameter.EqualitySupportValue.Unspecified; if (la.kind == 26) { Get(); Expect(27); Expect(28); eqSupport = TypeParameter.EqualitySupportValue.Required; } typeArgs.Add(new TypeParameter(id, id.val, eqSupport)); } Expect(30); } void FieldDecl(MemberModifiers mmod, List/*!*/ mm) { Contract.Requires(cce.NonNullElements(mm)); Attributes attrs = null; IToken/*!*/ id; Type/*!*/ ty; while (!(la.kind == 0 || la.kind == 23)) {SynErr(122); Get();} Expect(23); 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 == 24) { Get(); IdentType(out id, out ty, false); mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs)); } while (!(la.kind == 0 || la.kind == 14)) {SynErr(123); Get();} Expect(14); } 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 == 48) { Get(); if (la.kind == 31) { 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 == 26 || la.kind == 29) { if (la.kind == 29) { 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(124); } else if (la.kind == 49) { Get(); isPredicate = true; if (la.kind == 31) { 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(3)) { if (la.kind == 29) { GenericParameters(typeArgs); } if (la.kind == 26) { 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(125); } else if (la.kind == 50) { 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(3)) { if (la.kind == 29) { GenericParameters(typeArgs); } if (la.kind == 26) { 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(126); } else SynErr(127); decreases = isCoPredicate ? null : new List(); while (StartOf(4)) { 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; 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 signatureOmitted = false; IToken bodyStart = Token.NoToken; IToken bodyEnd = Token.NoToken; while (!(la.kind == 0 || la.kind == 31 || la.kind == 32)) {SynErr(128); Get();} if (la.kind == 31) { Get(); } else if (la.kind == 32) { Get(); if (allowConstructor) { isConstructor = true; } else { SemErr(t, "constructors are only allowed in classes"); } } else SynErr(129); if (isConstructor) { if (mmod.IsGhost) { SemErr(t, "constructors cannot be declared 'ghost'"); } if (mmod.IsStatic) { SemErr(t, "constructors cannot be declared 'static'"); } } while (la.kind == 6) { Attribute(ref attrs); } NoUSIdent(out id); if (la.kind == 26 || la.kind == 29) { if (la.kind == 29) { 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(130); while (StartOf(5)) { 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, id.val, typeArgs, ins, 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 == 26) { 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(26); if (StartOf(6)) { TypeIdentOptional(out id, out name, out ty, out isGhost); formals.Add(new Formal(id, name, ty, true, isGhost)); while (la.kind == 24) { Get(); TypeIdentOptional(out id, out name, out ty, out isGhost); formals.Add(new Formal(id, name, ty, true, isGhost)); } } Expect(28); } 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 == 8) { 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 == 8) { 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 40: { Get(); tok = t; break; } case 41: { Get(); tok = t; ty = new NatType(); break; } case 42: { Get(); tok = t; ty = new IntType(); break; } case 43: { 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 44: { 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 45: { 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 46: { 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 47: { ReferenceType(out tok, out ty); break; } default: SynErr(131); break; } } void Formals(bool incoming, bool allowGhostKeyword, List/*!*/ formals, out IToken openParen) { Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; bool isGhost; Expect(26); openParen = t; if (la.kind == 1 || la.kind == 8) { GIdentType(allowGhostKeyword, out id, out ty, out isGhost); formals.Add(new Formal(id, id.val, ty, incoming, isGhost)); while (la.kind == 24) { Get(); GIdentType(allowGhostKeyword, out id, out ty, out isGhost); formals.Add(new Formal(id, id.val, ty, incoming, isGhost)); } } Expect(28); } 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(7))) {SynErr(132); Get();} if (la.kind == 35) { Get(); while (IsAttribute()) { Attribute(ref modAttrs); } if (StartOf(8)) { FrameExpression(out fe); mod.Add(fe); while (la.kind == 24) { Get(); FrameExpression(out fe); mod.Add(fe); } } while (!(la.kind == 0 || la.kind == 14)) {SynErr(133); Get();} Expect(14); } else if (la.kind == 36 || la.kind == 37 || la.kind == 38) { if (la.kind == 36) { Get(); isFree = true; } if (la.kind == 37) { Get(); Expression(out e); while (!(la.kind == 0 || la.kind == 14)) {SynErr(134); Get();} Expect(14); req.Add(new MaybeFreeExpression(e, isFree)); } else if (la.kind == 38) { Get(); while (IsAttribute()) { Attribute(ref ensAttrs); } Expression(out e); while (!(la.kind == 0 || la.kind == 14)) {SynErr(135); Get();} Expect(14); ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs)); } else SynErr(136); } else if (la.kind == 39) { Get(); while (IsAttribute()) { Attribute(ref decAttrs); } DecreasesList(decreases, false); while (!(la.kind == 0 || la.kind == 14)) {SynErr(137); Get();} Expect(14); } else SynErr(138); } 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(9)) { Stmt(body); } Expect(7); bodyEnd = t; block = new BlockStmt(bodyStart, body); } 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(10)) { Expression(out e); feTok = e.tok; if (la.kind == 53) { Get(); Ident(out id); fieldName = id.val; feTok = id; } fe = new FrameExpression(feTok, e, fieldName); } else if (la.kind == 53) { Get(); Ident(out id); fieldName = id.val; fe = new FrameExpression(id, new ImplicitThisExpr(id), fieldName); } else SynErr(139); } 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"); } else { decreases.Add(e); } while (la.kind == 24) { Get(); PossiblyWildExpression(out e); if (!allowWildcard && e is WildcardExpr) { SemErr(e.tok, "'decreases *' is only allowed on loops"); } else { decreases.Add(e); } } } void GenericInstantiation(List/*!*/ gt) { Contract.Requires(cce.NonNullElements(gt)); Type/*!*/ ty; Expect(29); Type(out ty); gt.Add(ty); while (la.kind == 24) { Get(); Type(out ty); gt.Add(ty); } Expect(30); } 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 == 47) { 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 == 17) { path.Add(tok); Get(); Ident(out tok); } if (la.kind == 29) { GenericInstantiation(gt); } ty = new UserDefinedType(tok, tok.val, gt, path); } else SynErr(140); } 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 == 37) { while (!(la.kind == 0 || la.kind == 37)) {SynErr(141); Get();} Get(); Expression(out e); while (!(la.kind == 0 || la.kind == 14)) {SynErr(142); Get();} Expect(14); reqs.Add(e); } else if (la.kind == 51) { Get(); if (StartOf(11)) { PossiblyWildFrameExpression(out fe); reads.Add(fe); while (la.kind == 24) { Get(); PossiblyWildFrameExpression(out fe); reads.Add(fe); } } while (!(la.kind == 0 || la.kind == 14)) {SynErr(143); Get();} Expect(14); } else if (la.kind == 38) { Get(); Expression(out e); while (!(la.kind == 0 || la.kind == 14)) {SynErr(144); Get();} Expect(14); ens.Add(e); } else if (la.kind == 39) { 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 == 14)) {SynErr(145); Get();} Expect(14); } else SynErr(146); } 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 == 52) { Get(); fe = new FrameExpression(t, new WildcardExpr(t), null); } else if (StartOf(8)) { FrameExpression(out fe); } else SynErr(147); } void PossiblyWildExpression(out Expression/*!*/ e) { Contract.Ensures(Contract.ValueAtReturn(out e)!=null); e = dummyExpr; if (la.kind == 52) { Get(); e = new WildcardExpr(t); } else if (StartOf(10)) { Expression(out e); } else SynErr(148); } 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(12))) {SynErr(149); Get();} switch (la.kind) { case 6: { BlockStmt(out bs, out bodyStart, out bodyEnd); s = bs; break; } case 72: { AssertStmt(out s); break; } case 60: { AssumeStmt(out s); break; } case 73: { PrintStmt(out s); break; } case 1: case 2: case 22: case 26: case 97: case 98: case 99: case 100: case 101: case 102: { UpdateStmt(out s); break; } case 8: case 23: { VarDeclStatement(out s); break; } case 65: { IfStmt(out s); break; } case 69: { WhileStmt(out s); break; } case 71: { MatchStmt(out s); break; } case 74: { ParallelStmt(out s); break; } case 54: { Get(); x = t; NoUSIdent(out id); Expect(5); OneStmt(out s); s.Labels = new LList