	/*-----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation.  All Rights Reserved.
//
//-----------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
// Dafny
// Rustan Leino, first created 25 January 2008
//--------------------------------------------------------------------------*/
using System.Collections.Generic;
using System.Numerics;
using Microsoft.Boogie;
using System.IO;
using System.Text;
COMPILER Dafny
/*--------------------------------------------------------------------------*/
readonly Expression/*!*/ dummyExpr;
readonly AssignmentRhs/*!*/ dummyRhs;
readonly FrameExpression/*!*/ dummyFrameExpr;  
readonly Statement/*!*/ dummyStmt;
readonly Statement/*!*/ dummyIfStmt;
readonly Include theInclude;
readonly ModuleDecl theModule;
readonly BuiltIns theBuiltIns;
readonly bool theVerifyThisFile;
int anonymousIds = 0;

/// <summary>
/// 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.
/// </summary>
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;
}

// 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;
}

/// <summary>
// A flags type used to tell what declaration modifiers are allowed for a declaration.
/// </summary>
[Flags]
enum AllowedDeclModifiers {
  None = 0,
  Abstract = 1,
  Ghost = 2,

  // Means ghost not allowed because already implicitly ghost.
  AlreadyGhost = 4,
  Static = 8,
  Protected = 16, 
};

/// <summary>
/// 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.
///</summary>
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;
  }
}

///<summary>
/// 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.
///</summary>
public static int Parse (string/*!*/ filename, Include include, 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<string>());
    return Parse(s, filename, filename, include, module, builtIns, errors, verifyThisFile);
  } else {
    using (System.IO.StreamReader reader = new System.IO.StreamReader(filename)) {
      s = Microsoft.Boogie.ParserHelper.Fill(reader, new List<string>());
      return Parse(s, filename, DafnyOptions.Clo.UseBaseNameForFileName ? Path.GetFileName(filename) : filename, include, module, builtIns, errors, verifyThisFile);
    }
  }
}
///<summary>
/// 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.
///</summary>
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, null, module, builtIns, errors, verifyThisFile);
}

public static Parser SetupParser(string/*!*/ s, string/*!*/ fullFilename, string/*!*/ filename, Include include, 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);
  return new Parser(scanner, errors, include, module, builtIns, verifyThisFile);
}

public static Expression ParseExpression(string/*!*/ s, string/*!*/ fullFilename, string/*!*/ filename, Include include, ModuleDecl module,
                                         BuiltIns builtIns, Errors/*!*/ errors, bool verifyThisFile=true) {
  Parser parser = SetupParser(s, fullFilename, filename, include, module, builtIns, errors, verifyThisFile);
  parser.la = new Token();
  parser.la.val = "";
  parser.Get();
  Expression e;
  parser.Expression(out e, true, true, true);
  return e;
}

///<summary>
/// 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.
///</summary>
public static int Parse (string/*!*/ s, string/*!*/ fullFilename, string/*!*/ filename, Include include, ModuleDecl module,
                         BuiltIns builtIns, Errors/*!*/ errors, bool verifyThisFile=true) {
  Parser parser = SetupParser(s, fullFilename, filename, include, module, builtIns, errors, verifyThisFile);
  parser.Parse();
  return parser.errors.ErrorCount;
}

public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors, Include include, 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);
  var dummyBlockStmt = new BlockStmt(Token.NoToken, Token.NoToken, new List<Statement>());
  dummyIfStmt = new IfStmt(Token.NoToken, Token.NoToken, false, null, dummyBlockStmt, null);
  theInclude = include; // the "include" that includes this file
  theModule = module;
  theBuiltIns = builtIns;
  theVerifyThisFile = verifyThisFile;
}

bool IsAttribute() {
  IToken x = scanner.Peek();
  return la.kind == _lbrace && x.kind == _colon;
}

bool IsLabel(bool allowLabel) {
  if (!allowLabel) {
    return false;
  }
  scanner.ResetPeek();
  IToken x = scanner.Peek();
  return (la.kind == _ident || la.kind == _digits) && x.kind == _colon;
}

bool IsAlternative() {
  IToken x = scanner.Peek();
  return (la.kind == _lbrace && x.kind == _case)
      || la.kind == _case;
}

bool FollowedByColon() {
  IToken x = la;
  while (x.kind == _ident || x.kind == _openparen)
     x = scanner.Peek();
  return x.kind == _colon;
}

bool IsGets() {
  return la.kind == _gets;
}

// 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 IsWitness() {
  scanner.ResetPeek();
  if (la.kind == _witness) {
    return true;
  } else if (la.kind == _ghost) {
    Token x = scanner.Peek();
    return x.kind == _witness;
  }
  return false;
}

bool IsFunctionDecl() {
  switch (la.kind) {
    case _function:
    case _predicate:
    case _copredicate:
      return true;
    case _inductive:
      return scanner.Peek().kind != _lemma;
    case _twostate:
      var x = scanner.Peek();
      return x.kind == _function || x.kind == _predicate;
    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 IsBitwiseAndOp() {
  return la.val == "&";
}
bool IsBitwiseOrOp() {
  return la.val == "|";
}
bool IsBitwiseXorOp() {
  return la.val == "^";
}
bool IsBitwiseOp() {
  return IsBitwiseAndOp() || IsBitwiseOrOp() || IsBitwiseXorOp();
}
bool IsAs() {
  return la.kind == _as;
}
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 IsShiftOp() {
  if (la.kind == _openAngleBracket) {
  } else if (la.kind == _closeAngleBracket) {
  } else {
    return false;
  }
  scanner.ResetPeek();
  var x = scanner.Peek();
  if (x.kind != la.kind) {
    return false;
  }
  return x.pos == la.pos + 1;  // return true only if the tokens are adjacent to each other
}
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() {
  scanner.ResetPeek();
  return la.kind == _map && scanner.Peek().kind == _lbracket;
}
bool IsIMapDisplay() {
  scanner.ResetPeek();
  return la.kind == _imap && scanner.Peek().kind == _lbracket;
}
bool IsISetDisplay() {
  scanner.ResetPeek();
  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 == _reads || x.kind == _requires;
}

bool IsIdentParen() {
  scanner.ResetPeek();
  Token x = scanner.Peek();
  return la.kind == _ident && x.kind == _openparen;
}

/* Used to disambiguate the LHS of a VarDeclStmt. If it looks like the start of a CasePattern,
 * we consider it to be a LetStmt. But if we are looking at a simple identifier, then we
 * consider it to be a VarDeclStmt.
 */
bool IsLetStmt() {
  return IsIdentParen() || la.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 || (e is RevealExpr && (((RevealExpr)e).Expr is ApplySuffix)));
}

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(bool inExpressionContext) {
  scanner.ResetPeek();
  if (!inExpressionContext) {
    return la.kind == _openAngleBracket;
  }
  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 "<b,c>" 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<b,c>" 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 _comma:
    case _semi:
    case _then:
    case _else:
    case _case:
    case _eq:
    case _neq:
    case _neqAlt:
    case _as:
    case _by:
    case _in:
    case _openAngleBracket:
    case _closeAngleBracket:
    case _EOF:
    // (specification clauses that can follow an expression)
    case _decreases:
    case _modifies:
    case _reads:
    case _requires:
    case _ensures:
    case _invariant:
    case _witness:
    // (top-level declarations that can follow an expression)
    case _function:
    case _predicate:
    case _inductive:
    case _twostate:
    case _lemma:
    case _copredicate:
    case _ghost:
    case _static:
    case _protected:
    case _import:
    case _export:
    case _class:
    case _trait:
    case _datatype:
    case _codatatype:
    case _var:
    case _const:
    case _newtype:
    case _type:
    case _iterator:
    case _method:
    case _colemma:
    case _constructor:
      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 _ORDINAL:
    case _string:
    case _object_q:
    case _object:
      pt = scanner.Peek();
      return true;
    case _arrayToken:
    case _arrayToken_q:
    case _bvToken:
    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;
  }
}


void ConvertKeywordTokenToIdent() {
  var oldKind = la.kind;
  la.kind = _ident;

  // call CheckLiteral with la
  var origT = t;
  t = la;
  scanner.CheckLiteral();
  t = origT;

  if (la.kind != _ident) {
    // it has been changed by CheckLiteral, which means it was a keyword
    la.kind = _ident;  // convert it to an ident
  } else {
    // la was something other than a keyword
    la.kind = oldKind;
  }
}

int StringToInt(string s, int defaultValue, string errString) {
  Contract.Requires(s != null);
  Contract.Requires(errString != null);
  try {
    if (s != "") {
      defaultValue = int.Parse(s);
    }
  } catch (System.OverflowException) {
    SemErr(string.Format("sorry, {0} ({1}) are not supported", errString, s));
  }
  return defaultValue;
}

/*--------------------------------------------------------------------------*/
CHARACTERS
  letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
  digit = "0123456789".
  posDigit = "123456789".
  hexdigit = "0123456789ABCDEFabcdef".
  special = "'_?".
  glyph = "`~!@#$%^&*()-_=+[{]}|;:',<.>/?\\".
  cr        = '\r'.
  lf        = '\n'.
  tab       = '\t'.
  space = ' '.
  nondigit = letter + special.
  idchar = nondigit + digit.
  nonidchar = ANY - idchar.
  /* exclude the characters in 'array' and '\'' */
  nondigitMinusABTick = nondigit - 'a' - 'b' - '\''.
  nondigitMinusQuery = nondigit - '?'.
  idcharMinusA = idchar - 'a'.
  idcharMinusR = idchar - 'r'.
  idcharMinusY = idchar - 'y'.
  idcharMinusV = idchar - 'v'.
  idcharMinusPosDigitMinusQuery = idchar - posDigit - '?'.
  idcharMinusTick = idchar - '\''.
  /* string literals */
  charChar = ANY - '\'' - '\\' - cr - lf.
  stringChar = ANY - '"' - '\\' - cr - lf.
  verbatimStringChar = ANY - '"'.

/*------------------------------------------------------------------------*/
TOKENS
  ident =  nondigitMinusABTick {idchar}       /* if char 0 is not an 'a' or '\'', then anything else is fine */
        |  'a' [ idcharMinusR {idchar} ]      /* if char 0 is an 'a', then either there is no char 1 or char 1 is not an 'r' */
        |  'a' 'r' [ idcharMinusR {idchar} ]  /* etc. */
        |  'a' 'r' 'r' [ idcharMinusA {idchar} ]
        |  'a' 'r' 'r' 'a' [ idcharMinusY {idchar} ]
        |  'a' 'r' 'r' 'a' 'y' idcharMinusPosDigitMinusQuery {idchar}
        |  'a' 'r' 'r' 'a' 'y' '?' idchar {idchar}
        |  'a' 'r' 'r' 'a' 'y' posDigit {digit} nondigitMinusQuery {idchar}
        |  'a' 'r' 'r' 'a' 'y' posDigit {digit} '?' idchar {idchar}
        |  'b' [ idcharMinusV {idchar} ]
        |  'b' 'v' [ nondigit {idchar} ]
        |  'b' 'v' '0' idchar {idchar}
        |  'b' 'v' posDigit {idchar} nondigit {idchar}
        |  "'" [ idchar ]                        /* if char 0 is a '\'' and length is 1 or 2, then it is an identifier */
        |  "'" idchar idcharMinusTick            /* if char 0 is '\'' and length is 3, then it is an identifier provided char 2 is not '\'' */
        |  "'" idchar idchar idchar { idchar }   /* if char 0 is '\'' and length exceeds 3, then it is an identifier */
        .
  digits = digit {['_'] digit}.
  hexdigits = "0x" hexdigit {['_'] hexdigit}.
  decimaldigits = digit {['_'] digit} '.' digit {['_'] digit}.
  arrayToken = "array" [posDigit {digit}].
  arrayToken_q = "array" [posDigit {digit}] '?'.
  bvToken = "bv" ( '0' | posDigit {digit} ).
  bool = "bool".
  char = "char".
  int = "int".
  nat = "nat".
  real = "real".
  ORDINAL = "ORDINAL".
  object = "object".
  object_q = "object?".
  string = "string".
  set = "set".
  iset = "iset".
  multiset = "multiset".
  seq = "seq".
  map = "map".
  imap = "imap".
  charToken =
      "'"
      ( charChar
        | "\\\'" | "\\\"" | "\\\\" | "\\0" | "\\n" | "\\r" | "\\t"
        | "\\u" hexdigit hexdigit hexdigit hexdigit
      )
      "'".
  stringToken =
      '"'
      { stringChar
        | "\\\'" | "\\\"" | "\\\\" | "\\0" | "\\n" | "\\r" | "\\t"
        | "\\u" hexdigit hexdigit hexdigit hexdigit
      }
      '"'
    | '@' '"' { verbatimStringChar | "\"\"" } '"'.
  colon = ':'.
  comma = ','.
  verticalbar = '|'.
  doublecolon = "::".
  gets = ":=".
  boredSmiley = ":|".
  bullet = '\u2022'.
  dot = '.'.
  backtick = "`".
  semi = ';'.
  darrow = "=>".
  assume = "assume".
  calc = "calc".
  case = "case".
  then = "then".
  else = "else".
  as = "as".
  by = "by".
  in = "in".
  decreases = "decreases".
  invariant = "invariant".
  function = "function".
  predicate = "predicate".
  inductive = "inductive".
  twostate = "twostate".
  copredicate = "copredicate".
  lemma = "lemma".
  static = "static".
  protected = "protected".
  import = "import".
  export = "export".
  class = "class".
  trait = "trait".
  datatype = "datatype".
  codatatype = "codatatype".
  var = "var".
  const = "const".
  newtype = "newtype".
  type = "type".
  iterator = "iterator".
  method = "method".
  colemma = "colemma".
  constructor = "constructor".
  modifies = "modifies".
  reads = "reads".
  requires = "requires".
  ensures = "ensures".
  ghost = "ghost".
  witness = "witness".
  lbrace = '{'.
  rbrace = '}'.
  lbracket = '['.
  rbracket = ']'.
  openparen = '('.
  closeparen = ')'.
  openAngleBracket = '<'.
  closeAngleBracket = '>'.
  eq = "==".
  neq = "!=".
  neqAlt = '\u2260'.
  star = '*'.
  notIn = "!in" CONTEXT (nonidchar).
  ellipsis = "...".
  reveal = "reveal".
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
IGNORE cr + lf + tab
/*------------------------------------------------------------------------*/
PRODUCTIONS
Dafny
= (. List<MemberDecl/*!*/> membersDefaultClass = new List<MemberDecl/*!*/>();
     // 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);
  .)
  { "include" stringToken               (. {
                                             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, parsedFile, includedFile, fullPath));
                                           }
                                        .)
  }
  { TopDecl<defaultModule, membersDefaultClass, /* isTopLevel */ true, /* isAbstract */ false> }
  (. // find the default class in the default module, then append membersDefaultClass to its member list
     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);
     } .)
  EOF
  .

DeclModifier<ref DeclModifierData dmod>
= ( "abstract"                             (. dmod.IsAbstract = true;  CheckAndSetToken(ref dmod.AbstractToken); .)
  | "ghost"                                (. dmod.IsGhost = true;  CheckAndSetToken(ref dmod.GhostToken); .)
  | "static"                               (. dmod.IsStatic = true; CheckAndSetToken(ref dmod.StaticToken); .)
  | "protected"                            (. dmod.IsProtected = true; CheckAndSetToken(ref dmod.ProtectedToken); .)
  )
  .

TopDecl<. ModuleDefinition module, List<MemberDecl/*!*/> membersDefaultClass, bool isTopLevel, bool isAbstract .>
= (. DeclModifierData dmod = new DeclModifierData(); ModuleDecl submodule;
     ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; TopLevelDecl td; IteratorDecl iter;
     TraitDecl/*!*/ trait;
  .)
  { DeclModifier<ref dmod> }
  ( SubModuleDecl<dmod, module, out submodule> (. var litmod = submodule as LiteralModuleDecl;
                                                  if (litmod != null && litmod.ModuleDef.PrefixIds.Count != 0) {
                                                    var tup = new Tuple<List<IToken>, LiteralModuleDecl>(litmod.ModuleDef.PrefixIds, litmod);
                                                    module.PrefixNamedModules.Add(tup);
                                                  } else {
                                                    module.TopLevelDecls.Add(submodule);
                                                  } .)
  | ClassDecl<dmod, module, out c>             (. module.TopLevelDecls.Add(c); .)
  | DatatypeDecl<dmod, module, out dt>         (. module.TopLevelDecls.Add(dt); .)
  | NewtypeDecl<dmod, module, out td>          (. module.TopLevelDecls.Add(td); .)
  | OtherTypeDecl<dmod, module, out td>        (. module.TopLevelDecls.Add(td); .)
  | IteratorDecl<dmod, module, out iter>       (. module.TopLevelDecls.Add(iter); .)
  | TraitDecl<dmod, module, out trait>         (. module.TopLevelDecls.Add(trait); .)
  | ClassMemberDecl<dmod, membersDefaultClass, false, !DafnyOptions.O.AllowGlobals, 
                    !isTopLevel && DafnyOptions.O.IronDafny && isAbstract>
  ) .

