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 _hexdigits = 3;
public const int _decimaldigits = 4;
public const int _arrayToken = 5;
public const int _bool = 6;
public const int _char = 7;
public const int _int = 8;
public const int _nat = 9;
public const int _real = 10;
public const int _object = 11;
public const int _string = 12;
public const int _set = 13;
public const int _iset = 14;
public const int _multiset = 15;
public const int _seq = 16;
public const int _map = 17;
public const int _imap = 18;
public const int _charToken = 19;
public const int _stringToken = 20;
public const int _colon = 21;
public const int _comma = 22;
public const int _verticalbar = 23;
public const int _doublecolon = 24;
public const int _boredSmiley = 25;
public const int _bullet = 26;
public const int _dot = 27;
public const int _semi = 28;
public const int _darrow = 29;
public const int _arrow = 30;
public const int _assume = 31;
public const int _calc = 32;
public const int _case = 33;
public const int _then = 34;
public const int _else = 35;
public const int _decreases = 36;
public const int _invariant = 37;
public const int _function = 38;
public const int _predicate = 39;
public const int _inductive = 40;
public const int _lemma = 41;
public const int _copredicate = 42;
public const int _modifies = 43;
public const int _reads = 44;
public const int _requires = 45;
public const int _lbrace = 46;
public const int _rbrace = 47;
public const int _lbracket = 48;
public const int _rbracket = 49;
public const int _openparen = 50;
public const int _closeparen = 51;
public const int _openAngleBracket = 52;
public const int _closeAngleBracket = 53;
public const int _eq = 54;
public const int _neq = 55;
public const int _neqAlt = 56;
public const int _star = 57;
public const int _notIn = 58;
public const int _ellipsis = 59;
public const int maxT = 140;
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 ModuleDecl theModule;
readonly BuiltIns theBuiltIns;
readonly bool theVerifyThisFile;
int anonymousIds = 0;
///
/// Holds the modifiers given for a declaration
///
/// Not all modifiers are applicable to all kinds of declarations.
/// Errors are given when a modify does not apply.
/// We also record the tokens for the specified modifiers so that
/// they can be used in error messages.
///
struct DeclModifierData {
public bool IsAbstract;
public IToken AbstractToken;
public bool IsGhost;
public IToken GhostToken;
public bool IsStatic;
public IToken StaticToken;
public bool IsProtected;
public IToken ProtectedToken;
public bool IsExtern;
public IToken ExternToken;
public StringLiteralExpr ExternName;
}
// Check that token has not been set, then set it.
public void CheckAndSetToken(ref IToken token)
{
if (token != null) {
SemErr(t, "Duplicate declaration modifier: " + t.val);
}
token = t;
}
///
// A flags type used to tell what declaration modifiers are allowed for a declaration.
///
[Flags]
enum AllowedDeclModifiers {
None = 0,
Abstract = 1,
Ghost = 2,
// Means ghost not allowed because already implicitly ghost.
AlreadyGhost = 4,
Static = 8,
Protected = 16,
Extern = 32
};
///
/// Check the declaration modifiers against those that are allowed.
///
/// The 'allowed' parameter specifies which declaratio modifiers are allowed.
/// The 'declCaption' parameter should be a string describing the kind of declaration.
/// It is used in error messages.
/// Any declaration modifiers that are present but not allowed are cleared.
///
void CheckDeclModifiers(DeclModifierData dmod, string declCaption, AllowedDeclModifiers allowed)
{
if (dmod.IsAbstract && ((allowed & AllowedDeclModifiers.Abstract) == 0)) {
SemErr(dmod.AbstractToken, declCaption + " cannot be declared 'abstract'.");
dmod.IsAbstract = false;
}
if (dmod.IsGhost) {
if ((allowed & AllowedDeclModifiers.AlreadyGhost) != 0) {
SemErr(dmod.GhostToken, declCaption + " cannot be declared ghost (they are 'ghost' by default).");
dmod.IsGhost = false;
} else if ((allowed & AllowedDeclModifiers.Ghost) == 0) {
SemErr(dmod.GhostToken, declCaption + " cannot be declared 'ghost'.");
dmod.IsGhost = false;
}
}
if (dmod.IsStatic && ((allowed & AllowedDeclModifiers.Static) == 0)) {
SemErr(dmod.StaticToken, declCaption + " cannot be declared 'static'.");
dmod.IsStatic = false;
}
if (dmod.IsProtected && ((allowed & AllowedDeclModifiers.Protected) == 0)) {
SemErr(dmod.ProtectedToken, declCaption + " cannot be declared 'protected'.");
dmod.IsProtected = false;
}
if (dmod.IsExtern && ((allowed & AllowedDeclModifiers.Extern) == 0)) {
SemErr(dmod.ExternToken, declCaption + " cannot be declared 'extern'.");
dmod.IsExtern = false;
}
}
///
/// Encode an 'extern' declaration modifier as an {:extern name} attribute.
///
/// We also include an {:axiom} attribute since the specification of an
/// external entity is assumed to hold, but only for methods or functions.
///
static void EncodeExternAsAttribute(DeclModifierData dmod, ref Attributes attrs, IToken/*!*/ id, bool needAxiom) {
if (dmod.IsExtern) {
StringLiteralExpr name = dmod.ExternName;
if (name == null) {
bool isVerbatimString = false;
name = new StringLiteralExpr(id, id.val, isVerbatimString);
}
var args = new List();
args.Add(name);
attrs = new Attributes("extern", args, attrs);
// Also 'extern' implies 'axiom' for methods or functions.
if (needAxiom) {
attrs = new Attributes("axiom", new List(), attrs);
}
}
}
///
/// 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, Errors/*!*/ errors, bool verifyThisFile=true) /* 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, filename, module, builtIns, errors, verifyThisFile);
} else {
using (System.IO.StreamReader reader = new System.IO.StreamReader(filename)) {
s = Microsoft.Boogie.ParserHelper.Fill(reader, new List());
return Parse(s, filename, DafnyOptions.Clo.UseBaseNameForFileName ? Path.GetFileName(filename) : filename, module, builtIns, errors, verifyThisFile);
}
}
}
///
/// 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/*!*/ fullFilename, string/*!*/ filename, ModuleDecl module, BuiltIns builtIns, ErrorReporter reporter, bool verifyThisFile=true) {
Contract.Requires(s != null);
Contract.Requires(filename != null);
Contract.Requires(module != null);
Errors errors = new Errors(reporter);
return Parse(s, fullFilename, filename, module, builtIns, errors, verifyThisFile);
}
///
/// 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/*!*/ fullFilename, string/*!*/ filename, ModuleDecl module,
BuiltIns builtIns, Errors/*!*/ errors, bool verifyThisFile=true) {
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, fullFilename, filename);
Parser parser = new Parser(scanner, errors, module, builtIns, verifyThisFile);
parser.Parse();
return parser.errors.ErrorCount;
}
public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors, ModuleDecl module, BuiltIns builtIns, bool verifyThisFile=true)
: 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, Token.NoToken, null);
theModule = module;
theBuiltIns = builtIns;
theVerifyThisFile = verifyThisFile;
}
bool IsAttribute() {
Token x = scanner.Peek();
return la.kind == _lbrace && x.kind == _colon;
}
bool IsAlternative() {
Token x = scanner.Peek();
return la.kind == _lbrace && x.kind == _case;
}
// an existential guard starts with an identifier and is then followed by
// * a colon (if the first identifier is given an explicit type),
// * a comma (if there's a list a bound variables and the first one is not given an explicit type),
// * a start-attribute (if there's one bound variable and it is not given an explicit type and there are attributes), or
// * a bored smiley (if there's one bound variable and it is not given an explicit type).
bool IsExistentialGuard() {
scanner.ResetPeek();
if (la.kind == _ident) {
Token x = scanner.Peek();
if (x.kind == _colon || x.kind == _comma || x.kind == _boredSmiley) {
return true;
} else if (x.kind == _lbrace) {
x = scanner.Peek();
return x.kind == _colon;
}
}
return false;
}
bool IsLoopSpec() {
return la.kind == _invariant | la.kind == _decreases | la.kind == _modifies;
}
bool IsFunctionDecl() {
switch (la.kind) {
case _function:
case _predicate:
case _copredicate:
return true;
case _inductive:
return scanner.Peek().kind != _lemma;
default:
return false;
}
}
bool IsParenStar() {
scanner.ResetPeek();
Token x = scanner.Peek();
return la.kind == _openparen && x.kind == _star;
}
bool IsEquivOp() {
return la.val == "<==>" || la.val == "\u21d4";
}
bool IsImpliesOp() {
return la.val == "==>" || la.val == "\u21d2";
}
bool IsExpliesOp() {
return la.val == "<==" || la.val == "\u21d0";
}
bool IsAndOp() {
return la.val == "&&" || la.val == "\u2227";
}
bool IsOrOp() {
return la.val == "||" || la.val == "\u2228";
}
bool IsRelOp() {
return la.val == "=="
|| la.val == "<"
|| la.val == ">"
|| la.val == "<="
|| la.val == ">="
|| la.val == "!="
|| la.val == "in"
|| la.kind == _notIn
|| la.val =="!"
|| la.val == "\u2260"
|| la.val == "\u2264"
|| la.val == "\u2265";
}
bool IsAddOp() {
return la.val == "+" || la.val == "-";
}
bool IsMulOp() {
return la.kind == _star || la.val == "/" || la.val == "%";
}
bool IsQSep() {
return la.kind == _doublecolon || la.kind == _bullet;
}
bool IsNonFinalColon() {
return la.kind == _colon && scanner.Peek().kind != _rbracket;
}
bool IsMapDisplay() {
return la.kind == _map && scanner.Peek().kind == _lbracket;
}
bool IsIMapDisplay() {
return la.kind == _imap && scanner.Peek().kind == _lbracket;
}
bool IsISetDisplay() {
return la.kind == _iset && scanner.Peek().kind == _lbrace;
}
bool IsSuffix() {
return la.kind == _dot || la.kind == _lbracket || la.kind == _openparen;
}
string UnwildIdent(string x, bool allowWildcardId) {
if (x.StartsWith("_")) {
if (allowWildcardId && x.Length == 1) {
return "_v" + anonymousIds++;
} else {
SemErr("cannot declare identifier beginning with underscore");
}
}
return x;
}
bool IsLambda(bool allowLambda)
{
if (!allowLambda) {
return false;
}
scanner.ResetPeek();
Token x;
// peek at what might be a signature of a lambda expression
if (la.kind == _ident) {
// cool, that's the entire candidate signature
} else if (la.kind != _openparen) {
return false; // this is not a lambda expression
} else {
int identCount = 0;
x = scanner.Peek();
while (x.kind != _closeparen) {
if (identCount != 0) {
if (x.kind != _comma) {
return false; // not the signature of a lambda
}
x = scanner.Peek();
}
if (x.kind != _ident) {
return false; // not a lambda expression
}
identCount++;
x = scanner.Peek();
if (x.kind == _colon) {
// a colon belongs only in a lamdba signature, so this must be a lambda (or something ill-formed)
return true;
}
}
}
// What we have seen so far could have been a lambda signature or could have been some
// other expression (in particular, an identifier, a parenthesized identifier, or a
// tuple all of whose subexpressions are identifiers).
// It is a lambda expression if what follows is something that must be a lambda.
x = scanner.Peek();
return x.kind == _darrow || x.kind == _arrow || x.kind == _reads || x.kind == _requires;
}
bool IsIdentParen() {
Token x = scanner.Peek();
return la.kind == _ident && x.kind == _openparen;
}
bool IsIdentColonOrBar() {
Token x = scanner.Peek();
return la.kind == _ident && (x.kind == _colon || x.kind == _verticalbar);
}
bool SemiFollowsCall(bool allowSemi, Expression e) {
return allowSemi && la.kind == _semi && e is ApplySuffix;
}
bool CloseOptionalBrace(bool usesOptionalBrace) {
return usesOptionalBrace && la.kind == _rbrace;
}
bool IsNotEndOfCase() {
return la.kind != _EOF && la.kind != _rbrace && la.kind != _case;
}
/* The following is the largest lookahead there is. It needs to check if what follows
* can be nothing but "<" Type { "," Type } ">".
*/
bool IsGenericInstantiation() {
scanner.ResetPeek();
IToken pt = la;
if (!IsTypeList(ref pt)) {
return false;
}
/* There are ambiguities in the parsing. For example:
* F( a < b , c > (d) )
* can either be a unary function F whose argument is a function "a" with type arguments "" and
* parameter "d", or can be a binary function F with the two boolean arguments "a < b" and "c > (d)".
* To make the situation a little better, we (somewhat heuristically) look at the character that
* follows the ">". Note that if we, contrary to a user's intentions, pick "a" out as a function
* with a type instantiation, the user can disambiguate it by making sure the ">" sits inside some
* parentheses, like:
* F( a < b , (c > (d)) )
*/
switch (pt.kind) {
case _dot: // here, we're sure it must have been a type instantiation we saw, because an expression cannot begin with dot
case _openparen: // it was probably a type instantiation of a function/method
case _lbracket: // it is possible that it was a type instantiation
case _lbrace: // it was probably a type instantiation of a function/method
// In the following cases, we're sure we must have read a type instantiation that just ended an expression
case _closeparen:
case _rbracket:
case _rbrace:
case _semi:
case _then:
case _else:
case _case:
case _eq:
case _neq:
case _neqAlt:
case _openAngleBracket:
case _closeAngleBracket:
return true;
default:
return false;
}
}
/* Returns true if the next thing is of the form:
* "<" Type { "," Type } ">"
*/
bool IsTypeList(ref IToken pt) {
if (pt.kind != _openAngleBracket) {
return false;
}
pt = scanner.Peek();
return IsTypeSequence(ref pt, _closeAngleBracket);
}
/* Returns true if the next thing is of the form:
* Type { "," Type }
* followed by an endBracketKind.
*/
bool IsTypeSequence(ref IToken pt, int endBracketKind) {
while (true) {
if (!IsType(ref pt)) {
return false;
}
if (pt.kind == endBracketKind) {
// end of type list
pt = scanner.Peek();
return true;
} else if (pt.kind == _comma) {
// type list continues
pt = scanner.Peek();
} else {
// not a type list
return false;
}
}
}
bool IsType(ref IToken pt) {
switch (pt.kind) {
case _bool:
case _char:
case _nat:
case _int:
case _real:
case _object:
case _string:
pt = scanner.Peek();
return true;
case _arrayToken:
case _set:
case _iset:
case _multiset:
case _seq:
case _map:
case _imap:
pt = scanner.Peek();
return pt.kind != _openAngleBracket || IsTypeList(ref pt);
case _ident:
while (true) {
// invariant: next token is an ident
pt = scanner.Peek();
if (pt.kind == _openAngleBracket && !IsTypeList(ref pt)) {
return false;
}
if (pt.kind != _dot) {
// end of the type
return true;
}
pt = scanner.Peek(); // get the _dot
if (pt.kind != _ident) {
return false;
}
}
case _openparen:
pt = scanner.Peek();
if (pt.kind == _closeparen) {
// end of type list
pt = scanner.Peek();
return true;
}
return IsTypeSequence(ref pt, _closeparen);
default:
return false;
}
}
bool IsDefaultImport() {
scanner.ResetPeek();
Token x = scanner.Peek(); // lookahead token again
return la.val == "default" && x.val != "export";
}
/*--------------------------------------------------------------------------*/
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() {
List membersDefaultClass = new List();
// 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 (la.kind == 60) {
Get();
Expect(20);
{
string parsedFile = scanner.FullFilename;
bool isVerbatimString;
string includedFile = Util.RemoveParsedStringQuotes(t.val, out isVerbatimString);
includedFile = Util.RemoveEscaping(includedFile, isVerbatimString);
string fullPath = includedFile;
if (!Path.IsPathRooted(includedFile)) {
string basePath = Path.GetDirectoryName(parsedFile);
includedFile = Path.Combine(basePath, includedFile);
fullPath = Path.GetFullPath(includedFile);
}
defaultModule.Includes.Add(new Include(t, includedFile, fullPath));
}
}
while (StartOf(1)) {
TopDecl(defaultModule, membersDefaultClass, /* isTopLevel */ true, /* isAbstract */ false);
}
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 TopDecl(ModuleDefinition module, List membersDefaultClass, bool isTopLevel, bool isAbstract ) {
DeclModifierData dmod = new DeclModifierData(); ModuleDecl submodule;
ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; TopLevelDecl td; IteratorDecl iter;
TraitDecl/*!*/ trait;
while (StartOf(2)) {
DeclModifier(ref dmod);
}
switch (la.kind) {
case 66: case 69: case 73: case 74: {
SubModuleDecl(dmod, module, out submodule);
module.TopLevelDecls.Add(submodule);
break;
}
case 77: {
ClassDecl(dmod, module, out c);
module.TopLevelDecls.Add(c);
break;
}
case 79: case 80: {
DatatypeDecl(dmod, module, out dt);
module.TopLevelDecls.Add(dt);
break;
}
case 82: {
NewtypeDecl(dmod, module, out td);
module.TopLevelDecls.Add(td);
break;
}
case 83: {
OtherTypeDecl(dmod, module, out td);
module.TopLevelDecls.Add(td);
break;
}
case 84: {
IteratorDecl(dmod, module, out iter);
module.TopLevelDecls.Add(iter);
break;
}
case 78: {
TraitDecl(dmod, module, out trait);
module.TopLevelDecls.Add(trait);
break;
}
case 38: case 39: case 40: case 41: case 42: case 81: case 87: case 88: case 89: case 90: {
ClassMemberDecl(dmod, membersDefaultClass, false, !DafnyOptions.O.AllowGlobals,
!isTopLevel && DafnyOptions.O.IronDafny && isAbstract);
break;
}
default: SynErr(141); break;
}
}
void DeclModifier(ref DeclModifierData dmod) {
if (la.kind == 61) {
Get();
dmod.IsAbstract = true; CheckAndSetToken(ref dmod.AbstractToken);
} else if (la.kind == 62) {
Get();
dmod.IsGhost = true; CheckAndSetToken(ref dmod.GhostToken);
} else if (la.kind == 63) {
Get();
dmod.IsStatic = true; CheckAndSetToken(ref dmod.StaticToken);
} else if (la.kind == 64) {
Get();
dmod.IsProtected = true; CheckAndSetToken(ref dmod.ProtectedToken);
} else if (la.kind == 65) {
Get();
dmod.IsExtern = true; CheckAndSetToken(ref dmod.ExternToken);
if (la.kind == 20) {
Get();
bool isVerbatimString;
string s = Util.RemoveParsedStringQuotes(t.val, out isVerbatimString);
dmod.ExternName = new StringLiteralExpr(t, s, isVerbatimString);
}
} else SynErr(142);
}
void SubModuleDecl(DeclModifierData dmod, ModuleDefinition parent, out ModuleDecl submodule) {
Attributes attrs = null; IToken/*!*/ id;
List namedModuleDefaultClassMembers = new List();;
List idRefined = null, idPath = null, idAssignment = null;
ModuleDefinition module;
submodule = null; // appease compiler
bool isAbstract = dmod.IsAbstract;
bool isExclusively = false;
bool opened = false;
CheckDeclModifiers(dmod, "Modules", AllowedDeclModifiers.Abstract | AllowedDeclModifiers.Extern);
if (la.kind == 66) {
Get();
while (la.kind == 46) {
Attribute(ref attrs);
}
NoUSIdent(out id);
EncodeExternAsAttribute(dmod, ref attrs, id, /* needAxiom */ false);
if (la.kind == 67 || la.kind == 68) {
if (la.kind == 67) {
Get();
Expect(68);
QualifiedModuleName(out idRefined);
isExclusively = true;
} else {
Get();
QualifiedModuleName(out idRefined);
isExclusively = false;
}
}
module = new ModuleDefinition(id, id.val, isAbstract, false, isExclusively, idRefined == null ? null : idRefined, parent, attrs, false, this);
Expect(46);
module.BodyStartTok = t;
while (StartOf(1)) {
TopDecl(module, namedModuleDefaultClassMembers, /* isTopLevel */ false, isAbstract);
}
Expect(47);
module.BodyEndTok = t;
module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers));
submodule = new LiteralModuleDecl(module, parent);
} else if (la.kind == 69) {
Get();
if (la.kind == 70) {
Get();
opened = true;
}
NoUSIdent(out id);
EncodeExternAsAttribute(dmod, ref attrs, id, /* needAxiom */ false);
if (StartOf(3)) {
if (la.kind == 71) {
Get();
QualifiedModuleName(out idPath);
submodule = new AliasModuleDecl(idPath, id, parent, opened);
} else if (la.kind == 72) {
Get();
QualifiedModuleName(out idPath);
if (IsDefaultImport()) {
Expect(73);
QualifiedModuleName(out idAssignment);
}
submodule = new ModuleFacadeDecl(idPath, id, parent, idAssignment, opened);
errors.Warning(t, "\"import A as B\" has been deprecated; in the new syntax, it is \"import A:B\"");
} else if (la.kind == 21) {
Get();
QualifiedModuleName(out idPath);
submodule = new ModuleFacadeDecl(idPath, id, parent, idAssignment, opened);
} else {
Get();
QualifiedModuleName(out idPath);
idPath.Insert(0, id);
submodule = new AliasModuleDecl(idPath, id, parent, opened);
}
}
if (la.kind == 28) {
while (!(la.kind == 0 || la.kind == 28)) {SynErr(143); Get();}
Get();
errors.Warning(t, "the semi-colon that used to terminate a sub-module declaration has been deprecated; in the new syntax, just leave off the semi-colon");
}
if (submodule == null) {
idPath = new List();
idPath.Add(id);
submodule = new AliasModuleDecl(idPath, id, parent, opened);
}
} else if (la.kind == 73 || la.kind == 74) {
bool isDefault = false;
bool includeBody;
IToken exportId;
List exports = new List();;
List extends = new List();
if (la.kind == 73) {
Get();
isDefault = true;
}
Expect(74);
NoUSIdent(out exportId);
if (la.kind == 75) {
Get();
NoUSIdent(out id);
extends.Add(id.val);
while (la.kind == 22) {
Get();
NoUSIdent(out id);
extends.Add(id.val);
}
}
Expect(46);
NoUSIdent(out id);
includeBody = false;
if (la.kind == 76) {
Get();
includeBody = true;
}
exports.Add(new ExportSignature(id, includeBody));
while (la.kind == 22) {
Get();
NoUSIdent(out id);
includeBody = false;
if (la.kind == 76) {
Get();
includeBody = true;
}
exports.Add(new ExportSignature(id, includeBody));
}
Expect(47);
submodule = new ModuleExportDecl(exportId, parent, isDefault, exports, extends);
} else SynErr(144);
}
void ClassDecl(DeclModifierData dmodClass, ModuleDefinition/*!*/ module, out ClassDecl/*!*/ c) {
Contract.Requires(module != null);
Contract.Ensures(Contract.ValueAtReturn(out c) != null);
IToken/*!*/ id;
Type trait = null;
List/*!*/ traits = new List();
Attributes attrs = null;
List typeArgs = new List();
List members = new List();
IToken bodyStart;
CheckDeclModifiers(dmodClass, "Classes", AllowedDeclModifiers.Extern);
DeclModifierData dmod;
while (!(la.kind == 0 || la.kind == 77)) {SynErr(145); Get();}
Expect(77);
while (la.kind == 46) {
Attribute(ref attrs);
}
NoUSIdent(out id);
EncodeExternAsAttribute(dmodClass, ref attrs, id, /* needAxiom */ false);
if (la.kind == 52) {
GenericParameters(typeArgs);
}
if (la.kind == 75) {
Get();
Type(out trait);
traits.Add(trait);
while (la.kind == 22) {
Get();
Type(out trait);
traits.Add(trait);
}
}
Expect(46);
bodyStart = t;
while (StartOf(4)) {
dmod = new DeclModifierData();
while (StartOf(2)) {
DeclModifier(ref dmod);
}
ClassMemberDecl(dmod, members, true, false, false);
}
Expect(47);
c = new ClassDecl(id, id.val, module, typeArgs, members, attrs, traits);
c.BodyStartTok = bodyStart;
c.BodyEndTok = t;
}
void DatatypeDecl(DeclModifierData dmod, 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;
CheckDeclModifiers(dmod, "Datatypes or codatatypes", AllowedDeclModifiers.None);
while (!(la.kind == 0 || la.kind == 79 || la.kind == 80)) {SynErr(146); Get();}
if (la.kind == 79) {
Get();
} else if (la.kind == 80) {
Get();
co = true;
} else SynErr(147);
while (la.kind == 46) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 52) {
GenericParameters(typeArgs);
}
Expect(71);
bodyStart = t;
DatatypeMemberDecl(ctors);
while (la.kind == 23) {
Get();
DatatypeMemberDecl(ctors);
}
if (la.kind == 28) {
while (!(la.kind == 0 || la.kind == 28)) {SynErr(148); Get();}
Get();
errors.Warning(t, "the semi-colon that used to terminate a (co)datatype declaration has been deprecated; in the new syntax, just leave off the semi-colon");
}
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 NewtypeDecl(DeclModifierData dmod, ModuleDefinition module, out TopLevelDecl td) {
IToken id, bvId;
Attributes attrs = null;
td = null;
Type baseType = null;
Expression wh;
CheckDeclModifiers(dmod, "Newtypes", AllowedDeclModifiers.None);
Expect(82);
while (la.kind == 46) {
Attribute(ref attrs);
}
NoUSIdent(out id);
Expect(71);
if (IsIdentColonOrBar()) {
NoUSIdent(out bvId);
if (la.kind == 21) {
Get();
Type(out baseType);
}
if (baseType == null) { baseType = new OperationTypeProxy(true, true, false, false, false, false); }
Expect(23);
Expression(out wh, false, true);
td = new NewtypeDecl(theVerifyThisFile ? id : new IncludeToken(id), id.val, module, new BoundVar(bvId, bvId.val, baseType), wh, attrs);
} else if (StartOf(5)) {
Type(out baseType);
td = new NewtypeDecl(theVerifyThisFile ? id : new IncludeToken(id), id.val, module, baseType, attrs);
} else SynErr(149);
}
void OtherTypeDecl(DeclModifierData dmod, ModuleDefinition module, out TopLevelDecl td) {
IToken id;
Attributes attrs = null;
var eqSupport = TypeParameter.EqualitySupportValue.Unspecified;
var typeArgs = new List();
td = null;
Type ty;
CheckDeclModifiers(dmod, "Type aliases", AllowedDeclModifiers.None);
Expect(83);
while (la.kind == 46) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 50) {
Get();
Expect(54);
Expect(51);
eqSupport = TypeParameter.EqualitySupportValue.Required;
if (la.kind == 52) {
GenericParameters(typeArgs);
}
} else if (StartOf(6)) {
if (la.kind == 52) {
GenericParameters(typeArgs);
}
if (la.kind == 71) {
Get();
Type(out ty);
td = new TypeSynonymDecl(id, id.val, typeArgs, module, ty, attrs);
}
} else SynErr(150);
if (td == null) {
td = new OpaqueTypeDecl(id, id.val, module, eqSupport, typeArgs, attrs);
}
if (la.kind == 28) {
while (!(la.kind == 0 || la.kind == 28)) {SynErr(151); Get();}
Get();
errors.Warning(t, "the semi-colon that used to terminate an opaque-type declaration has been deprecated; in the new syntax, just leave off the semi-colon");
}
}
void IteratorDecl(DeclModifierData dmod, ModuleDefinition module, out IteratorDecl/*!*/ iter) {
Contract.Ensures(Contract.ValueAtReturn(out iter) != null);
IToken/*!*/ id;
Attributes attrs = null;
List/*!*/ typeArgs = new List();
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;
IToken signatureEllipsis = null;
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
CheckDeclModifiers(dmod, "Iterators", AllowedDeclModifiers.None);
while (!(la.kind == 0 || la.kind == 84)) {SynErr(152); Get();}
Expect(84);
while (la.kind == 46) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 50 || la.kind == 52) {
if (la.kind == 52) {
GenericParameters(typeArgs);
}
Formals(true, true, ins);
if (la.kind == 85 || la.kind == 86) {
if (la.kind == 85) {
Get();
} else {
Get();
SemErr(t, "iterators don't have a 'returns' clause; did you mean 'yields'?");
}
Formals(false, true, outs);
}
} else if (la.kind == 59) {
Get();
signatureEllipsis = t;
} else SynErr(153);
while (StartOf(7)) {
IteratorSpec(reads, mod, decreases, req, ens, yieldReq, yieldEns, ref readsAttrs, ref modAttrs, ref decrAttrs);
}
if (la.kind == 46) {
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, signatureEllipsis);
iter.BodyStartTok = bodyStart;
iter.BodyEndTok = bodyEnd;
}
void TraitDecl(DeclModifierData dmodIn, ModuleDefinition/*!*/ module, out TraitDecl/*!*/ trait) {
Contract.Requires(module != null);
Contract.Ensures(Contract.ValueAtReturn(out trait) != null);
CheckDeclModifiers(dmodIn, "Traits", AllowedDeclModifiers.None);
IToken/*!*/ id;
Attributes attrs = null;
List typeArgs = new List(); //traits should not support type parameters at the moment
List members = new List();
IToken bodyStart;
DeclModifierData dmod;
while (!(la.kind == 0 || la.kind == 78)) {SynErr(154); Get();}
Expect(78);
while (la.kind == 46) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 52) {
GenericParameters(typeArgs);
}
Expect(46);
bodyStart = t;
while (StartOf(4)) {
dmod = new DeclModifierData();
while (StartOf(2)) {
DeclModifier(ref dmod);
}
ClassMemberDecl(dmod, members, true, false, false);
}
Expect(47);
trait = new TraitDecl(id, id.val, module, typeArgs, members, attrs);
trait.BodyStartTok = bodyStart;
trait.BodyEndTok = t;
}
void ClassMemberDecl(DeclModifierData dmod, List mm, bool allowConstructors, bool moduleLevelDecl, bool isWithinAbstractModule) {
Contract.Requires(cce.NonNullElements(mm));
Method/*!*/ m;
Function/*!*/ f;
if (la.kind == 81) {
if (moduleLevelDecl) {
SemErr(la, "fields are not allowed to be declared at the module level; instead, wrap the field in a 'class' declaration");
dmod.IsStatic = false;
}
FieldDecl(dmod, mm);
} else if (IsFunctionDecl()) {
if (moduleLevelDecl && dmod.StaticToken != null) {
errors.Warning(dmod.StaticToken, "module-level functions are always non-instance, so the 'static' keyword is not allowed here");
dmod.IsStatic = false;
}
FunctionDecl(dmod, isWithinAbstractModule, out f);
mm.Add(f);
} else if (StartOf(8)) {
if (moduleLevelDecl && dmod.StaticToken != null) {
errors.Warning(dmod.StaticToken, "module-level methods are always non-instance, so the 'static' keyword is not allowed here");
dmod.IsStatic = false;
}
MethodDecl(dmod, allowConstructors, isWithinAbstractModule, out m);
mm.Add(m);
} else SynErr(155);
}
void Attribute(ref Attributes attrs) {
IToken x; string name;
var args = new List();
Expect(46);
Expect(21);
NoUSIdent(out x);
name = x.val;
if (StartOf(9)) {
Expressions(args);
}
Expect(47);
attrs = new Attributes(name, args, attrs);
}
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 QualifiedModuleName(out List ids) {
IToken id; ids = new List();
Ident(out id);
ids.Add(id);
while (la.kind == 27) {
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(52);
NoUSIdent(out id);
eqSupport = TypeParameter.EqualitySupportValue.Unspecified;
if (la.kind == 50) {
Get();
Expect(54);
Expect(51);
eqSupport = TypeParameter.EqualitySupportValue.Required;
}
typeArgs.Add(new TypeParameter(id, id.val, eqSupport));
while (la.kind == 22) {
Get();
NoUSIdent(out id);
eqSupport = TypeParameter.EqualitySupportValue.Unspecified;
if (la.kind == 50) {
Get();
Expect(54);
Expect(51);
eqSupport = TypeParameter.EqualitySupportValue.Required;
}
typeArgs.Add(new TypeParameter(id, id.val, eqSupport));
}
Expect(53);
}
void Type(out Type ty) {
Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken/*!*/ tok;
TypeAndToken(out tok, out ty);
}
void FieldDecl(DeclModifierData dmod, List/*!*/ mm) {
Contract.Requires(cce.NonNullElements(mm));
Attributes attrs = null;
IToken/*!*/ id; Type/*!*/ ty;
CheckDeclModifiers(dmod, "Fields", AllowedDeclModifiers.Ghost);
while (!(la.kind == 0 || la.kind == 81)) {SynErr(156); Get();}
Expect(81);
while (la.kind == 46) {
Attribute(ref attrs);
}
FIdentType(out id, out ty);
mm.Add(new Field(id, id.val, dmod.IsGhost, ty, attrs));
while (la.kind == 22) {
Get();
FIdentType(out id, out ty);
mm.Add(new Field(id, id.val, dmod.IsGhost, ty, attrs));
}
OldSemi();
}
void FunctionDecl(DeclModifierData dmod, bool isWithinAbstractModule, 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 isIndPredicate = false; bool isCoPredicate = false;
bool isFunctionMethod = false;
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
IToken signatureEllipsis = null;
bool missingOpenParen;
if (la.kind == 38) {
Get();
if (la.kind == 87) {
Get();
isFunctionMethod = true;
}
AllowedDeclModifiers allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static | AllowedDeclModifiers.Protected;
string caption = "Functions";
if (isFunctionMethod) {
allowed |= AllowedDeclModifiers.Extern;
caption = "Function methods";
}
CheckDeclModifiers(dmod, caption, allowed);
while (la.kind == 46) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 50 || la.kind == 52) {
if (la.kind == 52) {
GenericParameters(typeArgs);
}
Formals(true, isFunctionMethod, formals);
Expect(21);
Type(out returnType);
} else if (la.kind == 59) {
Get();
signatureEllipsis = t;
} else SynErr(157);
} else if (la.kind == 39) {
Get();
isPredicate = true;
if (la.kind == 87) {
Get();
isFunctionMethod = true;
}
AllowedDeclModifiers allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static | AllowedDeclModifiers.Protected;
string caption = "Predicates";
if (isFunctionMethod) {
allowed |= AllowedDeclModifiers.Extern;
caption = "Predicate methods";
}
CheckDeclModifiers(dmod, caption, allowed);
while (la.kind == 46) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (StartOf(10)) {
if (la.kind == 52) {
GenericParameters(typeArgs);
}
missingOpenParen = true;
if (la.kind == 50) {
Formals(true, isFunctionMethod, formals);
missingOpenParen = false;
}
if (missingOpenParen) { errors.Warning(t, "with the new support of higher-order functions in Dafny, parentheses-less predicates are no longer supported; in the new syntax, parentheses are required for the declaration and uses of predicates, even if the predicate takes no additional arguments"); }
if (la.kind == 21) {
Get();
SemErr(t, "predicates do not have an explicitly declared return type; it is always bool");
}
} else if (la.kind == 59) {
Get();
signatureEllipsis = t;
} else SynErr(158);
} else if (la.kind == 40) {
Get();
Expect(39);
isIndPredicate = true;
CheckDeclModifiers(dmod, "Inductive predicates",
AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static | AllowedDeclModifiers.Protected);
while (la.kind == 46) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 50 || la.kind == 52) {
if (la.kind == 52) {
GenericParameters(typeArgs);
}
Formals(true, isFunctionMethod, formals);
if (la.kind == 21) {
Get();
SemErr(t, "inductive predicates do not have an explicitly declared return type; it is always bool");
}
} else if (la.kind == 59) {
Get();
signatureEllipsis = t;
} else SynErr(159);
} else if (la.kind == 42) {
Get();
isCoPredicate = true;
CheckDeclModifiers(dmod, "Copredicates",
AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static | AllowedDeclModifiers.Protected);
while (la.kind == 46) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 50 || la.kind == 52) {
if (la.kind == 52) {
GenericParameters(typeArgs);
}
Formals(true, isFunctionMethod, formals);
if (la.kind == 21) {
Get();
SemErr(t, "copredicates do not have an explicitly declared return type; it is always bool");
}
} else if (la.kind == 59) {
Get();
signatureEllipsis = t;
} else SynErr(160);
} else SynErr(161);
decreases = isIndPredicate || isCoPredicate ? null : new List();
while (StartOf(11)) {
FunctionSpec(reqs, reads, ens, decreases);
}
if (la.kind == 46) {
FunctionBody(out body, out bodyStart, out bodyEnd);
}
if (!isWithinAbstractModule && DafnyOptions.O.DisallowSoundnessCheating && body == null && ens.Count > 0 &&
!Attributes.Contains(attrs, "axiom") && !Attributes.Contains(attrs, "imported")) {
SemErr(t, "a function with an ensures clause must have a body, unless given the :axiom attribute");
}
EncodeExternAsAttribute(dmod, ref attrs, id, /* needAxiom */ true);
IToken tok = theVerifyThisFile ? id : new IncludeToken(id);
if (isPredicate) {
f = new Predicate(tok, id.val, dmod.IsStatic, dmod.IsProtected, !isFunctionMethod, typeArgs, formals,
reqs, reads, ens, new Specification(decreases, null), body, Predicate.BodyOriginKind.OriginalOrInherited, attrs, signatureEllipsis);
} else if (isIndPredicate) {
f = new InductivePredicate(tok, id.val, dmod.IsStatic, dmod.IsProtected, typeArgs, formals,
reqs, reads, ens, body, attrs, signatureEllipsis);
} else if (isCoPredicate) {
f = new CoPredicate(tok, id.val, dmod.IsStatic, dmod.IsProtected, typeArgs, formals,
reqs, reads, ens, body, attrs, signatureEllipsis);
} else {
f = new Function(tok, id.val, dmod.IsStatic, dmod.IsProtected, !isFunctionMethod, typeArgs, formals, returnType,
reqs, reads, ens, new Specification(decreases, null), body, attrs, signatureEllipsis);
}
f.BodyStartTok = bodyStart;
f.BodyEndTok = bodyEnd;
theBuiltIns.CreateArrowTypeDecl(formals.Count);
if (isIndPredicate || isCoPredicate) {
// also create an arrow type for the corresponding prefix predicate
theBuiltIns.CreateArrowTypeDecl(formals.Count + 1);
}
}
void MethodDecl(DeclModifierData dmod, bool allowConstructor, bool isWithinAbstractModule, 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();
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 isLemma = false;
bool isConstructor = false;
bool isIndLemma = false;
bool isCoLemma = false;
IToken signatureEllipsis = null;
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
AllowedDeclModifiers allowed = AllowedDeclModifiers.None;
string caption = "";
while (!(StartOf(12))) {SynErr(162); Get();}
switch (la.kind) {
case 87: {
Get();
caption = "Methods";
allowed = AllowedDeclModifiers.Ghost | AllowedDeclModifiers.Static
| AllowedDeclModifiers.Extern;
break;
}
case 41: {
Get();
isLemma = true; caption = "Lemmas";
allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static
| AllowedDeclModifiers.Protected;
break;
}
case 88: {
Get();
isCoLemma = true; caption = "Colemmas";
allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static
| AllowedDeclModifiers.Protected;
break;
}
case 89: {
Get();
isCoLemma = true; caption = "Comethods";
allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static
| AllowedDeclModifiers.Protected;
errors.Warning(t, "the 'comethod' keyword has been deprecated; it has been renamed to 'colemma'");
break;
}
case 40: {
Get();
Expect(41);
isIndLemma = true; caption = "Inductive lemmas";
allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static;
break;
}
case 90: {
Get();
if (allowConstructor) {
isConstructor = true;
} else {
SemErr(t, "constructors are allowed only in classes");
}
caption = "Constructors";
allowed = AllowedDeclModifiers.None;
break;
}
default: SynErr(163); break;
}
keywordToken = t;
CheckDeclModifiers(dmod, caption, allowed);
while (la.kind == 46) {
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)");
}
}
EncodeExternAsAttribute(dmod, ref attrs, id, /* needAxiom */ true);
if (la.kind == 50 || la.kind == 52) {
if (la.kind == 52) {
GenericParameters(typeArgs);
}
Formals(true, !dmod.IsGhost, ins);
if (la.kind == 86) {
Get();
if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); }
Formals(false, !dmod.IsGhost, outs);
}
} else if (la.kind == 59) {
Get();
signatureEllipsis = t;
} else SynErr(164);
while (StartOf(13)) {
MethodSpec(req, mod, ens, dec, ref decAttrs, ref modAttrs);
}
if (la.kind == 46) {
BlockStmt(out body, out bodyStart, out bodyEnd);
}
if (!isWithinAbstractModule && DafnyOptions.O.DisallowSoundnessCheating && body == null && ens.Count > 0 && !Attributes.Contains(attrs, "axiom") && !Attributes.Contains(attrs, "imported") && !Attributes.Contains(attrs, "decl") && theVerifyThisFile) {
SemErr(t, "a method with an ensures clause must have a body, unless given the :axiom attribute");
}
IToken tok = theVerifyThisFile ? id : new IncludeToken(id);
if (isConstructor) {
m = new Constructor(tok, hasName ? id.val : "_ctor", typeArgs, ins,
req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis);
} else if (isIndLemma) {
m = new InductiveLemma(tok, id.val, dmod.IsStatic, typeArgs, ins, outs,
req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis);
} else if (isCoLemma) {
m = new CoLemma(tok, id.val, dmod.IsStatic, typeArgs, ins, outs,
req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis);
} else if (isLemma) {
m = new Lemma(tok, id.val, dmod.IsStatic, typeArgs, ins, outs,
req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis);
} else {
m = new Method(tok, id.val, dmod.IsStatic, dmod.IsGhost, typeArgs, ins, outs,
req, new Specification(mod, modAttrs), ens, new Specification(dec, decAttrs), body, attrs, signatureEllipsis);
}
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 == 46) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (la.kind == 50) {
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(50);
if (StartOf(14)) {
TypeIdentOptional(out id, out name, out ty, out isGhost);
formals.Add(new Formal(id, name, ty, true, isGhost));
while (la.kind == 22) {
Get();
TypeIdentOptional(out id, out name, out ty, out isGhost);
formals.Add(new Formal(id, name, ty, true, isGhost));
}
}
Expect(51);
}
void FIdentType(out IToken/*!*/ id, out Type/*!*/ ty) {
Contract.Ensures(Contract.ValueAtReturn(out id) != null); Contract.Ensures(Contract.ValueAtReturn(out ty) != null);
id = Token.NoToken;
if (la.kind == 1) {
WildIdent(out id, false);
} else if (la.kind == 2) {
Get();
id = t;
} else SynErr(165);
Expect(21);
Type(out ty);
}
void OldSemi() {
if (la.kind == 28) {
while (!(la.kind == 0 || la.kind == 28)) {SynErr(166); Get();}
Get();
}
}
void Expression(out Expression e, bool allowSemi, bool allowLambda) {
Expression e0; IToken endTok;
EquivExpression(out e, allowSemi, allowLambda);
if (SemiFollowsCall(allowSemi, e)) {
Expect(28);
endTok = t;
Expression(out e0, allowSemi, allowLambda);
e = new StmtExpr(e.tok,
new UpdateStmt(e.tok, endTok, new List(), new List() { new ExprRhs(e, null) }),
e0);
}
}
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 == 62) {
Get();
if (allowGhostKeyword) { isGhost = true; } else { SemErr(t, "formal cannot be declared 'ghost' in this context"); }
}
IdentType(out id, out ty, true);
}
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(21);
Type(out ty);
}
void WildIdent(out IToken x, bool allowWildcardId) {
Contract.Ensures(Contract.ValueAtReturn(out x) != null);
Expect(1);
x = t;
t.val = UnwildIdent(t.val, allowWildcardId);
}
void LocalIdentTypeOptional(out LocalVariable var, bool isGhost) {
IToken id; Type ty; Type optType = null;
WildIdent(out id, true);
if (la.kind == 21) {
Get();
Type(out ty);
optType = ty;
}
var = new LocalVariable(id, 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 == 21) {
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; id = Token.NoToken; ty = new BoolType()/*dummy*/; isGhost = false;
if (la.kind == 62) {
Get();
isGhost = true;
}
if (StartOf(5)) {
TypeAndToken(out id, out ty);
if (la.kind == 21) {
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);
}
} else if (la.kind == 2) {
Get();
id = t; name = id.val;
Expect(21);
Type(out ty);
} else SynErr(167);
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; List tupleArgTypes = null;
switch (la.kind) {
case 6: {
Get();
tok = t;
break;
}
case 7: {
Get();
tok = t; ty = new CharType();
break;
}
case 9: {
Get();
tok = t; ty = new NatType();
break;
}
case 8: {
Get();
tok = t; ty = new IntType();
break;
}
case 10: {
Get();
tok = t; ty = new RealType();
break;
}
case 11: {
Get();
tok = t; ty = new ObjectType();
break;
}
case 13: {
Get();
tok = t; gt = new List();
if (la.kind == 52) {
GenericInstantiation(gt);
}
if (gt.Count > 1) {
SemErr("set type expects only one type argument");
}
ty = new SetType(true, gt.Count == 1 ? gt[0] : null);
break;
}
case 14: {
Get();
tok = t; gt = new List();
if (la.kind == 52) {
GenericInstantiation(gt);
}
if (gt.Count > 1) {
SemErr("set type expects only one type argument");
}
ty = new SetType(false, gt.Count == 1 ? gt[0] : null);
break;
}
case 15: {
Get();
tok = t; gt = new List();
if (la.kind == 52) {
GenericInstantiation(gt);
}
if (gt.Count > 1) {
SemErr("multiset type expects only one type argument");
}
ty = new MultiSetType(gt.Count == 1 ? gt[0] : null);
break;
}
case 16: {
Get();
tok = t; gt = new List();
if (la.kind == 52) {
GenericInstantiation(gt);
}
if (gt.Count > 1) {
SemErr("seq type expects only one type argument");
}
ty = new SeqType(gt.Count == 1 ? gt[0] : null);
break;
}
case 12: {
Get();
tok = t; ty = new UserDefinedType(tok, tok.val, null);
break;
}
case 17: {
Get();
tok = t; gt = new List();
if (la.kind == 52) {
GenericInstantiation(gt);
}
if (gt.Count == 0) {
ty = new MapType(true, null, null);
} else if (gt.Count != 2) {
SemErr("map type expects two type arguments");
ty = new MapType(true, gt[0], gt.Count == 1 ? new InferredTypeProxy() : gt[1]);
} else {
ty = new MapType(true, gt[0], gt[1]);
}
break;
}
case 18: {
Get();
tok = t; gt = new List();
if (la.kind == 52) {
GenericInstantiation(gt);
}
if (gt.Count == 0) {
ty = new MapType(false, null, null);
} else if (gt.Count != 2) {
SemErr("imap type expects two type arguments");
ty = new MapType(false, gt[0], gt.Count == 1 ? new InferredTypeProxy() : gt[1]);
} else {
ty = new MapType(false, gt[0], gt[1]);
}
break;
}
case 5: {
Get();
tok = t; gt = null;
if (la.kind == 52) {
gt = new List();
GenericInstantiation(gt);
}
int dims = tok.val.Length == 5 ? 1 : int.Parse(tok.val.Substring(5));
ty = theBuiltIns.ArrayType(tok, dims, gt, true);
break;
}
case 50: {
Get();
tok = t; tupleArgTypes = new List();
if (StartOf(5)) {
Type(out ty);
tupleArgTypes.Add(ty);
while (la.kind == 22) {
Get();
Type(out ty);
tupleArgTypes.Add(ty);
}
}
Expect(51);
if (tupleArgTypes.Count == 1) {
// just return the type 'ty'
} else {
var dims = tupleArgTypes.Count;
var tmp = theBuiltIns.TupleType(tok, dims, true); // make sure the tuple type exists
ty = new UserDefinedType(tok, BuiltIns.TupleTypeName(dims), dims == 0 ? null : tupleArgTypes);
}
break;
}
case 1: {
Expression e; tok = t;
NameSegmentForTypeName(out e);
tok = t;
while (la.kind == 27) {
Get();
Expect(1);
tok = t; List typeArgs = null;
if (la.kind == 52) {
typeArgs = new List();
GenericInstantiation(typeArgs);
}
e = new ExprDotName(tok, e, tok.val, typeArgs);
}
ty = new UserDefinedType(e.tok, e);
break;
}
default: SynErr(168); break;
}
if (la.kind == 30) {
Type t2;
Get();
tok = t;
Type(out t2);
if (tupleArgTypes != null) {
gt = tupleArgTypes;
} else {
gt = new List{ ty };
}
ty = new ArrowType(tok, gt, t2);
theBuiltIns.CreateArrowTypeDecl(gt.Count);
}
}
void Formals(bool incoming, bool allowGhostKeyword, List formals) {
Contract.Requires(cce.NonNullElements(formals)); IToken id; Type ty; bool isGhost;
Expect(50);
if (la.kind == 1 || la.kind == 62) {
GIdentType(allowGhostKeyword, out id, out ty, out isGhost);
formals.Add(new Formal(id, id.val, ty, incoming, isGhost));
while (la.kind == 22) {
Get();
GIdentType(allowGhostKeyword, out id, out ty, out isGhost);
formals.Add(new Formal(id, id.val, ty, incoming, isGhost));
}
}
Expect(51);
}
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(15))) {SynErr(169); Get();}
if (la.kind == 44) {
Get();
while (IsAttribute()) {
Attribute(ref readsAttrs);
}
FrameExpression(out fe, false, false);
reads.Add(fe);
while (la.kind == 22) {
Get();
FrameExpression(out fe, false, false);
reads.Add(fe);
}
OldSemi();
} else if (la.kind == 43) {
Get();
while (IsAttribute()) {
Attribute(ref modAttrs);
}
FrameExpression(out fe, false, false);
mod.Add(fe);
while (la.kind == 22) {
Get();
FrameExpression(out fe, false, false);
mod.Add(fe);
}
OldSemi();
} else if (StartOf(16)) {
if (la.kind == 91) {
Get();
isFree = true;
errors.Warning(t, "the 'free' keyword is soon to be deprecated");
}
if (la.kind == 93) {
Get();
isYield = true;
}
if (la.kind == 45) {
Get();
Expression(out e, false, false);
OldSemi();
if (isYield) {
yieldReq.Add(new MaybeFreeExpression(e, isFree));
} else {
req.Add(new MaybeFreeExpression(e, isFree));
}
} else if (la.kind == 92) {
Get();
while (IsAttribute()) {
Attribute(ref ensAttrs);
}
Expression(out e, false, false);
OldSemi();
if (isYield) {
yieldEns.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
} else {
ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
}
} else SynErr(170);
} else if (la.kind == 36) {
Get();
while (IsAttribute()) {
Attribute(ref decrAttrs);
}
DecreasesList(decreases, false, false);
OldSemi();
} else SynErr(171);
}
void BlockStmt(out BlockStmt/*!*/ block, out IToken bodyStart, out IToken bodyEnd) {
Contract.Ensures(Contract.ValueAtReturn(out block) != null);
List body = new List();
Expect(46);
bodyStart = t;
while (StartOf(17)) {
Stmt(body);
}
Expect(47);
bodyEnd = t;
block = new BlockStmt(bodyStart, bodyEnd, 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(18))) {SynErr(172); Get();}
if (la.kind == 43) {
Get();
while (IsAttribute()) {
Attribute(ref modAttrs);
}
FrameExpression(out fe, false, false);
mod.Add(fe);
while (la.kind == 22) {
Get();
FrameExpression(out fe, false, false);
mod.Add(fe);
}
OldSemi();
} else if (la.kind == 45 || la.kind == 91 || la.kind == 92) {
if (la.kind == 91) {
Get();
isFree = true;
errors.Warning(t, "the 'free' keyword is soon to be deprecated");
}
if (la.kind == 45) {
Get();
Expression(out e, false, false);
OldSemi();
req.Add(new MaybeFreeExpression(e, isFree));
} else if (la.kind == 92) {
Get();
while (IsAttribute()) {
Attribute(ref ensAttrs);
}
Expression(out e, false, false);
OldSemi();
ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
} else SynErr(173);
} else if (la.kind == 36) {
Get();
while (IsAttribute()) {
Attribute(ref decAttrs);
}
DecreasesList(decreases, true, false);
OldSemi();
} else SynErr(174);
}
void FrameExpression(out FrameExpression fe, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out fe) != null);
Expression/*!*/ e;
IToken/*!*/ id;
string fieldName = null; IToken feTok = null;
fe = null;
if (StartOf(9)) {
Expression(out e, allowSemi, allowLambda);
feTok = e.tok;
if (la.kind == 94) {
Get();
Ident(out id);
fieldName = id.val; feTok = id;
}
fe = new FrameExpression(feTok, e, fieldName);
} else if (la.kind == 94) {
Get();
Ident(out id);
fieldName = id.val;
fe = new FrameExpression(id, new ImplicitThisExpr(id), fieldName);
} else SynErr(175);
}
void DecreasesList(List decreases, bool allowWildcard, bool allowLambda) {
Expression e;
PossiblyWildExpression(out e, allowLambda);
if (!allowWildcard && e is WildcardExpr) {
SemErr(e.tok, "'decreases *' is allowed only on loops and tail-recursive methods");
} else {
decreases.Add(e);
}
while (la.kind == 22) {
Get();
PossiblyWildExpression(out e, allowLambda);
if (!allowWildcard && e is WildcardExpr) {
SemErr(e.tok, "'decreases *' is allowed only on loops and tail-recursive methods");
} else {
decreases.Add(e);
}
}
}
void GenericInstantiation(List/*!*/ gt) {
Contract.Requires(cce.NonNullElements(gt)); Type/*!*/ ty;
Expect(52);
Type(out ty);
gt.Add(ty);
while (la.kind == 22) {
Get();
Type(out ty);
gt.Add(ty);
}
Expect(53);
}
void NameSegmentForTypeName(out Expression e) {
IToken id;
List typeArgs = null;
Ident(out id);
if (la.kind == 52) {
typeArgs = new List();
GenericInstantiation(typeArgs);
}
e = new NameSegment(id, id.val, typeArgs);
}
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;
while (!(StartOf(19))) {SynErr(176); Get();}
if (la.kind == 45) {
Get();
Expression(out e, false, false);
OldSemi();
reqs.Add(e);
} else if (la.kind == 44) {
Get();
PossiblyWildFrameExpression(out fe, false);
reads.Add(fe);
while (la.kind == 22) {
Get();
PossiblyWildFrameExpression(out fe, false);
reads.Add(fe);
}
OldSemi();
} else if (la.kind == 92) {
Get();
Expression(out e, false, false);
OldSemi();
ens.Add(e);
} else if (la.kind == 36) {
Get();
if (decreases == null) {
SemErr(t, "'decreases' clauses are meaningless for copredicates, so they are not allowed");
decreases = new List();
}
DecreasesList(decreases, false, false);
OldSemi();
} else SynErr(177);
}
void FunctionBody(out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd) {
Contract.Ensures(Contract.ValueAtReturn(out e) != null); e = dummyExpr;
Expect(46);
bodyStart = t;
Expression(out e, true, true);
Expect(47);
bodyEnd = t;
}
void PossiblyWildFrameExpression(out FrameExpression fe, bool allowSemi) {
Contract.Ensures(Contract.ValueAtReturn(out fe) != null); fe = dummyFrameExpr;
if (la.kind == 57) {
Get();
fe = new FrameExpression(t, new WildcardExpr(t), null);
} else if (StartOf(20)) {
FrameExpression(out fe, allowSemi, false);
} else SynErr(178);
}
void PossiblyWildExpression(out Expression e, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out e)!=null);
e = dummyExpr;
if (la.kind == 57) {
Get();
e = new WildcardExpr(t);
} else if (StartOf(9)) {
Expression(out e, false, allowLambda);
} else SynErr(179);
}
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(21))) {SynErr(180); Get();}
switch (la.kind) {
case 46: {
BlockStmt(out bs, out bodyStart, out bodyEnd);
s = bs;
break;
}
case 104: {
AssertStmt(out s);
break;
}
case 31: {
AssumeStmt(out s);
break;
}
case 105: {
PrintStmt(out s);
break;
}
case 1: case 2: case 3: case 4: case 8: case 10: case 19: case 20: case 23: case 50: case 133: case 134: case 135: case 136: case 137: case 138: {
UpdateStmt(out s);
break;
}
case 62: case 81: {
VarDeclStatement(out s);
break;
}
case 101: {
IfStmt(out s);
break;
}
case 102: {
WhileStmt(out s);
break;
}
case 103: {
MatchStmt(out s);
break;
}
case 106: case 107: {
ForallStmt(out s);
break;
}
case 32: {
CalcStmt(out s);
break;
}
case 108: {
ModifyStmt(out s);
break;
}
case 95: {
Get();
x = t;
NoUSIdent(out id);
Expect(21);
OneStmt(out s);
s.Labels = new LList