SubModuleDecl<DeclModifierData dmod, ModuleDefinition parent, out ModuleDecl submodule>
= (. Attributes attrs = null;  IToken/*!*/ id; var prefixIds = new List<IToken>();
     List<MemberDecl/*!*/> namedModuleDefaultClassMembers = new List<MemberDecl>();;
     List<IToken> idPath, idExports;
     IToken idRefined = null;
     ModuleDefinition module;
     submodule = null; // appease compiler
     bool isAbstract = dmod.IsAbstract;
     bool isProtected = dmod.IsProtected;
     bool opened = false;
     CheckDeclModifiers(dmod, "Modules", AllowedDeclModifiers.Abstract | AllowedDeclModifiers.Protected);
  .)
  ( "module"
    { Attribute<ref attrs> }
    NoUSIdent<out id>
    { (. prefixIds.Add(id); .)
      "." NoUSIdent<out id>
    }
    [ "refines" ModuleName<out idRefined> ] 
    (. module = new ModuleDefinition(id, id.val, prefixIds, isAbstract, isProtected, false, idRefined, parent, attrs, false); module.IsToBeVerified = theVerifyThisFile; .)  
    "{"                                 (. module.BodyStartTok = t; .)
      { TopDecl<module, namedModuleDefaultClassMembers, /* isTopLevel */ false, isAbstract>}
    "}"                                 (. module.BodyEndTok = t;
                                           module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers));
                                           submodule = new LiteralModuleDecl(module, parent); .)
  |
    "import" ["opened" (.opened = true;.)]
    ModuleName<out id>
    ( (. idPath = new List<IToken>(); idExports = new List<IToken>(); .)
      [ QualifiedModuleExportSuffix<idPath, idExports> ]
      (. if (idPath.Count > 0)
           SemErr(idPath[0], "Qualified imports must be given a name.");
        idPath.Insert(0, id);
        submodule = new AliasModuleDecl(idPath, id, parent, opened, idExports); 
      .)
    | "=" QualifiedModuleExport<out idPath, out idExports>
      (. submodule = new AliasModuleDecl(idPath, id, parent, opened, idExports); .)
    | ":" QualifiedModuleExport<out idPath, out idExports>
        (. submodule = new ModuleFacadeDecl(idPath, id, parent, opened, idExports); .)

    )
    

    [ SYNC ";"
        // This semi-colon used to be required, but it seems silly to have it.
        // To stage the transition toward not having it at all, let's make it optional for now.  Then,
        // in the next big version of Dafny, don't allow the semi-colon at all.
        (. errors.Deprecated(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"); .)
    ]
  | (.      
      IToken exportId;
      List<ExportSignature> exports = new List<ExportSignature>();;
      List<string> extends = new List<string>();
      bool provideAll = false;
      bool revealAll = false;
      bool isDefault = false;
      ExportSignature exsig;
    .)
    "export" (. exportId = t; .)
    [ ModuleExport<out exportId> ]
    {
       "provides"
       ( 
         ( ModuleExportSignature<true, out exsig> 
           (. exports.Add(exsig); .)
           {"," ModuleExportSignature<true, out exsig>  (. exports.Add(exsig); .) }
         )
        | "*" (. provideAll = true; .)
       )
     | "reveals"
       ( 
         ( ModuleExportSignature<false, out exsig> 
           (. exports.Add(exsig); .)
           {"," ModuleExportSignature<false, out exsig>  (. exports.Add(exsig); .) }
         )
        | "*" (. revealAll = true; .)
       )
     | "extends" 
       ModuleExport<out id>(. extends.Add(id.val); .) 
       {"," ModuleExport<out id>  (. extends.Add(id.val); .) }
    }
    (.
       if (exportId.val == "export" || exportId.val == parent.Name) {
         isDefault = true;
       }
       submodule = new ModuleExportDecl(exportId, parent, exports, extends, provideAll, revealAll, isDefault);
    .)
  )
.

ModuleExportSignature<bool opaque, out ExportSignature exsig>
= (. IToken prefix; IToken suffix = null; .)
  NoUSIdent<out prefix> [ "." NoUSIdent<out suffix> ]
  (. if (suffix != null) {
       exsig = new ExportSignature(prefix, prefix.val, suffix, suffix.val, opaque);
     } else {
       exsig = new ExportSignature(prefix, prefix.val, opaque);
     }
  .)
  .
  

/* The only modules in any given scope are siblings, so we no longer need qualified lookups */
ModuleName<out IToken id>
= Ident<out id>
  .

/* For declaring or referring to module exports from the current module */
ModuleExport<out IToken id>
= (. IToken afterdot; .) 
  DotSuffix<out id, out afterdot> 
  (. if (afterdot != null)
       SemErr(afterdot, "Decimal export sets are not supported");
  .)
  .

/* This production is for referring to module exports for imports (both normal and facades) */
QualifiedModuleExportSuffix<.List<IToken> ids, List<IToken> exports.>
= (. IToken id; .)
  (
    "." ModuleName<out id> (. ids.Add(id); .)
    { "." ModuleName<out id> (. ids.Add(id); .) }
  | "`" ( ModuleExport<out id> (. exports.Add(id); .)
        | "{" ModuleExport<out id> (. exports.Add(id); .)
          { "," ModuleExport<out id> (. exports.Add(id); .) }
          "}"
        )
  )
  .

QualifiedModuleExport<.out List<IToken> ids, out List<IToken> exports.>
= (. IToken id; ids = new List<IToken>();
     List<IToken> sids = new List<IToken>(); exports = new List<IToken>();
  .)
  ModuleName<out id> (. ids.Add(id); .)
  [ QualifiedModuleExportSuffix<sids, exports> ]
  (. ids.AddRange(sids); .)
  .

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<Type>/*!*/ traits = new List<Type>();
   Attributes attrs = null;
     List<TypeParameter/*!*/> typeArgs = new List<TypeParameter/*!*/>();
     List<MemberDecl/*!*/> members = new List<MemberDecl/*!*/>();
     IToken bodyStart;
     CheckDeclModifiers(dmodClass, "Classes", AllowedDeclModifiers.None);
     DeclModifierData dmod; 
  .)
  SYNC
  "class"
  { Attribute<ref attrs> }
  NoUSIdent<out id>
  [ GenericParameters<typeArgs, true> ]
  ["extends" 
  Type<out trait>    (. traits.Add(trait); .) 
  {"," Type<out trait>  (. traits.Add(trait); .) }
  ]         
  "{"                                            (. bodyStart = t;  .)
  { (. dmod = new DeclModifierData(); .)
    { DeclModifier<ref dmod> }
    ClassMemberDecl<dmod, members, true, false, false>
  }
  "}"
  (. c = new ClassDecl(id, id.val, module, typeArgs, members, attrs, traits);
     c.BodyStartTok = bodyStart;
     c.BodyEndTok = t;
  .)
  .

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<TypeParameter/*!*/> typeArgs = new List<TypeParameter/*!*/>(); //traits should not support type parameters at the moment
     List<MemberDecl/*!*/> members = new List<MemberDecl/*!*/>();
     IToken bodyStart;
     DeclModifierData dmod; 
    .)
  SYNC
  "trait"
  { Attribute<ref attrs> }
  NoUSIdent<out id>
  [ GenericParameters<typeArgs, true> ]
    "{"                                            (. bodyStart = t; .)
      {                                            (. dmod  = new DeclModifierData(); .)
        { DeclModifier<ref dmod> }
        ClassMemberDecl<dmod, members, true, false, false>
      }
    "}"
  (. trait = new TraitDecl(id, id.val, module, typeArgs, members, attrs);
     trait.BodyStartTok = bodyStart;
     trait.BodyEndTok = t;
    .)
  .

ClassMemberDecl<. DeclModifierData dmod, List<MemberDecl> mm, bool allowConstructors, bool moduleLevelDecl, bool isWithinAbstractModule.>
= (. Contract.Requires(cce.NonNullElements(mm));
     Method/*!*/ m;
     Function/*!*/ f;
  .)
  ( (. 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>
  | ConstantFieldDecl<dmod, mm, moduleLevelDecl>
  | 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); .)
  | (. 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); .)
  )
  .
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<TypeParameter/*!*/> typeArgs = new List<TypeParameter/*!*/>();
     List<DatatypeCtor/*!*/> ctors = new List<DatatypeCtor/*!*/>();
     IToken bodyStart = Token.NoToken;  // dummy assignment
     bool co = false;
     CheckDeclModifiers(dmod, "Datatypes or codatatypes", AllowedDeclModifiers.None);
  .)
  SYNC
  ( "datatype"
  | "codatatype"     (. co = true; .)
  )
  { Attribute<ref attrs> }
  NoUSIdent<out id>
  [ GenericParameters<typeArgs, true> ]
  "="                                      (. bodyStart = t; .)
  [ "|" ] DatatypeMemberDecl<ctors>
  { "|" DatatypeMemberDecl<ctors> }
  [ SYNC ";"
      // This semi-colon used to be required, but it seems silly to have it.
      // To stage the transition toward not having it at all, let's make it optional for now.  Then,
      // in the next big version of Dafny, don't allow the semi-colon at all.
      (. errors.Deprecated(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;
  .)
  .
DatatypeMemberDecl<.List<DatatypeCtor/*!*/>/*!*/ ctors.>
= (. Contract.Requires(cce.NonNullElements(ctors));
     Attributes attrs = null;
     IToken/*!*/ id;
     List<Formal/*!*/> formals = new List<Formal/*!*/>();
  .)
  { Attribute<ref attrs> }
  NoUSIdent<out id>
  [ FormalsOptionalIds<formals> ]
  (. ctors.Add(new DatatypeCtor(id, id.val, formals, attrs)); .)
  .
FieldDecl<.DeclModifierData dmod, List<MemberDecl/*!*/>/*!*/ mm.>
= (. Contract.Requires(cce.NonNullElements(mm));
     Attributes attrs = null;
     IToken/*!*/ id;  Type/*!*/ ty;
     CheckDeclModifiers(dmod, "Fields", AllowedDeclModifiers.Ghost);
  .)
  SYNC
  "var"
  { Attribute<ref attrs> }
  FIdentType<out id, out ty>                        (. mm.Add(new Field(id, id.val, dmod.IsGhost, ty, attrs)); .)
  { "," FIdentType<out id, out ty>                  (. mm.Add(new Field(id, id.val, dmod.IsGhost, ty, attrs)); .)
  }
  OldSemi
  .
ConstantFieldDecl<.DeclModifierData dmod, List<MemberDecl/*!*/>/*!*/ mm, bool moduleLevelDecl.>
= (. Contract.Requires(cce.NonNullElements(mm));
     Attributes attrs = null;
     IToken/*!*/ id;  Type/*!*/ ty;
     Expression e = null;
     if (moduleLevelDecl && dmod.StaticToken != null) {
       errors.Warning(dmod.StaticToken, "module-level const declarations are always non-instance, so the 'static' keyword is not allowed here");
       dmod.IsStatic = false;
     }
     CheckDeclModifiers(dmod, "Fields", AllowedDeclModifiers.Ghost | AllowedDeclModifiers.Static);
  .)
  SYNC
  "const"
  { Attribute<ref attrs> }
  CIdentType<out id, out ty>                 (. if (ty == null) { ty = new InferredTypeProxy(); } .)
  [ ":=" Expression<out e, false, true> ]
                                             (. if (e == null && ty is InferredTypeProxy) {
                                                  SemErr(id, "a const declaration must have a type or a RHS value");
                                                }
                                                mm.Add(new ConstantField(id, id.val, e, dmod.IsStatic, dmod.IsGhost, ty, attrs)); 
                                             .)
  OldSemi
  .
NewtypeDecl<DeclModifierData dmod, ModuleDefinition module, out TopLevelDecl td>
= (. IToken id, bvId;
     Attributes attrs = null;
     td = null;
     Type baseType = null;
     Expression constraint;
     Expression witness = null;
     bool witnessIsGhost = false;
     CheckDeclModifiers(dmod, "Newtypes", AllowedDeclModifiers.None);
  .)
  "newtype"
  { Attribute<ref attrs> }
  NoUSIdent<out id>
  "="
  ( IF(IsIdentColonOrBar())
    NoUSIdent<out bvId>
    [ ":" Type<out baseType> ]       (. if (baseType == null) { baseType = new InferredTypeProxy(); } .)
    "|"
    Expression<out constraint, false, true>
    [ IF(IsWitness())
      [ "ghost"                      (. witnessIsGhost = true; .)
      ]
      "witness" Expression<out witness, false, true>
    ]
                                     (. var witnessKind = witness == null ? SubsetTypeDecl.WKind.None :
                                          witnessIsGhost ? SubsetTypeDecl.WKind.Ghost : SubsetTypeDecl.WKind.Compiled;
                                        td = new NewtypeDecl(id, id.val, module, new BoundVar(bvId, bvId.val, baseType), constraint, witnessKind, witness, attrs); .)
  | Type<out baseType>               (. td = new NewtypeDecl(id, id.val, module, baseType, attrs); .)
  )
  .
OtherTypeDecl<DeclModifierData dmod, ModuleDefinition module, out TopLevelDecl td>
= (. IToken id, bvId;
     Attributes attrs = null;
     var characteristics = new TypeParameter.TypeParameterCharacteristics(false);
     var typeArgs = new List<TypeParameter>();
     td = null;
     Type ty = null;
     Expression constraint;
     Expression witness = null;
     bool witnessIsGhost = false;
     var kind = "Opaque type";
  .)
  "type"
  { Attribute<ref attrs> }
  NoUSIdent<out id>
  { TypeParameterCharacteristics<ref characteristics> }
  [ GenericParameters<typeArgs, true> ]
  [ "="
    ( IF(IsIdentColonOrBar())
      NoUSIdent<out bvId>
      [ ":" Type<out ty> ]   (. if (ty == null) { ty = new InferredTypeProxy(); } .)
      "|"
      Expression<out constraint, false, true>
      [ IF(IsWitness())
        [ "ghost"            (. witnessIsGhost = true; .)
        ]
        "witness" Expression<out witness, false, true>
      ]
                             (. var witnessKind = witness == null ? SubsetTypeDecl.WKind.None :
                                  witnessIsGhost ? SubsetTypeDecl.WKind.Ghost : SubsetTypeDecl.WKind.Compiled;
                                td = new SubsetTypeDecl(id, id.val, characteristics, typeArgs, module, new BoundVar(bvId, bvId.val, ty), constraint, witnessKind, witness, attrs);
                                kind = "Subset type";
                             .)
    |
      Type<out ty>           (. td = new TypeSynonymDecl(id, id.val, characteristics, typeArgs, module, ty, attrs);
                                kind = "Type synonym";
                             .)
    )
  ]
                             (. if (td == null) {
                                  if (module is DefaultModuleDecl) {
                                    // opaque type declarations at the very outermost program scope get an automatic (!new)
                                    characteristics.DisallowReferenceTypes = true;
                                  }
                                  td = new OpaqueTypeDecl(id, id.val, module, characteristics, typeArgs, attrs);
                                }
                             .)
  (. CheckDeclModifiers(dmod, kind, AllowedDeclModifiers.None); .)
  [ SYNC ";"
      // This semi-colon used to be required, but it seems silly to have it.
      // To stage the transition toward not having it at all, let's make it optional for now.  Then,
      // in the next big version of Dafny, don't allow the semi-colon at all.
      (. errors.Deprecated(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"); .)
  ]
  .
GIdentType<bool allowGhostKeyword, bool allowNewKeyword, out IToken/*!*/ id, out Type/*!*/ ty, out bool isGhost, out bool isOld>
/* isGhost always returns as false if allowGhostKeyword is false */
= (. Contract.Ensures(Contract.ValueAtReturn(out id)!=null);
     Contract.Ensures(Contract.ValueAtReturn(out ty)!=null);
     isGhost = false; isOld = allowNewKeyword; .)
  { "ghost"                    (. if (allowGhostKeyword) { isGhost = true; } else { SemErr(t, "formal cannot be declared 'ghost' in this context"); } .)
  | "new"                      (. if (allowNewKeyword) { isOld = false; } else { SemErr(t, "formal cannot be declared 'new' in this context"); } .)
  }
  IdentType<out id, out ty, true>
  .
FIdentType<out IToken/*!*/ id, out Type/*!*/ ty>
= (.Contract.Ensures(Contract.ValueAtReturn(out id) != null); Contract.Ensures(Contract.ValueAtReturn(out ty) != null);
    id = Token.NoToken;
  .)
  ( WildIdent<out id, false>
  | digits         (. id = t; .)
  )
  ":"
  Type<out ty>
  .
CIdentType<out IToken/*!*/ id, out Type ty>
= (.Contract.Ensures(Contract.ValueAtReturn(out id) != null);
    id = Token.NoToken;
    ty = null;
  .)
  ( WildIdent<out id, false>
  | digits         (. id = t; .)
  )
  [ ":"
    Type<out ty>
  ]
  .
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>
  ":"
  Type<out ty>
  .
LocalIdentTypeOptional<out LocalVariable var, bool isGhost>
= (. IToken id;  Type ty;  Type optType = null;
  .)
  WildIdent<out id, true>
  [ ":" Type<out ty>             (. optType = ty; .)
  ]
  (. var = new LocalVariable(id, id, id.val, optType == null ? new InferredTypeProxy() : optType, isGhost); .)
  .
IdentTypeOptional<out BoundVar var>
= (. Contract.Ensures(Contract.ValueAtReturn(out var) != null);
     IToken id;  Type ty;  Type optType = null;
  .)
  WildIdent<out id, true>
  [ ":" Type<out ty>             (. optType = ty; .)
  ]
  (. var = new BoundVar(id, id.val, optType == null ? new InferredTypeProxy() : optType); .)
  .
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; .)
  [ "ghost"                            (. isGhost = true; .)
  ]
  ( TypeAndToken<out id, out ty, false>
    [ ":"
      (. /* try to convert ty to an identifier */
         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>
    ]
  | digits         (. id = t; name = id.val;.)
    ":"
    Type<out ty>
  )
  (. if (name != null) {
       identName = name;
     } else {
       identName = "#" + anonymousIds++;
     }
  .)
  .
/*------------------------------------------------------------------------*/
IteratorDecl<DeclModifierData dmod, ModuleDefinition module, out IteratorDecl/*!*/ iter>
= (. Contract.Ensures(Contract.ValueAtReturn(out iter) != null);
     IToken/*!*/ id;
     Attributes attrs = null;
     List<TypeParameter/*!*/>/*!*/ typeArgs = new List<TypeParameter/*!*/>();
     List<Formal/*!*/> ins = new List<Formal/*!*/>();
     List<Formal/*!*/> outs = new List<Formal/*!*/>();
     List<FrameExpression/*!*/> reads = new List<FrameExpression/*!*/>();
     List<FrameExpression/*!*/> mod = new List<FrameExpression/*!*/>();
     List<Expression/*!*/> decreases = new List<Expression>();
     List<MaybeFreeExpression/*!*/> req = new List<MaybeFreeExpression/*!*/>();
     List<MaybeFreeExpression/*!*/> ens = new List<MaybeFreeExpression/*!*/>();
     List<MaybeFreeExpression/*!*/> yieldReq = new List<MaybeFreeExpression/*!*/>();
     List<MaybeFreeExpression/*!*/> yieldEns = new List<MaybeFreeExpression/*!*/>();
     List<Expression/*!*/> dec = new List<Expression/*!*/>();
     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);
  .)
  SYNC
  "iterator"
  { Attribute<ref attrs> }
  NoUSIdent<out id>
  (
    [ GenericParameters<typeArgs, true> ]
    Formals<true, true, false, ins>
    [ ( "yields"
      | "returns"           (. SemErr(t, "iterators don't have a 'returns' clause; did you mean 'yields'?"); .)
      )
      Formals<false, true, false, outs>
    ]
  | "..."                                       (. signatureEllipsis = t; .)
  )
  { IteratorSpec<reads, mod, decreases, req, ens, yieldReq, yieldEns, ref readsAttrs, ref modAttrs, ref decrAttrs> }
  [ BlockStmt<out body, out bodyStart, out bodyEnd>
  ]
  (. iter = new IteratorDecl(id, id.val, module, typeArgs, ins, outs,
                             new Specification<FrameExpression>(reads, readsAttrs),
                             new Specification<FrameExpression>(mod, modAttrs),
                             new Specification<Expression>(decreases, decrAttrs),
                             req, ens, yieldReq, yieldEns,
                             body, attrs, signatureEllipsis);
     iter.BodyStartTok = bodyStart;
     iter.BodyEndTok = bodyEnd;
 .)
  .
/*------------------------------------------------------------------------*/
GenericParameters<.List<TypeParameter/*!*/>/*!*/ typeArgs, bool allowVariance.>
= (. Contract.Requires(cce.NonNullElements(typeArgs));
     IToken/*!*/ id;
     TypeParameter.TypeParameterCharacteristics characteristics;
     TypeParameter.TPVarianceSyntax variance = TypeParameter.TPVarianceSyntax.NonVariant_Strict;  // assignment is to please compiler
     characteristics = new TypeParameter.TypeParameterCharacteristics(false);
  .)
  // There's a subtle issue here.  The next things in the input could be a '<' followed by an '=' (and then an identifier).
  // This is legal (provided "allowVariance" is "true").  However, unless there's whitespace between the '<' and '=', the
  // scanner will read these two characters as a "<=" token.
  "<"
  [ Variance<out variance>  (. if (!allowVariance) { SemErr(t, "type-parameter variance is not allowed to be specified in this context"); } .)
  ]
  NoUSIdent<out id>
  { TypeParameterCharacteristics<ref characteristics> }
  (. typeArgs.Add(new TypeParameter(id, id.val, variance, characteristics)); .)
  { ","
    (. variance = TypeParameter.TPVarianceSyntax.NonVariant_Strict;
       characteristics = new TypeParameter.TypeParameterCharacteristics(false);
    .)
    [ Variance<out variance>  (. if (!allowVariance) { SemErr(t, "type-parameter variance is not allowed to be specified in this context"); } .)
    ]
    NoUSIdent<out id>
    { TypeParameterCharacteristics<ref characteristics> }
    (. typeArgs.Add(new TypeParameter(id, id.val, variance, characteristics)); .)
  }
  ">"
  .
Variance<out TypeParameter.TPVarianceSyntax variance>
= (. variance = TypeParameter.TPVarianceSyntax.NonVariant_Strict;  // never used; here just to please the C# compiler
  .)
  ( "*"  (. variance = TypeParameter.TPVarianceSyntax.Covariant_Permissive; .)
  | "+"  (. variance = TypeParameter.TPVarianceSyntax.Covariant_Strict; .)
  | "!"  (. variance = TypeParameter.TPVarianceSyntax.NonVariant_Permissive; .)
  | "-"  (. variance = TypeParameter.TPVarianceSyntax.Contravariance; .)
  )
  .
TypeParameterCharacteristics<ref TypeParameter.TypeParameterCharacteristics characteristics>
= "("
  TPCharOption<ref characteristics>
  { ","
    TPCharOption<ref characteristics>
  }
  ")"
  .
TPCharOption<ref TypeParameter.TypeParameterCharacteristics characteristics>
= ( "=="       (. characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.Required; .)
  | digits     (. if (t.val == "0") {
                    characteristics.MustSupportZeroInitialization = true;
                  } else {
                    SemErr(t, "unexpected TPCharOption");
                  }
               .)
  | "!" "new"  (. characteristics.DisallowReferenceTypes = true; .)
  )
  .
/*------------------------------------------------------------------------*/
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<TypeParameter/*!*/>/*!*/ typeArgs = new List<TypeParameter/*!*/>();
     List<Formal/*!*/> ins = new List<Formal/*!*/>();
     List<Formal/*!*/> outs = new List<Formal/*!*/>();
     List<MaybeFreeExpression/*!*/> req = new List<MaybeFreeExpression/*!*/>();
     List<FrameExpression/*!*/> mod = new List<FrameExpression/*!*/>();
     List<MaybeFreeExpression/*!*/> ens = new List<MaybeFreeExpression/*!*/>();
     List<Expression/*!*/> dec = new List<Expression/*!*/>();
     Attributes decAttrs = null;
     Attributes modAttrs = null;
     BlockStmt body = null;
     bool isPlainOlMethod = false;
     bool isLemma = false;
     bool isTwoStateLemma = 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 = "";
     FixpointPredicate.KType kType = FixpointPredicate.KType.Unspecified;
  .)
  SYNC
  ( "method"                        (. isPlainOlMethod = true; caption = "Methods";
                                       allowed = AllowedDeclModifiers.Ghost | AllowedDeclModifiers.Static; .)
  | "lemma"                         (. isLemma = true; caption = "Lemmas";
                                       allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static 
                                         | AllowedDeclModifiers.Protected; .)
  | "colemma"                       (. isCoLemma = true; caption = "Colemmas";
                                       allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static 
                                         | AllowedDeclModifiers.Protected; .)
  | "comethod"                      (. isCoLemma = true; caption = "Comethods";
                                       allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static 
                                         | AllowedDeclModifiers.Protected;
                                       errors.Deprecated(t, "the 'comethod' keyword has been deprecated; it has been renamed to 'colemma'");
                                    .)
  | "inductive" "lemma"             (. isIndLemma = true;  caption = "Inductive lemmas";
                                       allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static;.)
  | "twostate" "lemma"              (. isTwoStateLemma = true; caption = "Two-state lemmas";
                                       allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static 
                                         | AllowedDeclModifiers.Protected; .)
  | "constructor"                   (. if (allowConstructor) {
                                         isConstructor = true;
                                       } else {
                                         SemErr(t, "constructors are allowed only in classes");
                                       } 
                                       caption = "Constructors";
                                       allowed = AllowedDeclModifiers.None;
                                    .)
  )                                 (. keywordToken = t; 
                                       CheckDeclModifiers(dmod, caption, allowed); .)
  { Attribute<ref attrs> }
  [ FuMe_Ident<out id>               (. hasName = true; .)
  ]
  (. if (!hasName) {
       id = keywordToken;
       if (!isConstructor) {
         SemErr(la, "a method must be given a name (expecting identifier)");
       }
     }
  .)
  (
    [ GenericParameters<typeArgs, false> ]
    [ KType<ref kType>              (. if (!(isCoLemma || isIndLemma)) { SemErr(t, "type of _k can only be specified for inductive lemmas and co-lemmas"); } .)
    ]
    (. var isCompilable = (isPlainOlMethod && !dmod.IsGhost) || isConstructor; .)
    Formals<true, isCompilable, isTwoStateLemma, ins>
    [ "returns"                                 (. if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); } .)
      Formals<false, isCompilable, false, outs>
    ]
  | "..."                                       (. signatureEllipsis = t; .)
  )
  { MethodSpec<req, mod, ens, dec, ref decAttrs, ref modAttrs, caption, isConstructor> }
  [ IF(isConstructor)
    (. DividedBlockStmt dividedBody; .)
    DividedBlockStmt<out dividedBody, out bodyStart, out bodyEnd>
    (. body = dividedBody; .)
  | 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 = id;
     if (isConstructor) {
       m = new Constructor(tok, hasName ? id.val : "_ctor", typeArgs, ins,
                           req, new Specification<FrameExpression>(mod, modAttrs), ens, new Specification<Expression>(dec, decAttrs), (DividedBlockStmt)body, attrs, signatureEllipsis);
     } else if (isIndLemma) {
       m = new InductiveLemma(tok, id.val, dmod.IsStatic, kType, typeArgs, ins, outs,
                              req, new Specification<FrameExpression>(mod, modAttrs), ens, new Specification<Expression>(dec, decAttrs), body, attrs, signatureEllipsis);
     } else if (isCoLemma) {
       m = new CoLemma(tok, id.val, dmod.IsStatic, kType, typeArgs, ins, outs,
                       req, new Specification<FrameExpression>(mod, modAttrs), ens, new Specification<Expression>(dec, decAttrs), body, attrs, signatureEllipsis);
     } else if (isLemma) {
       m = new Lemma(tok, id.val, dmod.IsStatic, typeArgs, ins, outs,
                     req, new Specification<FrameExpression>(mod, modAttrs), ens, new Specification<Expression>(dec, decAttrs), body, attrs, signatureEllipsis);
     } else if (isTwoStateLemma) {
       m = new TwoStateLemma(tok, id.val, dmod.IsStatic, typeArgs, ins, outs,
                             req, new Specification<FrameExpression>(mod, modAttrs),
                             ens, new Specification<Expression>(dec, decAttrs), body, attrs, signatureEllipsis);
     } else {
       m = new Method(tok, id.val, dmod.IsStatic, dmod.IsGhost, typeArgs, ins, outs,
                      req, new Specification<FrameExpression>(mod, modAttrs), ens, new Specification<Expression>(dec, decAttrs), body, attrs, signatureEllipsis);
     }
     m.BodyStartTok = bodyStart;
     m.BodyEndTok = bodyEnd;
 .)
  .
KType<ref FixpointPredicate.KType kType>
= "["
  ( "nat"       (. kType = FixpointPredicate.KType.Nat; .)
  | "ORDINAL"   (. kType = FixpointPredicate.KType.ORDINAL; .)
  )
  "]"
  .
MethodSpec<.List<MaybeFreeExpression> req, List<FrameExpression> mod, List<MaybeFreeExpression> ens,
            List<Expression> decreases, ref Attributes decAttrs, ref Attributes modAttrs, string caption, bool performThisDeprecatedCheck.>
= (. 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; Attributes reqAttrs = null;
     IToken lbl = null;
  .)
  SYNC
  ( "modifies" { IF(IsAttribute()) Attribute<ref modAttrs> }
               FrameExpression<out fe, false, false>         (. Util.AddFrameExpression(mod, fe, performThisDeprecatedCheck, errors); .)
               { "," FrameExpression<out fe, false, false>   (. Util.AddFrameExpression(mod, fe, performThisDeprecatedCheck, errors); .)
               }
               OldSemi
  | [ "free"                                                 (. isFree = true;
                                                                errors.Deprecated(t, "the 'free' keyword is soon to be deprecated");
                                                             .)
    ]
    ( "requires" 
		  { IF(IsAttribute()) Attribute<ref reqAttrs> }
      [ IF(IsLabel(true))
        LabelIdent<out lbl> ":"
      ]
		  Expression<out e, false, false> OldSemi                (. req.Add(new MaybeFreeExpression(e, isFree, lbl == null ? null : new AssertLabel(lbl, lbl.val), reqAttrs)); .)
    | "ensures"
      { IF(IsAttribute()) Attribute<ref ensAttrs> }
      Expression<out e, false, false> OldSemi                (. ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs)); .)
    )
  | "decreases" { IF(IsAttribute()) Attribute<ref decAttrs> } DecreasesList<decreases, true, false> OldSemi
  )
  .
IteratorSpec<.List<FrameExpression/*!*/>/*!*/ reads, List<FrameExpression/*!*/>/*!*/ mod, List<Expression/*!*/> decreases,
              List<MaybeFreeExpression/*!*/>/*!*/ req, List<MaybeFreeExpression/*!*/>/*!*/ ens,
              List<MaybeFreeExpression/*!*/>/*!*/ yieldReq, List<MaybeFreeExpression/*!*/>/*!*/ yieldEns,
              ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs.>
= (. Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; bool isYield = false; Attributes ensAttrs = null;
     IToken lbl = null;
  .)
  SYNC
  ( "reads"    { IF(IsAttribute()) Attribute<ref readsAttrs> }
               FrameExpression<out fe, false, false>       (. reads.Add(fe); .)
               { "," FrameExpression<out fe, false, false> (. reads.Add(fe); .)
               }
               OldSemi
  | "modifies" { IF(IsAttribute()) Attribute<ref modAttrs> }
               FrameExpression<out fe, false, false>       (. mod.Add(fe); .)
               { "," FrameExpression<out fe, false, false> (. mod.Add(fe); .)
               }
               OldSemi
  | [ "free"                                                 (. isFree = true;
                                                                errors.Deprecated(t, "the 'free' keyword is soon to be deprecated");
                                                             .)
    ]
    [ "yield"                                                (. isYield = true; .)
    ]
    ( "requires"
      [ IF(IsLabel(!isYield))
        LabelIdent<out lbl> ":"
      ]
      Expression<out e, false, false> OldSemi                (. AssertLabel al = lbl == null ? null : new AssertLabel(lbl, lbl.val);
                                                                if (isYield) {
                                                                  yieldReq.Add(new MaybeFreeExpression(e, isFree, al, null));
                                                                } else {
                                                                  req.Add(new MaybeFreeExpression(e, isFree, al, null));
                                                                }
                                                             .)
    | "ensures" { IF(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));
                                                                }
                                                             .)
    )
  | "decreases" { IF(IsAttribute()) Attribute<ref decrAttrs> } DecreasesList<decreases, false, false> OldSemi
  )
  .
Formals<.bool incoming, bool allowGhostKeyword, bool allowNewKeyword, List<Formal> formals.>
= (. Contract.Requires(cce.NonNullElements(formals));
     IToken id;
     Type ty;
     bool isGhost;
     bool isOld;
  .)
  "("
  [
    GIdentType<allowGhostKeyword, allowNewKeyword, out id, out ty, out isGhost, out isOld>
                 (. formals.Add(new Formal(id, id.val, ty, incoming, isGhost, isOld)); .)
    { "," GIdentType<allowGhostKeyword, allowNewKeyword, out id, out ty, out isGhost, out isOld>
                 (. formals.Add(new Formal(id, id.val, ty, incoming, isGhost, isOld)); .)
    }
  ]
  ")"
  .
FormalsOptionalIds<.List<Formal/*!*/>/*!*/ formals.>
= (. Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id;  Type/*!*/ ty;  string/*!*/ name;  bool isGhost; .)
  "("
  [
    TypeIdentOptional<out id, out name, out ty, out isGhost>        (. formals.Add(new Formal(id, name, ty, true, isGhost)); .)
    { "," TypeIdentOptional<out id, out name, out ty, out isGhost>  (. formals.Add(new Formal(id, name, ty, true, isGhost)); .)
    }
  ]
  ")"
  .
/*------------------------------------------------------------------------*/
Type<out Type ty>
= (. Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken/*!*/ tok; .)
  TypeAndToken<out tok, out ty, false>
  .

TypeAndToken<out IToken tok, out Type ty, bool inExpressionContext>
= (. Contract.Ensures(Contract.ValueAtReturn(out tok)!=null); Contract.Ensures(Contract.ValueAtReturn(out ty) != null);
     tok = Token.NoToken;  ty = new BoolType();  /*keep compiler happy*/
     List<Type> gt; List<Type> tupleArgTypes = null;
  .)
  ( "bool"                          (. tok = t; .)
  | "char"                          (. tok = t;  ty = new CharType(); .)
  | "int"                           (. tok = t;  ty = new IntType(); .)
  | "nat"                           (. tok = t;  ty = new UserDefinedType(tok, tok.val, null); .)
  | "real"                          (. tok = t;  ty = new RealType(); .)
  | "ORDINAL"                       (. tok = t;  ty = new BigOrdinalType(); .)
  | bvToken                         (. tok = t;
                                       int w = StringToInt(tok.val.Substring(2), 0, "bitvectors that wide");
                                       ty = new BitvectorType(w);
                                    .)
  | "set"                           (. tok = t;.)
    OptGenericInstantiation<out gt, inExpressionContext>
                                    (. if (gt != null && gt.Count > 1) {
                                         SemErr("set type expects only one type argument");
                                       }
                                       ty = new SetType(true, gt != null ?gt[0] : null);
                                    .)
  | "iset"                          (. tok = t; .)
    OptGenericInstantiation<out gt, inExpressionContext>
                                    (. if (gt != null && gt.Count > 1) {
                                         SemErr("set type expects only one type argument");
                                       }
                                       ty = new SetType(false, gt != null ? gt[0] : null);
                                    .)
  | "multiset"                      (. tok = t; .)
    OptGenericInstantiation<out gt, inExpressionContext>
                                    (. if (gt != null && gt.Count > 1) {
                                         SemErr("multiset type expects only one type argument");
                                       }
                                       ty = new MultiSetType(gt != null ? gt[0] : null);
                                    .)
  | "seq"                           (. tok = t; .)
    OptGenericInstantiation<out gt, inExpressionContext>
                                    (. if (gt != null && gt.Count > 1) {
                                         SemErr("seq type expects only one type argument");
                                       }
                                       ty = new SeqType(gt != null ? gt[0] : null);
                                    .)
  | "string"                        (. tok = t;  ty = new UserDefinedType(tok, tok.val, null); .)
  | "object"                        (. tok = t;  ty = new UserDefinedType(tok, tok.val, null); .)
  | "object?"                       (. tok = t;  ty = new UserDefinedType(tok, tok.val, null); .)
  | "map"                           (. tok = t; .)
    OptGenericInstantiation<out gt, inExpressionContext>
                                    (. if (gt == null) {
                                         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]);
                                       }
                                    .)
  | "imap"                          (. tok = t; .)
    OptGenericInstantiation<out gt, inExpressionContext>
                                    (. if (gt == null) {
                                         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]);
                                       }
                                    .)
  | arrayToken                      (. tok = t; .)
    OptGenericInstantiation<out gt, inExpressionContext>
                                    (. var dimString = tok.val.Substring(5);
                                       int dims = StringToInt(dimString, 1, "arrays of that many dimensions");
                                       ty = theBuiltIns.ArrayType(tok, dims, gt, true);
                                    .)
  | arrayToken_q                    (. tok = t; .)
    OptGenericInstantiation<out gt, inExpressionContext>
                                    (. var dimString = tok.val.Substring(5);
                                       dimString = dimString.Substring(0, dimString.Length - 1);
                                       int dims = StringToInt(dimString, 1, "arrays of that many dimensions");
                                       ty = theBuiltIns.ArrayType(tok, dims, gt, true, true);
                                    .)
  | "("                             (. tok = t; tupleArgTypes = new List<Type>(); .)
    [ Type<out ty>                  (. tupleArgTypes.Add(ty); .)
      { "," Type<out ty>            (. tupleArgTypes.Add(ty); .)
      }
    ]
    ")"                             (. 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);
                                       }
                                    .)
  | (. Expression e; .)
    NameSegmentForTypeName<out e, inExpressionContext>  (. tok = t; .)
    { "." TypeNameOrCtorSuffix<out tok>       (. List<Type> typeArgs; .)
      OptGenericInstantiation<out typeArgs, inExpressionContext>
      (. e = new ExprDotName(tok, e, tok.val, typeArgs); .)
    }
    (. ty = new UserDefinedType(e.tok, e); .)
  )
  [ (. int arrowKind = 0; /* 0: any, 1: partial, 2: total */
       Type t2;
    .)
    ( "~>"           (. tok = t; arrowKind = 0; .)
    | "-->"          (. tok = t; arrowKind = 1; .)
    | "->"           (. tok = t; arrowKind = 2; .)
    )
    Type<out t2>
    (. if (tupleArgTypes != null) {
         gt = tupleArgTypes;
        } else {
         gt = new List<Type>{ ty };
       }
       var arity = gt.Count;
       theBuiltIns.CreateArrowTypeDecl(arity);
       if (arrowKind == 0) {
         ty = new ArrowType(tok, gt, t2);
       } else {
         gt.Add(t2);
         if (arrowKind == 1) {
           ty = new UserDefinedType(tok, ArrowType.PartialArrowTypeName(arity), gt);
         } else {
           ty = new UserDefinedType(tok, ArrowType.TotalArrowTypeName(arity), gt);
         }
       }
    .)
  ]
  .
OptGenericInstantiation<.out List<Type> gt, bool inExpressionContext.>  /* NOTE: Coco complains about "OptGenericInstantiation deletable". That's okay. */
= (. gt = null; .)
  [ IF(IsGenericInstantiation(inExpressionContext))  /* be greedy -- if it looks like a type instantiation, take it */
    (. gt = new List<Type>(); .)
    GenericInstantiation<gt>
  ]
  .
GenericInstantiation<.List<Type> gt.>
= (. Contract.Requires(cce.NonNullElements(gt)); Type/*!*/ ty; .)
  "<"
    Type<out ty>                     (. gt.Add(ty); .)
    { "," Type<out ty>               (. gt.Add(ty); .)
    }
  ">"
  .
/*------------------------------------------------------------------------*/
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<TypeParameter/*!*/> typeArgs = new List<TypeParameter/*!*/>();
     List<Formal/*!*/> formals = new List<Formal/*!*/>();
     Formal/*!*/ result = null;
     Type/*!*/ returnType = new BoolType();
     List<MaybeFreeExpression/*!*/> reqs = new List<MaybeFreeExpression/*!*/>();
     List<MaybeFreeExpression/*!*/> ens = new List<MaybeFreeExpression/*!*/>();
     List<FrameExpression/*!*/> reads = new List<FrameExpression/*!*/>();
     List<Expression/*!*/> 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;
     bool isTwoState = false;
     FixpointPredicate.KType kType = FixpointPredicate.KType.Unspecified;
  .)
  /* ----- function ----- */
  [ "twostate"               (. isTwoState = true; .)
  ]
  ( "function"
    [ "method"                 (. if (isTwoState) { SemErr(t, "twostate functions are supported only as a ghosts, not as function methods"); }
                                  else { isFunctionMethod = true; }
                               .)
    ]
    (. AllowedDeclModifiers allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static;
       if (!isTwoState) { allowed |= AllowedDeclModifiers.Protected; }
       string caption = "Functions";
       if (isFunctionMethod) { 
         caption = "Function methods";
       }
       CheckDeclModifiers(dmod, caption, allowed);
    .)
    { Attribute<ref attrs> }
    FuMe_Ident<out id>
    (
      [ GenericParameters<typeArgs, false> ]
      Formals<true, isFunctionMethod, isTwoState, formals>
      ":"
      (  IF(FollowedByColon()) 
         "("
           (. 
              IToken resultId;
              Type ty;
              bool isGhost;
              bool isOld;
           .)
           GIdentType<false, false, out resultId, out ty, out isGhost, out isOld>
           (. Contract.Assert(!isGhost && !isOld);
              result = new Formal(resultId, resultId.val, ty, false, false, false);
           .)
         ")"
         | Type<out returnType>
      )
    | "..."                    (. signatureEllipsis = t; .)
    )

  /* ----- predicate ----- */
  | "predicate"                (. isPredicate = true; .)
    [ "method"                 (. if (isTwoState) { SemErr(t, "twostate predicates are supported only as a ghosts, not as predicate methods"); }
                                  else { isFunctionMethod = true; }
                               .)
    ]
    (. AllowedDeclModifiers allowed = AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static;
       if (!isTwoState) { allowed |= AllowedDeclModifiers.Protected; }
       string caption = "Predicates";
       if (isFunctionMethod) { 
         caption = "Predicate methods";
       }
       CheckDeclModifiers(dmod, caption, allowed);
    .)
    { Attribute<ref attrs> }
    NoUSIdent<out id>
    (
      [ GenericParameters<typeArgs, false> ]                 (. missingOpenParen = true; .)
      [ Formals<true, isFunctionMethod, isTwoState, 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"); } .)
      [ ":"                    (. SemErr(t, "predicates do not have an explicitly declared return type; it is always bool"); .)
      ]
    | "..."                    (. signatureEllipsis = t; .)
    )

  /* ----- inductive predicate ----- */
  | (. Contract.Assert(!isTwoState);  // the IsFunctionDecl check checks that "twostate" is not followed by "inductive"
    .)
    "inductive" "predicate"    (. isIndPredicate = true; .)
    (. CheckDeclModifiers(dmod, "Inductive predicates",
         AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static | AllowedDeclModifiers.Protected);
    .)
    { Attribute<ref attrs> }
    FuMe_Ident<out id>
    (
      [ GenericParameters<typeArgs, false> ]
      [ KType<ref kType> ]
      Formals<true, isFunctionMethod, false, formals>
      [ ":"                    (. SemErr(t, "inductive predicates do not have an explicitly declared return type; it is always bool"); .)
      ]
    | "..."                    (. signatureEllipsis = t; .)
    )

  /* ----- copredicate ----- */
  | (. Contract.Assert(!isTwoState);  // the IsFunctionDecl check checks that "twostate" is not followed by "copredicate"
    .)
    "copredicate"              (. isCoPredicate = true; .)
    (. CheckDeclModifiers(dmod, "Copredicates",
         AllowedDeclModifiers.AlreadyGhost | AllowedDeclModifiers.Static | AllowedDeclModifiers.Protected);
    .)
    { Attribute<ref attrs> }
    NoUSIdent<out id>
    (
      [ GenericParameters<typeArgs, false> ]
      [ KType<ref kType> ]
      Formals<true, isFunctionMethod, false, formals>
      [ ":"                    (. SemErr(t, "copredicates do not have an explicitly declared return type; it is always bool"); .)
      ]
    | "..."                    (. signatureEllipsis = t; .)
    )
  )

  (. decreases = isIndPredicate || isCoPredicate ? null : new List<Expression/*!*/>(); .)
  { FunctionSpec<reqs, reads, ens, decreases> }
  [ 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");
     }
     IToken tok = id;
     if (isTwoState && isPredicate) {
        f = new TwoStatePredicate(tok, id.val, dmod.IsStatic, typeArgs, formals,
                                  reqs, reads, ens, new Specification<Expression>(decreases, null), body, attrs, signatureEllipsis);
     } else if (isTwoState) {
        f = new TwoStateFunction(tok, id.val, dmod.IsStatic, typeArgs, formals, result, returnType,
                                 reqs, reads, ens, new Specification<Expression>(decreases, null), body, attrs, signatureEllipsis);
     } else if (isPredicate) {
        f = new Predicate(tok, id.val, dmod.IsStatic, dmod.IsProtected, !isFunctionMethod, typeArgs, formals,
                          reqs, reads, ens, new Specification<Expression>(decreases, null), body, Predicate.BodyOriginKind.OriginalOrInherited, attrs, signatureEllipsis);
     } else if (isIndPredicate) {
        f = new InductivePredicate(tok, id.val, dmod.IsStatic, dmod.IsProtected, kType, typeArgs, formals,
                                   reqs, reads, ens, body, attrs, signatureEllipsis);
     } else if (isCoPredicate) {
        f = new CoPredicate(tok, id.val, dmod.IsStatic, dmod.IsProtected, kType, typeArgs, formals,
                            reqs, reads, ens, body, attrs, signatureEllipsis);
     } else {
        f = new Function(tok, id.val, dmod.IsStatic, dmod.IsProtected, !isFunctionMethod, typeArgs, formals, result, returnType,
                         reqs, reads, ens, new Specification<Expression>(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);
     }
  .)
  .
FunctionSpec<.List<MaybeFreeExpression/*!*/>/*!*/ reqs, List<FrameExpression/*!*/>/*!*/ reads, List<MaybeFreeExpression/*!*/>/*!*/ ens, List<Expression/*!*/> decreases.>
= (. Contract.Requires(cce.NonNullElements(reqs));
     Contract.Requires(cce.NonNullElements(reads));
     Contract.Requires(decreases == null || cce.NonNullElements(decreases));
     Expression/*!*/ e;  FrameExpression/*!*/ fe;
		 Attributes ensAttrs = null; Attributes reqAttrs = null; .)
  SYNC
  ( "requires" 
	  { IF(IsAttribute()) Attribute<ref reqAttrs> }
		  Expression<out e, false, false> OldSemi                (. reqs.Add(new MaybeFreeExpression(e, false, reqAttrs)); .)
  | "reads"
    PossiblyWildFrameExpression<out fe, false>          (. reads.Add(fe); .)
    { "," PossiblyWildFrameExpression<out fe, false>    (. reads.Add(fe); .)
    }
    OldSemi
  | "ensures"
	  { IF(IsAttribute()) Attribute<ref ensAttrs> }
      Expression<out e, false, false> OldSemi                (. ens.Add(new MaybeFreeExpression(e, false, ensAttrs)); .)
  | "decreases"                               (. if (decreases == null) {
                                                   SemErr(t, "'decreases' clauses are meaningless for copredicates, so they are not allowed");
                                                   decreases = new List<Expression/*!*/>();
                                                 }
                                              .)
    DecreasesList<decreases, false, false> OldSemi
  )
  .

PossiblyWildExpression<out Expression e, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out e)!=null);
     e = dummyExpr; .)
  /* A decreases clause on a loop asks that no termination check be performed.
   * Use of this feature is sound only with respect to partial correctness.
   */
  ( "*"                        (. e = new WildcardExpr(t); .)
  | Expression<out e, false, allowLambda>
  )
  .
PossiblyWildFrameExpression<out FrameExpression fe, bool allowSemi>
= (. Contract.Ensures(Contract.ValueAtReturn(out fe) != null); fe = dummyFrameExpr; .)
  /* A reads clause can list a wildcard, which allows the enclosing function to
   * read anything.  In many cases, and in particular in all cases where
   * the function is defined recursively, this makes it next to impossible to make
   * any use of the function.  Nevertheless, as an experimental feature, the
   * language allows it (and it is sound).
   */
  ( "*"                        (. fe = new FrameExpression(t, new WildcardExpr(t), null); .)
  | FrameExpression<out fe, allowSemi, false>
  )
  .
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 = dummyFrameExpr;
  .)
  ( Expression<out e, allowSemi, allowLambda>   (. feTok = e.tok; .)
    [ "`" Ident<out id>        (. fieldName = id.val;  feTok = id; .)
    ]                          (. fe = new FrameExpression(feTok, e, fieldName); .)
  |
    "`" Ident<out id>          (. fieldName = id.val; .)
                               (. fe = new FrameExpression(id, new ImplicitThisExpr(id), fieldName); .)
  )
  .
FunctionBody<out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); e = dummyExpr; .)
  "{"                         (. bodyStart = t; .)
  Expression<out e, true, true>
  "}"                         (. bodyEnd = t; .)
  .
/*------------------------------------------------------------------------*/
BlockStmt<out BlockStmt/*!*/ block, out IToken bodyStart, out IToken bodyEnd>
= (. Contract.Ensures(Contract.ValueAtReturn(out block) != null);
     List<Statement/*!*/> body = new List<Statement/*!*/>();
  .)
  "{"                                  (. bodyStart = t; .)
  { Stmt<body>
  }
  "}"                                  (. bodyEnd = t;
                                          block = new BlockStmt(bodyStart, bodyEnd, body); .)
  .
DividedBlockStmt<out DividedBlockStmt body, out IToken bodyStart, out IToken bodyEnd>
= (. Contract.Ensures(Contract.ValueAtReturn(out body) != null);
     List<Statement> bodyInit = new List<Statement>();
     IToken separatorTok = null;
     List<Statement> bodyProper = new List<Statement>();
  .)
  "{"                                  (. bodyStart = t; .)
  { Stmt<bodyInit> }
  [ "new"                              (. separatorTok = t; .)
    ";"
    { Stmt<bodyProper> }
  ]
  "}"                                  (. bodyEnd = t; .)
  (. body = new DividedBlockStmt(bodyStart, bodyEnd, bodyInit, separatorTok, bodyProper); .)
  .
Stmt<.List<Statement/*!*/>/*!*/ ss.>
= (. Statement/*!*/ s;
  .)
  OneStmt<out s>                                (. ss.Add(s); .)
  .
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;
  .)
  SYNC
  ( BlockStmt<out bs, out bodyStart, out bodyEnd>  (. s = bs; .)
  | AssertStmt<out s, false>
  | AssumeStmt<out s>
  | PrintStmt<out s>
  | RevealStmt<out s>
  | UpdateStmt<out s>
  | VarDeclStatement<out s>
  | IfStmt<out s>
  | WhileStmt<out s>
  | MatchStmt<out s>
  | ForallStmt<out s>
  | CalcStmt<out s>
  | ModifyStmt<out s>
  | "label"
    LabelIdent<out id> ":"
    OneStmt<out s>                     (. s.Labels = new LList<Label>(new Label(id, id.val), s.Labels); .)
  | "break"                            (. x = t; breakCount = 1; label = null; .)
    ( LabelIdent<out id>               (. label = id.val; .)
    | { "break"                        (. breakCount++; .)
      }
    )
    SYNC
    ";"                                (. s = label != null ? new BreakStmt(x, t, label) : new BreakStmt(x, t, breakCount); .)
  | ReturnStmt<out s>
  | SkeletonStmt<out s>
  )
  .

SkeletonStmt<out Statement s>
= (. List<IToken> names = null;
     List<Expression> exprs = null;
     IToken tok, dotdotdot, whereTok;
     Expression e; .)
  "..."                                (. dotdotdot = t; .)
  ["where"                             (. names = new List<IToken>(); exprs = new List<Expression>(); whereTok = t;.)
     Ident<out tok>                    (. names.Add(tok); .)
     {"," Ident<out tok>               (. names.Add(tok); .)
     }
     ":="
     Expression<out e, false, true>          (. exprs.Add(e); .)
     {"," Expression<out e, false, true>     (. exprs.Add(e); .)
     }
                                       (. if (exprs.Count != names.Count) {
                                            SemErr(whereTok, exprs.Count < names.Count ? "not enough expressions" : "too many expressions");
                                            names = null; exprs = null;
                                          }
                                       .)
  ]
  ";"
  (. s = new SkeletonStatement(dotdotdot, t, names, exprs); .)
  .
ReturnStmt<out Statement/*!*/ s>
= (.
   IToken returnTok = null;
   List<AssignmentRhs> rhss = null;
   AssignmentRhs r;
   bool isYield = false;
   .)
  ( "return"                         (. returnTok = t; .)
  | "yield"                          (. returnTok = t; isYield = true; .)
  )
  [ Rhs<out r>                       (. rhss = new List<AssignmentRhs>(); rhss.Add(r); .)
    { "," Rhs<out r>                 (. rhss.Add(r); .)
    }
  ]
  ";"                                (. if (isYield) {
                                          s = new YieldStmt(returnTok, t, rhss);
                                        } else {
                                          s = new ReturnStmt(returnTok, t, rhss);
                                        }
                                     .)
  .
UpdateStmt<out Statement/*!*/ s>
= (. List<Expression> lhss = new List<Expression>();
     List<AssignmentRhs> rhss = new List<AssignmentRhs>();
     Expression e;  AssignmentRhs r;
     IToken x, endTok = Token.NoToken;
     Attributes attrs = null;
     IToken suchThatAssume = null;
     Expression suchThat = null;
  .)
  Lhs<out e>                       (. x = e.tok; .)
  ( { Attribute<ref attrs> }
    ";"                            (. endTok = t; rhss.Add(new ExprRhs(e, attrs)); .)
  |                                (. lhss.Add(e); .)
    { "," Lhs<out e>               (. lhss.Add(e); .)
    }
    ( ":="                         (. x = t; .)
      Rhs<out r>                   (. rhss.Add(r); .)
      { "," Rhs<out r>             (. rhss.Add(r); .)
      }
    | ":|"                         (. x = t; .)
      [ IF(la.kind == _assume)     /* an Expression can also begin with an "assume", so this says to resolve it to pick up any "assume" here */
        "assume"                   (. suchThatAssume = t; .)
      ]
      Expression<out suchThat, false, true>
    )
    ";"                            (. endTok = t; .)
  | ":"                            (. SemErr(t, "invalid statement (did you forget the 'label' keyword?)"); .)
  )
  (. if (suchThat != null) {
       s = new AssignSuchThatStmt(x, endTok, lhss, suchThat, suchThatAssume, null);
     } else {
       if (lhss.Count == 0 && rhss.Count == 0) {
         s = new BlockStmt(x, endTok, new List<Statement>()); // error, give empty statement
       } else {
         s = new UpdateStmt(x, endTok, lhss, rhss);
       }
     }
  .)
  .
Rhs<out AssignmentRhs r>
= (. Contract.Ensures(Contract.ValueAtReturn<AssignmentRhs>(out r) != null);
     IToken/*!*/ x, newToken;  Expression/*!*/ e;
     Type ty = new InferredTypeProxy();
     List<Expression> ee = null;
     List<Expression> args = null;
     Expression arrayElementInit = null;
     List<Expression> display = null;
     r = dummyRhs;  // to please compiler
     Attributes attrs = null;
  .)
  ( "new"                              (. newToken = t; .)
    ( NewArray<out ee, out arrayElementInit, out display>  // "ty" is set to InferredTypeProxy above
    | TypeAndToken<out x, out ty, false>
      [ NewArray<out ee, out arrayElementInit, out display>
      |                                (. x = null; args = new List<Expression/*!*/>(); .)
        "("
          [ Expressions<args> ]
        ")"
      ]
    )
    (. if (ee != null) {
         if (display != null) {
           r = new TypeRhs(newToken, ty, ee[0], display);
         } else {
           r = new TypeRhs(newToken, ty, ee, arrayElementInit);
         }
       } else if (args != null) {
         r = new TypeRhs(newToken, ty, args, false);
       } else {
         r = new TypeRhs(newToken, ty);
       }
    .)
  | "*"                                (. r = new HavocRhs(t); .)
  | Expression<out e, false, true>     (. r = new ExprRhs(e); .)
  )
  { Attribute<ref attrs> }             (. r.Attributes = attrs; .)
  .
NewArray<. out List<Expression> ee, out Expression arrayElementInit, out List<Expression> display .>
= (. ee = new List<Expression>();
     arrayElementInit = null;
     display = null;
     IToken x;
  .)
  "["                                (. x = t; .)
  ( "]"                              /* no size is given; this is allowed as long as an initialization display is given */
    "["                              (. display = new List<Expression>(); .)
    [ Expressions<display> ]
    "]"                              (. // we fill in the size
                                        ee.Add(new LiteralExpr(x, display.Count));
                                     .)
  | Expressions<ee>
    "]"                              (. // make sure an array class with this dimensionality exists
                                        var tmp = theBuiltIns.ArrayType(ee.Count, new IntType(), true);
                                     .)
    [ "(" Expression<out arrayElementInit, true, true>
      ")"
    | "["                            (. if (ee.Count > 1) {
                                          SemErr(t, "An initializing element display is allowed only for 1-dimensional arrays");
                                        }
                                        display = new List<Expression>();
                                     .)
      [ Expressions<display> ]
      "]"
    ]
  )
  (. if (ee.Count == 0) {
       // an error occurred while parsing, but we still want to make sure to return a nonempty "ee"
       ee.Add(new LiteralExpr(x, 0));
     }
  .)
  .
VarDeclStatement<.out Statement/*!*/ s.>
= (. IToken x = null, assignTok = null;  bool isGhost = false;
     LocalVariable d;
     AssignmentRhs r;
     List<LocalVariable> lhss = new List<LocalVariable>();
     List<AssignmentRhs> rhss = new List<AssignmentRhs>();
     IToken suchThatAssume = null;
     Expression suchThat = null;
     Attributes attrs = null;
     IToken endTok;
     s = dummyStmt;
  .)
  [ "ghost"                                 (. isGhost = true;  x = t; .)
  ]
  "var"                                     (. if (!isGhost) { x = t; } .)
  ( IF(!IsLetStmt())
    { Attribute<ref attrs> }
    LocalIdentTypeOptional<out d, isGhost>    (. lhss.Add(d); d.Attributes = attrs; attrs = null; .)
    { ","
      { Attribute<ref attrs> }
      LocalIdentTypeOptional<out d, isGhost>  (. lhss.Add(d); d.Attributes = attrs; attrs = null; .)
    }
    [ ":="                           (. assignTok = t; .)
      Rhs<out r>                     (. rhss.Add(r); .)
      { "," Rhs<out r>               (. rhss.Add(r); .)
      }
    | { Attribute<ref attrs> }
      ":|"                           (. assignTok = t; .)
      [ IF(la.kind == _assume)       /* an Expression can also begin with an "assume", so this says to resolve it to pick up any "assume" here */
        "assume"                     (. suchThatAssume = t; .)
      ]
      Expression<out suchThat, false, true>
    ]
    SYNC ";"                         (. endTok = t; .)
    (. ConcreteUpdateStatement update;
       if (suchThat != null) {
         var ies = new List<Expression>();
         foreach (var lhs in lhss) {
           ies.Add(new IdentifierExpr(lhs.Tok, lhs.Name));
         }
         update = new AssignSuchThatStmt(assignTok, endTok, ies, suchThat, suchThatAssume, attrs);
       } else if (rhss.Count == 0) {
         update = null;
       } else {
         var ies = new List<Expression>();
         foreach (var lhs in lhss) {
           ies.Add(new AutoGhostIdentifierExpr(lhs.Tok, lhs.Name));
         }
         update = new UpdateStmt(assignTok, endTok, ies, rhss);
       }
       s = new VarDeclStmt(x, endTok, lhss, update);
    .)
  | (. CasePattern<LocalVariable> pat;
       Expression e = dummyExpr;
       IToken id = t;
    .)
    CasePatternLocal<out pat, isGhost>
    ( ":="
    | { Attribute<ref attrs> }
      ":|"                          (.  SemErr(pat.tok, "LHS of assign-such-that expression must be variables, not general patterns"); .)
    )
    Expression<out e, false, true>
    
    ";"
    (. s = new LetStmt(e.tok, e.tok, pat, e); .)
  )
  .
IfStmt<out Statement/*!*/ ifStmt>
= (. Contract.Ensures(Contract.ValueAtReturn(out ifStmt) != null); IToken/*!*/ x;
     Expression guard = null;  IToken guardEllipsis = null;  bool isExistentialGuard = false;
     BlockStmt/*!*/ thn;
     BlockStmt/*!*/ bs;
     Statement/*!*/ s;
     Statement els = null;
     IToken bodyStart, bodyEnd, endTok;
     List<GuardedAlternative> alternatives;
     ifStmt = dummyIfStmt;  // to please the compiler
     bool usesOptionalBraces;
  .)
  "if"                       (. x = t; .)
  (
    IF(IsAlternative())
    AlternativeBlock<true, out alternatives, out usesOptionalBraces, out endTok>
    (. ifStmt = new AlternativeStmt(x, endTok, alternatives, usesOptionalBraces); .)
  |
    ( IF(IsExistentialGuard())
      ExistentialGuard<out guard, true>  (. isExistentialGuard = true; .)
    | Guard<out guard>
    | "..."                              (. guardEllipsis = t; .)
    )
    BlockStmt<out thn, out bodyStart, out bodyEnd>    (. endTok = thn.EndTok; .)
    [ "else"
      ( IfStmt<out s>                                 (. els = s; endTok = s.EndTok; .)
      | BlockStmt<out bs, out bodyStart, out bodyEnd> (. els = bs; endTok = bs.EndTok; .)
      )
    ]
    (. if (guardEllipsis != null) {
         ifStmt = new SkeletonStatement(new IfStmt(x, endTok, isExistentialGuard, guard, thn, els), guardEllipsis, null);
       } else {
         ifStmt = new IfStmt(x, endTok, isExistentialGuard, guard, thn, els);
       }
    .)
  )
  .
AlternativeBlock<.bool allowExistentialGuards, out List<GuardedAlternative> alternatives, out bool usesOptionalBraces, out IToken endTok.>
= (. alternatives = new List<GuardedAlternative>();
     endTok = null;
     usesOptionalBraces = false;
     GuardedAlternative alt;
  .)
  ( "{"    (. usesOptionalBraces = true; .)
    {
      AlternativeBlockCase<allowExistentialGuards, out alt>  (. alternatives.Add(alt); .)
    }
    "}"
  | /* Note, an alternative-less while is not parsed here; it is a body-less while (not an alternative while).
       Also, an alternative-less if is not allowed.
       These decisions save a Coco warning.
    */
    AlternativeBlockCase<allowExistentialGuards, out alt>  (. alternatives.Add(alt); .)
    { IF(la.kind == _case)
      AlternativeBlockCase<allowExistentialGuards, out alt>  (. alternatives.Add(alt); .)
    }
  )
  (. endTok = t; .)
  .
AlternativeBlockCase<.bool allowExistentialGuards, out GuardedAlternative alt.>
= (. IToken x;
     Expression e; bool isExistentialGuard;
     List<Statement> body;
  .)
  "case"                             (. x = t; isExistentialGuard = false; e = dummyExpr; .)
  ( IF(allowExistentialGuards && IsExistentialGuard())
    ExistentialGuard<out e, false >  (. isExistentialGuard = true; .)  // NB: don't allow lambda here
  | Expression<out e, true, false> // NB: don't allow lambda here
  )
  "=>"
  (. body = new List<Statement>(); .)
  SYNC  /* this SYNC and the one inside the loop below are used to avoid problems with the IsNotEndOfCase test. The SYNC will
          * skip until the next symbol that can legally occur here, which is either the beginning of a Stmt or whatever is allowed
          * to follow the CaseStatement.
          */
  { IF(IsNotEndOfCase()) /* This is a little sketchy. It would be nicer to be able to write IF(la is start-symbol of Stmt), but Coco doesn't allow that */
    Stmt<body>
    SYNC  /* see comment about SYNC above */
  }
  (. alt = new GuardedAlternative(x, isExistentialGuard, e, body); .)
  .
WhileStmt<out Statement stmt>
= (. Contract.Ensures(Contract.ValueAtReturn(out stmt) != null); IToken x;
     Expression guard = null;  IToken guardEllipsis = null;

     List<MaybeFreeExpression> invariants = new List<MaybeFreeExpression>();
     List<Expression> decreases = new List<Expression>();
     Attributes decAttrs = null;
     Attributes modAttrs = null;
     List<FrameExpression> mod = null;

     BlockStmt body = null;  IToken bodyEllipsis = null;
     IToken bodyStart = null, bodyEnd = null, endTok = Token.NoToken;
     List<GuardedAlternative> alternatives;
     stmt = dummyStmt;  // to please the compiler
     bool isDirtyLoop = true;
     bool usesOptionalBraces;
  .)
  "while"                    (. x = t; .)
  (
    IF(IsLoopSpec() || IsAlternative())
    { LoopSpec<invariants, decreases, ref mod, ref decAttrs, ref modAttrs> }
    AlternativeBlock<false, out alternatives, out usesOptionalBraces, out endTok>
    (. stmt = new AlternativeLoopStmt(x, endTok, invariants, new Specification<Expression>(decreases, decAttrs), new Specification<FrameExpression>(mod, modAttrs), alternatives, usesOptionalBraces); .)
  |
    ( Guard<out guard>           (. Contract.Assume(guard == null || cce.Owner.None(guard)); .)
    | "..."                      (. guardEllipsis = t; .)
    )
    { LoopSpec<invariants, decreases, ref mod, ref decAttrs, ref modAttrs> }
    ( IF(la.kind == _lbrace)      /* if there's an open brace, claim it as the beginning of the loop body (as opposed to a BlockStmt following the loop) */
      BlockStmt<out body, out bodyStart, out bodyEnd>  (. endTok = body.EndTok; isDirtyLoop = false; .)
    | IF(la.kind == _ellipsis)    /* if there's an ellipsis, claim it as standing for the loop body (as opposed to a "...;" statement following the loop) */
      "..."                      (. bodyEllipsis = t; endTok = t; isDirtyLoop = false; .)
    | /* go body-less */
    )
    (.
      if (guardEllipsis != null || bodyEllipsis != null) {
        if (mod != null) {
          SemErr(mod[0].E.tok, "'modifies' clauses are not allowed on refining loops");
        }
        if (body == null && !isDirtyLoop) {
          body = new BlockStmt(x, endTok, new List<Statement>());
        }
        stmt = new WhileStmt(x, endTok, guard, invariants, new Specification<Expression>(decreases, decAttrs), new Specification<FrameExpression>(null, null), body);
        stmt = new SkeletonStatement(stmt, guardEllipsis, bodyEllipsis);
      } else {
        // The following statement protects against crashes in case of parsing errors
        if (body == null && !isDirtyLoop) {
          body = new BlockStmt(x, endTok, new List<Statement>());
        }
        stmt = new WhileStmt(x, endTok, guard, invariants, new Specification<Expression>(decreases, decAttrs), new Specification<FrameExpression>(mod, modAttrs), body);
      }
    .)
  )
  .
LoopSpec<.List<MaybeFreeExpression> invariants, List<Expression> decreases, ref List<FrameExpression> mod, ref Attributes decAttrs, ref Attributes modAttrs.>
= (. Expression e; FrameExpression fe;
     bool isFree = false; Attributes attrs = null;
  .)
  ( SYNC
    [ "free"                                      (. isFree = true; errors.Deprecated(t, "the 'free' keyword is soon to be deprecated"); .)
    ]
    "invariant"
    { IF(IsAttribute()) Attribute<ref attrs> }
    Expression<out e, false, true>                (. invariants.Add(new MaybeFreeExpression(e, isFree, attrs)); .)
    OldSemi
  | SYNC "decreases"
    { IF(IsAttribute()) Attribute<ref decAttrs> }
    DecreasesList<decreases, true, true>
    OldSemi
  | SYNC "modifies"                               (. mod = mod ?? new List<FrameExpression>(); .)
    { IF(IsAttribute()) Attribute<ref modAttrs> }
    FrameExpression<out fe, false, true>          (. mod.Add(fe); .)
    { "," FrameExpression<out fe, false, true>    (. mod.Add(fe); .)
    }
    OldSemi
  )
  .
DecreasesList<.List<Expression> 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);
                                                }
                                             .)
  { "," 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);
                                                }
                                             .)
  }
  .
Guard<out Expression e>   /* null represents demonic-choice */
= (. Expression/*!*/ ee;  e = null; .)
  ( "*"                             (. e = null; .)
  | IF(IsParenStar())  "(" "*" ")"  (. e = null; .)
  | Expression<out ee, true, true>        (. e = ee; .)
  )
  .
ExistentialGuard<out Expression e, bool allowLambda>
= (. var bvars = new List<BoundVar>();
     BoundVar bv;  IToken x;
     Attributes attrs = null;
     Expression body;
  .)
  IdentTypeOptional<out bv>                    (. bvars.Add(bv); x = bv.tok; .)
  { ","
    IdentTypeOptional<out bv>                  (. bvars.Add(bv); .)
  }
  { Attribute<ref attrs> }
  ":|"
  Expression<out body, true, allowLambda>
  (. e = new ExistsExpr(x, bvars, null, body, attrs); .)
  .
MatchStmt<out Statement/*!*/ s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null);
     IToken x;  Expression/*!*/ e;  MatchCaseStmt/*!*/ c;
     List<MatchCaseStmt/*!*/> cases = new List<MatchCaseStmt/*!*/>();
     bool usesOptionalBraces = false;
  .)
  "match"                     (. x = t; .)
  Expression<out e, true, true>
  ( IF(la.kind == _lbrace)  /* always favor brace-enclosed match body to a case-less match */
    "{" (. usesOptionalBraces = true; .)
        { CaseStatement<out c> (. cases.Add(c); .) }
    "}"
  |     { IF(la.kind == _case)  /* let each "case" bind to the closest preceding "match" */
          CaseStatement<out c> (. cases.Add(c); .)
        }
  )
  (. s = new MatchStmt(x, t, e, cases, usesOptionalBraces); .)
  .
CaseStatement<out MatchCaseStmt/*!*/ c>
= (. Contract.Ensures(Contract.ValueAtReturn(out c) != null);
     IToken/*!*/ x, id;
     var arguments = new List<CasePattern<BoundVar>>();
     CasePattern<BoundVar>/*!*/ pat;
     var body = new List<Statement/*!*/>();
     string/*!*/ name = "";
  .)
  "case"                      (. x = t; .)
  ( Ident<out id>             (. name = id.val; .)
    [ "("
       [ CasePattern<out pat>        (. arguments.Add(pat); .)
         { "," CasePattern<out pat>  (. arguments.Add(pat); .)
         }
       ]
    ")" ]
  | "("
      CasePattern<out pat>        (. arguments.Add(pat); .)
      { "," CasePattern<out pat>  (. arguments.Add(pat); .)
      }
    ")"
  )
  "=>"
    SYNC  /* this SYNC and the one inside the loop below are used to avoid problems with the IsNotEndOfCase test. The SYNC will
           * skip until the next symbol that can legally occur here, which is either the beginning of a Stmt or whatever is allowed
           * to follow the CaseStatement.
           */
    { IF(IsNotEndOfCase()) /* This is a little sketchy. It would be nicer to be able to write IF(la is start-symbol of Stmt), but Coco doesn't allow that */
      Stmt<body>
      SYNC  /* see comment about SYNC above */
    }
  (. c = new MatchCaseStmt(x, name, arguments, body); .)
  .
/*------------------------------------------------------------------------*/
AssertStmt<out Statement/*!*/ s, bool inExprContext>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x;
     Expression e = dummyExpr; Attributes attrs = null;
     IToken dotdotdot = null;
     BlockStmt proof = null;
     IToken proofStart, proofEnd;
     IToken lbl = null;
  .)
  "assert"                                     (. x = t; .)
  { IF(IsAttribute()) Attribute<ref attrs> }
  ( [ IF(IsLabel(!inExprContext))
      LabelIdent<out lbl> ":"
    ]
    Expression<out e, false, true>
    ( "by"
      BlockStmt<out proof, out proofStart, out proofEnd>
    | ";"
    )
  | "..."                                      (. dotdotdot = t; .)
    ";"
  )
  (. if (dotdotdot != null) {
       s = new SkeletonStatement(new AssertStmt(x, t, new LiteralExpr(x, true), null, null, attrs), dotdotdot, null);
     } else {
       s = new AssertStmt(x, t, e, proof, lbl == null ? null : new AssertLabel(lbl, lbl.val), attrs);
     }
  .)
  .
AssumeStmt<out Statement/*!*/ s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x;
     Expression e = dummyExpr; Attributes attrs = null;
     IToken dotdotdot = null;
  .)
  "assume"                                     (. x = t; .)
  { IF(IsAttribute()) Attribute<ref attrs> }
  ( Expression<out e, false, true>
  | "..."                                      (. dotdotdot = t; .)
  )
  ";"
  (. if (dotdotdot != null) {
       s = new SkeletonStatement(new AssumeStmt(x, t, new LiteralExpr(x, true), attrs), dotdotdot, null);
     } else {
       s = new AssumeStmt(x, t, e, attrs);
     }
  .)
  .
PrintStmt<out Statement s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null);
     IToken x;  Expression e;
     var args = new List<Expression>();
  .)
  "print"                                      (. x = t; .)
  Expression<out e, false, true>               (. args.Add(e); .)
  { "," Expression<out e, false, true>         (. args.Add(e); .)
  }
  ";"                                          (. s = new PrintStmt(x, t, args); .)
  .

RevealStmt<out Statement s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null);
     IToken x; Expression e; var es = new List<Expression>();
  .)
  "reveal"                                      (. x = t; .)
  Expression<out e, false, true>                (. es.Add(e); .)
  { "," Expression<out e, false, true>          (. es.Add(e); .)
  }
  ";"                                           (. s = new RevealStmt(x, t, es); .)
  .

ForallStmt<out Statement/*!*/ s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null);
     IToken/*!*/ x = Token.NoToken;
     List<BoundVar> bvars = null;
     Attributes attrs = null;
     Expression range = null;
     var ens = new List<MaybeFreeExpression/*!*/>();
     bool isFree;
     Expression/*!*/ e;
     BlockStmt block = null;
     IToken bodyStart, bodyEnd;
     IToken tok = Token.NoToken;
  .)
  ( "forall"                                  (. x = t; tok = x; .)
  | "parallel"                                (. x = t;
                                                 errors.Deprecated(t, "the 'parallel' keyword has been deprecated; the comprehension statement now uses the keyword 'forall' (and the parentheses around the bound variables are now optional)");
                                              .)
  )

  ( IF(la.kind == _openparen)  /* disambiguation needed, because of the possibility of a body-less forall statement */
    "(" [ QuantifierDomain<out bvars, out attrs, out range> ] ")"
  |     [ IF(la.kind == _ident)  /* disambiguation needed, because of the possibility of a body-less forall statement */
          QuantifierDomain<out bvars, out attrs, out range>
        ]
  )
  (. if (bvars == null) { bvars = new List<BoundVar>(); }
     if (range == null) { range = new LiteralExpr(x, true); }
  .)

  {                                         (. isFree = false; .)
    [ "free"                                (. isFree = true;
                                               errors.Deprecated(t, "the 'free' keyword is soon to be deprecated");
                                            .)
    ]
    "ensures" Expression<out e, false, true>  (. ens.Add(new MaybeFreeExpression(e, isFree)); .)
    OldSemi                                   (. tok = t; .)
  }
  [ IF(la.kind == _lbrace)  /* if the input continues like a block statement, take it to be the body of the forall statement; a body-less forall statement must continue in some other way */
    BlockStmt<out block, out bodyStart, out bodyEnd>
  ]
  (. if (DafnyOptions.O.DisallowSoundnessCheating && block == null && 0 < ens.Count) {
        SemErr(t, "a forall statement with an ensures clause must have a body");
     }

     if (block != null) {
        tok = block.EndTok;
     }
     s = new ForallStmt(x, tok, bvars, attrs, range, ens, block);
  .)
  .

ModifyStmt<out Statement s>
= (. IToken tok;  IToken endTok = Token.NoToken;
     Attributes attrs = null;
     FrameExpression fe;  var mod = new List<FrameExpression>();
     BlockStmt body = null;  IToken bodyStart;
     IToken ellipsisToken = null;
  .)
  "modify"           (. tok = t; .)
  { IF(IsAttribute()) Attribute<ref attrs> }
  /* Note, there is an ambiguity here, because a curly brace may look like a FrameExpression and
   * may also look like a BlockStmt.  We're happy to parse the former, because if the user intended
   * the latter, then an explicit FrameExpression of {} could be given.
   */
  ( FrameExpression<out fe, false, true>       (. mod.Add(fe); .)
    { "," FrameExpression<out fe, false, true> (. mod.Add(fe); .)
    }
  | "..."                               (. ellipsisToken = t; .)
  )
  ( BlockStmt<out body, out bodyStart, out endTok>
  | SYNC ";"         (. endTok = t; .)
  )
  (. s = new ModifyStmt(tok, endTok, mod, attrs, body);
     if (ellipsisToken != null) {
       s = new SkeletonStatement(s, ellipsisToken, null);
     }
  .)
  .

CalcStmt<out Statement s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null);
     IToken x;
     Attributes attrs = null;
     CalcStmt.CalcOp op, userSuppliedOp = null, resOp = Microsoft.Dafny.CalcStmt.DefaultOp;
     var lines = new List<Expression>();
     var hints = new List<BlockStmt>();
     CalcStmt.CalcOp stepOp;
     var stepOps = new List<CalcStmt.CalcOp>();
     Expression e;
     IToken opTok;
     IToken danglingOperator = null;
  .)
  "calc"                                                  (. x = t; .)
  { IF(IsAttribute()) Attribute<ref attrs> }
  [ CalcOp<out opTok, out userSuppliedOp>                 (. if (userSuppliedOp.ResultOp(userSuppliedOp) == null) { // guard against non-transitive calcOp (like !=)
                                                               SemErr(opTok, "the main operator of a calculation must be transitive");
                                                             } else {
                                                               resOp = userSuppliedOp;
                                                             }
                                                          .)
  ]
  "{"
  { Expression<out e, false, true>                        (. lines.Add(e); stepOp = null; danglingOperator = null; .)
    ";"
    [ CalcOp<out opTok, out op>                           (. var maybeOp = resOp.ResultOp(op);
                                                             if (maybeOp == null) {
                                                               SemErr(opTok, "this operator cannot continue this calculation");
                                                             } else {
                                                               stepOp = op;
                                                               resOp = maybeOp;
                                                               danglingOperator = opTok;
                                                             }
                                                          .)
    ]                                                     (. stepOps.Add(stepOp); .)

    /* now for the hint, which we build up as a possibly empty sequence of statements placed into one BlockStmt */
    (. var subhints = new List<Statement>();
       IToken hintStart = la;  IToken hintEnd = hintStart;
       IToken t0, t1;
       BlockStmt subBlock; Statement subCalc;
    .)
    { IF(la.kind == _lbrace || la.kind == _calc)  /* Grab as a hint if possible, not a next line in the calculation whose expression begins with an open brace
                                                   * or StmtExpr containing a calc.  A user has to rewrite such a line to be enclosed in parentheses.
                                                   */
      ( BlockStmt<out subBlock, out t0, out t1>   (. hintEnd = subBlock.EndTok; subhints.Add(subBlock); .)
      | CalcStmt<out subCalc>                     (. hintEnd = subCalc.EndTok; subhints.Add(subCalc); .)
      )
    }
    (. var h = new BlockStmt(hintStart, hintEnd, subhints); // if the hint is empty, hintStart is the first token of the next line, but it doesn't matter because the block statement is just used as a container
       hints.Add(h);
       if (h.Body.Count != 0) { danglingOperator = null; }
    .)
  }
  "}"
  (.
    if (danglingOperator != null) {
      SemErr(danglingOperator, "a calculation cannot end with an operator");
    }
    if (lines.Count > 0) {
      // Repeat the last line to create a dummy line for the dangling hint
      lines.Add(lines[lines.Count - 1]);
    }
    s = new CalcStmt(x, t, userSuppliedOp, lines, hints, stepOps, attrs);
  .)
  .
CalcOp<out IToken x, out CalcStmt.CalcOp/*!*/ op>
= (. var binOp = BinaryExpr.Opcode.Eq; // Returns Eq if parsing fails because it is compatible with any other operator
     Expression k = null;
     x = null;
  .)
  ( "=="           (. x = t;  binOp = BinaryExpr.Opcode.Eq; .)
    [ "#" "[" Expression<out k, true, true> "]" ]
  | "<"            (. x = t;  binOp = BinaryExpr.Opcode.Lt; .)
  | ">"            (. x = t;  binOp = BinaryExpr.Opcode.Gt; .)
  | "<="           (. x = t;  binOp = BinaryExpr.Opcode.Le; .)
  | ">="           (. x = t;  binOp = BinaryExpr.Opcode.Ge; .)
  | "!="           (. x = t;  binOp = BinaryExpr.Opcode.Neq; .)
  | '\u2260'       (. x = t;  binOp = BinaryExpr.Opcode.Neq; .)
  | '\u2264'       (. x = t;  binOp = BinaryExpr.Opcode.Le; .)
  | '\u2265'       (. x = t;  binOp = BinaryExpr.Opcode.Ge; .)
  | EquivOp        (. x = t;  binOp = BinaryExpr.Opcode.Iff; .)
  | ImpliesOp      (. x = t;  binOp = BinaryExpr.Opcode.Imp; .)
  | ExpliesOp      (. x = t;  binOp = BinaryExpr.Opcode.Exp; .)
  )
  (.
    if (k == null) {
      op = new Microsoft.Dafny.CalcStmt.BinaryCalcOp(binOp);
    } else {
      op = new Microsoft.Dafny.CalcStmt.TernaryCalcOp(k);
    }
  .)
  .

/*------------------------------------------------------------------------*/
/* Note. In order to avoid LL(1) warnings for expressions that "parse as far as possible", it is
 * necessary to use Coco/R's IF construct.  That means there are two ways to check for some of
 * these operators, both in Is...() methods (defined above) and as grammar non-terminals (defined
 * here).  These pairs of definitions must be changed together.
 */
EquivOp = "<==>" | '\u21d4'.
ImpliesOp = "==>" | '\u21d2'.
ExpliesOp = "<==" | '\u21d0'.
AndOp = "&&" | '\u2227'.
OrOp = "||" | '\u2228'.

NegOp = "!" | '\u00ac'.
Forall = "forall" | '\u2200'.
Exists = "exists" | '\u2203'.
QSep = "::" | '\u2022'.

/* The "allowSemi" argument says whether or not the expression
 * to be parsed is allowed to have the form S;E where S is a call to a lemma.
 * "allowSemi" should be passed in as "false" whenever the expression to
 * be parsed sits in a context that itself is terminated by a semi-colon.
 *
 * The "allowLambda" says whether or not the expression to be parsed is
 * allowed to be a lambda expression.  More precisely, an identifier or
 * parenthesized-enclosed comma-delimited list of identifiers is allowed to
 * continue as a lambda expression (that is, continue with a "reads", "requires",
 * or "=>") only if "allowLambda" is true.  This affects function/method/iterator
 * specifications, if/while statements with guarded alternatives, and expressions
 * in the specification of a lambda expression itself.
 *
 * The "allowBitwiseOps" says whether or not to include or bypass bitwise operators
 * at the top level of this expression. It is passed in as "false" only inside
 * cardinality brackets, that is, "|expr|".
 */
Expression<out Expression e, bool allowSemi, bool allowLambda, bool allowBitwiseOps = true>
= (. Expression e0; IToken endTok; .)
  EquivExpression<out e, allowSemi, allowLambda, allowBitwiseOps>
  [ IF(SemiFollowsCall(allowSemi, e))
    /* here we parse the ";E" that is part of a "LemmaCall;E" expression (other "S;E" expressions are parsed elsewhere) */
    ";"                       (. endTok = t; .)
    Expression<out e0, allowSemi, allowLambda>
    (. e = new StmtExpr(e.tok,
             new UpdateStmt(e.tok, endTok, new List<Expression>(), new List<AssignmentRhs>() { new ExprRhs(e, null) }),
             e0);
    .)
  ]
  .
/*------------------------------------------------------------------------*/
EquivExpression<out Expression e0, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x;  Expression/*!*/ e1; .)
  ImpliesExpliesExpression<out e0, allowSemi, allowLambda, allowBitwiseOps>
  { IF(IsEquivOp())  /* read an EquivExpression as far as possible */
    EquivOp                                                   (. x = t; .)
    ImpliesExpliesExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>  (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Iff, e0, e1); .)
  }
  .
/*------------------------------------------------------------------------*/
ImpliesExpliesExpression<out Expression e0, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x;  Expression/*!*/ e1; .)
  LogicalExpression<out e0, allowSemi, allowLambda, allowBitwiseOps>
  [ IF(IsImpliesOp() || IsExpliesOp())  /* read an ImpliesExpliesExpression as far as possible */
    /* Note, the asymmetry in the parsing of implies and explies expressions stems from the fact that
     * implies is right associative whereas reverse implication is left associative
     */
    ( ImpliesOp                                               (. x = t; .)
      ImpliesExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>       (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Imp, e0, e1); .)
    | ExpliesOp                                               (. x = t; .)
      LogicalExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>       (. // The order of operands is reversed so that it can be turned into implication during resolution 
                                                                 e0 = new BinaryExpr(x, BinaryExpr.Opcode.Exp, e1, e0); .)
      { IF(IsExpliesOp())  /* read a reverse implication as far as possible */
        ExpliesOp                                             (. x = t; .)
        LogicalExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>     (. //The order of operands is reversed so that it can be turned into implication during resolution
                                                                 e0 = new BinaryExpr(x, BinaryExpr.Opcode.Exp, e1, e0); 
                                                              .)
      }
    )
  ]
  .
ImpliesExpression<out Expression e0, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x;  Expression/*!*/ e1; .)
  LogicalExpression<out e0, allowSemi, allowLambda, allowBitwiseOps>
  [ IF(IsImpliesOp())  /* read an ImpliesExpression as far as possible */
    ImpliesOp                                               (. x = t; .)
    ImpliesExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>       (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Imp, e0, e1); .)
  ]
  .
/*------------------------------------------------------------------------*/
LogicalExpression<out Expression e0, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x;  Expression/*!*/ e1;
     Expression first;
     e0 = dummyExpr; /* mute the warning */
  .)
  ( AndOp                                                       (. x = t; .)
    RelationalExpression<out e0, allowSemi, allowLambda, allowBitwiseOps>        (. first = e0; .)
    { IF(IsAndOp())  /* read a conjunction as far as possible */
      AndOp                                                     (. x = t; .)
      RelationalExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>      (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1); .)
    }
    (. if (e0 == first) {
         // There was only one conjunct. To make sure that the type checker still checks it to
         // be a boolean, we conjoin "true" to its left.
         e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, new LiteralExpr(x, true), e0);
       }
    .)
  | OrOp                                                        (. x = t; .)
    RelationalExpression<out e0, allowSemi, allowLambda, allowBitwiseOps>        (. first = e0; .)
    { IF(IsOrOp())  /* read a disjunction as far as possible */
      OrOp                                                      (. x = t; .)
      RelationalExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>      (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1); .)
    }
    (. if (e0 == first) {
         // There was only one disjunct. To make sure that the type checker still checks it to
         // be a boolean, we disjoin [sic] "false" to its left.
         e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, new LiteralExpr(x, false), e0);
       }
    .)
  | RelationalExpression<out e0, allowSemi, allowLambda, allowBitwiseOps>
    [ IF(IsAndOp() || IsOrOp())  /* read a LogicalExpression as far as possible */
      ( AndOp                                                   (. x = t; .)
        RelationalExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>    (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1); .)
        { IF(IsAndOp())  /* read a conjunction as far as possible */
          AndOp                                                 (. x = t; .)
          RelationalExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>  (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1); .)
        }
      | OrOp                                                    (. x = t; .)
        RelationalExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>    (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1); .)
        { IF(IsOrOp())  /* read a disjunction as far as possible */
          OrOp                                                  (. x = t; .)
          RelationalExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>  (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1); .)
        }
      )
    ]
  )
  .
/*------------------------------------------------------------------------*/
RelationalExpression<out Expression e, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
     IToken x = null;  Expression e0, e1 = null;  BinaryExpr.Opcode op;
     List<Expression> chain = null;
     List<BinaryExpr.Opcode> ops = null;
     List<IToken> opLocs = null;
     List<Expression/*?*/> prefixLimits = null;
     Expression k;
     int kind = 0;  // 0 ("uncommitted") indicates chain of ==, possibly with one !=
                    // 1 ("ascending")   indicates chain of ==, <, <=, possibly with one !=
                    // 2 ("descending")  indicates chain of ==, >, >=, possibly with one !=
                    // 3 ("illegal")     indicates illegal chain
                    // 4 ("disjoint")    indicates chain of disjoint set operators
     bool hasSeenNeq = false;
  .)
  ShiftTerm<out e0, allowSemi, allowLambda, allowBitwiseOps>
                                   (. e = e0; .)
  [ IF(IsRelOp())  /* read a RelationalExpression as far as possible */
    RelOp<out x, out op, out k>
    ShiftTerm<out e1, allowSemi, allowLambda, allowBitwiseOps>
                                   (. if (k == null) {
                                        e = new BinaryExpr(x, op, e0, e1);
                                      } else {
                                        Contract.Assert(op == BinaryExpr.Opcode.Eq || op == BinaryExpr.Opcode.Neq);
                                        e = new TernaryExpr(x, op == BinaryExpr.Opcode.Eq ? TernaryExpr.Opcode.PrefixEqOp : TernaryExpr.Opcode.PrefixNeqOp, k, e0, e1);
                                      }
                                   .)
    { IF(IsRelOp())  /* read a RelationalExpression as far as possible */
                                   (. if (chain == null) {
                                        chain = new List<Expression>();
                                        ops = new List<BinaryExpr.Opcode>();
                                        opLocs = new List<IToken>();
                                        prefixLimits = new List<Expression>();
                                        chain.Add(e0); ops.Add(op); opLocs.Add(x); prefixLimits.Add(k); chain.Add(e1);
                                        switch (op) {
                                          case BinaryExpr.Opcode.Eq:
                                            kind = 0;  break;
                                          case BinaryExpr.Opcode.Neq:
                                            kind = 0;  hasSeenNeq = true;  break;
                                          case BinaryExpr.Opcode.Lt:
                                          case BinaryExpr.Opcode.Le:
                                            kind = 1;  break;
                                          case BinaryExpr.Opcode.Gt:
                                          case BinaryExpr.Opcode.Ge:
                                            kind = 2;  break;
                                          case BinaryExpr.Opcode.Disjoint:
                                            kind = 4;  break;
                                          default:
                                            kind = 3;  break;
                                        }
                                      }
                                   .)
      RelOp<out x, out op, out k>  (. switch (op) {
                                        case BinaryExpr.Opcode.Eq:
                                          if (kind != 0 && kind != 1 && kind != 2) { SemErr(x, "chaining not allowed from the previous operator"); kind = 3; }
                                          break;
                                        case BinaryExpr.Opcode.Neq:
                                          if (hasSeenNeq) { SemErr(x, "a chain cannot have more than one != operator"); kind = 3; }
                                          else if (kind != 0 && kind != 1 && kind != 2) { SemErr(x, "this operator cannot continue this chain"); kind = 3; }
                                          hasSeenNeq = true;  break;
                                        case BinaryExpr.Opcode.Lt:
                                        case BinaryExpr.Opcode.Le:
                                          if (kind == 0) { kind = 1; }
                                          else if (kind != 1) { SemErr(x, "this operator chain cannot continue with an ascending operator"); kind = 3; }
                                          break;
                                        case BinaryExpr.Opcode.Gt:
                                        case BinaryExpr.Opcode.Ge:
                                          if (kind == 0) { kind = 2; }
                                          else if (kind != 2) { SemErr(x, "this operator chain cannot continue with a descending operator"); kind = 3; }
                                          break;
                                        case BinaryExpr.Opcode.Disjoint:
                                          if (kind != 4) { SemErr(x, "can only chain disjoint (!!) with itself."); kind = 3; }
                                          break;
                                        default:
                                          SemErr(x, "this operator cannot be part of a chain");
                                          kind = 3;  break;
                                      }
                                   .)
      ShiftTerm<out e1, allowSemi, allowLambda, allowBitwiseOps>
                                   (. ops.Add(op); opLocs.Add(x); prefixLimits.Add(k); chain.Add(e1);
                                   .)
    }
  ]
  (. if (chain != null && kind != 3) {
       e = new ChainingExpression(opLocs[0], chain, ops, opLocs, prefixLimits);
     }
  .)
  .
RelOp<out IToken/*!*/ x, out BinaryExpr.Opcode op, out Expression k>
= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null);
     x = Token.NoToken;  op = BinaryExpr.Opcode.Add/*(dummy)*/;
     IToken y;
     k = null;
  .)
  ( "=="           (. x = t;  op = BinaryExpr.Opcode.Eq; .)
    [ "#" "[" Expression<out k, true, true> "]" ]
  | "<"            (. x = t;  op = BinaryExpr.Opcode.Lt; .)
  | ">"            (. x = t;  op = BinaryExpr.Opcode.Gt; .)
  | "<="           (. x = t;  op = BinaryExpr.Opcode.Le; .)
  | ">="           (. x = t;  op = BinaryExpr.Opcode.Ge; .)
  | "!="           (. x = t;  op = BinaryExpr.Opcode.Neq; .)
    [ "#" "[" Expression<out k, true, true> "]" ]
  | "in"           (. x = t;  op = BinaryExpr.Opcode.In; .)
  | notIn          (. x = t;  op = BinaryExpr.Opcode.NotIn; .)
  | /* The next operator is "!!", but we have to scan it as two "!", since the scanner is greedy
       so if "!!" is a valid token, we won't be able to scan it as two "!" when needed: */
    "!"            (. x = t;  y = Token.NoToken; .)
    [ IF(la.val == "!")
      "!"          (. y = t; .)
    ]              (. if (y == Token.NoToken) {
                        SemErr(x, "invalid RelOp");
                      } else if (y.pos != x.pos + 1) {
                        SemErr(x, "invalid RelOp (perhaps you intended \"!!\" with no intervening whitespace?)");
                      } else {
                        x.val = "!!";
                        op = BinaryExpr.Opcode.Disjoint;
                      }
                   .)
  | '\u2260'       (. x = t;  op = BinaryExpr.Opcode.Neq; .)
  | '\u2264'       (. x = t;  op = BinaryExpr.Opcode.Le; .)
  | '\u2265'       (. x = t;  op = BinaryExpr.Opcode.Ge; .)
  )
  .
/*------------------------------------------------------------------------*/
ShiftTerm<out Expression e0, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null);
     IToken x = Token.NoToken;  Expression e1;  BinaryExpr.Opcode op = BinaryExpr.Opcode.LeftShift/*(dummy)*/;
  .)
  Term<out e0, allowSemi, allowLambda, allowBitwiseOps>
  { IF(IsShiftOp())  /* read a Term as far as possible */
    ( "<"            (. x = t;  op = BinaryExpr.Opcode.LeftShift; .)
      "<"            (. x.val = "<<";  Contract.Assert(t.pos == x.pos + 1); .)
    | ">"            (. x = t;  op = BinaryExpr.Opcode.RightShift; .)
      ">"            (. x.val = "<<";  Contract.Assert(t.pos == x.pos + 1); .)
    )
    Term<out e1, allowSemi, allowLambda, allowBitwiseOps> (. e0 = new BinaryExpr(x, op, e0, e1); .)
  }
  .
/*------------------------------------------------------------------------*/
Term<out Expression e0, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x;  Expression/*!*/ e1;  BinaryExpr.Opcode op; .)
  Factor<out e0, allowSemi, allowLambda, allowBitwiseOps>
  { IF(IsAddOp())  /* read a Term as far as possible */
    AddOp<out x, out op>
    Factor<out e1, allowSemi, allowLambda, allowBitwiseOps> (. e0 = new BinaryExpr(x, op, e0, e1); .)
  }
  .
AddOp<out IToken x, out BinaryExpr.Opcode op>
= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken;  op=BinaryExpr.Opcode.Add/*(dummy)*/; .)
  ( "+"            (. x = t;  op = BinaryExpr.Opcode.Add; .)
  | "-"            (. x = t;  op = BinaryExpr.Opcode.Sub; .)
  )
  .
/*------------------------------------------------------------------------*/
Factor<out Expression e0, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x;  Expression/*!*/ e1;  BinaryExpr.Opcode op; .)
  BitvectorFactor<out e0, allowSemi, allowLambda, allowBitwiseOps>
  { IF(IsMulOp())  /* read a Factor as far as possible */
    MulOp<out x, out op>
    BitvectorFactor<out e1, allowSemi, allowLambda, allowBitwiseOps> (. e0 = new BinaryExpr(x, op, e0, e1); .)
  }
  .
MulOp<out IToken x, out BinaryExpr.Opcode op>
= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken;  op = BinaryExpr.Opcode.Add/*(dummy)*/; .)
  ( "*"            (. x = t;  op = BinaryExpr.Opcode.Mul; .)
  | "/"            (. x = t;  op = BinaryExpr.Opcode.Div; .)
  | "%"            (. x = t;  op = BinaryExpr.Opcode.Mod; .)
  )
  .
/*------------------------------------------------------------------------*/
BitvectorFactor<out Expression e0, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x;  Expression/*!*/ e1;  BinaryExpr.Opcode op; .)
  AsExpression<out e0, allowSemi, allowLambda, allowBitwiseOps>
  [ IF(allowBitwiseOps && IsBitwiseOp())  /* read a BitvectorFactor as far as possible, but not in the context inside a |.| size expression */
    ( (. op = BinaryExpr.Opcode.BitwiseAnd; .)
      "&"                                                             (. x = t; .)
      AsExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>   (. e0 = new BinaryExpr(x, op, e0, e1); .)
      { IF(IsBitwiseAndOp())
        "&"                                                           (. x = t; .)
        AsExpression<out e1, allowSemi, allowLambda, allowBitwiseOps> (. e0 = new BinaryExpr(x, op, e0, e1); .)
      }
    | (. op = BinaryExpr.Opcode.BitwiseOr; .)
      "|"                                                             (. x = t; .)
      AsExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>   (. e0 = new BinaryExpr(x, op, e0, e1); .)
      { IF(IsBitwiseOrOp())
        "|"                                                           (. x = t; .)
        AsExpression<out e1, allowSemi, allowLambda, allowBitwiseOps> (. e0 = new BinaryExpr(x, op, e0, e1); .)
      }
    | (. op = BinaryExpr.Opcode.BitwiseXor; .)
      "^"                                                             (. x = t; .)
      AsExpression<out e1, allowSemi, allowLambda, allowBitwiseOps>   (. e0 = new BinaryExpr(x, op, e0, e1); .)
      { IF(IsBitwiseXorOp())
        "^"                                                           (. x = t; .)
        AsExpression<out e1, allowSemi, allowLambda, allowBitwiseOps> (. e0 = new BinaryExpr(x, op, e0, e1); .)
      }
    )
  ]
  .
/*------------------------------------------------------------------------*/
AsExpression<out Expression e, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. IToken tok; IToken x; Type toType; .)
  UnaryExpression<out e, allowSemi, allowLambda, allowBitwiseOps>
  { IF(IsAs())
    "as"                                     (. tok = t; .)
     TypeAndToken<out x, out toType, true>   (. e = new ConversionExpr(tok, e, toType); .)
  }
  .
UnaryExpression<out Expression e, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;  e = dummyExpr; .)
  ( "-"                                             (. x = t; .)
    UnaryExpression<out e, allowSemi, allowLambda, allowBitwiseOps>  (. e = new NegationExpression(x, e); .)
  | NegOp                                           (. x = t; .)
    UnaryExpression<out e, allowSemi, allowLambda, allowBitwiseOps>  (. e = new UnaryOpExpr(x, UnaryOpExpr.Opcode.Not, e); .)

  | IF(IsMapDisplay())  /* this alternative must be checked before going into EndlessExpression, where there is another "map" */
    "map"                                           (. x = t; .)
    MapDisplayExpr<x, true, out e>
    { IF(IsSuffix()) Suffix<ref e> }
  | IF(IsIMapDisplay())  /* this alternative must be checked before going into EndlessExpression, where there is another "imap" */
    "imap"                                          (. x = t; .)
    MapDisplayExpr<x, false, out e>
    { IF(IsSuffix()) Suffix<ref e> }
  | IF(IsISetDisplay())  /* this alternative must be checked before going into EndlessExpression, where there is another "iset" */
    "iset"                                          (. x = t; .)
    ISetDisplayExpr<x, false, out e>
    { IF(IsSuffix()) Suffix<ref e> }
  | IF(IsLambda(allowLambda))
    LambdaExpression<out e, allowSemi, allowBitwiseOps>  /* this is an endless expression */
  | EndlessExpression<out e, allowSemi, allowLambda, allowBitwiseOps>
  | NameSegment<out e>
    { IF(IsSuffix()) Suffix<ref e> }
  | DisplayExpr<out e>
    { IF(IsSuffix()) Suffix<ref e> }
  | MultiSetExpr<out e>
    { IF(IsSuffix()) Suffix<ref e> }
  | ConstAtomExpression<out e, allowSemi, allowLambda>
    { IF(IsSuffix()) Suffix<ref e> }
  )
  .
Lhs<out Expression e>
= (. e = dummyExpr;  // the assignment is to please the compiler, the dummy value to satisfy contracts in the event of a parse error
  .)
  ( NameSegment<out e>
    { Suffix<ref e> }
  | ConstAtomExpression<out e, false, false>
    Suffix<ref e>
    { Suffix<ref e> }
  )
  .

/* A ConstAtomExpression is never an l-value, and does not start with an identifier. */
ConstAtomExpression<out Expression e, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
     IToken/*!*/ x;  BigInteger n;   Basetypes.BigDec d;
     e = dummyExpr;  Type toType = null;
  .)
  ( "false"                                    (. e = new LiteralExpr(t, false); .)
  | "true"                                     (. e = new LiteralExpr(t, true); .)
  | "null"                                     (. e = new LiteralExpr(t); .)
  | Nat<out n>                                 (. e = new LiteralExpr(t, n); .)
  | Dec<out d>                                 (. e = new LiteralExpr(t, d); .)
  | charToken                                  (. e = new CharLiteralExpr(t, t.val.Substring(1, t.val.Length - 2)); .)
  | stringToken                                (. bool isVerbatimString;
                                                  string s = Util.RemoveParsedStringQuotes(t.val, out isVerbatimString);
                                                  e = new StringLiteralExpr(t, s, isVerbatimString);
                                               .)
  | "this"                                     (. e = new ThisExpr(t); .)
  | "fresh"                                    (. x = t; .)
    "(" Expression<out e, true, true> ")"      (. e = new UnaryOpExpr(x, UnaryOpExpr.Opcode.Fresh, e); .)
  | "allocated"                                (. x = t; .)
    "(" Expression<out e, true, true> ")"      (. e = new UnaryOpExpr(x, UnaryOpExpr.Opcode.Allocated, e); .)
  | "unchanged"                                (. x = t; FrameExpression fe; var mod = new List<FrameExpression>(); IToken oldAt = null; .)
    [ "@" LabelIdent<out oldAt> ]
    "(" 
      FrameExpression<out fe, false, false>         (. mod.Add(fe); .)
      { "," FrameExpression<out fe, false, false>   (. mod.Add(fe); .)
      }
    ")"                                        (. e = new UnchangedExpr(x, mod, oldAt?.val); .)
  | "old"                                      (. x = t; IToken oldAt = null; .)
    [ "@" LabelIdent<out oldAt> ]
    "(" Expression<out e, true, true> ")"      (. e = new OldExpr(x, e, oldAt?.val); .)
  | "|"                                        (. x = t; .)
      Expression<out e, true, true, false>     (. e = new UnaryOpExpr(x, UnaryOpExpr.Opcode.Cardinality, e); .)
    "|"
  | ( "int"                                    (. x = t; toType = new IntType(); .)
    | "real"                                   (. x = t; toType = new RealType(); .)
    )                                          (. errors.Deprecated(t, string.Format("the syntax \"{0}(expr)\" for type conversions has been deprecated; the new syntax is \"expr as {0}\"", x.val)); .)
    "(" Expression<out e, true, true> ")"      (. e = new ConversionExpr(x, e, toType); .)
  | ParensExpression<out e, allowSemi, allowLambda>
  )
  .

LambdaArrow = "=>".

LambdaExpression<out Expression e, bool allowSemi, bool allowBitwiseOps>
= (. IToken x = Token.NoToken;
     IToken id;  BoundVar bv;
     var bvs = new List<BoundVar>();
     FrameExpression fe;  Expression ee;
     var reads = new List<FrameExpression>();
     Expression req = null;
     Expression body = null;
  .)
  ( WildIdent<out id, true>                  (. x = t; bvs.Add(new BoundVar(id, id.val, new InferredTypeProxy())); .)
  | "("                                      (. x = t; .)
      [
        IdentTypeOptional<out bv>            (. bvs.Add(bv); .)
        { "," IdentTypeOptional<out bv>      (. bvs.Add(bv); .)
        }
      ]
    ")"
  )
  { "reads"
    PossiblyWildFrameExpression<out fe, true>         (. reads.Add(fe); .)
    { ","
      PossiblyWildFrameExpression<out fe, true>       (. reads.Add(fe); .)
    }
  | "requires" Expression<out ee, true, false>        (. req = req == null ? ee : new BinaryExpr(req.tok, BinaryExpr.Opcode.And, req, ee); .)
  }
  LambdaArrow
  Expression<out body, allowSemi, true, allowBitwiseOps>
  (. e = new LambdaExpr(x, bvs, req, reads, body);
     theBuiltIns.CreateArrowTypeDecl(bvs.Count);
  .)
  .
ParensExpression<out Expression e, bool allowSemi, bool allowLambda>
= (. IToken x;
     var args = new List<Expression>();
  .)
  "("                                        (. x = t; .)
  [ Expressions<args> ]
  ")"
  (. if (args.Count == 1) {
       e = new ParensExpression(x, args[0]);
     } else {
       // make sure the corresponding tuple type exists
       var tmp = theBuiltIns.TupleType(x, args.Count, true);
       e = new DatatypeValue(x, BuiltIns.TupleTypeName(args.Count), BuiltIns.TupleTypeCtorNamePrefix + args.Count, args);
     }
  .)
  .
ISetDisplayExpr<IToken/*!*/ setToken, bool finite, out Expression e>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
     List<Expression> elements = new List<Expression/*!*/>();;
     e = dummyExpr;
  .)
  "{"
      [ Expressions<elements> ]                (. e = new SetDisplayExpr(setToken, finite, elements);.)
  "}"
  .
DisplayExpr<out Expression e>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
     IToken x;  List<Expression> elements;
     e = dummyExpr;
  .)
  ( "{"                                        (. x = t;  elements = new List<Expression/*!*/>(); .)
      [ Expressions<elements> ]                (. e = new SetDisplayExpr(x, true, elements);.)
    "}"
  | "["                                        (. x = t;  elements = new List<Expression/*!*/>(); .)
      [ Expressions<elements> ]                (. e = new SeqDisplayExpr(x, elements); .)
    "]"
  )
  .
MultiSetExpr<out Expression e>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
     IToken/*!*/ x = null;  List<Expression/*!*/>/*!*/ elements;
     e = dummyExpr;
  .)
  "multiset"                                   (. x = t; .)
  ( "{"                                        (. elements = new List<Expression/*!*/>(); .)
      [ Expressions<elements> ]                (. e = new MultiSetDisplayExpr(x, elements);.)
    "}"
  | "("                                        (. x = t;  elements = new List<Expression/*!*/>(); .)
      Expression<out e, true, true>            (. e = new MultiSetFormingExpr(x, e); .)
    ")"
  )
  .
MapDisplayExpr<IToken/*!*/ mapToken, bool finite, out Expression e>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
     List<ExpressionPair/*!*/>/*!*/ elements= new List<ExpressionPair/*!*/>() ;
     e = dummyExpr;
  .)
  "["
    [ MapLiteralExpressions<out elements> ]  (. e = new MapDisplayExpr(mapToken, finite, elements);.)
  "]"
  .
MapLiteralExpressions<.out List<ExpressionPair> elements.>
= (. Expression/*!*/ d, r;
     elements = new List<ExpressionPair/*!*/>(); .)
  Expression<out d, true, true> ":=" Expression<out r, true, true>       (. elements.Add(new ExpressionPair(d,r)); .)
  { "," Expression<out d, true, true> ":=" Expression<out r, true, true> (. elements.Add(new ExpressionPair(d,r)); .)
  }
  .
MapComprehensionExpr<IToken mapToken, bool finite, out Expression e, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
     BoundVar bv;
     List<BoundVar> bvars = new List<BoundVar>();
     Expression range = null;
     Expression bodyLeft = null;
     Expression bodyRight;
     Attributes attrs = null;
  .)
  IdentTypeOptional<out bv>                    (. bvars.Add(bv); .)
  { ","
    IdentTypeOptional<out bv>                  (. bvars.Add(bv); .)
  }
  { Attribute<ref attrs> }
  [ "|" Expression<out range, true, true, true> ]
  QSep
  Expression<out bodyRight, allowSemi, allowLambda, allowBitwiseOps>
  [ IF(IsGets())  /* greedily parse ":=" */    (. bodyLeft = bodyRight; .)
    ":=" Expression<out bodyRight, allowSemi, allowLambda, allowBitwiseOps>
  ]
  (. if (bodyLeft == null && bvars.Count != 1) {
       SemErr(t, "a map comprehension with more than one bound variable must have a term expression of the form 'Expr := Expr'");
       e = dummyExpr;
     } else {
       e = new MapComprehension(mapToken, finite, bvars, range ?? new LiteralExpr(mapToken, true), bodyLeft, bodyRight, attrs);
     }
  .)
  .
EndlessExpression<out Expression e, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. IToken/*!*/ x;
     Expression e0, e1;
     Statement s;
     bool isExistentialGuard = false;
     e = dummyExpr;
  .)
  ( "if"                            (. x = t; .)
    ( IF(IsExistentialGuard())
      ExistentialGuard<out e, true>  (. isExistentialGuard = true; .)
    | Expression<out e, true, true>
    )
    "then" Expression<out e0, true, true, true>
    "else" Expression<out e1, allowSemi, allowLambda, allowBitwiseOps>
                                                         (.  if (isExistentialGuard) {
                                                               var exists = (ExistsExpr) e;
                                                               var LHSs = new List<CasePattern<BoundVar>>();
                                                               foreach (var v in exists.BoundVars) {
                                                                 LHSs.Add(new CasePattern<BoundVar>(e.tok, v));
                                                               }
                                                               e0 = new LetExpr(e.tok, LHSs, new List<Expression>() { exists.Term }, e0, false);                                                           
                                                             }
                                                             e = new ITEExpr(x, isExistentialGuard, e, e0, e1);
                                                         .)
  | MatchExpression<out e, allowSemi, allowLambda, allowBitwiseOps>
  | QuantifierGuts<out e, allowSemi, allowLambda>  /* types are such that we can allow bitwise operations in the quantifier body */
  | "set"                           (. x = t; .)
    SetComprehensionExpr<x, true, out e, allowSemi, allowLambda, allowBitwiseOps>
  | "iset"                          (. x = t; .)
    SetComprehensionExpr<x, false, out e, allowSemi, allowLambda, true>
  | StmtInExpr<out s>
    Expression<out e, allowSemi, allowLambda, allowBitwiseOps>    (. e = new StmtExpr(s.Tok, s, e); .)
  | LetExpr<out e, allowSemi, allowLambda, allowBitwiseOps>
  | "map"                           (. x = t; .)
    MapComprehensionExpr<x, true, out e, allowSemi, allowLambda, allowBitwiseOps>
  | "imap"                          (. x = t; .)
    MapComprehensionExpr<x, false, out e, allowSemi, allowLambda, true>
  | "reveal"
    Expression<out e, false, false, allowBitwiseOps> (. e = new RevealExpr(e.tok, e); .)
  | NamedExpr<out e, allowSemi, allowLambda, allowBitwiseOps>
  )
  .

StmtInExpr<out Statement s>
= (. s = dummyStmt; .)
  ( AssertStmt<out s, true>
  | AssumeStmt<out s>
  | CalcStmt<out s>
  )
  .

LetExpr<out Expression e, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. IToken x = null;
     bool isGhost = false;
     var letLHSs = new List<CasePattern<BoundVar>>();
     var letRHSs = new List<Expression>();
     CasePattern<BoundVar> pat;
     bool exact = true;
     Attributes attrs = null;
     e = dummyExpr;
  .)
    [ "ghost"                       (. isGhost = true;  x = t; .)
    ]
    "var"                           (. if (!isGhost) { x = t; } .)
    CasePattern<out pat>            (. if (isGhost) { pat.Vars.Iter(bv => bv.IsGhost = true); }
                                       letLHSs.Add(pat);
                                    .)
    { "," CasePattern<out pat>      (. if (isGhost) { pat.Vars.Iter(bv => bv.IsGhost = true); }
                                       letLHSs.Add(pat);
                                    .)
    }
    ( ":="
    | { Attribute<ref attrs> }
      ":|"                          (. exact = false;
                                       foreach (var lhs in letLHSs) {
                                         if (lhs.Arguments != null) {
                                           SemErr(lhs.tok, "LHS of let-such-that expression must be variables, not general patterns");
                                         }
                                       }
                                    .)
    )
    Expression<out e, false, true>        (. letRHSs.Add(e); .)
    { "," Expression<out e, false, true>  (. letRHSs.Add(e); .)
    }
    ";"
    Expression<out e, allowSemi, allowLambda, allowBitwiseOps>    (. e = new LetExpr(x, letLHSs, letRHSs, e, exact, attrs); .)
  .

NamedExpr<out Expression e, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. IToken/*!*/ x, d;
     e = dummyExpr;
     Expression expr;
  .)
    "label"                          (. x = t; .)
    NoUSIdent<out d>
    ":"
    Expression<out e, allowSemi, allowLambda, allowBitwiseOps>
                                     (. expr = e;
                                        e = new NamedExpr(x, d.val, expr); .)
  .

MatchExpression<out Expression e, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x;  MatchCaseExpr/*!*/ c;
     List<MatchCaseExpr/*!*/> cases = new List<MatchCaseExpr/*!*/>();
     bool usesOptionalBraces = false;
  .)
  "match"                     (. x = t; .)
  Expression<out e, allowSemi, allowLambda, allowBitwiseOps>
  ( IF(la.kind == _lbrace)  /* always favor brace-enclosed match body to a case-less match */
    "{" (. usesOptionalBraces = true; .)
        { CaseExpression<out c, true, true, allowBitwiseOps> (. cases.Add(c); .) }
    "}"
  |     { IF(la.kind == _case)  /* let each "case" bind to the closest preceding "match" */
          CaseExpression<out c, allowSemi, allowLambda, allowBitwiseOps> (. cases.Add(c); .)
        }
  )
  (. e = new MatchExpr(x, e, cases, usesOptionalBraces); .)
  .
CaseExpression<out MatchCaseExpr c, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out c) != null); IToken/*!*/ x, id;
     var arguments = new List<CasePattern<BoundVar>>();
     CasePattern<BoundVar>/*!*/ pat;
     Expression/*!*/ body;
     string/*!*/ name = "";
  .)
  "case"                      (. x = t; .)
  ( Ident<out id>             (. name = id.val; .)
    [ "("
       [ CasePattern<out pat>        (. arguments.Add(pat); .)
         { "," CasePattern<out pat>  (. arguments.Add(pat); .)
         }
       ]
    ")" ]
  | "("
      CasePattern<out pat>        (. arguments.Add(pat); .)
      { "," CasePattern<out pat>  (. arguments.Add(pat); .)
      }
    ")"
  )
  "=>"
  Expression<out body, allowSemi, allowLambda, allowBitwiseOps>    (. c = new MatchCaseExpr(x, name, arguments, body); .)
  .
CasePattern<.out CasePattern<BoundVar> pat.>
= (. IToken id;  List<CasePattern<BoundVar>> arguments;
     BoundVar bv;
     pat = null;
  .)
  ( IF(IsIdentParen())
    Ident<out id>
    "("                                (. arguments = new List<CasePattern<BoundVar>>(); .)
      [ CasePattern<out pat>           (. arguments.Add(pat); .)
        { "," CasePattern<out pat>     (. arguments.Add(pat); .)
        }
      ]
    ")"                                (. pat = new CasePattern<BoundVar>(id, id.val, arguments); .)
  | "("                                (. id = t;                                                           
                                          arguments = new List<CasePattern<BoundVar>>(); 
                                       .)
      [ CasePattern<out pat>           (. arguments.Add(pat); .)
        { "," CasePattern<out pat>     (. arguments.Add(pat); .)
        }
      ]
    ")"                                (. // Parse parenthesis without an identifier as a built in tuple type.
                                          theBuiltIns.TupleType(id, arguments.Count, true); // make sure the tuple type exists
                                          string ctor = BuiltIns.TupleTypeCtorNamePrefix + arguments.Count;  //use the TupleTypeCtors
                                          pat = new CasePattern<BoundVar>(id, ctor, arguments); 
                                       .)
  | IdentTypeOptional<out bv>          (. // This could be a BoundVar of a parameter-less constructor and we may not know until resolution.
                                          // Nevertheless, we do put the "bv" into the CasePattern here (even though it will get thrown out
                                          // later if resolution finds the CasePattern to denote a parameter-less constructor), because this
                                          // (in particular, bv.IsGhost) is the place where a LetExpr records whether or not the "ghost"
                                          // keyword was used in the declaration.
                                          pat = new CasePattern<BoundVar>(bv.tok, bv);
                                       .)
  )
  (. // In case of parsing errors, make sure 'pat' still returns as non-null
     if (pat == null) {
       pat = new CasePattern<BoundVar>(t, "_ParseError", new List<CasePattern<BoundVar>>());
     }
  .)
  .
/* CasePatternLocal is identical to CasePattern, except that it uses LocalVariable instead of BoundVar. Coco does
 * not have a way to make the patterns take a bounded type parameter.
 */
CasePatternLocal<.out CasePattern<LocalVariable> pat, bool isGhost.>
= (. IToken id;  List<CasePattern<LocalVariable>> arguments;
     LocalVariable local;
     pat = null;
  .)
  ( IF(IsIdentParen())
    Ident<out id>
    "("                                          (. arguments = new List<CasePattern<LocalVariable>>(); .)
      [ CasePatternLocal<out pat, isGhost>       (. arguments.Add(pat); .)
        { "," CasePatternLocal<out pat, isGhost> (. arguments.Add(pat); .)
        }
      ]
    ")"                                          (. pat = new CasePattern<LocalVariable>(id, id.val, arguments); .)
  | "("                                          (. id = t;                                                           
                                                    arguments = new List<CasePattern<LocalVariable>>(); 
                                                 .)
      [ CasePatternLocal<out pat, isGhost>       (. arguments.Add(pat); .)
        { "," CasePatternLocal<out pat, isGhost> (. arguments.Add(pat); .)
        }
      ]
    ")"                                (. // Parse parenthesis without an identifier as a built in tuple type.
                                          theBuiltIns.TupleType(id, arguments.Count, true); // make sure the tuple type exists
                                          string ctor = BuiltIns.TupleTypeCtorNamePrefix + arguments.Count;  //use the TupleTypeCtors
                                          pat = new CasePattern<LocalVariable>(id, ctor, arguments); 
                                       .)
  | LocalIdentTypeOptional<out local, isGhost>
                                       (. // This could be a LocalVariable of a parameter-less constructor and we may not know until resolution.
                                          // Nevertheless, we do put the local" into the CasePattern here (even though it will get thrown out
                                          // later if resolution finds the CasePattern to denote a parameter-less constructor), because this
                                          // (in particular, local.IsGhost) is the place where a LetExpr records whether or not the "ghost"
                                          // keyword was used in the declaration.
                                          pat = new CasePattern<LocalVariable>(local.Tok, local);
                                       .)
  )
  (. // In case of parsing errors, make sure 'pat' still returns as non-null
     if (pat == null) {
       pat = new CasePattern<LocalVariable>(t, "_ParseError", new List<CasePattern<LocalVariable>>());
     }
  .)
  .
/*------------------------------------------------------------------------*/
NameSegment<out Expression e>
= (. IToken id;
     IToken openParen = null;  List<Type> typeArgs = null;  List<Expression> args = null;
  .)
  Ident<out id>
  ( IF(IsGenericInstantiation(true))
    (. typeArgs = new List<Type>(); .)
    GenericInstantiation<typeArgs>
  | HashCall<id, out openParen, out typeArgs, out args>
  | /* empty */
  )
  /* Note, since HashCall updates id.val, we make sure not to use id.val until after the possibility of calling HashCall. */
  (. e = new NameSegment(id, id.val, typeArgs);
     if (openParen != null) {
       e = new ApplySuffix(openParen, e, args);
     }
  .)
  .
/* NameSegmentForTypeName is like the production NameSegment, except that it does not allow HashCall */
NameSegmentForTypeName<out Expression e, bool inExpressionContext>
= (. IToken id;  List<Type> typeArgs; .)
  Ident<out id>
  OptGenericInstantiation<out typeArgs, inExpressionContext>
  (. e = new NameSegment(id, id.val, typeArgs);
  .)
  .
/* The HashCall production extends a given identifier with a hash sign followed by
 * a list of argument expressions.  That is, if what was just parsed was an identifier id,
 * then the HashCall production will continue parsing into id#[arg](args).
 * One could imagine parsing just the id# as an expression, but Dafny doesn't do that
 * since the first argument to a prefix predicate/method is textually set apart; instead
 * if a programmer wants to curry the arguments, one has to resort to using a lambda
 * expression, just like for other function applications.
 * Note: This grammar production mutates the id.val field to append the hash sign.
 */
HashCall<.IToken id, out IToken openParen, out List<Type> typeArgs, out List<Expression> args.>
= (. Expression k; args = new List<Expression>(); typeArgs = null; .)
  "#"                                      (. id.val = id.val + "#"; .)
  [                                        (. typeArgs = new List<Type>(); .)
    GenericInstantiation<typeArgs>
  ]
  "[" Expression<out k, true, true> "]"    (. args.Add(k); .)
  "("                                      (. openParen = t; .)
    [ Expressions<args> ]
  ")"
  .
Suffix<ref Expression e>
= (. Contract.Requires(e != null); Contract.Ensures(e!=null);
     IToken id, x;
     Expression e0 = null;  Expression e1 = null;  Expression ee;  bool anyDots = false;
     List<Expression> multipleLengths = null; bool takeRest = false; // takeRest is relevant only if multipleLengths is non-null
     List<Expression> multipleIndices = null;
     List<Tuple<IToken, string, Expression>> updates;
     Expression v;
  .)
  ( "."
    ( "("                                             (. x = t; updates = new List<Tuple<IToken, string, Expression>>(); .)
        MemberBindingUpdate<out id, out v>            (. updates.Add(Tuple.Create(id, id.val, v)); .)
        { "," MemberBindingUpdate<out id, out v>      (. updates.Add(Tuple.Create(id, id.val, v)); .)
        }
      ")"
      (. e = new DatatypeUpdateExpr(x, e, updates); .)
    | DotSuffix<out id, out x>                 (. if (x != null) {
                                                    // process id as a Suffix in its own right
                                                    e = new ExprDotName(id, e, id.val, null);
                                                    id = x;  // move to the next Suffix
                                                  }
                                                  IToken openParen = null;  List<Type> typeArgs = null;  List<Expression> args = null;
                                               .)


      ( IF(IsGenericInstantiation(true))
        (. typeArgs = new List<Type>(); .)
        GenericInstantiation<typeArgs>
      | HashCall<id, out openParen, out typeArgs, out args>
      | /* empty */
      )
      (. e = new ExprDotName(id, e, id.val, typeArgs);
         if (openParen != null) {
           e = new ApplySuffix(openParen, e, args);
         }
      .)
    )
  | "["                                        (. x = t; .)
      ( Expression<out ee, true, true>         (. e0 = ee; .)
        ( ".."                                 (. anyDots = true; .)
          [ Expression<out ee, true, true>     (. e1 = ee; .)
          ]
        | ":="
          Expression<out ee, true, true>       (. e1 = ee; .)
        | ":"                                  (. multipleLengths = new List<Expression>();
                                                  multipleLengths.Add(e0);  // account for the Expression read before the colon
                                                  takeRest = true;
                                               .)
          [ Expression<out ee, true, true>     (. multipleLengths.Add(ee); takeRest = false; .)
            { IF(IsNonFinalColon())
              ":"
              Expression<out ee, true, true>   (. multipleLengths.Add(ee); .)
            }
            [ ":"                              (. takeRest = true; .)
            ]
          ]
        | { "," Expression<out ee, true, true> (. if (multipleIndices == null) {
                                                    multipleIndices = new List<Expression>();
                                                    multipleIndices.Add(e0);
                                                  }
                                                  multipleIndices.Add(ee);
                                               .)
          }
        )
      | ".."                                   (. anyDots = true; .)
        [ Expression<out ee, true, true>       (. e1 = ee; .)
        ]
      )
      (. if (multipleIndices != null) {
           e = new MultiSelectExpr(x, e, multipleIndices);
           // make sure an array class with this dimensionality exists
           var tmp = theBuiltIns.ArrayType(multipleIndices.Count, new IntType(), true);
         } else {
           if (!anyDots && e0 == null) {
             /* a parsing error occurred */
             e0 = dummyExpr;
           }
           Contract.Assert(anyDots || e0 != null);
           if (anyDots) {
             //Contract.Assert(e0 != null || e1 != null);
             e = new SeqSelectExpr(x, false, e, e0, e1);
           } else if (multipleLengths != null) {
             Expression prev = null;
             List<Expression> seqs = new List<Expression>();
              foreach (var len in multipleLengths) {
                var end = prev == null ? len : new BinaryExpr(x, BinaryExpr.Opcode.Add, prev, len);
                seqs.Add(new SeqSelectExpr(x, false, e, prev, end));
                prev = end;
              }
             if (takeRest) {
               seqs.Add(new SeqSelectExpr(x, false, e, prev, null));
             }
             e = new SeqDisplayExpr(x, seqs);
           } else if (e1 == null) {
             Contract.Assert(e0 != null);
             e = new SeqSelectExpr(x, true, e, e0, null);
           } else {
             Contract.Assert(e0 != null);
             e = new SeqUpdateExpr(x, e, e0, e1);
           }
         }
      .)
    "]"
  | "("                                    (. IToken openParen = t; var args = new List<Expression>(); .)
    [ Expressions<args> ]
    ")"                                    (. e = new ApplySuffix(openParen, e, args); .)
  )
  .

/*------------------------------------------------------------------------*/
QuantifierGuts<out Expression q, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out q) != null); IToken/*!*/ x = Token.NoToken;
     bool univ = false;
     List<BoundVar/*!*/> bvars;
     Attributes attrs;
     Expression range;
     Expression/*!*/ body;
  .)
  ( Forall                                     (. x = t;  univ = true; .)
  | Exists                                     (. x = t; .)
  )
  QuantifierDomain<out bvars, out attrs, out range>
  QSep
  Expression<out body, allowSemi, allowLambda>
  (. if (univ) {
       q = new ForallExpr(x, bvars, range, body, attrs);
     } else {
       q = new ExistsExpr(x, bvars, range, body, attrs);
     }
  .)
  .

QuantifierDomain<.out List<BoundVar> bvars, out Attributes attrs, out Expression range.>
= (.
     bvars = new List<BoundVar>();
     BoundVar/*!*/ bv;
     attrs = null;
     range = null;
  .)
  IdentTypeOptional<out bv>                    (. bvars.Add(bv); .)
  { ","
    IdentTypeOptional<out bv>                  (. bvars.Add(bv); .)
  }
  { IF(IsAttribute()) Attribute<ref attrs> }
  [ IF(la.kind == _verticalbar)   /* Coco complains about this ambiguity, thinking that a "|" can follow a body-less forall statement; I don't see how that's possible, but this IF is good and suppresses the reported ambiguity */
    "|"
    Expression<out range, true, true>
  ]
  .

SetComprehensionExpr<IToken setToken, bool finite, out Expression q, bool allowSemi, bool allowLambda, bool allowBitwiseOps>
= (. Contract.Ensures(Contract.ValueAtReturn(out q) != null);
     BoundVar bv;
     List<BoundVar/*!*/> bvars = new List<BoundVar>();
     Expression range;
     Expression body = null;
     Attributes attrs = null;
  .)
  IdentTypeOptional<out bv>                    (. bvars.Add(bv); .)
  { ","
    IdentTypeOptional<out bv>                  (. bvars.Add(bv); .)
  }
  { Attribute<ref attrs> }
  "|" Expression<out range, allowSemi, allowLambda, allowBitwiseOps>
  [ IF(IsQSep())  /* let any given body bind to the closest enclosing set comprehension */
    QSep
    Expression<out body, allowSemi, allowLambda, allowBitwiseOps>
  ]
  (. if (body == null && bvars.Count != 1) {
       SemErr(t, "a set comprehension with more than one bound variable must have a term expression");
       q = dummyExpr;
     } else {
       q = new SetComprehension(setToken, finite, bvars, range, body, attrs);
     }
  .)
  .
Expressions<.List<Expression> args.>
= (. Expression e; .)
  Expression<out e, true, true>                      (. args.Add(e); .)
  { "," Expression<out e, true, true>                (. args.Add(e); .)
  }
  .
/*------------------------------------------------------------------------*/
Attribute<ref Attributes attrs>
= (. IToken openBrace, colon, closeBrace;
     IToken x = null;
     var args = new List<Expression>();
  .)
  "{"                         (. openBrace = t; .)
  ":"                         (. colon = t; .)
  (. ConvertKeywordTokenToIdent(); .)
  NoUSIdent<out x>
  [ Expressions<args> ]
  "}"                         (. closeBrace = t; .)
  (. attrs = new UserSuppliedAttributes(x, openBrace, colon, closeBrace, args, attrs); .)
  .
/*------------------------------------------------------------------------*/
Ident<out IToken/*!*/ x>
= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null); .)
  ident            (. x = t; .)
  .
// Identifier or sequence of digits
// Parse one of the following, which are supposed to follow a ".":
//        ident
//        digits
//        digits . digits
// In the first two cases, x returns as the token for the ident/digits and y returns as null.
// In the third case, x and y return as the tokens for the first and second digits.
// This parser production solves a problem where the scanner might parse a real number instead
// of stopping at the decimal point.
DotSuffix<out IToken x, out IToken y>
= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null);
     x = Token.NoToken;
     y = null;
  .)
  ( ident          (. x = t; .)
  | digits         (. x = t; .)
  | decimaldigits  (. x = t;
                      int exponent = x.val.IndexOf('e');
                      if (0 <= exponent) {
                        // this is not a legal field/destructor name
                        SemErr(x, "invalid DotSuffix");
                      } else {
                        int dot = x.val.IndexOf('.');
                        if (0 <= dot) {
                          y = new Token();
                          y.pos = x.pos + dot + 1;
                          y.val = x.val.Substring(dot + 1);
                          x.val = x.val.Substring(0, dot);
                          y.col = x.col + dot + 1;
                          y.line = x.line;
                          y.filename = x.filename;
                          y.kind = x.kind;
                        }
                      }
                   .)
  | "requires"    (. x = t; .)
  | "reads"       (. x = t; .)
  )
  .
MemberBindingUpdate<out IToken id, out Expression e>
= (. id = Token.NoToken; e = dummyExpr; .)
  ( ident          (. id = t; .)
  | digits         (. id = t; .)
  )
  ":="
  Expression<out e, true, true>
  .

LabelIdent<out IToken id>
= (. id = Token.NoToken; .)
  ( NoUSIdent<out id>
  | digits         (. id = t; .)
  )
  .
FuMe_Ident<out IToken id>
= (. id = Token.NoToken; .)
  ( NoUSIdent<out id>
  | digits         (. id = t; .)
  )
  .
TypeNameOrCtorSuffix<out IToken id>
= (. id = Token.NoToken; .)
  ( ident          (. id = t; .)
  | digits         (. id = t; .)
  )
  .

// Identifier, disallowing leading underscores
NoUSIdent<out IToken/*!*/ x>
= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null); .)
  ident            (. x = t;
                      if (x.val.StartsWith("_")) {
                        SemErr("cannot declare identifier beginning with underscore");
                      }
                   .)
  .

// Identifier, disallowing leading underscores, except possibly the "wildcard" identifier "_"
WildIdent<out IToken x, bool allowWildcardId>
= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null); .)
  ident            (. x = t;
                      t.val = UnwildIdent(t.val, allowWildcardId);
                   .)
  .

OldSemi  /* NOTE: Coco complains about "OldSemi deletable". That's okay. */
= /* In the future, it may be that semi-colons will be neither needed nor allowed in certain places where,
   * in the past, they were required.  As a period of transition between the two, such semi-colons are optional.
   */
  [ SYNC ";"    (. errors.DeprecatedStyle(t, "deprecated style: a semi-colon is not needed here"); .)
  ].

Nat<out BigInteger n>
= (. n = BigInteger.Zero;
     string S;
  .)
  ( digits
    (. S = Util.RemoveUnderscores(t.val);
       try {
         n = BigIntegerParser.Parse(S);
       } catch (System.FormatException) {
         SemErr("incorrectly formatted number");
         n = BigInteger.Zero;
       }
    .)
  | hexdigits
    (. S = Util.RemoveUnderscores(t.val.Substring(2));
       try {
         // note: leading 0 required when parsing positive hex numbers
         n = BigIntegerParser.Parse("0" + S, System.Globalization.NumberStyles.HexNumber);
       } catch (System.FormatException) {
         SemErr("incorrectly formatted number");
         n = BigInteger.Zero;
       }
    .)
  )
  .
Dec<out Basetypes.BigDec d>
= (. d = Basetypes.BigDec.ZERO; .)
  (decimaldigits
    (. var S = Util.RemoveUnderscores(t.val);
       try {
         d = Basetypes.BigDec.FromString(S);
       } catch (System.FormatException) {
         SemErr("incorrectly formatted number");
         d = Basetypes.BigDec.ZERO;
       }
    .)
  )
  .
END Dafny.
