// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.google.dart.compiler.parser;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.CharStreams;
import com.google.dart.compiler.DartCompilationError;
import com.google.dart.compiler.DartCompilerListener;
import com.google.dart.compiler.DartSource;
import com.google.dart.compiler.ErrorCode;
import com.google.dart.compiler.ErrorSeverity;
import com.google.dart.compiler.InternalCompilerException;
import com.google.dart.compiler.LibrarySource;
import com.google.dart.compiler.PackageLibraryManager;
import com.google.dart.compiler.Source;
import com.google.dart.compiler.ast.DartAnnotation;
import com.google.dart.compiler.ast.DartArrayAccess;
import com.google.dart.compiler.ast.DartArrayLiteral;
import com.google.dart.compiler.ast.DartAssertStatement;
import com.google.dart.compiler.ast.DartBinaryExpression;
import com.google.dart.compiler.ast.DartBlock;
import com.google.dart.compiler.ast.DartBooleanLiteral;
import com.google.dart.compiler.ast.DartBreakStatement;
import com.google.dart.compiler.ast.DartCascadeExpression;
import com.google.dart.compiler.ast.DartCase;
import com.google.dart.compiler.ast.DartCatchBlock;
import com.google.dart.compiler.ast.DartClass;
import com.google.dart.compiler.ast.DartConditional;
import com.google.dart.compiler.ast.DartContinueStatement;
import com.google.dart.compiler.ast.DartDeclaration;
import com.google.dart.compiler.ast.DartDefault;
import com.google.dart.compiler.ast.DartDirective;
import com.google.dart.compiler.ast.DartDoWhileStatement;
import com.google.dart.compiler.ast.DartDoubleLiteral;
import com.google.dart.compiler.ast.DartEmptyStatement;
import com.google.dart.compiler.ast.DartExportDirective;
import com.google.dart.compiler.ast.DartExprStmt;
import com.google.dart.compiler.ast.DartExpression;
import com.google.dart.compiler.ast.DartField;
import com.google.dart.compiler.ast.DartFieldDefinition;
import com.google.dart.compiler.ast.DartForInStatement;
import com.google.dart.compiler.ast.DartForStatement;
import com.google.dart.compiler.ast.DartFunction;
import com.google.dart.compiler.ast.DartFunctionExpression;
import com.google.dart.compiler.ast.DartFunctionObjectInvocation;
import com.google.dart.compiler.ast.DartFunctionTypeAlias;
import com.google.dart.compiler.ast.DartIdentifier;
import com.google.dart.compiler.ast.DartIfStatement;
import com.google.dart.compiler.ast.DartImportDirective;
import com.google.dart.compiler.ast.DartInitializer;
import com.google.dart.compiler.ast.DartIntegerLiteral;
import com.google.dart.compiler.ast.DartLabel;
import com.google.dart.compiler.ast.DartLibraryDirective;
import com.google.dart.compiler.ast.DartMapLiteral;
import com.google.dart.compiler.ast.DartMapLiteralEntry;
import com.google.dart.compiler.ast.DartMethodDefinition;
import com.google.dart.compiler.ast.DartMethodInvocation;
import com.google.dart.compiler.ast.DartNamedExpression;
import com.google.dart.compiler.ast.DartNativeBlock;
import com.google.dart.compiler.ast.DartNativeDirective;
import com.google.dart.compiler.ast.DartNewExpression;
import com.google.dart.compiler.ast.DartNode;
import com.google.dart.compiler.ast.DartNodeWithMetadata;
import com.google.dart.compiler.ast.DartNullLiteral;
import com.google.dart.compiler.ast.DartParameter;
import com.google.dart.compiler.ast.DartParameterizedTypeNode;
import com.google.dart.compiler.ast.DartParenthesizedExpression;
import com.google.dart.compiler.ast.DartPartOfDirective;
import com.google.dart.compiler.ast.DartPropertyAccess;
import com.google.dart.compiler.ast.DartRedirectConstructorInvocation;
import com.google.dart.compiler.ast.DartReturnBlock;
import com.google.dart.compiler.ast.DartReturnStatement;
import com.google.dart.compiler.ast.DartSourceDirective;
import com.google.dart.compiler.ast.DartStatement;
import com.google.dart.compiler.ast.DartStringInterpolation;
import com.google.dart.compiler.ast.DartStringLiteral;
import com.google.dart.compiler.ast.DartSuperConstructorInvocation;
import com.google.dart.compiler.ast.DartSuperExpression;
import com.google.dart.compiler.ast.DartSwitchMember;
import com.google.dart.compiler.ast.DartSwitchStatement;
import com.google.dart.compiler.ast.DartSyntheticErrorExpression;
import com.google.dart.compiler.ast.DartSyntheticErrorIdentifier;
import com.google.dart.compiler.ast.DartSyntheticErrorStatement;
import com.google.dart.compiler.ast.DartThisExpression;
import com.google.dart.compiler.ast.DartThrowExpression;
import com.google.dart.compiler.ast.DartTryStatement;
import com.google.dart.compiler.ast.DartTypeExpression;
import com.google.dart.compiler.ast.DartTypeNode;
import com.google.dart.compiler.ast.DartTypeParameter;
import com.google.dart.compiler.ast.DartUnaryExpression;
import com.google.dart.compiler.ast.DartUnit;
import com.google.dart.compiler.ast.DartUnqualifiedInvocation;
import com.google.dart.compiler.ast.DartVariable;
import com.google.dart.compiler.ast.DartVariableStatement;
import com.google.dart.compiler.ast.DartWhileStatement;
import com.google.dart.compiler.ast.HasObsoleteMetadata;
import com.google.dart.compiler.ast.ImportCombinator;
import com.google.dart.compiler.ast.ImportHideCombinator;
import com.google.dart.compiler.ast.ImportShowCombinator;
import com.google.dart.compiler.ast.LibraryNode;
import com.google.dart.compiler.ast.LibraryUnit;
import com.google.dart.compiler.ast.Modifiers;
import com.google.dart.compiler.metrics.CompilerMetrics;
import com.google.dart.compiler.parser.DartScanner.Location;
import com.google.dart.compiler.resolver.Elements;
import com.google.dart.compiler.util.Lists;
import com.google.dart.compiler.util.apache.StringUtils;

import java.io.IOException;
import java.io.Reader;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * The Dart parser. Parses a single compilation unit and produces a {@link DartUnit}.
 * The grammar rules are taken from Dart.g revision 557.
 */
public class DartParser extends CompletionHooksParserBase {

  private final Source source;
  private final String sourceCode;
  private final boolean isDietParse;
  private final Set<String> prefixes;
  private boolean allowNativeKeyword;
  private final Set<Integer> errorHistory = new HashSet<Integer>();
  private boolean isParsingInterface;
  private boolean isTopLevelAbstract;
  private int topLevelAbstractModifierPosition;
  private boolean isParsingClass;
  private int errorCount = 0;
  
  /**
   * Determines the maximum number of errors before terminating the parser. See
   * {@link #reportError(int, ErrorCode, Object...)}.
   */
  final int MAX_DEFAULT_ERRORS = Short.MAX_VALUE;

  // Pseudo-keywords that should also be valid identifiers.
  private static final String ABSTRACT_KEYWORD = "abstract";
  private static final String AS_KEYWORD = "as";
  private static final String CALL_KEYWORD = "call";
  public static final String DYNAMIC_KEYWORD = "dynamic";
  private static final String EXPORT_KEYWORD = "export";
  private static final String EXTERNAL_KEYWORD = "external";
  private static final String FACTORY_KEYWORD = "factory";
  private static final String GETTER_KEYWORD = "get";
  private static final String HIDE_KEYWORD = "hide";
  private static final String IMPLEMENTS_KEYWORD = "implements";
  private static final String IMPORT_KEYWORD = "import";
  private static final String INTERFACE_KEYWORD = "interface";
  private static final String LIBRARY_KEYWORD = "library";
  private static final String NATIVE_KEYWORD = "native";
  private static final String OF_KEYWORD = "of";
  private static final String ON_KEYWORD = "on";
  private static final String OPERATOR_KEYWORD = "operator";
  private static final String PART_KEYWORD = "part";
  private static final String PREFIX_KEYWORD = "prefix";
  private static final String SETTER_KEYWORD = "set";
  private static final String SHOW_KEYWORD = "show";
  private static final String STATIC_KEYWORD = "static";
  private static final String TYPEDEF_KEYWORD = "typedef";
  // does not exist in specification
  private static final String PATCH_KEYWORD = "patch";


  public static final String[] PSEUDO_KEYWORDS = {
    ABSTRACT_KEYWORD,
    AS_KEYWORD,
    DYNAMIC_KEYWORD,
    EXPORT_KEYWORD,
    EXTERNAL_KEYWORD,
    FACTORY_KEYWORD,
    GETTER_KEYWORD,
    IMPLEMENTS_KEYWORD,
    IMPORT_KEYWORD,
    LIBRARY_KEYWORD,
    OPERATOR_KEYWORD,
    PART_KEYWORD,
    SETTER_KEYWORD,
    STATIC_KEYWORD,
    TYPEDEF_KEYWORD
  };
  public static final Set<String> PSEUDO_KEYWORDS_SET = ImmutableSet.copyOf(PSEUDO_KEYWORDS);

  public static final String[] RESERVED_WORDS = {
      "break",
      "case",
      "catch",
      "class",
      "const",
      "continue",
      "default",
      "do",
      "else",
      "extends",
      "false",
      "final",
      "finally",
      "for",
      "if",
      "in",
      "is",
      "new",
      "null",
      "return",
      "super",
      "switch",
      "this",
      "throw",
      "true",
      "try",
      "var",
      "void",
      "while"};
  public static final Set<String> RESERVED_WORDS_SET = ImmutableSet.copyOf(RESERVED_WORDS);

  public DartParser(Source source,
                    String sourceCode,
                    boolean isDietParse,
                    Set<String> prefixes,
                    DartCompilerListener listener,
                    CompilerMetrics compilerMetrics) {
    super(new DartParserCommentsHelper.CommentParserContext(source, sourceCode, listener, compilerMetrics));
    this.source = source;
    this.sourceCode = sourceCode;
    this.isDietParse = isDietParse;
    this.prefixes = prefixes;
    this.allowNativeKeyword = source != null && PackageLibraryManager.isDartUri(source.getUri());
  }

  public static String read(Source source) throws IOException {
    return read(source.getSourceReader());
  }

  public static String read(Reader reader) throws IOException {
    try {
      return CharStreams.toString(reader);
    } finally {
      reader.close();
    }
  }

  /**
   * A flag indicating whether function expressions are allowed.  See
   * {@link #setAllowFunctionExpression(boolean)}.
   */
  private boolean allowFunctionExpression = true;

  /**
   * 'break' (with no labels) and 'continue' stmts are not valid
   * just anywhere, they must be inside a loop or a case stmt.
   *
   * A break with a label may be valid and is allowed through and
   * checked in the resolver.
   */
  private boolean inLoopStatement = false;
  private boolean inCaseStatement = false;

  /**
   * Set the {@link #allowFunctionExpression} flag indicating whether function expressions are
   * allowed, returning the old value. This is required to avoid ambiguity in a few places in the
   * grammar.
   *
   * @param allow true if function expressions are allowed, false if not
   * @return previous value of the flag, which should be restored
   */
  private boolean setAllowFunctionExpression(boolean allow) {
    boolean old = allowFunctionExpression;
    allowFunctionExpression = allow;
    return old;
  }

  /**
   * <pre>
   * compilationUnit
   *     : libraryDeclaration? topLevelDefinition* EOF
   *     ;
   *
   * libraryDeclaration
   *     : libraryDirective? importDirective* sourceDirective* resourceDirective* nativeDirective*
   *
   * topLevelDefinition
   *     : classDefinition
   *     | interfaceDefinition
   *     | functionTypeAlias
   *     | methodOrConstructorDeclaration functionStatementBody
   *     | type? getOrSet identifier formalParameterList functionStatementBody
   *     | CONST type? staticConstDeclarationList ';'
   *     | variableDeclaration ';'
   *     ;
   * </pre>
   */
  @Terminals(tokens={Token.EOS, Token.CLASS, Token.LIBRARY, Token.IMPORT, Token.SOURCE,
      Token.RESOURCE, Token.NATIVE})
  public DartUnit parseUnit() {
    DartSource dartSource = (DartSource) source;
    
    errorCount = 0;
    
    try {
      beginCompilationUnit();
      ctx.unitAboutToCompile(dartSource, isDietParse);
      DartUnit unit = new DartUnit(dartSource, isDietParse);
      List<DartAnnotation> metadata = parseMetadata();

      // parse any directives at the beginning of the source
      metadata = parseDirectives(unit, metadata);

      while (!EOS()) {
        DartNodeWithMetadata node = null;
        beginTopLevelElement();
        isParsingClass = isParsingInterface = false;
        // Check for ABSTRACT_KEYWORD.
        isTopLevelAbstract = false;
        topLevelAbstractModifierPosition = 0;
        if (optionalPseudoKeyword(ABSTRACT_KEYWORD)) {
          isTopLevelAbstract = true;
          topLevelAbstractModifierPosition = position();
        }
        // skip "patch" before "class"
        if (peek(1) == Token.CLASS && optionalPseudoKeyword(PATCH_KEYWORD)) {
        }
        // Parse top level element.
        if (optional(Token.CLASS)) {
          isParsingClass = true;
          node = done(parseClass());
        } else if (peekPseudoKeyword(0, INTERFACE_KEYWORD) && peek(1).equals(Token.IDENTIFIER)) {
          consume(Token.IDENTIFIER);
          isParsingInterface = true;
          // TODO(scheglov) remove after http://code.google.com/p/dart/issues/detail?id=6318 
          if (!Elements.isCoreLibrarySource(source)
              && !Elements.isLibrarySource(source, "/isolate/isolate.dart")
              && !Elements.isLibrarySource(source, "crypto/crypto.dart")) {
            reportError(position(), ParserErrorCode.DEPRECATED_INTERFACE);
          }
          node = done(parseClass());
        } else if (peekPseudoKeyword(0, TYPEDEF_KEYWORD)
            && (peek(1).equals(Token.IDENTIFIER) || peek(1).equals(Token.VOID) || peek(1).equals(Token.AS))) {
          consume(Token.IDENTIFIER);
          node = done(parseFunctionTypeAlias());
        } else if (looksLikeDirective()) {
          reportErrorWithoutAdvancing(ParserErrorCode.DIRECTIVE_OUT_OF_ORDER);
          metadata = parseDirectives(unit, metadata);
        } else {
          node = done(parseFieldOrMethod(false));
        }
        // Parsing was successful, add node.
        if (node != null) {
          unit.getTopLevelNodes().add(node);
          setMetadata(node, metadata);
          metadata = parseMetadata();
          // Only "class" can be top-level abstract element.
          if (isTopLevelAbstract && !isParsingClass) {
            int abstractPositionEnd = topLevelAbstractModifierPosition + ABSTRACT_KEYWORD.length();
            Location location = new Location(topLevelAbstractModifierPosition, abstractPositionEnd);
            reportError(new DartCompilationError(source, location,
                ParserErrorCode.ABSTRACT_TOP_LEVEL_ELEMENT));
          }
        }
      }
      expect(Token.EOS);
      // add comments
      {
        List<int[]> commentLocs = ((DartParserCommentsHelper.CommentParserContext) ctx).getCommentLocs();
        DartParserCommentsHelper.addComments(unit, source, sourceCode, commentLocs);
      }
      // done
      unit.setHasParseErrors(errorCount != 0);
      return done(unit);
    } catch (StringInterpolationParseError exception) {
      throw new InternalCompilerException("Failed to parse " + source.getUri(), exception);
    }
  }

  /**
   * Set the metadata associated with the given node to the given annotations.
   * 
   * @param node the node with which the metadata is to be associated
   * @param metadata the metadata to be associated with the node
   */
  private void setMetadata(DartNodeWithMetadata node, List<DartAnnotation> annotations) {
    if (node instanceof DartFieldDefinition) {
      DartFieldDefinition fieldDefinition = (DartFieldDefinition) node;
      List<DartField> fields = fieldDefinition.getFields();
      for (DartField field : fields) {
        setMetadata(field, annotations);
      }
      return;
    }
    if (annotations != null && !annotations.isEmpty()) {
      node.setMetadata(annotations);
      if (node instanceof HasObsoleteMetadata) {
        HasObsoleteMetadata declaration = (HasObsoleteMetadata) node;
        for (int i = 0, size = annotations.size(); i < size; i++) {
          DartAnnotation annotation = annotations.get(i);
          DartExpression nameNode = annotation.getName();
          if (nameNode instanceof DartIdentifier) {
            String name = ((DartIdentifier) nameNode).getName();
            if (name.equals("deprecated")) {
              declaration.setObsoleteMetadata(declaration.getObsoleteMetadata().makeDeprecated());
            } else if (name.equals("override")) {
              declaration.setObsoleteMetadata(declaration.getObsoleteMetadata().makeOverride());
            }
          }
        }
      }
    }
  }

  private boolean looksLikeDirective() {
    switch(peek(0)) {
      case LIBRARY:
      case IMPORT:
      case SOURCE:
      case RESOURCE:
      case NATIVE:
        return true;
    }
    return peekPseudoKeyword(0, LIBRARY_KEYWORD) || peekPseudoKeyword(0, IMPORT_KEYWORD) || peekPseudoKeyword(0, PART_KEYWORD);
  }

  /**
   * 'interface' and 'typedef' are valid to use as names of fields and methods, so you can't
   * just blindly recover when you see them in any context.  This does a further test to make
   * sure they are followed by another identifier.  This would be illegal as a field or method
   * definition, as you cannot use 'interface' or 'typedef' as a type name.
   */
  private boolean looksLikeTopLevelKeyword() {
    if (peek(0).equals(Token.CLASS)) {
      return true;
    }
    if (peekPseudoKeyword(0, INTERFACE_KEYWORD)
        && peek(1).equals(Token.IDENTIFIER)) {
      return true;
    } else if (peekPseudoKeyword(0, TYPEDEF_KEYWORD)
        && (peek(1).equals(Token.IDENTIFIER) || peek(1).equals(Token.VOID))) {
      return true;
    }
    return false;
  }

  /**
   * A version of the parser which only parses the directives of a library.
   *
   * TODO(jbrosenberg): consider parsing the whole file here, in order to avoid
   * duplicate work.  Probably requires removing use of LibraryUnit's, etc.
   * Also, this minimal parse does have benefit in the incremental compilation
   * case.
   */
  @SuppressWarnings("deprecation")
  public LibraryUnit preProcessLibraryDirectives(LibrarySource source) {
    beginCompilationUnit();
    LibraryUnit libUnit = new LibraryUnit(source);
    if (peekPseudoKeyword(0, LIBRARY_KEYWORD)) {
      DartLibraryDirective libraryDirective = parseLibraryDirective();
      libUnit.setName(libraryDirective.getLibraryName());
    }
    while (peekPseudoKeyword(0, IMPORT_KEYWORD) || peekPseudoKeyword(0, EXPORT_KEYWORD)) {
      if (peekPseudoKeyword(0, IMPORT_KEYWORD)) {
        DartImportDirective importDirective = parseImportDirective();
        LibraryNode importPath = new LibraryNode(importDirective);
        importPath.setSourceInfo(importDirective.getSourceInfo());
        libUnit.addImportPath(importPath);
      }
      if (peekPseudoKeyword(0, EXPORT_KEYWORD)) {
        DartExportDirective exportDirective = parseExportDirective();
        LibraryNode importPath = new LibraryNode(exportDirective);
        importPath.setSourceInfo(exportDirective.getSourceInfo());
        libUnit.addExportPath(importPath);
      }
    }
    while (peekPseudoKeyword(0, PART_KEYWORD)) {
      if (peekPseudoKeyword(1, OF_KEYWORD)) {
        parsePartOfDirective();
      } else {
        DartSourceDirective sourceDirective = parsePartDirective();
        LibraryNode sourcePath = new LibraryNode(sourceDirective.getSourceUri().getValue());
        sourcePath.setSourceInfo(sourceDirective.getSourceInfo());
        libUnit.addSourcePath(sourcePath);
      }
    }
    //
    // The code below is obsolete. We do not make any effort to find duplications between the old
    // and the new syntax because support for the old syntax will be removed very soon.
    //
    if (peek(0) == Token.LIBRARY) {
      beginLibraryDirective();
      DartLibraryDirective libDirective = done(parseObsoleteLibraryDirective());
      libUnit.setName(libDirective.getLibraryName());
    }
    while (peek(0) == Token.IMPORT) {
      beginImportDirective();
      DartImportDirective importDirective = done(parseObsoleteImportDirective());
      LibraryNode importPath;
      if (importDirective.getOldPrefix() != null) {
        importPath =
            new LibraryNode(importDirective);
      } else {
        importPath = new LibraryNode(importDirective.getLibraryUri().getValue());
      }
      importPath.setSourceInfo(importDirective.getSourceInfo());
      libUnit.addImportPath(importPath);
    }
    while (peek(0) == Token.SOURCE) {
      beginSourceDirective();
      DartSourceDirective sourceDirective = done(parseSourceDirective());
      LibraryNode sourcePath = new LibraryNode(sourceDirective.getSourceUri().getValue());
      sourcePath.setSourceInfo(sourceDirective.getSourceInfo());
      libUnit.addSourcePath(sourcePath);
    }
    while (peek(0) == Token.RESOURCE) {
      parseResourceDirective();
    }
    while (peek(0) == Token.NATIVE) {
      beginNativeDirective();
      DartNativeDirective nativeDirective = done(parseNativeDirective());
      LibraryNode nativePath = new LibraryNode(nativeDirective.getNativeUri().getValue());
      nativePath.setSourceInfo(nativeDirective.getSourceInfo());
      libUnit.addNativePath(nativePath);
    }

    // add ourselves to the list of sources, so inline dart code will be parsed
    libUnit.addSourcePath(libUnit.getSelfSourcePath());
    return done(libUnit);
  }

  private List<DartAnnotation> parseDirectives(DartUnit unit, List<DartAnnotation> metadata) {
    boolean hasLibraryDirective = false;
    if (peekPseudoKeyword(0, LIBRARY_KEYWORD)) {
      DartLibraryDirective libraryDirective = parseLibraryDirective();
      for (DartDirective directive : unit.getDirectives()) {
        if (directive instanceof DartLibraryDirective) {
          reportError(position(), ParserErrorCode.ONLY_ONE_LIBRARY_DIRECTIVE);
          break;
        }
      }
      unit.getDirectives().add(libraryDirective);
      hasLibraryDirective = true;
      setMetadata(libraryDirective, metadata);
      metadata = parseMetadata();
    }
    while (peekPseudoKeyword(0, IMPORT_KEYWORD) || peekPseudoKeyword(0, EXPORT_KEYWORD)) {
      if (peekPseudoKeyword(0, IMPORT_KEYWORD)) {
        DartImportDirective importDirective = parseImportDirective();
        unit.getDirectives().add(importDirective);
        setMetadata(importDirective, metadata);
        metadata = parseMetadata();
      } else {
        DartExportDirective exportDirective = parseExportDirective();
        unit.getDirectives().add(exportDirective);
        if (!hasLibraryDirective) {
          reportError(exportDirective, ParserErrorCode.EXPORT_WITHOUT_LIBRARY_DIRECTIVE);
        }
        setMetadata(exportDirective, metadata);
        metadata = parseMetadata();
      }
    }
    while (peekPseudoKeyword(0, PART_KEYWORD)) {
      if (peekPseudoKeyword(1, OF_KEYWORD)) {
        DartPartOfDirective partOfDirective = parsePartOfDirective();
        unit.getDirectives().add(partOfDirective);
        setMetadata(partOfDirective, metadata);
        metadata = parseMetadata();
      } else {
        DartSourceDirective partDirective = parsePartDirective();
        unit.getDirectives().add(partDirective);
        setMetadata(partDirective, metadata);
        metadata = parseMetadata();
      }
    }
    //
    // The code below is obsolete. We do not make any effort to find duplications between the old
    // and the new syntax because support for the old syntax will be removed very soon.
    //
    if (peek(0) == Token.LIBRARY) {
      beginLibraryDirective();
      DartLibraryDirective libraryDirective = parseObsoleteLibraryDirective();
      for (DartDirective directive : unit.getDirectives()) {
        if (directive instanceof DartLibraryDirective) {
          reportError(position(), ParserErrorCode.ONLY_ONE_LIBRARY_DIRECTIVE);
          break;
        }
      }
      unit.getDirectives().add(libraryDirective);
      done(libraryDirective);
      setMetadata(libraryDirective, metadata);
      metadata = parseMetadata();
    }
    while (peek(0) == Token.IMPORT) {
      beginImportDirective();
      DartImportDirective importDirective = parseObsoleteImportDirective();
      unit.getDirectives().add(done(importDirective));
      setMetadata(importDirective, metadata);
      metadata = parseMetadata();
    }
    while (peek(0) == Token.SOURCE) {
      beginSourceDirective();
      DartSourceDirective sourceDirective = parseSourceDirective();
      unit.getDirectives().add(done(sourceDirective));
      setMetadata(sourceDirective, metadata);
      metadata = parseMetadata();
    }
    while (peek(0) == Token.RESOURCE) {
      parseResourceDirective();
    }
    while (peek(0) == Token.NATIVE) {
      beginNativeDirective();
      DartNativeDirective nativeDirective = parseNativeDirective();
      unit.getDirectives().add(done(nativeDirective));
      setMetadata(nativeDirective, metadata);
      metadata = parseMetadata();
    }
    return metadata;
  }

  private DartLibraryDirective parseLibraryDirective() {
    beginLibraryDirective();
    next(); // "library"
    DartExpression libraryName = parseLibraryName();
    expect(Token.SEMICOLON);
    return done(new DartLibraryDirective(libraryName));
  }

  private DartExpression parseLibraryName() {
    beginQualifiedIdentifier();
    DartExpression libraryName = parseIdentifier();
    while (optional(Token.PERIOD)) {
      beginQualifiedIdentifier();
      DartIdentifier identifier = parseIdentifier();
      libraryName = done(new DartPropertyAccess(libraryName, identifier));
    }
    return done(libraryName);
  }

  private DartLibraryDirective parseObsoleteLibraryDirective() {
    expect(Token.LIBRARY);
    reportDeprecatedError(position(), ParserErrorCode.DEPRECATED_LIBRARY_DIRECTIVE);
    expect(Token.LPAREN);
    beginLiteral();
    expect(Token.STRING);
    DartStringLiteral libname = done(DartStringLiteral.get(ctx.getTokenString()));
    expectCloseParen();
    expect(Token.SEMICOLON);
    return new DartLibraryDirective(libname);
  }

  protected DartExportDirective parseExportDirective() {
    beginExportDirective();
    next(); // "export"
    beginLiteral();
    expect(Token.STRING);
    DartStringLiteral libUri = done(DartStringLiteral.get(ctx.getTokenString()));

    List<ImportCombinator> combinators = new ArrayList<ImportCombinator>();
    while (peekPseudoKeyword(0, HIDE_KEYWORD) || peekPseudoKeyword(0, SHOW_KEYWORD)) {
      beginImportCombinator();
      if (optionalPseudoKeyword(HIDE_KEYWORD)) {
        List<DartIdentifier> hiddenNames = parseIdentifierList();
        combinators.add(done(new ImportHideCombinator(hiddenNames)));
      } else if (optionalPseudoKeyword(SHOW_KEYWORD)) {
        List<DartIdentifier> shownNames = parseIdentifierList();
        combinators.add(done(new ImportShowCombinator(shownNames)));
      }
    }

    if (!optional(Token.SEMICOLON)) {
      // If there is no semicolon, then we probably don't want to consume the next token. It might
      // make sense to advance to the next valid token for a directive or top-level declaration, but
      // our recovery mechanism isn't quite sophisticated enough for that.
      reportUnexpectedToken(position(), Token.SEMICOLON, peek(0));
    }
    return done(new DartExportDirective(libUri, combinators));
  }

  protected DartImportDirective parseImportDirective() {
    beginImportDirective();
    next(); // "import"
    beginLiteral();
    expect(Token.STRING);
    DartStringLiteral libUri = done(DartStringLiteral.get(ctx.getTokenString()));
    
    // allow "native" if we have "dart-ext:" import
    if (StringUtils.startsWith(libUri.getValue(), "dart-ext:")) {
      allowNativeKeyword = true;
    }
    
    DartIdentifier prefix = null;
    if (optional(Token.AS)) {
      prefix = parseIdentifier();
      if (prefix instanceof DartSyntheticErrorIdentifier) {
        if (peekPseudoKeyword(1, HIDE_KEYWORD) || peekPseudoKeyword(1, SHOW_KEYWORD)
            || peek(1) == Token.BIT_AND || peek(1) == Token.COLON) {
          next();
        }
      }
    }

    List<ImportCombinator> combinators = new ArrayList<ImportCombinator>();
    while (peekPseudoKeyword(0, HIDE_KEYWORD) || peekPseudoKeyword(0, SHOW_KEYWORD)) {
      if (optionalPseudoKeyword(HIDE_KEYWORD)) {
        List<DartIdentifier> hiddenNames = parseIdentifierList();
        combinators.add(new ImportHideCombinator(hiddenNames));
      } else if (optionalPseudoKeyword(SHOW_KEYWORD)) {
        List<DartIdentifier> shownNames = parseIdentifierList();
        combinators.add(new ImportShowCombinator(shownNames));
      }
    }

    if (!optional(Token.SEMICOLON)) {
      // If there is no semicolon, then we probably don't want to consume the next token. It might
      // make sense to advance to the next valid token for a directive or top-level declaration, but
      // our recovery mechanism isn't quite sophisticated enough for that.
      reportUnexpectedToken(position(), Token.SEMICOLON, peek(0));
    }
    return done(new DartImportDirective(libUri, prefix, combinators));
  }

  /**
   * Parse a comma-separated list of identifiers.
   *
   * @return the identifiers that were parsed
   */
  private List<DartIdentifier> parseIdentifierList() {
    ArrayList<DartIdentifier> identifiers = new ArrayList<DartIdentifier>();
    identifiers.add(parseIdentifier());
    while (optional(Token.COMMA)) {
      identifiers.add(parseIdentifier());
    }
    return identifiers;
  }

  protected DartImportDirective parseObsoleteImportDirective() {
    expect(Token.IMPORT);
    reportDeprecatedError(position(), ParserErrorCode.DEPRECATED_IMPORT_DIRECTIVE);
    expect(Token.LPAREN);
    
    beginLiteral();
    expect(Token.STRING);
    DartStringLiteral libUri = done(DartStringLiteral.get(ctx.getTokenString()));
    
    // allow "native" if we have "dart-ext:" import
    if (StringUtils.startsWith(libUri.getValue(), "dart-ext:")) {
      allowNativeKeyword = true;
    }
    
    DartBooleanLiteral export = null;
    List<ImportCombinator> combinators = new ArrayList<ImportCombinator>();
    DartStringLiteral prefix = null;
    if (optional(Token.COMMA)) {
      if (optionalPseudoKeyword(PREFIX_KEYWORD)) {
        expect(Token.COLON);
        beginLiteral();
        expect(Token.STRING);
        String id = ctx.getTokenString();
        // The specification requires the value of this string be a valid identifier
        if(id == null || !id.matches("[_a-zA-Z]([_A-Za-z0-9]*)")) {
          reportError(position(), ParserErrorCode.EXPECTED_PREFIX_IDENTIFIER);
        }
        prefix = done(DartStringLiteral.get(ctx.getTokenString()));
      } else {
        reportError(position(), ParserErrorCode.EXPECTED_PREFIX_KEYWORD);
      }
    }
    expectCloseParen();
    expect(Token.SEMICOLON);
    return new DartImportDirective(libUri, export, combinators, prefix);
  }

  private DartSourceDirective parsePartDirective() {
    beginPartDirective();
    next(); // "part"
    beginLiteral();
    expect(Token.STRING);
    DartStringLiteral partUri = done(DartStringLiteral.get(ctx.getTokenString()));
    expect(Token.SEMICOLON);
    return done(new DartSourceDirective(partUri));
  }

  private DartSourceDirective parseSourceDirective() {
    expect(Token.SOURCE);
    reportDeprecatedError(position(), ParserErrorCode.DEPRECATED_SOURCE_DIRECTIVE);
    expect(Token.LPAREN);
    beginLiteral();
    expect(Token.STRING);
    DartStringLiteral sourceUri = done(DartStringLiteral.get(ctx.getTokenString()));
    expectCloseParen();
    expect(Token.SEMICOLON);
    return new DartSourceDirective(sourceUri);
  }

  private DartPartOfDirective parsePartOfDirective() {
    beginPartOfDirective();
    next(); // "part"
    next(); // "of"
    int ofOffset=  position();
    DartExpression libraryName = parseLibraryName();
    expect(Token.SEMICOLON);
    return done(new DartPartOfDirective(ofOffset, libraryName));
  }

  private void parseResourceDirective() {
    expect(Token.RESOURCE);
    reportError(position(), ParserErrorCode.DEPRECATED_RESOURCE_DIRECTIVE);
    expect(Token.LPAREN);
    beginLiteral();
    expect(Token.STRING);
    @SuppressWarnings("unused")
    DartStringLiteral resourceUri = done(DartStringLiteral.get(ctx.getTokenString()));
    expectCloseParen();
    expect(Token.SEMICOLON);
  }

  private DartNativeDirective parseNativeDirective() {
    expect(Token.NATIVE);
    expect(Token.LPAREN);
    beginLiteral();
    expect(Token.STRING);
    DartStringLiteral nativeUri = done(DartStringLiteral.get(ctx.getTokenString()));
    expect(Token.RPAREN);
    expect(Token.SEMICOLON);
    return new DartNativeDirective(nativeUri);
  }

  private List<DartAnnotation> parseMetadata() {
    List<DartAnnotation> metadata = new ArrayList<DartAnnotation>();
    while (match(Token.AT)) {
      beginMetadata();
      next();
      beginQualifiedIdentifier();
      DartExpression name = parseQualified(true);
      if (optional(Token.PERIOD)) {
        name = new DartPropertyAccess(name, parseIdentifier());
      }
      done(name);
      List<DartExpression> arguments = null;
      if (match(Token.LPAREN)) {
        arguments = parseArguments();
      }
      metadata.add(done(new DartAnnotation(name, arguments)));
    }
    return metadata;
  }

  /**
   * <pre>
   * typeParameter
   *     : identifier (EXTENDS type)?
   *     ;
   *
   * typeParameters
   *     : '<' typeParameter (',' typeParameter)* '>'
   *     ;
   * </pre>
   */
  @Terminals(tokens={Token.GT, Token.COMMA})
  private List<DartTypeParameter> parseTypeParameters() {
    List<DartTypeParameter> types = new ArrayList<DartTypeParameter>();
    expect(Token.LT);
    do {
      DartTypeParameter typeParameter = parseTypeParameter();
      types.add(typeParameter);

    } while (optional(Token.COMMA));
    expect(Token.GT);
    return types;
  }

  /**
   * Parses single {@link DartTypeParameter} for {@link #parseTypeParameters()}.
   */
  private DartTypeParameter parseTypeParameter() {
    beginTypeParameter();
    List<DartAnnotation> metadata = parseMetadata();
    DartIdentifier name = parseIdentifier();
    if (PSEUDO_KEYWORDS_SET.contains(name.getName())) {
      reportError(name, ParserErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_VARIABLE_NAME);
    }
    // Try to parse bound.
    DartTypeNode bound = null;
    if (peek(0) != Token.EOS && peek(0) != Token.COMMA && peek(0) != Token.GT) {
      if (optional(Token.EXTENDS)) {
        // OK, this is EXTENDS, parse type.
        bound = parseTypeAnnotation();
      } else if (looksLikeTopLevelKeyword()) {
        return done(new DartTypeParameter(name, bound));
      } else if (peek(0) == Token.IDENTIFIER && (peek(1) == Token.COMMA || peek(1) == Token.GT)) {
        // <X exte{cursor}>
        // User tries to type "extends", but it is not finished yet.
        // Report problem and try to continue.
        next();
        reportError(position(), ParserErrorCode.EXPECTED_EXTENDS);
      } else if (peek(0) == Token.IDENTIFIER
          && peek(1) == Token.IDENTIFIER
          && (peek(2) == Token.COMMA || peek(2) == Token.GT)) {
        // <X somethingLikeExtends Type>
        // User mistyped word "extends" or it is not finished yet.
        // Report problem and try to continue.
        next();
        reportError(position(), ParserErrorCode.EXPECTED_EXTENDS);
        bound = parseTypeAnnotation();
      } else {
        // Something else, restart parsing from next top level element.
        next();
        reportError(position(), ParserErrorCode.EXPECTED_EXTENDS);
      }
    }
    // Ready to create DartTypeParameter.
    DartTypeParameter parameter = new DartTypeParameter(name, bound);
    parameter.setMetadata(metadata);
    return done(parameter);
  }

  private List<DartTypeParameter> parseTypeParametersOpt() {
    return (peek(0) == Token.LT)
        ? parseTypeParameters()
        : Collections.<DartTypeParameter>emptyList();
  }

  /**
   * <pre>
   * classDefinition
   *     : CLASS identifier typeParameters? superclass? interfaces?
   *       '{' classMemberDefinition* '}'
   *     ;
   *
   * superclass
   *     : EXTENDS type
   *     ;
   *
   * interfaces
   *     : IMPLEMENTS typeList
   *     ;
   *
   * superinterfaces
   *     : EXTENDS typeList
   *     ;
   *
   * classMemberDefinition
   *     : declaration ';'
   *     | methodDeclaration blockOrNative
   *
   * interfaceDefinition
   *     : INTERFACE identifier typeParameters? superinterfaces?
   *       (DEFAULT type)? '{' (interfaceMemberDefinition)* '}'
   *     ;
   * </pre>
   */
  private DartDeclaration<?> parseClass() {
    beginClassBody();
    
    int tokenOffset = ctx.getTokenLocation().getBegin();
    int tokenLength = ctx.getTokenLocation().getEnd() - tokenOffset;

    // Parse modifiers.
    Modifiers modifiers = Modifiers.NONE;
    if (isTopLevelAbstract) {
      modifiers = modifiers.makeAbstract();
    }

    DartIdentifier name = parseIdentifier();
    if (name.getName().equals("")) {
      // something went horribly wrong.
      if (peek(0).equals(Token.LBRACE)) {
        parseBlock();
      }
      return done(null);
    }
    if (PSEUDO_KEYWORDS_SET.contains(name.getName())) {
      reportError(name, ParserErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME);
    }
    List<DartTypeParameter> typeParameters = parseTypeParametersOpt();

    // Parse the extends and implements clauses.
    DartTypeNode superType = null;
    int implementsOffset = -1;
    List<DartTypeNode> interfaces = null;
    if (isParsingInterface) {
      if (optional(Token.EXTENDS)) {
        interfaces = parseTypeAnnotationList();
      }
    } else {
      if (optional(Token.EXTENDS)) {
        superType = parseTypeAnnotation();
      }
      if (optionalPseudoKeyword(IMPLEMENTS_KEYWORD)) {
        implementsOffset = position();
        interfaces = parseTypeAnnotationList();
      }
    }

    // Deal with factory clause for interfaces.
    DartParameterizedTypeNode defaultClass = null;
    int defaultTokenOffset = -1;
    if (isParsingInterface &&
        (optionalDeprecatedFactory() || optional(Token.DEFAULT))) {
      defaultTokenOffset = position();
      beginTypeAnnotation();
      DartExpression qualified = parseQualified(false);
      List<DartTypeParameter> defaultTypeParameters = parseTypeParametersOpt();
      defaultClass = doneWithoutConsuming(new DartParameterizedTypeNode(qualified,
                                                                        defaultTypeParameters));
    }

    // Deal with native clause for classes.
    DartStringLiteral nativeName = null;
    if (optionalPseudoKeyword(NATIVE_KEYWORD)) {
      if (isParsingInterface) {
        reportError(position(), ParserErrorCode.NATIVE_ONLY_CLASS);
      }
      if (!allowNativeKeyword) {
        reportError(position(), ParserErrorCode.NATIVE_ONLY_CORE_LIB);
      }
      beginLiteral();
      if (expect(Token.STRING)) {
        nativeName = done(DartStringLiteral.get(ctx.getTokenString()));
      }
      modifiers = modifiers.makeNative();
    }

    // Parse the members.
    int openBraceOffset = -1;
    int closeBraceOffset = -1;
    List<DartNode> members = new ArrayList<DartNode>();
    if (optional(Token.LBRACE)) {
      openBraceOffset = ctx.getTokenLocation().getBegin();
      parseClassOrInterfaceBody(members);
      expectCloseBrace(true);
      closeBraceOffset = ctx.getTokenLocation().getBegin();
    } else {
      reportErrorWithoutAdvancing(ParserErrorCode.EXPECTED_CLASS_DECLARATION_LBRACE);
    }

    if (isParsingInterface) {
      return done(new DartClass(tokenOffset, tokenLength, name, superType, implementsOffset,
          interfaces, defaultTokenOffset, openBraceOffset, closeBraceOffset, members,
          typeParameters, defaultClass));
    } else {
      return done(new DartClass(tokenOffset, tokenLength, name, nativeName, superType,
          implementsOffset, interfaces, defaultTokenOffset, openBraceOffset, closeBraceOffset,
          members, typeParameters, modifiers));
    }
  }

  /**
   * Helper for {@link #parseClass()}.
   *
   * classMemberDefinition*
   */
  @Terminals(tokens={Token.RBRACE, Token.SEMICOLON})
  private void parseClassOrInterfaceBody(List<DartNode> members) {
    while (!match(Token.RBRACE) && !EOS() && !looksLikeTopLevelKeyword()) {
      List<DartAnnotation> metadata = parseMetadata();
      DartNodeWithMetadata member = parseFieldOrMethod(true);
      if (member != null) {
        setMetadata(member, metadata);
        members.add(member);
      }
      // Recover at a semicolon
      if (optional(Token.SEMICOLON)) {
        reportUnexpectedToken(position(), null, Token.SEMICOLON);
      }
    }
  }

  private boolean optionalDeprecatedFactory() {
    if (optionalPseudoKeyword(FACTORY_KEYWORD)) {
      reportError(position(), ParserErrorCode.DEPRECATED_USE_OF_FACTORY_KEYWORD);
      return true;
    }
    return false;
  }

  private List<DartTypeNode> parseTypeAnnotationList() {
    List<DartTypeNode> result = new ArrayList<DartTypeNode>();
    do {
      result.add(parseTypeAnnotation());
    } while (optional(Token.COMMA));
    return result;
  }

  /**
   * Look ahead to detect if we are seeing ident [ TypeParameters ] "(".
   * We need this lookahead to distinguish between the optional return type
   * and the alias name of a function type alias.
   * Token position remains unchanged.
   *
   * @return true if the next tokens should be parsed as a type
   */
  private boolean isFunctionTypeAliasName() {
    beginFunctionTypeInterface();
    try {
      if ((peek(0) == Token.IDENTIFIER || peek(0) == Token.AS) && peek(1) == Token.LPAREN) {
        return true;
      }
      if ((peek(0) == Token.IDENTIFIER || peek(0) == Token.AS) && peek(1) == Token.LT) {
        consume(Token.IDENTIFIER);
        // isTypeParameter leaves the position advanced if it matches
        if (isTypeParameter() && peek(0) == Token.LPAREN) {
          return true;
        }
      }
      return false;
    } finally {
      rollback();
    }
  }

  /**
   * Returns true if the current and next tokens can be parsed as type
   * parameters. Current token position is not saved and restored.
   */
  private boolean isTypeParameter() {
    if (peek(0) == Token.LT) {
      // We are possibly looking at type parameters. Find closing ">".
      consume(Token.LT);
      int nestingLevel = 1;
      while (nestingLevel > 0) {
        switch (peek(0)) {
          case LT:
            nestingLevel++;
            break;
          case GT:
            nestingLevel--;
            break;
          case SAR:   // >>
            nestingLevel -= 2;
            break;
          case COMMA:
          case EXTENDS:
          case IDENTIFIER:
            break;
          default:
            // We are looking at something other than type parameters.
            return false;
        }
        next();
        if (nestingLevel < 0) {
          return false;
        }
      }
    }
    return true;
  }

  /**
   * <pre>
   * functionTypeAlias
   *     : TYPEDEF functionPrefix typeParameters?
   *       formalParameterList ';'
   *
   * functionPrefix
   *     : returnType? identifier
   * </pre>
   */
  private DartFunctionTypeAlias parseFunctionTypeAlias() {
    beginFunctionTypeInterface();

    DartTypeNode returnType = null;
    if (peek(0) == Token.VOID) {
      returnType = parseVoidType();
    } else if (!isFunctionTypeAliasName()) {
      returnType = parseTypeAnnotation();
    }

    DartIdentifier name = parseIdentifier();
    if (PSEUDO_KEYWORDS_SET.contains(name.getName())) {
      reportError(name, ParserErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME);
    }

    List<DartTypeParameter> typeParameters = parseTypeParametersOpt();
    FormalParameters params = parseFormalParameterList();
    expect(Token.SEMICOLON);
    validateNoDefaultParameterValues(
        params.val,
        ParserErrorCode.DEFAULT_VALUE_CAN_NOT_BE_SPECIFIED_IN_TYPEDEF);

    return done(new DartFunctionTypeAlias(name, returnType, params.val, typeParameters));
  }

  /**
   * Parse a field or method, which may be inside a class or at the top level.
   *
   * <pre>
   * // This rule is organized in a way that may not be most readable, but
   * // gives the best error messages.
   * classMemberDefinition
   *     : declaration ';'
   *     | methodDeclaration bodyOrNative
   *     ;
   *
   * // Note: this syntax is not official, but used in dart_interpreter. It
   * // is unlikely that Dart will support numbered natives.
   * bodyOrNative
   *     : error=NATIVE (':' (STRING | RATIONAL_NUMBER))? ';'
   *       { legacy($error, "native not supported (yet)"); }
   *     | functionStatementBody
   *     ;
   *
   * // A method, operator, or constructor (which all should be followed by
   * // a function body).
   * methodDeclaration
   *     : factoryConstructorDeclaration
   *     | STATIC methodOrConstructorDeclaration
   *     | specialSignatureDefinition
   *     | methodOrConstructorDeclaration initializers?
   *     | namedConstructorDeclaration initializers?
   *     ;
   *
   *
   * // An abstract method/operator, a field, or const constructor (which
   * // all should be followed by a semicolon).
   * declaration
   *     : constantConstructorDeclaration initializers?
   *     | ABSTRACT specialSignatureDefinition
   *     | ABSTRACT methodOrConstructorDeclaration
   *     | STATIC CONST type? staticConstDeclarationList
   *     | STATIC? variableDeclaration
   *     ;
   *
   * interfaceMemberDefinition
   *     : STATIC CONST type? initializedIdentifierList ';'
   *     | methodOrConstructorDeclaration ';'
   *     | constantConstructorDeclaration ';'
   *     | namedConstructorDeclaration ';'
   *     | specialSignatureDefinition ';'
   *     | variableDeclaration ';'
   *     ;
   *
   * variableDeclaration
   *     : constVarOrType identifierList
   *     ;
   *
   * methodOrConstructorDeclaration
   *     : typeOrFunction? identifier formalParameterList
   *     ;
   *
   * factoryConstructorDeclaration
   *     : FACTORY qualified ('.' identifier)? formalParameterList
   *     ;
   *
   * namedConstructorDeclaration
   *     : identifier typeArguments? '.' identifier formalParameterList
   *     ;
   *
   * constructorDeclaration
   *     : identifier typeArguments? formalParameterList
   *     | namedConstructorDeclaration
   *     ;
   *
   * constantConstructorDeclaration
   *     : CONST qualified formalParameterList
   *     ;
   *
   * specialSignatureDefinition
   *     : STATIC? type? getOrSet identifier formalParameterList
   *     | type? OPERATOR operator formalParameterList
   *     ;
   *
   * getOrSet
   *     : GET
   *     | SET
   *     ;
   *
   * operator
   *     : unaryOperator
   *     | binaryOperator
   *     | '[' ']' { "[]".equals($text) }?
   *     | '[' ']' '=' { "[]=".equals($text) }?
   *     | NEGATE
   *     | CALL
   *     ;
   * </pre>
   *
   * @param allowStatic true if the static modifier is allowed
   * @return a {@link DartNode} representing the grammar fragment above
   */
  @Terminals(tokens={Token.SEMICOLON})
  private DartNodeWithMetadata parseFieldOrMethod(boolean allowStatic) {
    beginClassMember();
    Modifiers modifiers = Modifiers.NONE;
    if (peek(1) != Token.LPAREN && optionalPseudoKeyword(EXTERNAL_KEYWORD)) {
      modifiers = modifiers.makeExternal();
    }
    if (peek(1) != Token.LPAREN && optionalPseudoKeyword(STATIC_KEYWORD)) {
      if (!allowStatic) {
        reportError(position(), ParserErrorCode.TOP_LEVEL_CANNOT_BE_STATIC);
      } else {
        if (isParsingInterface
            && peek(0) != Token.FINAL && peek(0) != Token.CONST) {
          reportError(position(), ParserErrorCode.NON_FINAL_STATIC_MEMBER_IN_INTERFACE);
        }
        modifiers = modifiers.makeStatic();
      }
    }
    if (optionalPseudoKeyword(ABSTRACT_KEYWORD)) {
      if (modifiers.isStatic()) {
        reportError(position(), ParserErrorCode.STATIC_MEMBERS_CANNOT_BE_ABSTRACT);
      }
      if (modifiers.isExternal()) {
        reportError(position(), ParserErrorCode.EXTERNAL_ABSTRACT);
      }
      modifiers = modifiers.makeAbstract();
    }
    if (optionalPseudoKeyword(FACTORY_KEYWORD)) {
      if (isParsingInterface) {
        reportError(position(), ParserErrorCode.FACTORY_MEMBER_IN_INTERFACE);
      }
      if (modifiers.isStatic()) {
        reportError(position(), ParserErrorCode.FACTORY_CANNOT_BE_STATIC);
      }
      if (modifiers.isAbstract()) {
        reportError(position(), ParserErrorCode.FACTORY_CANNOT_BE_ABSTRACT);
      }

      modifiers = modifiers.makeFactory();
    }

    if (match(Token.VAR) || match(Token.FINAL)) {
      if (modifiers.isAbstract()) {
        reportError(position(), ParserErrorCode.DISALLOWED_ABSTRACT_KEYWORD);
      }
      if (modifiers.isFactory()) {
        reportError(position(), ParserErrorCode.DISALLOWED_FACTORY_KEYWORD);
      }
    }
    
    // report "abstract" warning after all other checks to don't hide error with warning
    // we ignore problems if there was already reported problem after given position
    if (modifiers.isAbstract()) {
      // TODO(scheglov) remove after http://code.google.com/p/dart/issues/detail?id=6322
      // TODO(scheglov) remove after http://code.google.com/p/dart/issues/detail?id=6323
      if (!Elements.isCoreLibrarySource(source)
          && !Elements.isLibrarySource(source, "html/dartium/html_dartium.dart")
          && !Elements.isLibrarySource(source, "/math/math.dart")
          && !Elements.isLibrarySource(source, "/io/io_runtime.dart")
          && !Elements.isLibrarySource(source, "/crypto/crypto.dart")
          && !Elements.isLibrarySource(source, "/utf/utf.dart")) {
        reportError(position(), ParserErrorCode.DEPRECATED_ABSTRACT_METHOD);
      }
    }

    if (modifiers.isFactory()) {
      if (!isParsingClass) {
        reportError(position(), ParserErrorCode.FACTORY_CANNOT_BE_TOP_LEVEL);
      }
      // Do parse factory.
      DartMethodDefinition factoryNode = parseFactory(modifiers);
      // If factory is not allowed, ensure that it is valid as method.
      DartExpression actualName = factoryNode.getName();
      if (!allowStatic && !(actualName instanceof DartIdentifier)) {
        DartExpression replacementName = new DartIdentifier(actualName.toString());
        factoryNode.setName(replacementName);
      }
      // Done.
      return done(factoryNode);
    }

    final DartNodeWithMetadata member;

    switch (peek(0)) {
      case VAR: {
        consume(Token.VAR);
        // Check for malformed method starting with 'var' : var ^ foo() { }
        if (peek(0).equals(Token.IDENTIFIER) && looksLikeMethodOrAccessorDefinition()) {
          reportError(position(), ParserErrorCode.VAR_IS_NOT_ALLOWED_ON_A_METHOD_DEFINITION);
          member = parseMethodOrAccessor(modifiers, null);
          break;
        }

        member = parseFieldDeclaration(modifiers, null);
        expectStatmentTerminator();
        break;
      }

      case CONST: {
        consume(Token.CONST);
        modifiers = modifiers.makeConstant();
        // Allow "const factory ... native" constructors for core libraries only
        if (optionalPseudoKeyword(FACTORY_KEYWORD)) {
          modifiers = modifiers.makeFactory();
        }
        if (peek(0).equals(Token.IDENTIFIER) && looksLikeMethodOrAccessorDefinition()) {
          return done(parseMethod(modifiers, null));
        }
        // Try to find type, may be "const ^ Type field".
        DartTypeNode type = null;
        if (peek(1) != Token.COMMA
            && peek(1) != Token.ASSIGN
            && peek(1) != Token.SEMICOLON) {
          type = parseTypeAnnotation();
        }
        // Parse field.
        modifiers = modifiers.makeFinal();
        member = parseFieldDeclaration(modifiers, type);
        expectStatmentTerminator();
        break;
      }

      case FINAL: {
        consume(Token.FINAL);
        modifiers = modifiers.makeFinal();

        // Check for malformed method starting with 'final':   final ^ foo() { }
        if (peek(0).equals(Token.IDENTIFIER) && looksLikeMethodOrAccessorDefinition()) {
          reportError(position(), ParserErrorCode.FINAL_IS_NOT_ALLOWED_ON_A_METHOD_DEFINITION);
          member = parseMethodOrAccessor(modifiers, null);
          break;
        }
        DartTypeNode type = null;
        if (peek(1) != Token.COMMA
            && peek(1) != Token.ASSIGN
            && peek(1) != Token.SEMICOLON) {
          type = parseTypeAnnotation();

          // Check again for malformed method starting with 'final':   final String ^ foo() { }
          if (peek(0).equals(Token.IDENTIFIER) && looksLikeMethodOrAccessorDefinition()) {
            reportError(position(), ParserErrorCode.FINAL_IS_NOT_ALLOWED_ON_A_METHOD_DEFINITION);
            member = parseMethodOrAccessor(modifiers, null);
            break;
          }
        }
        member = parseFieldDeclaration(modifiers, type);
        expectStatmentTerminator();
        break;
      }

      case IDENTIFIER: {

        // Check to see if it looks like the start of a method definition (sans type).
        if (looksLikeMethodOrAccessorDefinition()) {
          member = parseMethodOrAccessor(modifiers, null);
          break;
        }
      }
      //$FALL-THROUGH$

      case VOID: {

        // The next token may be a type specification or parameterized constructor: either a method or field.
        boolean isVoidType = peek(0) == Token.VOID;
        DartTypeNode type;
        if (isVoidType) {
          type = parseVoidType();
        } else {
          int nameIndex = skipTypeName(0);
          if (nameIndex < 0 || (peek(nameIndex) != Token.IDENTIFIER && peek(nameIndex) != Token.AS)) {
            // There was no type name.
            type = null;
          } else {
            type = parseTypeAnnotation();
          }
        }
        if (peek(1) == Token.SEMICOLON
            || peek(1) == Token.COMMA
            || peek(1) == Token.ASSIGN) {
          if (modifiers.isAbstract()) {
            reportError(position(), ParserErrorCode.INVALID_FIELD_DECLARATION);
          }
          member = parseFieldDeclaration(modifiers, type);
          if (isVoidType) {
            reportError(type, ParserErrorCode.VOID_FIELD);
          } else if (!modifiers.isFinal() && type == null) {
            reportError(position(), ParserErrorCode.INVALID_FIELD_DECLARATION);
          }
          expectStatmentTerminator();
        } else {
          member = parseMethodOrAccessor(modifiers, type);
        }
        break;
      }

      case SEMICOLON:
      default: {
        done(null);
        reportUnexpectedToken(position(), null, next());
        member = null;
        break;
      }
    }
    return member;
  }

  /**
   * Returns true if the beginning of a method definition follows.
   *
   * This test is needed to disambiguate between a method that returns a type
   * and a plain method.
   *
   * Assumes the next token has already been determined to be an identifier.
   *
   * The following constructs will match:
   *
   *      : get (
   *      | get identifier (
   *      | set (
   *      | set identifier (
   *      | operator (
   *      | operator <op> (
   *      | identifier (
   *      | identifier DOT identifier  (
   *      | identifier DOT identifier DOT identifier (
   *
   * @return <code>true</code> if the signature of a method has been found.  No tokens are consumed.
   */
  private boolean looksLikeMethodOrAccessorDefinition() {
    assert (peek(0).equals(Token.IDENTIFIER));
    beginMethodName(); // begin() equivalent
    try {
      if (peekPseudoKeyword(0, OPERATOR_KEYWORD)) {
        next();
        // Using 'operator' as a field name is valid
        if (peek(0).equals(Token.SEMICOLON) || peek(0).equals(Token.ASSIGN)) {
          return false;
        }
        // Using 'operator' as a method name is valid (but discouraged)
        if (peek(0).equals(Token.LPAREN)) {
          return true;
        }
        // operator call (
        if (peekPseudoKeyword(0, CALL_KEYWORD) && peek(1).equals(Token.LPAREN)) {
          return true;
        }
        // TODO(zundel): Look for valid operator overload tokens.  For now just assuming
        // non-idents are good enough
        // operator ??? (
        if (!(peek(0).equals(Token.IDENTIFIER) &&  peek(1).equals(Token.LPAREN))) {
          return true;
        }
        if (peek(0).equals(Token.LBRACK) && peek(1).equals(Token.RBRACK)) {
          // operator [] (
          if (peek(2).equals(Token.LPAREN)) {
            return true;
          }
          // operator []= (
          if (peek(2).equals(Token.ASSIGN) && peek(3).equals(Token.LPAREN)) {
            return true;
          }
        }
        return false;
      }

      if (peekPseudoKeyword(0, GETTER_KEYWORD)
          || peekPseudoKeyword(0, SETTER_KEYWORD)) {
        boolean isGetter = peekPseudoKeyword(0, GETTER_KEYWORD);
        next();
        // Using 'get' or 'set' as a field name is valid
        if (peek(0).equals(Token.SEMICOLON) || peek(0).equals(Token.ASSIGN)) {
          return false;
        }
        // Using 'get' or 'set' as a method name is valid (but discouraged)
        if (peek(0).equals(Token.LPAREN)) {
          return true;
        }
        // normal case:  get foo (
        if (peek(0).equals(Token.IDENTIFIER) && (isGetter || peek(1).equals(Token.LPAREN))) {
          return true;
        }
        return false;
      }

      consume(Token.IDENTIFIER);

      if (peek(0).equals(Token.PERIOD) && peek(1).equals(Token.IDENTIFIER)) {
        consume(Token.PERIOD);
        consume(Token.IDENTIFIER);

        if (peek(0).equals(Token.PERIOD) && peek(1).equals(Token.IDENTIFIER)) {
          consume(Token.PERIOD);
          consume(Token.IDENTIFIER);
        }
      }

      // next token should be LPAREN
      return (peek(0).equals(Token.LPAREN));
    } finally {
      rollback();
    }
  }

  /**
   * <pre>
   * factoryConstructorDeclaration
   *     : FACTORY qualified ('.' identifier)? formalParameterList
   *     ;
   * </pre>
   */
  private DartMethodDefinition parseFactory(Modifiers modifiers) {
    beginMethodName();
    DartExpression name = parseQualified(true);
    if (optional(Token.PERIOD)) {
      name = doneWithoutConsuming(new DartPropertyAccess(name, parseIdentifier()));
    }
    done(name);
    FormalParameters formals = parseFormalParameterList();
    int parametersCloseParen = ctx.getTokenLocation().getBegin();

    // Parse redirecting factory
    if (match(Token.ASSIGN)) {
      next();
      if (!modifiers.isFactory()) {
        reportError(position(), ParserErrorCode.ONLY_FACTORIES_CAN_REDIRECT);
      }
      modifiers = modifiers.makeRedirectedConstructor();
      DartTypeNode redirectedTypeName = parseTypeAnnotationPossiblyFollowedByName();
      DartIdentifier redirectedConstructorName = null;
      if (optional(Token.PERIOD)) {
        redirectedConstructorName = parseIdentifier();
      }
      expect(Token.SEMICOLON);
      DartFunction function = doneWithoutConsuming(new DartFunction(formals.val,
          formals.optionalOpenOffset, formals.optionalCloseOffset, parametersCloseParen, null, null));
      return DartMethodDefinition.create(name, function, modifiers, redirectedTypeName, 
                                         redirectedConstructorName);
    }

    DartFunction function;
    if (peekPseudoKeyword(0, NATIVE_KEYWORD)) {
      modifiers = modifiers.makeNative();
      function = new DartFunction(formals.val, formals.optionalOpenOffset,
          formals.optionalCloseOffset, parametersCloseParen, parseNativeBlock(modifiers), null);
    } else {
      function = new DartFunction(formals.val, formals.optionalOpenOffset,
          formals.optionalCloseOffset, parametersCloseParen, parseFunctionStatementBody(
              !modifiers.isExternal(), true), null);
    }
    doneWithoutConsuming(function);
    return DartMethodDefinition.create(name, function, modifiers, null);
  }

  private DartIdentifier parseVoidIdentifier() {
    beginIdentifier();
    expect(Token.VOID);
    return done(new DartIdentifier(Token.VOID.getSyntax()));
  }

  private DartTypeNode parseVoidType() {
    beginTypeAnnotation();
    return done(new DartTypeNode(parseVoidIdentifier()));
  }

  private DartMethodDefinition parseMethod(Modifiers modifiers, DartTypeNode returnType) {
    DartExpression name = new DartIdentifier("");

    if (modifiers.isFactory()) {
      if (modifiers.isAbstract()) {
        reportError(position(), ParserErrorCode.FACTORY_CANNOT_BE_ABSTRACT);
      }
      if (modifiers.isStatic()) {
        reportError(position(), ParserErrorCode.FACTORY_CANNOT_BE_STATIC);
      }
    }

    int arity = -1;
    Token operation = null;
    if (peek(1) != Token.LPAREN && optionalPseudoKeyword(OPERATOR_KEYWORD)) {
      // Overloaded operator.
      if (modifiers.isStatic()) {
        reportError(position(), ParserErrorCode.OPERATOR_CANNOT_BE_STATIC);
      }
      modifiers = modifiers.makeOperator();

      beginOperatorName();
      operation = next();
      if (operation.isUserDefinableOperator()) {
        name = done(new DartIdentifier(operation.getSyntax()));
        if (operation == Token.ASSIGN_INDEX) {
          arity = 2;
        } else if (operation == Token.SUB) {
          arity = -1;
        } else if (operation.isBinaryOperator()) {
          arity = 1;
        } else if (operation == Token.INDEX) {
          arity = 1;
        } else {
          assert operation.isUnaryOperator();
          arity = 0;
        }
      } else if (operation == Token.IDENTIFIER
                 && ctx.getTokenString().equals(CALL_KEYWORD)) {
        name = done(new DartIdentifier(CALL_KEYWORD));
        arity = -1;
      } else if (operation == Token.IDENTIFIER
          && ctx.getTokenString().equals(CALL_KEYWORD)) {
        name = done(new DartIdentifier(CALL_KEYWORD));
      } else {
        // Not a valid operator.  Try to recover.
        boolean found = false;
        for (int i = 0; i < 4; ++i) {
          if (peek(i).equals(Token.LPAREN)) {
            found = true;
            break;
          }
        }
        StringBuilder buf = new StringBuilder();
        buf.append(operation.getSyntax());
        if (found) {
          reportError(position(), ParserErrorCode.OPERATOR_IS_NOT_USER_DEFINABLE);
          while(true) {
            Token token = peek(0);
            if (token.equals(Token.LPAREN)) {
              break;
            }
            buf.append(next().getSyntax());
          }
          name = done(new DartIdentifier(buf.toString()));
        } else {
          reportUnexpectedToken(position(), Token.COMMENT, operation);
          done(null);
        }
      }
    } else {
      beginMethodName();
      // Check for getters and setters.
      if (peek(1) != Token.LPAREN && optionalPseudoKeyword(GETTER_KEYWORD)) {
        name = parseIdentifier();
        modifiers = modifiers.makeGetter();
        arity = 0;
      } else if (peek(1) != Token.LPAREN && optionalPseudoKeyword(SETTER_KEYWORD)) {
        name = parseIdentifier();
        modifiers = modifiers.makeSetter();
        arity = 1;
      } else {
        // Normal method or property.
        name = parseIdentifier();
      }

      // Check for named constructor.
      if (optional(Token.PERIOD)) {
        name = doneWithoutConsuming(new DartPropertyAccess(name, parseIdentifier()));
        if(currentlyParsingToplevel()) {
          // TODO: Error recovery could find a missing brace and treat this as an expression
          reportError(name,  ParserErrorCode.FUNCTION_NAME_EXPECTED_IDENTIFIER);
        }
        if (optional(Token.PERIOD)) {
          name = doneWithoutConsuming(new DartPropertyAccess(name, parseIdentifier()));
        }
      }
      done(null);
    }

    // Parse the parameters definitions.
    FormalParameters parametersInfo;
    if (modifiers.isGetter()) {
      parametersInfo = new FormalParameters(new ArrayList<DartParameter>(), -1, -1);
      if (peek(0) == Token.LPAREN) {
        // TODO(scheglov) remove after http://code.google.com/p/dart/issues/detail?id=6297
        if (!Elements.isHtmlLibrarySource(source)) {
          reportError(position(), ParserErrorCode.DEPRECATED_GETTER);
        }
        parametersInfo = parseFormalParameterList();
      }
    } else {
      parametersInfo = parseFormalParameterList();
    }
    List<DartParameter> parameters = parametersInfo.val;
    int parametersCloseParen = ctx.getTokenLocation().getBegin();

    if (arity != -1) {
      if (parameters.size() != arity) {
        reportError(position(), ParserErrorCode.ILLEGAL_NUMBER_OF_PARAMETERS);
      }
      // In methods with required arity each parameter is required.
      for (int i = 0, size = parameters.size(); i < size; i++) {
        DartParameter parameter = parameters.get(i);
        if (parameter.getModifiers().isOptional()) {
          reportError(parameter, ParserErrorCode.OPTIONAL_POSITIONAL_PARAMETER_NOT_ALLOWED);
        }
        if (parameter.getModifiers().isNamed()) {
          reportError(parameter, ParserErrorCode.NAMED_PARAMETER_NOT_ALLOWED);
        }
      }
    } else if (operation == Token.SUB) {
      if (parameters.size() != 0 && parameters.size() != 1) {
        reportError(position(), ParserErrorCode.ILLEGAL_NUMBER_OF_PARAMETERS);
      }
      // In methods with required arity each parameter is required.
      for (int i = 0, size = parameters.size(); i < size; i++) {
        DartParameter parameter = parameters.get(i);
        if (parameter.getModifiers().isNamed()) {
          reportError(parameter, ParserErrorCode.NAMED_PARAMETER_NOT_ALLOWED);
        }
      }
    }

    // Parse redirecting factory
    DartTypeNode redirectedTypeName = null;
    DartIdentifier redirectedConstructorName = null;
    if (match(Token.ASSIGN)) {
      next();
      if (!modifiers.isFactory()) {
        reportError(position(), ParserErrorCode.ONLY_FACTORIES_CAN_REDIRECT);
      }
      modifiers = modifiers.makeRedirectedConstructor();
      redirectedTypeName = parseTypeAnnotationPossiblyFollowedByName();
      if (optional(Token.PERIOD)) {
        redirectedConstructorName = parseIdentifier();
      }
      expect(Token.SEMICOLON);
      DartFunction function = doneWithoutConsuming(new DartFunction(parameters,
          parametersInfo.optionalOpenOffset, parametersInfo.optionalCloseOffset,
          parametersCloseParen, null, returnType));
      return DartMethodDefinition.create(name, function, modifiers, redirectedTypeName, 
                                         redirectedConstructorName);
    }

    // Parse initializer expressions for constructors.
    List<DartInitializer> initializers = new ArrayList<DartInitializer>();
    if (match(Token.COLON) && !(isParsingInterface || modifiers.isFactory())) {
      parseInitializers(initializers);
      boolean isRedirectedConstructor = validateInitializers(parameters, initializers);
      if (isRedirectedConstructor) {
        modifiers = modifiers.makeRedirectedConstructor();
      }
    }

    // Parse the body.
    DartBlock body = null;
    if (!optional(Token.SEMICOLON)) {
      if (peekPseudoKeyword(0, NATIVE_KEYWORD)) {
        modifiers = modifiers.makeNative();
        body = parseNativeBlock(modifiers);
      } else {
        body = parseFunctionStatementBody(!modifiers.isExternal(), true);
      }
      if (body != null && modifiers.isRedirectedConstructor()) {
        reportError(position(), ParserErrorCode.REDIRECTING_CONSTRUCTOR_CANNOT_HAVE_A_BODY);
      }
    }

    DartFunction function = doneWithoutConsuming(new DartFunction(parameters,
        parametersInfo.optionalOpenOffset, parametersInfo.optionalCloseOffset,
        parametersCloseParen, body, returnType));
    return DartMethodDefinition.create(name, function, modifiers, initializers);
  }

  private DartBlock parseNativeBlock(Modifiers modifiers) {
    beginNativeBody();
    if (!optionalPseudoKeyword(NATIVE_KEYWORD)) {
      throw new AssertionError();
    }
    if (!allowNativeKeyword) {
      reportError(position(), ParserErrorCode.NATIVE_ONLY_CORE_LIB);
    }
    DartExpression body = null;
    if (match(Token.STRING)) {
      body = parseStringWithPasting();
    }
    if (match(Token.LBRACE) || match(Token.ARROW)) {
      return done(parseFunctionStatementBody(!modifiers.isExternal(), true));
    } else {
      expect(Token.SEMICOLON);
      return done(new DartNativeBlock(body));
    }
  }

  private DartNodeWithMetadata parseMethodOrAccessor(Modifiers modifiers, DartTypeNode returnType) {
    DartMethodDefinition method = done(parseMethod(modifiers, returnType));
    // Abstract method can not have a body.
    if (method.getFunction().getBody() != null) {
      if (isParsingInterface) {
        reportError(method.getName(), ParserErrorCode.INTERFACE_METHOD_WITH_BODY);
      }
      if (method.getModifiers().isAbstract()) {
        reportError(method.getName(), ParserErrorCode.ABSTRACT_METHOD_WITH_BODY);
      }
    }
    // If getter or setter, generate DartFieldDefinition instead.
    if (method.getModifiers().isGetter() || method.getModifiers().isSetter()) {
      DartField field = new DartField((DartIdentifier) method.getName(),
                                      method.getModifiers().makeAbstractField(), method, null);
      field.setSourceInfo(method.getSourceInfo());
      DartFieldDefinition fieldDefinition =
        new DartFieldDefinition(null, Lists.<DartField>create(field));
      fieldDefinition.setSourceInfo(field.getSourceInfo());
      return fieldDefinition;
    }
    // OK, use method as method.
    return method;
  }

  /**
   * <pre>
   * initializers
   *            : ':' superCallOrFirstFieldInitializer (',' fieldInitializer)*
   *            | THIS ('.' identifier) formalParameterList
   *            ;
   *
   * fieldInitializer
   *            : (THIS '.')? identifier '=' conditionalExpression
   *            ;
   *
   * superCallOrFirstFieldInitializer
   *            : SUPER arguments | SUPER '.' identifier arguments
   *            | fieldInitializer
   *            ;
   *
   * fieldInitializer
   *            : (THIS '.')? identifier '=' conditionalExpression
   *            | THIS ('.' identifier)? arguments
   *            ;
   * </pre>
   */
  private void parseInitializers(List<DartInitializer> initializers) {
    expect(Token.COLON);
    do {
      beginInitializer();
      if (match(Token.SUPER)) {
        beginSuperInitializer();
        expect(Token.SUPER);
        DartIdentifier constructor = null;
        if (optional(Token.PERIOD)) {
          constructor = parseIdentifier();
        }
        DartSuperConstructorInvocation superInvocation =
          new DartSuperConstructorInvocation(constructor, parseArguments());
        initializers.add(done(new DartInitializer(null, done(superInvocation))));
      } else {
        boolean hasThisPrefix = optional(Token.THIS);
        if (hasThisPrefix) {
          if (match(Token.LPAREN)) {
            parseRedirectedConstructorInvocation(null, initializers);
            continue;
          }
          expect(Token.PERIOD);
        }
        DartIdentifier name = parseIdentifier();
        if (hasThisPrefix && match(Token.LPAREN)) {
          parseRedirectedConstructorInvocation(name, initializers);
          continue;
        } else {
          expect(Token.ASSIGN);
          boolean save = setAllowFunctionExpression(false);
          DartExpression initExpr = parseExpression();
          setAllowFunctionExpression(save);
          initializers.add(done(new DartInitializer(name, initExpr)));
        }
      }
    } while (optional(Token.COMMA));
  }

  private void parseRedirectedConstructorInvocation(DartIdentifier name,
      List<DartInitializer> initializers) {
    DartRedirectConstructorInvocation redirConstructor =
        new DartRedirectConstructorInvocation(name, parseArguments());
    initializers.add(done(new DartInitializer(null, doneWithoutConsuming(redirConstructor))));
  }

  private boolean validateInitializers(List<DartParameter> parameters,
      List<DartInitializer> initializers) {
    // Try to find DartRedirectConstructorInvocation, check for multiple invocations.
    // Check for DartSuperConstructorInvocation multiple invocations.
    DartInitializer redirectInitializer = null;
    boolean firstMultipleRedirectReported = false;
    {
      DartInitializer superInitializer = null;
      boolean firstMultipleSuperReported = false;
      for (DartInitializer initializer : initializers) {
        if (initializer.isInvocation()) {
          // DartSuperConstructorInvocation
          DartExpression initializerInvocation = initializer.getValue();
          if (initializerInvocation instanceof DartSuperConstructorInvocation) {
            if (superInitializer != null) {
              if (!firstMultipleSuperReported) {
                reportError(superInitializer, ParserErrorCode.SUPER_CONSTRUCTOR_MULTIPLE);
                firstMultipleSuperReported = true;
              }
              reportError(initializer, ParserErrorCode.SUPER_CONSTRUCTOR_MULTIPLE);
            } else {
              superInitializer = initializer;
            }
          }
          // DartRedirectConstructorInvocation
          if (initializerInvocation instanceof DartRedirectConstructorInvocation) {
            if (redirectInitializer != null) {
              if (!firstMultipleRedirectReported) {
                reportError(redirectInitializer, ParserErrorCode.REDIRECTING_CONSTRUCTOR_MULTIPLE);
                firstMultipleRedirectReported = true;
              }
              reportError(initializer, ParserErrorCode.REDIRECTING_CONSTRUCTOR_MULTIPLE);
            } else {
              redirectInitializer = initializer;
            }
          }
        }
      }
    }
    // If there is redirecting constructor, then there should be no other initializers.
    if (redirectInitializer != null) {
      boolean shouldRedirectInvocationReported = false;
      // Implicit initializer in form of "this.id" parameter.
      for (DartParameter parameter : parameters) {
        if (parameter.getName() instanceof DartPropertyAccess) {
          DartPropertyAccess propertyAccess = (DartPropertyAccess) parameter.getName();
          if (propertyAccess.getQualifier() instanceof DartThisExpression) {
            shouldRedirectInvocationReported = true;
            reportError(
                parameter,
                ParserErrorCode.REDIRECTING_CONSTRUCTOR_PARAM);
          }
        }
      }
      // Iterate all initializers and mark all except of DartRedirectConstructorInvocation
      for (DartInitializer initializer : initializers) {
        if (!(initializer.getValue() instanceof DartRedirectConstructorInvocation)) {
          shouldRedirectInvocationReported = true;
          reportError(
              initializer,
              ParserErrorCode.REDIRECTING_CONSTRUCTOR_OTHER);
        }
      }
      // Mark DartRedirectConstructorInvocation if needed.
      if (shouldRedirectInvocationReported) {
        reportError(
            redirectInitializer,
            ParserErrorCode.REDIRECTING_CONSTRUCTOR_ITSELF);
      }
    }
    // Done.
    return redirectInitializer != null;
  }

  /**
   * <pre>
   * variableDeclaration
   *    : constVarOrType identifierList
   *    ;
   * identifierList
   *    : identifier (',' identifier)*
   *    ;
   *
   * staticConstDeclarationList
   *    : staticConstDeclaration (',' staticConstDeclaration)*
   *    ;
   *
   * staticConstDeclaration
   *    : identifier '=' constantExpression
   *    ;
   *
   * // The compile-time expression production is used to mark certain expressions
   * // as only being allowed to hold a compile-time constant. The grammar cannot
   * // express these restrictions, so this will have to be enforced by a separate
   * // analysis phase.
   * constantExpression
   *    : expression
   *    ;
   * </pre>
   */
  private DartFieldDefinition parseFieldDeclaration(Modifiers modifiers, DartTypeNode type) {
    List<DartField> fields = new ArrayList<DartField>();
    List<DartAnnotation> metadata = parseMetadata();
    do {
      beginVariableDeclaration();
      DartIdentifier name = parseIdentifier();
      DartExpression value = null;
      if (optional(Token.ASSIGN)) {
        value = parseExpression();
        if (value != null) {
          modifiers = modifiers.makeInitialized();
        }
      }
      if (modifiers.isExternal()) {
        reportError(name, ParserErrorCode.EXTERNAL_ONLY_METHOD);
      }
      DartField field = done(new DartField(name, modifiers, null, value));
      setMetadata(field, metadata);
      fields.add(field);
    } while (optional(Token.COMMA));
    DartFieldDefinition definition = new DartFieldDefinition(type, fields);
    setMetadata(definition, metadata);
    return done(definition);
  }
  
  private static class FormalParameters {
    private final List<DartParameter> val;
    private final int optionalOpenOffset;
    private final int optionalCloseOffset;
    public FormalParameters(List<DartParameter> parameters, int optionalOpenOffset,
        int optionalCloseOffset) {
      this.val = parameters;
      this.optionalOpenOffset = optionalOpenOffset;
      this.optionalCloseOffset = optionalCloseOffset;
    }
  }

  /**
   * <pre>
   * formalParameterList
   *     : '(' ')'
   *     | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
   *     | '(' optionalFormalParameters ')'
   *     ;
   *
   * normalFormalParameters
   *     : normalFormalParameter (',' normalFormalParameter)*
   *     ;
   *
   * optionalFormalParameters
   *     : optionalPositionalFormalParameters
   *     | namedFormalParameters
   *     ;
   *
   * optionalPositionalFormalParameters
   *     : '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
   *     ;
   *
   * namedFormalParameters
   *     : '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
   *     ;
   * </pre>
   */
  @Terminals(tokens = {Token.COMMA, Token.RPAREN})
  private FormalParameters parseFormalParameterList() {
    beginFormalParameterList();
    List<DartParameter> params = new ArrayList<DartParameter>();
    int optionalOpenOffset = -1;
    int optionalCloseOffset = -1;
    expect(Token.LPAREN);
    boolean done = optional(Token.RPAREN);
    boolean isOptional = false;
    boolean isNamed = false;
    while (!done) {
      if (!isOptional && optional(Token.LBRACK)) {
        if (isNamed) {
          reportErrorWithoutAdvancing(ParserErrorCode.CANNOT_MIX_OPTIONAL_AND_NAMED_PARAMETERS);
        }
        isOptional = true;
        optionalOpenOffset = ctx.getTokenLocation().getBegin();
      }
      if (!isNamed && optional(Token.LBRACE)) {
        if (isOptional) {
          reportErrorWithoutAdvancing(ParserErrorCode.CANNOT_MIX_OPTIONAL_AND_NAMED_PARAMETERS);
        }
        isNamed = true;
        optionalOpenOffset = ctx.getTokenLocation().getBegin();
      }

      DartParameter param = parseFormalParameter(isOptional, isNamed);
      params.add(param);

      if (isOptional && optional(Token.RBRACK)) {
        optionalCloseOffset = ctx.getTokenLocation().getBegin();
        expectCloseParen();
        break;
      }
      if (isNamed && optional(Token.RBRACE)) {
        optionalCloseOffset = ctx.getTokenLocation().getBegin();
        expectCloseParen();
        break;
      }

      // Ensure termination if token is anything other than COMMA.
      // Must keep Token.COMMA in sync with @Terminals above
      if (!optional(Token.COMMA)) {
        if (isOptional && !optional(Token.RBRACE)) {
          reportErrorWithoutAdvancing(ParserErrorCode.MISSING_OPTIONAL_PARAMETER_END);
        }
        if (isNamed && !optional(Token.RBRACK)) {
          reportErrorWithoutAdvancing(ParserErrorCode.MISSING_NAMED_PARAMETER_END);
        }
        // Must keep Token.RPAREN in sync with @Terminals above
        expectCloseParen();
        done = true;
      }
    }

    return new FormalParameters(done(params), optionalOpenOffset, optionalCloseOffset);
  }

  /**
   * <pre>
   * normalFormalParameter
   *     : functionDeclaration
   *     | fieldFormalParameter
   *     | simpleFormalParameter
   *     ;
   *
   * defaultFormalParameter
   *     : normalFormalParameter ('=' constantExpression)?
   *     ;
   * 
   * defaultNamedParameter
   *     : normalFormalParameter (':' constantExpression)?
   *     ;
   * </pre>
   */
  private DartParameter parseFormalParameter(boolean isOptional, boolean isNamed) {
    beginFormalParameter();
    List<DartAnnotation> metadata = parseMetadata();
    DartExpression paramName = null;
    DartTypeNode type = null;
    DartExpression defaultExpr = null;
    List<DartParameter> functionParams = null;
    boolean hasVar = false;
    Modifiers modifiers = Modifiers.NONE;

    if (isOptional) {
      modifiers = modifiers.makeOptional();
    }
    if (isNamed) {
      modifiers = modifiers.makeNamed();
    }

    if (optional(Token.FINAL)) {
      modifiers = modifiers.makeFinal();
    } else if (optional(Token.CONST)) {
      reportError(position(), ParserErrorCode.FORMAL_PARAMETER_IS_CONST);
    } else if (optional(Token.VAR)) {
      hasVar = true;
    }

    boolean isVoidType = false;
    if (!hasVar) {
      isVoidType = (peek(0) == Token.VOID);
      if (isVoidType) {
        type = parseVoidType();
      } else if ((peek(0) != Token.ELLIPSIS)
                 && (peek(1) != Token.COMMA)
                 && (peek(1) != Token.RPAREN)
                 && (peek(1) != Token.RBRACE)
                 && (peek(1) != Token.RBRACK)
                 && (peek(1) != Token.ASSIGN)
                 && (peek(1) != Token.COLON)
                 && (peek(1) != Token.LPAREN)
                 && (peek(0) != Token.THIS)) {
        // Must be a type specification.
        type = parseTypeAnnotation();
      }
    }

    paramName = parseParameterName();

    if (peek(0) == Token.LPAREN) {
      // Function parameter.
      if (modifiers.isFinal()) {
        reportError(position(), ParserErrorCode.FUNCTION_TYPED_PARAMETER_IS_FINAL);
      }
      if (hasVar) {
        reportError(position(), ParserErrorCode.FUNCTION_TYPED_PARAMETER_IS_VAR);
      }
      functionParams = parseFormalParameterList().val;
      validateNoDefaultParameterValues(
          functionParams,
          ParserErrorCode.DEFAULT_VALUE_CAN_NOT_BE_SPECIFIED_IN_CLOSURE);
    } else {
      // Not a function parameter.
      if (isVoidType) {
        reportError(type, ParserErrorCode.VOID_PARAMETER);
      }
    }

    // Look for an initialization expression
    switch (peek(0)) {
      case COMMA:
      case RPAREN:
      case RBRACE:
      case RBRACK:
        // It is a simple parameter.
        break;

      case ASSIGN:
        // Default parameter -- only allowed for optional parameters.
        if (isOptional) {
          consume(Token.ASSIGN);
          defaultExpr = parseExpression();
        } else if (isNamed) {
          reportError(position(), ParserErrorCode.INVALID_SEPARATOR_FOR_NAMED);
          consume(Token.ASSIGN);
          defaultExpr = parseExpression();
        } else {
          reportError(position(), ParserErrorCode.DEFAULT_POSITIONAL_PARAMETER);
        }
        break;

      case COLON:
        // Default parameter -- only allowed for named parameters.
        if (isNamed) {
          consume(Token.COLON);
          defaultExpr = parseExpression();
        } else if (isOptional) {
          reportError(position(), ParserErrorCode.INVALID_SEPARATOR_FOR_OPTIONAL);
          consume(Token.COLON);
          defaultExpr = parseExpression();
        } else {
          reportError(position(), ParserErrorCode.DEFAULT_POSITIONAL_PARAMETER);
        }
        break;

      default:
        reportUnexpectedToken(position(), null, peek(0));
        break;
    }

    DartParameter parameter = new DartParameter(paramName, type, functionParams, defaultExpr,
        modifiers);
    setMetadata(parameter, metadata);
    return done(parameter);
  }

  /**
   * <pre>
   * simpleFormalParameter
   *     : declaredIdentifier
   *     | identifier
   *     ;
   *
   * fieldFormalParameter
   *    : finalVarOrType? THIS '.' identifier
   *    ;
   * </pre>
   */
  private DartExpression parseParameterName() {
    beginParameterName();
    if (match(Token.THIS)) {
      beginThisExpression();
      expect(Token.THIS);
      DartThisExpression thisExpression = done(DartThisExpression.get());
      expect(Token.PERIOD);
      return done(new DartPropertyAccess(thisExpression, parseIdentifier()));
    }
    return done(parseIdentifier());
  }

  /**
   * Validates that given {@link DartParameter}s have no default values, or marks existing default
   * values with given {@link ErrorCode}.
   */
  private void validateNoDefaultParameterValues(List<DartParameter> parameters,
      ErrorCode errorCode) {
    for (int i = 0, size = parameters.size(); i < size; i++) {
      DartParameter parameter = parameters.get(i);
      DartExpression defaultExpr = parameter.getDefaultExpr();
      if (defaultExpr != null) {
        reportError(defaultExpr,  errorCode);
      }
    }
  }

  /**
   * Parse an expression.
   *
   * <pre>
   * expression
   *     : assignableExpression assignmentOperator expression
   *     | conditionalExpression cascadeSection*
   *     | throwExpression
   *     ;
   *
   * assignableExpression
   *     : primary (arguments* assignableSelector)+
   *     | SUPER assignableSelector
   *     | identifier
   *     ;
   * </pre>
   *
   * @return an expression matching the {@code expression} production above
   */
  @VisibleForTesting
  public DartExpression parseExpression() {
    if (peek(0) == Token.THROW) {
      return parseThrowExpression(true);
    }
    beginExpression();
    if (looksLikeTopLevelKeyword() || peek(0).equals(Token.RBRACE)) {
      // Allow recovery back to the top level.
      reportErrorWithoutAdvancing(ParserErrorCode.UNEXPECTED_TOKEN);
      return done(null);
    }
    DartExpression result = parseConditionalExpression();
    Token token = peek(0);
    if (token == Token.CASCADE) {
      List<DartExpression> cascadeSections = new ArrayList<DartExpression>();
      while (token == Token.CASCADE) {
        beginExpression();
        DartExpression section = parseCascadeSection();
        done(section);
        if (section != null) {
          cascadeSections.add(section);
        }
        token = peek(0);
      }
      result = done(new DartCascadeExpression(result, cascadeSections));
    } else if (token.isAssignmentOperator()) {
      ensureAssignable(result);
      consume(token);
      int tokenOffset = ctx.getTokenLocation().getBegin();
      result = done(new DartBinaryExpression(token, tokenOffset, result, parseExpression()));
    } else {
      done(null);
    }
    return result;
  }

  /**
   * Parse an expression without a cascade.
   *
   * <pre>
   * expressionWithoutCascade
   *     : assignableExpression assignmentOperator expressionWithoutCascade
   *     | conditionalExpression
   *     ;
   * </pre>
   *
   * @return an expression matching the {@code expression} production above
   */
  private DartExpression parseExpressionWithoutCascade() {
    if (peek(0) == Token.THROW) {
      return parseThrowExpression(false);
    }
    beginExpression();
    if (looksLikeTopLevelKeyword() || peek(0).equals(Token.RBRACE)) {
      // Allow recovery back to the top level.
      reportErrorWithoutAdvancing(ParserErrorCode.UNEXPECTED_TOKEN);
      return done(null);
    }
    DartExpression result = parseConditionalExpression();
    Token token = peek(0);
   if (token.isAssignmentOperator()) {
      ensureAssignable(result);
      consume(token);
      int tokenOffset = ctx.getTokenLocation().getBegin();
      result = done(new DartBinaryExpression(token, tokenOffset, result, parseExpressionWithoutCascade()));
    } else {
      done(null);
    }
    return result;
  }

  /**
   * Parse a cascade section.
   * <pre>
   * cascadeSection
   *     : CASCADE (cascadeSelector arguments*) (assignableSelector arguments*)* (assignmentOperator
   * expressionWithoutCascade)?
   *     ;
   *
   * cascadeSelector
   *     : LBRACK expression RBRACK
   *     | identifier
   *     ;
   * </pre>
   *
   * @return the expression representing the cascaded method invocation
   */
  private DartExpression parseCascadeSection() {
    expect(Token.CASCADE);
    DartExpression result = null;
    DartIdentifier functionName = null;
    if (peek(0) == Token.IDENTIFIER) {
      functionName = parseIdentifier();
    } else if (peek(0) == Token.LBRACK) {
      consume(Token.LBRACK);
      result = doneWithoutConsuming(new DartArrayAccess(result, true, parseExpression()));
      expect(Token.RBRACK);
    } else {
      reportUnexpectedToken(position(), null, next());
      return result;
    }
    if (peek(0) == Token.LPAREN) {
      while (peek(0) == Token.LPAREN) {
        if (functionName != null) {
          result = doneWithoutConsuming(new DartMethodInvocation(result, result == null, functionName, parseArguments()));
          functionName = null;
        } else if (result == null) {
          return null;
        } else {
          result = doneWithoutConsuming(new DartFunctionObjectInvocation(result, parseArguments()));
        }
      }
    } else if (functionName != null) {
      result = doneWithoutConsuming(new DartPropertyAccess(result, result == null, functionName));
    }
    boolean progress = true;
    while (progress) {
      progress = false;
      DartExpression selector = tryParseAssignableSelector(result);
      if (selector != null) {
        result = selector;
        progress = true;
        while (peek(0) == Token.LPAREN) {
          result = doneWithoutConsuming(new DartFunctionObjectInvocation(result, parseArguments()));
        }
      }
    }
    Token token = peek(0);
    if (token.isAssignmentOperator()) {
      ensureAssignable(result);
      consume(token);
      int tokenOffset = ctx.getTokenLocation().getBegin();
      result = doneWithoutConsuming(new DartBinaryExpression(token, tokenOffset, result, parseExpressionWithoutCascade()));
    }
    return result;
  }

  /**
   * expressionList
   *     : expression (',' expression)*
   *     ;
   */
  @Terminals(tokens={Token.COMMA})
  private DartExpression parseExpressionList() {
    beginExpressionList();
    DartExpression result = parseExpression();
    // Must keep in sync with @Terminals above
    while (optional(Token.COMMA)) {
      int tokenOffset = ctx.getTokenLocation().getBegin();
      result = new DartBinaryExpression(Token.COMMA, tokenOffset, result, parseExpression());
      if (match(Token.COMMA)) {
        result = doneWithoutConsuming(result);
      }
    }
    return done(result);
  }


  /**
   * Parse a binary expression.
   *
   * <pre>
   * logicalOrExpression
   *     : logicalAndExpression ('||' logicalAndExpression)*
   *     ;
   *
   * logicalAndExpression
   *     : bitwiseOrExpression ('&&' bitwiseOrExpression)*
   *     ;
   *
   * bitwiseOrExpression
   *     : bitwiseXorExpression ('|' bitwiseXorExpression)*
   *     ;
   *
   * bitwiseXorExpression
   *     : bitwiseAndExpression ('^' bitwiseAndExpression)*
   *     ;
   *
   * bitwiseAndExpression
   *     : equalityExpression ('&' equalityExpression)*
   *     ;
   *
   * equalityExpression
   *     : relationalExpression (equalityOperator relationalExpression)?
   *     ;
   *
   * relationalExpression
   *     : shiftExpression (isOperator type | relationalOperator shiftExpression)?
   *     ;
   *
   * shiftExpression
   *     : additiveExpression (shiftOperator additiveExpression)*
   *     ;
   *
   * additiveExpression
   *     : multiplicativeExpression (additiveOperator multiplicativeExpression)*
   *     ;
   *
   * multiplicativeExpression
   *     : unaryExpression (multiplicativeOperator unaryExpression)*
   *     ;
   * </pre>
   *
   * @return an expression matching one of the productions above
   */
  private DartExpression parseBinaryExpression(int precedence) {
    assert (precedence >= 4);
    beginBinaryExpression();
    DartExpression lastResult = parseUnaryExpression();
    DartExpression result = lastResult;
    for (int level = peek(0).getPrecedence(); level >= precedence; level--) {
      while (peek(0).getPrecedence() == level) {
        int prevPositionStart = ctx.getTokenLocation().getBegin();
        int prevPositionEnd = ctx.getTokenLocation().getEnd();
        Token token = next();
        int tokenOffset = ctx.getTokenLocation().getBegin();
        if (lastResult instanceof DartSuperExpression
            && (token == Token.AND || token == Token.OR)) {
          reportErrorAtPosition(prevPositionStart, prevPositionEnd,
                                ParserErrorCode.SUPER_IS_NOT_VALID_AS_A_BOOLEAN_OPERAND);
        }
        DartExpression right;
        if (token == Token.IS) {
          beginTypeExpression();
          if (optional(Token.NOT)) {
            int notOffset = ctx.getTokenLocation().getBegin();
            beginTypeExpression();
            DartTypeExpression typeExpression = done(new DartTypeExpression(parseTypeAnnotation()));
            right = done(new DartUnaryExpression(Token.NOT, notOffset, typeExpression, true));
          } else {
            right = done(new DartTypeExpression(parseTypeAnnotation()));
          }
        } else if (token == Token.AS) {
          beginTypeExpression();
          right = done(new DartTypeExpression(parseTypeAnnotation()));
        } else {
          right = parseBinaryExpression(level + 1);
        }
        if (right instanceof DartSuperExpression) {
          reportError(position(), ParserErrorCode.SUPER_CANNOT_BE_USED_AS_THE_SECOND_OPERAND);
        }

        lastResult = right;
        result = doneWithoutConsuming(new DartBinaryExpression(token, tokenOffset, result, right));
        if (token == Token.IS
            || token == Token.AS
            || token.isRelationalOperator()
            || token.isEqualityOperator()) {
          // The operations cannot be chained.
          if (match(token)) {
            reportError(position(), ParserErrorCode.INVALID_OPERATOR_CHAINING,
              token.toString().toLowerCase());
          }
          break;
        }
      }
    }
    done(null);
    return result;
  }

  /**
   * Parse the arguments passed to a function or method invocation.
   *
   * <pre>
   * arguments
   *    : '(' argumentList? ')'
   *    ;
   *
   * argumentList
   *    : expression (',' expression)* (',' spreadArgument)?
   *    | spreadArgument
   *    ;
   *
   * spreadArgument
   *    : '...' expression
   *    ;
   * </pre>
   *
   * @return a list of expressions containing the arguments to be passed
   */
  @Terminals(tokens={Token.RPAREN, Token.COMMA})
  public List<DartExpression> parseArguments() {
    List<DartExpression> arguments = new ArrayList<DartExpression>();
    expect(Token.LPAREN);
    // SEMICOLON is for error recovery
    boolean namedArgumentParsed = false;
    outer: while (!match(Token.RPAREN) && !match(Token.EOS) && !match(Token.SEMICOLON)) {
      beginParameter();
      // parse argument, may be named
      DartExpression expression;
      if (peek(1) == Token.COLON) {
        DartIdentifier name = parseIdentifier();
        expect(Token.COLON);
        expression = new DartNamedExpression(name, parseExpression());
        namedArgumentParsed = true;
      } else {
        expression = parseExpression();
        if (namedArgumentParsed) {
          reportError(expression, ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT);
        }
      }
      done(expression);
      // add argument, if parsed successfully
      if (expression != null) {
        arguments.add(expression);
      }
      // do we have more arguments?
      switch(peek(0)) {
        // Must keep in sync with @Terminals above
        case COMMA:
          if (peek(-1) == Token.COMMA) {
            reportErrorWithoutAdvancing(ParserErrorCode.EXPECTED_EXPRESSION_AFTER_COMMA);
          }
          consume(Token.COMMA);
          break;
          // Must keep in sync with @Terminals above
        case RPAREN:
          break;
        default:
          Token actual = peek(0);
          Set<Token> terminals = collectTerminalAnnotations();
          if (terminals.contains(actual) || looksLikeTopLevelKeyword()) {
            // Looks like a method already on the stack could use this token.
            reportErrorWithoutAdvancing(ParserErrorCode.EXPECTED_COMMA_OR_RIGHT_PAREN);
            break outer;
          } else {
            // Advance the parser state if no other method on the stack can use this token.
            ctx.advance();
          }
          reportError(ctx.getTokenLocation().getEnd(),
              ParserErrorCode.EXPECTED_COMMA_OR_RIGHT_PAREN, actual);
          break;
      }
    }
    if (peek(-1) == Token.COMMA) {
      reportErrorWithoutAdvancing(ParserErrorCode.EXPECTED_EXPRESSION_AFTER_COMMA);
    }
    expectCloseParen();
    return arguments;
  }

  /**
   * Parse a conditional expression.
   *
   * <pre>
   * conditionalExpression
   *     : logicalOrExpression ('?' expression ':' expression)?
   *     ;
   * </pre>
   *
   * @return an expression matching the {@code conditionalExpression} production
   */
  private DartExpression parseConditionalExpression() {
    beginConditionalExpression();
    DartExpression result = parseBinaryExpression(4);
    if (result instanceof DartSuperExpression) {
      reportError(position(), ParserErrorCode.SUPER_IS_NOT_VALID_ALONE_OR_AS_A_BOOLEAN_OPERAND);
    }
    if (peek(0) != Token.CONDITIONAL) {
      return done(result);
    }
    consume(Token.CONDITIONAL);
    DartExpression yes = parseExpressionWithoutCascade();
    expect(Token.COLON);
    DartExpression no = parseExpressionWithoutCascade();
    return done(new DartConditional(result, yes, no));
  }

  private boolean looksLikeStringInterpolation() {
    int peekAhead = 0;
    while (true) {
      switch (peek(peekAhead++)) {
        case STRING:
          break;
        case STRING_SEGMENT:
        case STRING_LAST_SEGMENT:
        case STRING_EMBED_EXP_START:
        case STRING_EMBED_EXP_END:
          return true;
        default:
          return false;
      }
    }
  }
  /**
   * Pastes together adjacent strings.  Re-uses the StringInterpolation
   * node if there is more than one adjacent string.
   */
  private DartExpression parseStringWithPasting() {
    List<DartExpression> expressions = new ArrayList<DartExpression>();
    if (looksLikeStringInterpolation()) {
      beginStringInterpolation();
    } else {
      beginLiteral();
    }
    DartExpression result = null;
    boolean foundStringInterpolation = false;
    do {
      result = null;
      switch(peek(0)) {
        case STRING:
        case STRING_SEGMENT:
        case STRING_EMBED_EXP_START:
          // another string is coming, glue it together.
          result = parseString();
          if (result != null) {
            expressions.add(result);
          }
          if (result instanceof DartStringInterpolation) {
            foundStringInterpolation = true;
          }
          break;
      }
    } while (result != null);

    if (expressions.size() == 0) {
      return doneWithoutConsuming(null);
    } else if (expressions.size() == 1) {
      return done(expressions.get(0));
    }

    if (foundStringInterpolation) {
      DartStringInterpolationBuilder builder = new DartStringInterpolationBuilder();
      // Create a new DartStringInterpolation object from the expressions.
      boolean first = true;
      for (DartExpression expr : expressions) {
        if (!first) {
          // pad between interpolations with a dummy expression
          builder.addExpression(DartStringLiteral.get(""));
        }
        if (expr instanceof DartStringInterpolation) {
          builder.addInterpolation((DartStringInterpolation)expr);
        } else if (expr instanceof DartStringLiteral) {
          builder.addString((DartStringLiteral)expr);
        } else {
          throw new InternalCompilerException("Expected String or StringInterpolation");
        }
        first = false;
      }
      return done(builder.buildInterpolation());
    }

    // Synthesize a single String literal
    List<DartStringLiteral> stringParts = new ArrayList<DartStringLiteral>();
    StringBuilder builder = new StringBuilder();
    for (DartExpression expr : expressions) {
      DartStringLiteral stringPart = (DartStringLiteral)expr;
      stringParts.add(stringPart);
      builder.append(stringPart.getValue());
    }
    return done(DartStringLiteral.get(builder.toString(), stringParts));
  }

  private DartExpression parseString() {
    switch(peek(0)) {
      case STRING: {
        beginLiteral();
        consume(Token.STRING);
        return done(DartStringLiteral.get(ctx.getTokenString()));
      }

      case STRING_SEGMENT:
      case STRING_EMBED_EXP_START:
        return parseStringInterpolation();

      default:
        DartExpression expression = parseExpression();
        reportError(position(), ParserErrorCode.EXPECTED_STRING_LITERAL);
        return expression;
    }
  }

  private int skipStringLiteral(int offset) {
    Token token = peek(offset);
    while (token == Token.STRING || token == Token.STRING_SEGMENT || token == Token.STRING_EMBED_EXP_START) {
      switch(token) {
        case STRING:
          offset = offset + 1;
  
        case STRING_SEGMENT:
        case STRING_EMBED_EXP_START:
          offset = skipStringInterpolation(offset);
      }
      token = peek(offset);
    }
    return offset;
  }

  private int skipStringInterpolation(int offset) {
    Token token = peek(offset);
    if (token == Token.STRING_LAST_SEGMENT) {
      return -1;
    }
    boolean inString = true;
    while (inString) { // Iterate until we find the last string segment.
      switch (token) {
        case STRING_SEGMENT:
          offset = offset + 1;
          token = peek(offset);
          break;
        case STRING_LAST_SEGMENT:
          offset = offset + 1;
          token = peek(offset);
          inString = false;
          break;
        case STRING_EMBED_EXP_START: {
          offset = offset + 1;
          token = peek(offset);
          while (token != Token.EOS && token != Token.STRING_EMBED_EXP_END && token != Token.STRING_LAST_SEGMENT) {
            if (token == Token.STRING || token == Token.STRING_SEGMENT || token == Token.STRING_EMBED_EXP_START) {
              offset = skipStringLiteral(offset);
            } else {
              offset = offset + 1;
            }
            token = peek(offset);
          }
          if (token != Token.STRING_EMBED_EXP_END) {
            inString = Token.STRING_LAST_SEGMENT != token;
          }
          break;
        }
        default:
          inString = false;
          break;
      }
    }
    return offset;
  }

  /**
   * Instances of the class {@code DepthCounter} represent the number of less than tokens that have
   * not yet been matched.
   */
  private static class DepthCounter {
    /**
     * The number of less than tokens that have not yet been matched.
     */
    private int count = 0;

    /**
     * Increment the number of less than tokens that have not yet been matched by the given amount
     * (or decrement the count if the argument is negative).
     * 
     * @param value the amount by which the count should be changed
     * @return the count after it has been modified
     */
    public int add(int value) {
      count += value;
      return count;
    }

    /**
     * Return the number of less than tokens that have not yet been matched.
     * 
     * @return the number of less than tokens that have not yet been matched
     */
    public int getCount() {
      return count;
    }
  }

  /**
   * Return the offset of the first token after a type name, or {@code -1} if the token at the given
   * offset is not the start of a type name.
   * 
   * @param offset the offset of the first token of the type name
   * @return the offset of the first token after a type name
   */
  private int skipTypeName(int offset) {
    return skipTypeName(offset, new DepthCounter());
  }

  /**
   * Return the offset of the first token after a type name, or {@code -1} if the token at the given
   * offset is not the start of a type name.
   * 
   * @param offset the offset of the first token of the type name
   * @param depth the number of less-thans that have been encountered since the outer-most type name
   * @return the offset of the first token after a type name
   */
  private int skipTypeArguments(int offset, DepthCounter depth) {
    if (peek(offset) != Token.LT) {
      return -1;
    }
    int oldDepth = depth.add(1);
    offset = skipTypeName(offset + 1, depth);
    if (offset < 0) {
      return offset;
    }
    while (peek(offset) == Token.COMMA) {
      offset = skipTypeName(offset + 1, depth);
      if (offset < 0) {
        return offset;
      }
    }
    if (depth.getCount() < oldDepth) {
      // We already passed the closing '>' for this list of type arguments
      return offset;
    }
    if (peek(offset) == Token.GT) {
      depth.add(-1);
      return offset + 1;
    } else if (peek(offset) == Token.SAR) {
      depth.add(-2);
      return offset + 1;
    }
    return -1;
  }

  /**
   * Return the offset of the first token after a type name, or {@code -1} if the token at the given
   * offset is not the start of a type name.
   * 
   * @param offset the offset of the first token of the type name
   * @param depth the number of less-thans that have been encountered since the outer-most type name
   * @return the offset of the first token after a type name
   */
  private int skipTypeName(int offset, DepthCounter depth) {
    if (peek(offset) != Token.IDENTIFIER) {
      return -1;
    }
    offset++;
    if (peek(offset) == Token.PERIOD) {
      offset++;
      if (peek(offset) == Token.IDENTIFIER) {
        // We tolerate a missing identifier in order to recover better
        offset++;
      }
    }
    if (peek(offset) == Token.LT) {
      offset = skipTypeArguments(offset, depth);
    }
    return offset;
  }

  /**
   * Parse any literal that is not a function literal (those have already been
   * handled before this method is called, so we don't need to handle them
   * here).
   *
   * <pre>
   * nonFunctionLiteral
   *   : NULL
   *   | TRUE
   *   | FALSE
   *   | HEX_NUMBER
   *   | RATIONAL_NUMBER
   *   | DOUBLE_NUMBER
   *   | STRING
   *   | mapLiteral
   *   | arrayLiteral
   *   ;
   * </pre>
   *
   * @return an expression matching the {@code literal} production above
   */
  private DartExpression parseLiteral() {
    beginLiteral();
    if (PSEUDO_KEYWORDS_SET.contains(peek(0).getSyntax())) {
      return done(parseIdentifier());
    }
    switch (peek(0)) {
      case NULL_LITERAL: {
        consume(Token.NULL_LITERAL);
        return done(DartNullLiteral.get());
      }

      case TRUE_LITERAL: {
        consume(Token.TRUE_LITERAL);
        return done(DartBooleanLiteral.get(true));
      }

      case FALSE_LITERAL: {
        consume(Token.FALSE_LITERAL);
        return done(DartBooleanLiteral.get(false));
      }

      case INTEGER_LITERAL: {
        consume(Token.INTEGER_LITERAL);
        String number = ctx.getTokenString();
        return done(DartIntegerLiteral.get(new BigInteger(number)));
      }

      case DOUBLE_LITERAL: {
        consume(Token.DOUBLE_LITERAL);
        String number = ctx.getTokenString();
        return done(DartDoubleLiteral.get(Double.parseDouble(number)));
      }

      case HEX_LITERAL: {
        consume(Token.HEX_LITERAL);
        String number = ctx.getTokenString();
        return done(DartIntegerLiteral.get(new BigInteger(number, 16)));
      }

      case LBRACE: {
        return done(parseMapLiteral(false, null));
      }

      case INDEX: {
        expect(peek(0));
        return done(new DartArrayLiteral(false, null, new ArrayList<DartExpression>()));
      }

      case LBRACK: {
        return done(parseArrayLiteral(false, null));
      }

      case VOID:
        // For better error recovery / code completion in the IDE, treat "void" as an identifier
        // here and let it get reported as a resolution error.
      case IDENTIFIER: {
        return done(parseIdentifier());
      }

      case SEMICOLON: {
        // this is separate from the default case for better error recovery,
        // leaving the semicolon for the caller to use for a statement boundary

        // we have to advance to get the proper position, but we want to leave
        // the semicolon
        startLookahead();
        next();
        reportUnexpectedToken(position(), null, Token.SEMICOLON);
        rollback();
        return done(new DartSyntheticErrorExpression(""));
      }

      default: {
        Token unexpected = peek(0);
        String unexpectedString = ctx.getTokenString();
        if (unexpectedString == null && unexpected != Token.EOS) {
          unexpectedString = unexpected.getSyntax();
        }

        // Don't eat tokens that could be used to successfully terminate a non-terminal
        // further up the stack.
        Set<Token> terminals = collectTerminalAnnotations();
        if (!looksLikeTopLevelKeyword() && !terminals.contains(unexpected)) {
          next();
        }
        reportUnexpectedToken(position(), null, unexpected);
        StringBuilder tokenStr = new StringBuilder();
        if (unexpectedString != null) {
          tokenStr.append(unexpectedString);
        }
        // TODO(jat): should we eat additional tokens here for error recovery?
        return done(new DartSyntheticErrorExpression(tokenStr.toString()));
      }
    }
  }

  /**
   * mapLiteralEntry
   *     : STRING ':' expression
   *     ;
   */
  private DartMapLiteralEntry parseMapLiteralEntry() {
    beginMapLiteralEntry();
    // Parse the key.
    DartExpression keyExpr = parseStringWithPasting();
    if (keyExpr == null) {
      return done(null);
    }
    // Parse the value.
    DartExpression value;
    if (expect(Token.COLON)) {
      value = parseExpression();
    } else {
      value = doneWithoutConsuming(new DartSyntheticErrorExpression());
    }
    return done(new DartMapLiteralEntry(keyExpr, value));
  }
  private boolean looksLikeString() {
    switch(peek(0)) {
      case STRING:
      case STRING_SEGMENT:
      case STRING_EMBED_EXP_START:
        return true;
    }
    return false;
  }

  /**
   * <pre> mapLiteral : '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}' ;
   * </pre>
   */
  @Terminals(tokens={Token.RBRACE, Token.COMMA})
  private DartExpression parseMapLiteral(boolean isConst, List<DartTypeNode> typeArguments) {
    beginMapLiteral();
    boolean foundOpenBrace = expect(Token.LBRACE);
    boolean save = setAllowFunctionExpression(true);
    List<DartMapLiteralEntry> entries = new ArrayList<DartMapLiteralEntry>();

    while (!match(Token.RBRACE) && !match(Token.EOS)) {
      if (!looksLikeString()) {
        ctx.advance();
        reportError(position(), ParserErrorCode.EXPECTED_STRING_LITERAL_MAP_ENTRY_KEY);
        if (peek(0) == Token.COMMA) {
          // a common error is to put an empty entry in the list, allow it to
          // recover.
          continue;
        } else {
          break;
        }
      }
      DartMapLiteralEntry entry = parseMapLiteralEntry();
      if (entry != null) {
        entries.add(entry);
      }
      Token nextToken = peek(0);
      switch (nextToken) {
        // Must keep in sync with @Terminals above
        case COMMA:
          consume(Token.COMMA);
          break;
        // Must keep in sync with @Terminals above
        case RBRACE:
          break;
        default:
          if (entry == null) {
            Set<Token> terminals = collectTerminalAnnotations();
            if (!terminals.contains(nextToken) && !looksLikeTopLevelKeyword()) {
              if (entry == null) {
                // Ensure the parser makes progress.
                ctx.advance();
              }
            }
          }
          reportError(position(), ParserErrorCode.EXPECTED_COMMA_OR_RIGHT_BRACE);
          break;
      }
    }

    expectCloseBrace(foundOpenBrace);
    setAllowFunctionExpression(save);
    return done(new DartMapLiteral(isConst, typeArguments, entries));
  }

  /**
   * // The array literal syntax doesn't allow elided elements, unlike
   * // in ECMAScript.
   *
   * <pre>
   * arrayLiteral
   *     : '[' expressionList? ']'
   *     ;
   * </pre>
   */
  @Terminals(tokens={Token.RBRACK, Token.COMMA})
  private DartExpression parseArrayLiteral(boolean isConst, List<DartTypeNode> typeArguments) {
    beginArrayLiteral();
    expect(Token.LBRACK);
    boolean save = setAllowFunctionExpression(true);
    List<DartExpression> exprs = new ArrayList<DartExpression>();
    while (!match(Token.RBRACK) && !EOS()) {
      exprs.add(parseExpression());
      // Must keep in sync with @Terminals above
      if (!optional(Token.COMMA)) {
        break;
      }
    }
    // Must keep in sync with @Terminals above
    expect(Token.RBRACK);
    setAllowFunctionExpression(save);
    return done(new DartArrayLiteral(isConst, typeArguments, exprs));
  }

  /**
   * Parse a postfix expression.
   *
   * <pre>
   * postfixExpression
   *     | assignableExpression postfixOperator
   *     : primary selector*
   *     ;
   * </pre>
   *
   * @return an expression matching the {@code postfixExpression} production above
   */
  private DartExpression parsePostfixExpression() {
    beginPostfixExpression();
    DartExpression receiver = doneWithoutConsuming(parsePrimaryExpression());
    DartExpression result = receiver;
    do {
      receiver = result;
      result = doneWithoutConsuming(parseSelectorExpression(receiver));
    } while (receiver != result);

    Token token = peek(0);
    if (token.isCountOperator()) {
      ensureAssignable(result);
      consume(token);
      int tokenOffset = ctx.getTokenLocation().getBegin();
      result = doneWithoutConsuming(new DartUnaryExpression(token, tokenOffset, result, false));
    }

    return done(result);
  }

  /**
   * <pre>
   * typeParameters? (arrayLiteral | mapLiteral)
   * </pre>
   *
   * @param isConst <code>true</code> if a CONST expression
   *
   */
  private DartExpression tryParseTypedCompoundLiteral(boolean isConst) {
    beginLiteral();
    List<DartTypeNode> typeArguments = parseTypeArgumentsOpt();
    switch (peek(0)) {
      case INDEX:
        beginArrayLiteral();
        consume(Token.INDEX);
        return done(done(new DartArrayLiteral(isConst, typeArguments, new ArrayList<DartExpression>())));
      case LBRACK:
        return done(parseArrayLiteral(isConst, typeArguments));
      case LBRACE:
        return done(parseMapLiteral(isConst, typeArguments));
      default:
        if (typeArguments != null) {
          rollback();
          return null;
        }

    }
    // Doesn't look like a typed compound literal and no tokens consumed.
    return done(null);
  }

  private enum LastSeenNode {
    NONE,
    STRING,
    EXPRESSION;
  }

  private class DartStringInterpolationBuilder {

    private final List<DartStringLiteral> strings = new ArrayList<DartStringLiteral>();
    private final List<DartExpression> expressions = new ArrayList<DartExpression>();
    private LastSeenNode lastSeen = LastSeenNode.NONE;

    DartStringInterpolationBuilder() {
    }

    void addString(DartStringLiteral string) {
      if (lastSeen == LastSeenNode.STRING) {
        expressions.add(new DartSyntheticErrorExpression());
      }
      strings.add(string);
      lastSeen = LastSeenNode.STRING;
    }

    void addExpression(DartExpression expression) {
      switch (lastSeen) {
        case EXPRESSION:
        case NONE:
          strings.add(DartStringLiteral.get(""));
          break;
        default:
          break;
      }
      expressions.add(expression);
      lastSeen = LastSeenNode.EXPRESSION;
    }

    void addInterpolation(DartStringInterpolation interpolation) {
      strings.addAll(interpolation.getStrings());
      expressions.addAll(interpolation.getExpressions());
      lastSeen = LastSeenNode.STRING;
    }

    DartStringInterpolation buildInterpolation() {
      if (strings.size() == expressions.size()) {
        strings.add(DartStringLiteral.get(""));
      }
      return new DartStringInterpolation(strings, expressions);
    }
  }

  /**
   * Instances of the class {@code StringInterpolationParseError} represent the detection of an
   * error that needs to be handled in an enclosing context.
   */
  private static class StringInterpolationParseError extends RuntimeException {
    private static final long serialVersionUID = 1L;

    public StringInterpolationParseError() {
      super();
    }
  }

  /**
   * <pre>
   * string-interpolation
   *   : (STRING_SEGMENT? embedded-exp?)* STRING_LAST_SEGMENT
   *
   * embedded-exp
   *   : STRING_EMBED_EXP_START expression STRING_EMBED_EXP_END
   * </pre>
   */
  private DartExpression parseStringInterpolation() {
    // TODO(sigmund): generalize to parse string templates as well.
    if (peek(0) == Token.STRING_LAST_SEGMENT) {
      throw new InternalCompilerException("Invariant broken");
    }
    beginStringInterpolation();
    DartStringInterpolationBuilder builder = new DartStringInterpolationBuilder();
    boolean inString = true;
    while (inString) { // Iterate until we find the last string segment.
      switch (peek(0)) {
        case STRING_SEGMENT: {
          beginStringSegment();
          consume(Token.STRING_SEGMENT);
          builder.addString(done(DartStringLiteral.get(ctx.getTokenString())));
          break;
        }
        case STRING_LAST_SEGMENT: {
          beginStringSegment();
          consume(Token.STRING_LAST_SEGMENT);
          builder.addString(done(DartStringLiteral.get(ctx.getTokenString())));
          inString = false;
          break;
        }
        case STRING_EMBED_EXP_START: {
          consume(Token.STRING_EMBED_EXP_START);
          /*
           * We check for ILLEGAL specifically here to give nicer error
           * messages, and because the scanner doesn't generate a
           * STRING_EMBED_EXP_END to match the START in the case of an ILLEGAL
           * token.
           */
          if (peek(0) == Token.ILLEGAL) {
            reportError(position(), ParserErrorCode.UNEXPECTED_TOKEN_IN_STRING_INTERPOLATION,
                next());
            builder.addExpression(new DartSyntheticErrorExpression(""));
            break;
          } else {
            try {
              builder.addExpression(parseExpression());
            } catch (StringInterpolationParseError exception) {
              if (peek(0) == Token.STRING_LAST_SEGMENT) {
                break;
              }
              throw new InternalCompilerException("Invalid expression found in string interpolation");
            }
          }
          Token lookAhead = peek(0);
          String lookAheadString = getPeekTokenValue(0);
          if (!expect(Token.STRING_EMBED_EXP_END)) {
            String errorText = null;
            if (lookAheadString != null && lookAheadString.length() > 0) {
              errorText = lookAheadString;
            } else if (lookAhead.getSyntax() != null && lookAhead.getSyntax().length() > 0) {
              errorText = lookAhead.getSyntax();
            }
            if (errorText != null) {
              builder.addExpression(new DartSyntheticErrorExpression(errorText));
            }
            inString = !(Token.STRING_LAST_SEGMENT == lookAhead);
          }
          break;
        }
        case EOS: {
          reportError(position(), ParserErrorCode.INCOMPLETE_STRING_LITERAL);
          inString = false;
          break;
        }
        default: {
          String errorText = getPeekTokenValue(0) != null && getPeekTokenValue(0).length() > 0
              ? getPeekTokenValue(0) : null;
          if(errorText != null) {
            builder.addExpression(new DartSyntheticErrorExpression(getPeekTokenValue(0)));
          }
          reportError(position(), ParserErrorCode.UNEXPECTED_TOKEN_IN_STRING_INTERPOLATION,
              next());
          break;
        }
      }
    }
    return done(builder.buildInterpolation());
  }

  /**
   * Parse a return type, giving an error if the .
   *
   * @return a return type or null if the current text is not a return type
   */
  private DartTypeNode parseReturnType() {
    if (peek(0) == Token.VOID) {
      return parseVoidType();
    } else {
      return parseTypeAnnotation();
    }
  }

  /**
   * Check if the current text could be a return type, and advance past it if so.  The current
   * position is unchanged if it is not a return type.
   *
   * NOTE: if the grammar is changed for what constitutes an acceptable return type, this method
   * must be updated to match {@link #parseReturnType()}/etc.
   *
   * @return true if current text could be a return type, false otherwise
   */
  private boolean isReturnType() {
    beginReturnType();
    if (optional(Token.VOID)) {
      done(null);
      return true;
    }
    if (!optional(Token.IDENTIFIER)) {
      rollback();
      return false;
    }
    // handle prefixed identifiers
    if (optional(Token.PERIOD)) {
      if (!optional(Token.IDENTIFIER)) {
        rollback();
        return false;
      }
    }
    // skip over type arguments if they are present
    if (optional(Token.LT)) {
      int count = 1;
      while (count > 0) {
        switch (next()) {
          case EOS:
            rollback();
            return false;
          case LT:
            count++;
            break;
          case GT:
            count--;
            break;
          case SHL:
            count += 2;
            break;
          case SAR:  // >>
            count -= 2;
            break;
          case COMMA:
          case IDENTIFIER:
            // extends is a pseudokeyword, so shows up as IDENTIFIER
            break;
          default:
            rollback();
            return false;
        }
      }
      if (count < 0) {
        // if we had too many > (which can only be >> or >>>), can't be a return type
        rollback();
        return false;
      }
    }
    done(null);
    return true;
  }

  /**
   * Checks to see if the current text looks like a function expression:
   *
   * <pre>
   *   FUNCTION name? ( args ) < => | { >
   *   returnType name? ( args ) < => | { >
   *   name? ( args ) < => | { >
   * </pre>
   *
   * The current position is unchanged on return.
   *
   * NOTE: if the grammar for function expressions changes, this method must be
   * adapted to match the actual parsing code. It is acceptable for this method
   * to return true when the source text does not actually represent a function
   * expression (which would result in error messages assuming it was a function
   * expression, but it must not do so when the source text would be correct if
   * parsed as a non-function expression.
   *
   * @return true if the current text looks like a function expression, false
   *         otherwise
   */
  @VisibleForTesting
  boolean looksLikeFunctionExpression() {
    if (!allowFunctionExpression) {
      return false;
    }
    return looksLikeFunctionDeclarationOrExpression();
  }

  /**
   * Check to see if the following tokens could be a function expression, and if so try and parse
   * it as one.
   *
   * @return a function expression if found, or null (with no tokens consumed) if not
   */
  private DartExpression parseFunctionExpressionWithReturnType() {
    beginFunctionLiteral();
    DartIdentifier[] namePtr = new DartIdentifier[1];
    DartFunction function = parseFunctionDeclarationOrExpression(namePtr, false);
    if (function == null) {
      rollback();
      return null;
    }
    return done(new DartFunctionExpression(namePtr[0], doneWithoutConsuming(function), false));
  }

  /**
   * Parse a function declaration or expression, including the body.
   * <pre>
   *     ... | functionDeclaration functionBody
   *
   * functionDeclaration
   *    : returnType? identifier formalParameterList
   *    ;
   *
   * functionExpression
   *    : (returnType? identifier)? formalParameterList functionExpressionBody
   *    ;
   *
   * functionBody
   *    : '=>' expression ';'
   *    | block
   *    ;
   *
   * functionExpressionBody
   *    : '=>' expression
   *    | block
   *    ;
   * </pre>
   *
   * @param namePtr out parameter - parsed function name stored in namePtr[0]
   * @param isDeclaration true if this is a declaration (i.e. a name is required and a trailing
   *     semicolon is needed for arrow syntax
   * @return a {@link DartFunction} containing the body of the function, or null
   *     if the next tokens cannot be parsed as a function declaration or expression
   */
  private DartFunction parseFunctionDeclarationOrExpression(DartIdentifier[] namePtr,
      boolean isDeclaration) {
    DartTypeNode returnType = null;
    namePtr[0] = null;
    if (optionalPseudoKeyword(STATIC_KEYWORD)) {
      reportError(position(), ParserErrorCode.LOCAL_CANNOT_BE_STATIC);
    }
    switch (peek(0)) {
      case LPAREN:
        // no type or name, just the formal parameter list
        break;
      case IDENTIFIER:
        if (peek(1) == Token.LPAREN) {
          // if there is only one identifier, it must be the name
          namePtr[0] = parseIdentifier();
          break;
        }
        //$FALL-THROUGH$
      case VOID:
        returnType = parseReturnType();
        if (peek(0) == Token.IDENTIFIER) {
          namePtr[0] = parseIdentifier();
        }
        break;
      default:
        return null;
    }
    FormalParameters params = parseFormalParameterList();
    int parametersCloseParen = ctx.getTokenLocation().getBegin();
    DartBlock body = parseFunctionStatementBody(true, isDeclaration);
    DartFunction function = new DartFunction(params.val, params.optionalOpenOffset,
        params.optionalCloseOffset, parametersCloseParen, body, returnType);
    doneWithoutConsuming(function);
    return function;
  }

  /**
   * Parse a primary expression.
   *
   * <pre>
   * primary
   *   : THIS
   *   | SUPER assignableSelector
   *   | literal
   *   | identifier
   *   | NEW type ('.' identifier)? arguments
   *   | typeArguments? (arrayLiteral | mapLiteral)
   *   | CONST typeArguments? (arrayLiteral | mapLiteral)
   *   | CONST typeArguments? (arrayLiteral | mapLiteral)
   *   | CONST type ('.' identifier)? arguments
   *   | '(' expression ')'
   *   | string-interpolation
   *   | functionExpression
   *   ;
   * </pre>
   *
   * @return an expression matching the {@code primary} production above
   */
  private DartExpression parsePrimaryExpression() {
    if (looksLikeFunctionExpression()) {
      return parseFunctionExpressionWithReturnType();
    }
    switch (peek(0)) {
      case THIS: {
        beginThisExpression();
        consume(Token.THIS);
        return done(DartThisExpression.get());
      }

      case SUPER: {
        beginSuperExpression();
        consume(Token.SUPER);
        return done(DartSuperExpression.get());
      }

      case NEW: {
        beginNewExpression(); // DartNewExpression
        consume(Token.NEW);
        return done(parseConstructorInvocation(false));
      }

      case CONST: {
        beginConstExpression();
        consume(Token.CONST);

        DartExpression literal = tryParseTypedCompoundLiteral(true);
        if (literal != null) {
          return done(literal);
        }
        return done(parseConstructorInvocation(true));
      }

      case LPAREN: {
        beginParenthesizedExpression();
        consume(Token.LPAREN);
        beginExpression();
        // inside parens, function blocks are allowed again
        boolean save = setAllowFunctionExpression(true);
        DartExpression expression = done(parseExpression());
        setAllowFunctionExpression(save);
        expectCloseParen();
        return done(new DartParenthesizedExpression(expression));
      }

      case LT: {
        beginLiteral();
        DartExpression literal = tryParseTypedCompoundLiteral(false);
        if (literal == null) {
          reportError(position(), ParserErrorCode.EXPECTED_ARRAY_OR_MAP_LITERAL);
        }
        return done(literal);
      }

      case STRING:
      case STRING_SEGMENT:
      case STRING_EMBED_EXP_START: {
        return parseStringWithPasting();
      }

      case STRING_LAST_SEGMENT:
        throw new StringInterpolationParseError();

      case CONDITIONAL:
        return parseArgumentDefinitionTest();

      default: {
        return parseLiteral();
      }
    }
  }

  private DartExpression parseArgumentDefinitionTest() {
    beginArgumentDefinitionTest();
    int operatorOffset = position();
    expect(Token.CONDITIONAL);
    return done(new DartUnaryExpression(Token.CONDITIONAL, operatorOffset, parseIdentifier(), true));
  }

  private DartExpression parseConstructorInvocation(boolean isConst) {
    List<DartTypeNode> parts = new ArrayList<DartTypeNode>();
    beginConstructor();
    do {
      beginConstructorNamePart();
      parts.add(done(new DartTypeNode(parseIdentifier(), parseTypeArgumentsOpt())));
    } while (optional(Token.PERIOD));
    assert parts.size() > 0;

    DartNode constructor;
    switch (parts.size()) {
      case 1:
        constructor = doneWithoutConsuming(parts.get(0));
        break;

      case 2: {
        // This case is ambiguous. It can either be prefix.Type or
        // Type.namedConstructor.
        boolean hasPrefix = false;
        DartTypeNode part1 = parts.get(0);
        DartTypeNode part2 = parts.get(1);
        if (prefixes.contains(((DartIdentifier) part1.getIdentifier()).getName())) {
          hasPrefix = true;
        }
        if (!part2.getTypeArguments().isEmpty()) {
          // If the second part has type arguments, the first part must be a prefix.
          // If it isn't a prefix, the resolver will complain.
          hasPrefix = true;
        }
        if (hasPrefix) {
          constructor = doneWithoutConsuming(toPrefixedType(parts));
        } else {
          // Named constructor.
          DartIdentifier identifier = (DartIdentifier) part2.getIdentifier();
          constructor = doneWithoutConsuming(new DartPropertyAccess(part1, identifier));
        }
        break;
      }
      default: {
        // This case is unambiguous. It must be prefix.Type.namedConstructor.
        if (parts.size() > 3) {
          reportError(parts.get(3), ParserErrorCode.EXPECTED_LEFT_PAREN);
        }
        DartTypeNode typeNode = doneWithoutConsuming(toPrefixedType(parts));
        DartIdentifier identifier = (DartIdentifier)parts.get(2).getIdentifier();
        constructor = doneWithoutConsuming(new DartPropertyAccess(typeNode, identifier));
        break;
      }
    }

    boolean save = setAllowFunctionExpression(true);
    try {
      List<DartExpression> args = parseArguments();
      return done(new DartNewExpression(constructor, args, isConst));
    } finally {
      setAllowFunctionExpression(save);
    }
  }

  private DartTypeNode toPrefixedType(List<DartTypeNode> parts) {
    DartIdentifier part1 = (DartIdentifier)parts.get(0).getIdentifier();
    DartTypeNode part2 = parts.get(1);
    DartIdentifier identifier = (DartIdentifier) part2.getIdentifier();
    DartPropertyAccess access = doneWithoutConsuming(new DartPropertyAccess(part1, identifier));
    return new DartTypeNode(access, part2.getTypeArguments());
  }

  /**
   * Parse a selector expression.
   *
   * <pre>
   * selector
   *    : assignableSelector
   *    | arguments
   *    ;
   * </pre>
   *
   * @return an expression matching the {@code selector} production above
   */
  private DartExpression parseSelectorExpression(DartExpression receiver) {
    DartExpression expression = tryParseAssignableSelector(receiver);
    if (expression != null) {
      return expression;
    }

    if (peek(0) == Token.LPAREN) {
      beginSelectorExpression();
      boolean save = setAllowFunctionExpression(true);
      List<DartExpression> args = parseArguments();
      setAllowFunctionExpression(save);
      if (receiver instanceof DartIdentifier) {
        return(done(new DartUnqualifiedInvocation((DartIdentifier) receiver, args)));
      } else {
        return(done(new DartFunctionObjectInvocation(receiver, args)));
      }
    }

    return receiver;
  }

  /**
   * <pre>
   * assignableSelector
   *    : '[' expression ']'
   *    | '.' identifier
   *    ;
   * </pre>
   */
  private DartExpression tryParseAssignableSelector(DartExpression receiver) {
    switch (peek(0)) {
      case PERIOD:
        consume(Token.PERIOD);
        switch (peek(0)) {
          case SEMICOLON:
          case RBRACE:
            reportError(position(), ParserErrorCode.EXPECTED_IDENTIFIER);
            DartIdentifier error = doneWithoutConsuming(new DartIdentifier(""));
            return doneWithoutConsuming(new DartPropertyAccess(receiver, error));
        }
        // receiver.() = missing name
        if (peek(0) == Token.LPAREN) {
          reportUnexpectedToken(position(), Token.IDENTIFIER, peek(0));
          DartIdentifier name;
          {
            beginIdentifier();
            name = done(new DartSyntheticErrorIdentifier());
          }
          boolean save = setAllowFunctionExpression(true);
          DartMethodInvocation expr = doneWithoutConsuming(new DartMethodInvocation(receiver,
              false, name, parseArguments()));
          setAllowFunctionExpression(save);
          return expr;
        }
        // expect name
        DartIdentifier name = parseIdentifier();
        if (peek(0) == Token.LPAREN) {
          boolean save = setAllowFunctionExpression(true);
          DartMethodInvocation expr = doneWithoutConsuming(new DartMethodInvocation(receiver, false,
              name, parseArguments()));
          setAllowFunctionExpression(save);
          return expr;
        } else {
          return doneWithoutConsuming(new DartPropertyAccess(receiver, name));
        }

      case LBRACK:
        consume(Token.LBRACK);
        DartExpression key = parseExpression();
        expect(Token.RBRACK);
        return doneWithoutConsuming(new DartArrayAccess(receiver, key));

      default:
        return null;
    }
  }

  /**
   * <pre>
   * block
   *     : '{' statements deadCode* '}'
   *     ;
   *
   * statements
   *     : statement*
   *     ;
   *
   * deadCode
   *     : (normalCompletingStatement | abruptCompletingStatement)
   *     ;
   * </pre>
   */
  @Terminals(tokens={Token.RBRACE})
  private DartBlock parseBlock() {
    if (isDietParse) {
      expect(Token.LBRACE);
      DartBlock emptyBlock = new DartBlock(new ArrayList<DartStatement>());
      int nesting = 1;
      while (nesting > 0) {
        Token token = next();
        switch (token) {
          case LBRACE:
            ++nesting;
            break;
          case RBRACE:
            --nesting;
            break;
          case EOS:
            return emptyBlock;
        }
      }
      // Return an empty block so we don't generate unparseable code.
      return emptyBlock;
    } else {
      Token nextToken = peek(0);
      if (!nextToken.equals(Token.LBRACE)
          && (looksLikeTopLevelKeyword() || nextToken.equals(Token.RBRACE))) {
        beginBlock();
        // Allow recovery back to the top level.
        reportErrorWithoutAdvancing(ParserErrorCode.UNEXPECTED_TOKEN);
        return done(new DartBlock(new ArrayList<DartStatement>()));
      }
      beginBlock();
      List<DartStatement> statements = new ArrayList<DartStatement>();
      boolean foundOpenBrace = expect(Token.LBRACE);

      while (!match(Token.RBRACE) && !EOS()) {
        if (looksLikeTopLevelKeyword()) {
          reportErrorWithoutAdvancing(ParserErrorCode.UNEXPECTED_TOKEN);
          break;
        }
        int startPosition = position();
        DartStatement newStatement = parseStatement();
        if (newStatement == null) {
          break;
        }
        if (startPosition == position()) {
          // The parser is not making progress.
          Set<Token> terminals = this.collectTerminalAnnotations();
          if (terminals.contains(peek(0))) {
            // bail out of the block
            break;
          }
          reportUnexpectedToken(position(), null, next());
        }
        statements.add(newStatement);
      }
      expectCloseBrace(foundOpenBrace);
      return done(new DartBlock(statements));
    }
  }

  /**
   * Parse a function statement body.
   *
   * <pre>
   * functionStatementBody
   *    : '=>' expression ';'
   *    | block
   * </pre>
   *
   * @param requireSemicolonForArrow true if a semicolon is required after an arrow expression
   * @return {@link DartBlock} instance containing function body
   */
  private DartBlock parseFunctionStatementBody(boolean allowBody, boolean requireSemicolonForArrow) {
    // A break inside a function body should have nothing to do with a loop in
    // the code surrounding the definition.
    boolean oldInLoopStatement = inLoopStatement;
    boolean oldInCaseStatement = inCaseStatement;
    inLoopStatement = inCaseStatement = false;
    try {
      DartBlock result;
      if (isDietParse) {
        result = dietParseFunctionStatementBody();
      } else {
        beginFunctionStatementBody();
        if (optional(Token.SEMICOLON)) {
          if (allowBody) {
            reportError(position(), ParserErrorCode.EXPECTED_FUNCTION_STATEMENT_BODY);
          }
          result = done(null);
        } else if (optional(Token.ARROW)) {
          DartExpression expr = parseExpression();
          if (expr == null) {
            expr = new DartSyntheticErrorExpression();
          }
          if (requireSemicolonForArrow) {
            expect(Token.SEMICOLON);
          }
          result = done(makeReturnBlock(expr));
        } else {
          result = done(parseBlock());
        }
      }
      if (!allowBody && result != null) {
        reportError(result, ParserErrorCode.EXTERNAL_METHOD_BODY);
      }
      return result;
    } finally {
      inLoopStatement = oldInLoopStatement;
      inCaseStatement = oldInCaseStatement;
    }
  }

  private DartBlock dietParseFunctionStatementBody() {
    DartBlock emptyBlock = new DartBlock(new ArrayList<DartStatement>());
    if (optional(Token.ARROW)) {
      while (true) {
        Token token = next();
        if (token == Token.SEMICOLON) {
          break;
        }
      }
    } else {
      if (!peek(0).equals(Token.LBRACE) && looksLikeTopLevelKeyword()) {
        // Allow recovery back to the top level.
        reportErrorWithoutAdvancing(ParserErrorCode.UNEXPECTED_TOKEN);
        return done(emptyBlock);
      }
      expect(Token.LBRACE);
      int nesting = 1;
      while (nesting > 0) {
        Token token = next();
        switch (token) {
          case LBRACE:
            ++nesting;
            break;
          case RBRACE:
            --nesting;
            break;
          case EOS:
            return emptyBlock;
        }
      }
    }
    // Return an empty block so we don't generate unparseable code.
    return emptyBlock;
  }

  /**
   * Create a block containing a single return statement.
   *
   * @param returnVal return value expression
   * @return block containing a single return statement
   */
  private DartBlock makeReturnBlock(DartExpression returnVal) {
    return new DartReturnBlock(returnVal);
  }

  /**
   * <pre>
   * initializedVariableDeclaration
   *     : constVarOrType initializedIdentifierList
   *     ;
   *
   * initializedIdentifierList
   *     : initializedIdentifier (',' initializedIdentifier)*
   *     ;
   *
   * initializedIdentifier
   *     : IDENTIFIER ('=' assignmentExpression)?
   *     ;
   *  </pre>
   */
  private List<DartVariable> parseInitializedVariableList() {
    List<DartVariable> idents = new ArrayList<DartVariable>();
    do {
      beginVariableDeclaration();
      List<DartAnnotation> metadata = parseMetadata();
      DartIdentifier name = parseIdentifier();
      DartExpression value = null;
      if (isParsingInterface) {
        expect(Token.ASSIGN);
        value = parseExpression();
      } else if (optional(Token.ASSIGN)) {
        value = parseExpression();
      }
      DartVariable variable = done(new DartVariable(name, value));
      setMetadata(variable, metadata);
      idents.add(variable);
    } while (optional(Token.COMMA));

    return idents;
  }

  private DartAssertStatement parseAssertStatement() {
    beginAssertStatement();
    expect(Token.ASSERT);
    expect(Token.LPAREN);
    DartExpression condition = parseExpression();
    expectCloseParen();
    expectStatmentTerminator();
    return done(new DartAssertStatement(condition));
  }

  /**
   * <pre>
   * abruptCompletingStatement
   *     : BREAK identifier? ';'
   *     | CONTINUE identifier? ';'
   *     | RETURN expression? ';'
   *     | THROW expression? ';'
   *     ;
   *  </pre>
   */
  private DartBreakStatement parseBreakStatement() {
    beginBreakStatement();
    expect(Token.BREAK);
    DartIdentifier label = null;
    if (match(Token.IDENTIFIER)) {
      label = parseIdentifier();
    } else if (!inLoopStatement && !inCaseStatement) {
      // The validation of matching of labels to break statements is done later.
      reportErrorWithoutAdvancing(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP);
    }
    expectStatmentTerminator();
    return done(new DartBreakStatement(label));
  }

  private DartContinueStatement parseContinueStatement() {
    beginContinueStatement();
    expect(Token.CONTINUE);
    DartIdentifier label = null;
    if (!inLoopStatement && !inCaseStatement) {
      reportErrorWithoutAdvancing(ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP);
    }
    if (peek(0) == Token.IDENTIFIER) {
      label = parseIdentifier();
    } else if (!inLoopStatement && inCaseStatement) {
      reportErrorWithoutAdvancing(ParserErrorCode.CONTINUE_IN_CASE_MUST_HAVE_LABEL);
    }
    expectStatmentTerminator();
    return done(new DartContinueStatement(label));
  }

  private DartReturnStatement parseReturnStatement() {
    beginReturnStatement();
    expect(Token.RETURN);
    DartExpression value = null;
    if (peek(0) != Token.SEMICOLON) {
      value = parseExpression();
    }
    expectStatmentTerminator();
    return done(new DartReturnStatement(value));
  }

  private DartThrowExpression parseThrowExpression(boolean allowCascade) {
    beginThrowExpression();
    expect(Token.THROW);
    DartExpression exception = null;
    if (peek(0) != Token.SEMICOLON && peek(0) != Token.RPAREN) {
      if (allowCascade) {
        exception = parseExpression();
      } else {
        exception = parseExpressionWithoutCascade();
      }
    }
    return done(new DartThrowExpression(exception));
  }

  /**
   * <pre>
   * statement
   *     : label* nonLabelledStatement
   *     ;
   *
   * label
   *     : identifier ':'
   *     ;
   * </pre>
   *
   * @return a {@link DartStatement}
   */
  @VisibleForTesting
  public DartStatement parseStatement() {
    List<DartIdentifier> labels = new ArrayList<DartIdentifier>();
    while (peek(0) == Token.IDENTIFIER && peek(1) == Token.COLON) {
      beginLabel();
      labels.add(parseIdentifier());
      expect(Token.COLON);
    }
    List<DartAnnotation> metadata = parseMetadata();
    DartStatement statement = parseNonLabelledStatement();
    if (!metadata.isEmpty() && statement instanceof DartVariableStatement) {
      DartVariableStatement variableStatement = (DartVariableStatement) statement;
      if (!variableStatement.getVariables().isEmpty()) {
        setMetadata(variableStatement.getVariables().get(0), metadata);
      }
    }
    for (int i = labels.size() - 1; i >= 0; i--) {
      statement = done(new DartLabel(labels.get(i), statement));
    }
    return statement;
  }

  private boolean isFunctionExpression(DartStatement statement) {
    if (!(statement instanceof DartExprStmt)) {
      return false;
    }
    DartExpression expression = ((DartExprStmt) statement).getExpression();
    if (!(expression instanceof DartFunctionExpression)) {
      return false;
    }
    return ((DartFunctionExpression) expression).getName() == null;
  }

  /**
   * <pre>
   * normalCompletingStatement
   *     : functionStatement
   *     | initializedVariableDeclaration ';'
   *     | simpleStatement
   *     ;
   *
   * functionStatement
   *     : typeOrFunction identifier formalParameterList block
   *     ;
   *     ;
   *
   * simpleStatement
   *     : ('{')=> block // Guard to break tie with map literal.
   *     | expression? ';'
   *     | tryStatement
   *     | ASSERT '(' conditionalExpression ')' ';'
   *     | abruptCompletingStatement
   *     ;
   * </pre>
   */
  // TODO(zundel):  Possibly  we could use Token.IDENTIFIER too, but it is used
  // in so many places, it might make recovery worse rather than better.
  @Terminals(tokens={Token.IF, Token.SWITCH, Token.WHILE, Token.DO, Token.FOR,
      Token.VAR, Token.FINAL, Token.CONTINUE, Token.BREAK, Token.RETURN, Token.THROW,
      Token.TRY, Token.SEMICOLON })
  private DartStatement parseNonLabelledStatement() {
    // Try to parse as function declaration.
    if (looksLikeFunctionDeclarationOrExpression()) {
      ctx.begin();
      DartStatement functionDeclaration = parseFunctionDeclaration();
      // If "null", then we tried to parse, but found that this is not function declaration.
      // So, parsing was rolled back and we can try to parse it as expression.
      if (functionDeclaration != null) {
        if (!isFunctionExpression(functionDeclaration)) {
          ctx.done(null);
          return functionDeclaration;
        }
        ctx.rollback();
      } else {
        ctx.done(null);
      }
    }
    // Check possible statement kind.
    switch (peek(0)) {
      case ASSERT:
        return parseAssertStatement();

      case IF:
        return parseIfStatement();
        
      case SWITCH:
        return parseSwitchStatement();

      case WHILE:
        return parseWhileStatement();

      case DO:
        return parseDoWhileStatement();

      case FOR:
        return parseForStatement();

      case VAR: {
        beginVarDeclaration();
        consume(Token.VAR);
        List<DartVariable> vars = parseInitializedVariableList();
        expectStatmentTerminator();
        return done(new DartVariableStatement(vars, null));
      }

      case FINAL: {
        beginFinalDeclaration();
        consume(peek(0));
        DartTypeNode type = null;
        if (peek(1) == Token.IDENTIFIER || peek(1) == Token.LT || peek(1) == Token.PERIOD) {
          // We know we have a type.
          type = parseTypeAnnotation();
        }
        List<DartVariable> vars = parseInitializedVariableList();
        expectStatmentTerminator();
        return done(new DartVariableStatement(vars, type, Modifiers.NONE.makeFinal()));
      }

      case LBRACE:
        Token token = peek(1);
        if (token == Token.STRING || token == Token.STRING_SEGMENT || token == Token.STRING_EMBED_EXP_START) {
          int offset = skipStringLiteral(1);
          if (peek(offset) == Token.COLON) {
            DartStatement statement = parseExpressionStatement();
            if (statement instanceof DartExprStmt
                && ((DartExprStmt) statement).getExpression() instanceof DartMapLiteral) {
              reportError(
                  ((DartExprStmt) statement).getExpression(),
                  ParserErrorCode.NON_CONST_MAP_LITERAL_STATEMENT);
            }
            return statement;
          }
        }
        return parseBlock();

      case CONTINUE:
        return parseContinueStatement();

      case BREAK:
        return parseBreakStatement();

      case RETURN:
        return parseReturnStatement();

      case THROW:
       return parseExpressionStatement();

      case TRY:
        return parseTryStatement();

      case SEMICOLON:
        beginEmptyStatement();
        consume(Token.SEMICOLON);
        return done(new DartEmptyStatement());

      case CONST:
        // Check to see whether this is a variable declaration. If not, then default to parsing an
        // expression statement.
        int offset = skipTypeName(1);
        if (offset > 1 && (peek(offset) == Token.IDENTIFIER || (offset == 2
            && (peek(offset) == Token.ASSIGN || peek(offset) == Token.COMMA || peek(offset) == Token.SEMICOLON)))) {
          boolean hasType = peek(offset) == Token.IDENTIFIER;
          beginVariableDeclaration();
          next();
          DartTypeNode type = null;
          if (hasType) {
            type = parseTypeAnnotation();
          }
          List<DartVariable> vars = parseInitializedVariableList();
          expect(Token.SEMICOLON);
          return done(new DartVariableStatement(vars, type, Modifiers.NONE.makeConstant().makeFinal()));
        }
        break;

      case AS:
      case IDENTIFIER:
        // We have already eliminated function declarations earlier, so check for:
        // a) variable declarations;
        // b) beginning of function literal invocation.
        if (peek(1) == Token.LT || peek(1) == Token.IDENTIFIER
            || (peek(1) == Token.PERIOD && peek(2) == Token.IDENTIFIER)) {
          beginTypeFunctionOrVariable();
          DartTypeNode type = tryTypeAnnotation();
          if (type != null && peek(0) == Token.IDENTIFIER) {
            List<DartVariable> vars = parseInitializedVariableList();
            if (optional(Token.SEMICOLON)) {
              return done(new DartVariableStatement(vars, type));
            } else if (peek(0) == Token.LPAREN) {
              // Probably a function object invocation.
              rollback();
            } else {
              //reportError(position(), ParserErrorCode.EXPECTED_SEMICOLON);
              expectStatmentTerminator();
              return done(new DartVariableStatement(vars, type));
            }
          } else {
            rollback();
          }
        }
        break;
    }
    return parseExpressionStatement();
  }

  /**
   * Check if succeeding tokens look like a function declaration - the parser state is unchanged
   * upon return.
   *
   * See {@link #parseFunctionDeclaration()}.
   *
   * @return true if the following tokens should be parsed as a function definition
   */
  private boolean looksLikeFunctionDeclarationOrExpression() {
    beginMethodName();
    try {
      optionalPseudoKeyword(STATIC_KEYWORD);
      if (peek(0) == Token.IDENTIFIER && peek(1) == Token.LPAREN) {
        // just a name, no return type
        consume(Token.IDENTIFIER);
      } else if (isReturnType()) {
        if (!optional(Token.IDENTIFIER)) {
          // return types must be followed by a function name
          return false;
        }
      }
      // start of parameter list
      if (!optional(Token.LPAREN)) {
        return false;
      }
      // if it looks as "(Type name, ....)" then it may be function expression
      boolean hasTwoIdentifiersComma;
      {
        int nameOffset = skipTypeName(0);
        hasTwoIdentifiersComma = nameOffset != -1 && peek(nameOffset + 0) == Token.IDENTIFIER
            && peek(nameOffset + 1) == Token.COMMA;
      }
      // find matching parenthesis
      int count = 1;
      while (count != 0) {
        switch (next()) {
          case EOS:
            return false;
          case LPAREN:
            count++;
            break;
          case RPAREN:
            count--;
            break;
        }
      }
      return (peek(0) == Token.ARROW || peek(0) == Token.LBRACE) || hasTwoIdentifiersComma;
    } finally {
      rollback();
    }
  }

  /**
   * Parse a function declaration.
   *
   * <pre>
   * nonLabelledStatement : ...
   *     | functionDeclaration functionBody
   *
   * functionDeclaration
   *    : FUNCTION identifier formalParameterList
   *      { legacy($start, "deprecated 'function' keyword"); }
   *    | returnType error=FUNCTION identifier? formalParameterList
   *      { legacy($error, "deprecated 'function' keyword"); }
   *    | returnType? identifier formalParameterList
   *    ;
   * </pre>
   *
   * @return a {@link DartStatement} representing the function declaration or <code>null</code> if
   *         code ends with function invocation, so this is not function declaration.
   */
  private DartStatement parseFunctionDeclaration() {
    beginFunctionDeclaration();
    DartIdentifier[] namePtr = new DartIdentifier[1];
    DartFunction function = parseFunctionDeclarationOrExpression(namePtr, true);
    if (function.getBody() instanceof DartReturnBlock || peek(0) != Token.LPAREN) {
      return done(new DartExprStmt(doneWithoutConsuming(new DartFunctionExpression(namePtr[0],
          doneWithoutConsuming(function),
          true))));
    } else {
      rollback();
      return null;
    }
  }

  private DartStatement parseExpressionStatement() {
    beginExpressionStatement();
    DartExpression expression = parseExpression();
    expectStatmentTerminator();

    return done(new DartExprStmt(expression));
  }

  /**
   * Expect a close paren, reporting an error and consuming tokens until a
   * plausible continuation is found if it isn't present.
   */
  private void expectCloseParen() {
    int parenCount = 1;
    Token nextToken = peek(0);
    switch (nextToken) {
      case RPAREN:
        expect(Token.RPAREN);
        return;

      case EOS:
      case LBRACE:
      case SEMICOLON:
        reportError(position(), ParserErrorCode.EXPECTED_TOKEN, Token.RPAREN.getSyntax(),
            nextToken.getSyntax());
        return;

      case LPAREN:
        ++parenCount;
        //$FALL-THROUGH$
      default:
        reportError(position(), ParserErrorCode.EXPECTED_TOKEN, Token.RPAREN.getSyntax(),
            nextToken.getSyntax());
        Set<Token> terminals = this.collectTerminalAnnotations();
        if (terminals.contains(nextToken) || looksLikeTopLevelKeyword()) {
          return;
        }
        break;
    }

    // eat tokens until we get a close paren or a plausible terminator (which
    // is not consumed)
    while (parenCount > 0) {
      switch (peek(0)) {
        case RPAREN:
          expect(Token.RPAREN);
          --parenCount;
          break;

        case LPAREN:
          expect(Token.LPAREN);
          ++parenCount;
          break;

        case EOS:
          reportErrorWithoutAdvancing(ParserErrorCode.UNEXPECTED_TOKEN);
          return;

        case LBRACE:
        case SEMICOLON:
          return;

        default:
          next();
          break;
      }
    }
  }

  /**
   * Expect a close brace, reporting an error and consuming tokens until a
   * plausible continuation is found if it isn't present.
   */
  private void expectCloseBrace(boolean foundOpenBrace) {
    // If a top level keyword is seen, bail out to recover.
    if (looksLikeTopLevelKeyword()) {
      reportUnexpectedToken(position(), Token.RBRACE, peek(0));
      return;
    }

    int braceCount = 0;
    if (foundOpenBrace) {
      braceCount++;
    }
    Token nextToken = peek(0);
    if (expect(Token.RBRACE)) {
      return;
    }
    if (nextToken == Token.LBRACE) {
      braceCount++;
    }

    // eat tokens until we get a matching close brace or end of stream
    while (braceCount > 0) {
      if (looksLikeTopLevelKeyword()) {
        return;
      }
      switch (next()) {
        case RBRACE:
          braceCount--;
          break;

        case LBRACE:
          braceCount++;
          break;

        case EOS:
          return;
      }
    }
  }

  /**
   * Collect plausible statement tokens and return a synthetic error statement
   * containing them.
   * <p>
   * Note that this is a crude heuristic that needs to be improved for better
   * error recovery.
   *
   * @return a {@link DartSyntheticErrorStatement}
   */
  private DartStatement parseErrorStatement() {
    StringBuilder buf = new StringBuilder();
    boolean done = false;
    int braceCount = 1;
    while (!done) {
      buf.append(getPeekTokenValue(0));
      next();
      switch (peek(0)) {
        case RBRACE:
          if (--braceCount == 0) {
            done = true;
          }
          break;
        case LBRACE:
          braceCount++;
          break;
        case EOS:
        case SEMICOLON:
          done = true;
          break;
      }
    }
    return new DartSyntheticErrorStatement(buf.toString());
  }


  /**
   * Look for a statement terminator, giving error messages and consuming tokens
   * for error recovery.
   */
  protected void expectStatmentTerminator() {
    Token token = peek(0);
    if (expect(Token.SEMICOLON)) {
      return;
    }
    Set<Token> terminals = collectTerminalAnnotations();
    assert(terminals.contains(Token.SEMICOLON));

    if (peek(0) == token) {
      reportErrorWithoutAdvancing(ParserErrorCode.EXPECTED_SEMICOLON);
    } else {
      reportError(position(), ParserErrorCode.EXPECTED_SEMICOLON);
      token = peek(0);
    }

    // Consume tokens until we see something that could terminate or start a new statement
    while (token != Token.SEMICOLON) {
      if (looksLikeTopLevelKeyword() || terminals.contains(token)) {
        return;
      }
      token = next();
    }
  }

  /**
   * Report an error without advancing past the next token.
   *
   * @param errCode the error code to report, which may take a string parameter
   *     containing the actual token found
   */
  private void reportErrorWithoutAdvancing(ErrorCode errCode) {
    startLookahead();
    Token actual = peek(0);
    next();
    reportError(position(), errCode, actual);
    rollback();
  }

  /**
   * <pre>
   * iterationStatement
   *     : WHILE '(' expression ')' statement
   *     | DO statement WHILE '(' expression ')' ';'
   *     | FOR '(' forLoopParts ')' statement
   *     ;
   *  </pre>
   */
  private DartWhileStatement parseWhileStatement() {
    beginWhileStatement();
    expect(Token.WHILE);
    expect(Token.LPAREN);
    DartExpression condition = parseExpression();
    expectCloseParen();
    int closeParenOffset = ctx.getTokenLocation().getBegin();
    DartStatement body = parseLoopStatement();
    return done(new DartWhileStatement(condition, closeParenOffset, body));
  }

  /**
   * <pre>
   * iterationStatement
   *     : WHILE '(' expression ')' statement
   *     | DO statement WHILE '(' expression ')' ';'
   *     | FOR '(' forLoopParts ')' statement
   *     ;
   *  </pre>
   */
  private DartDoWhileStatement parseDoWhileStatement() {
    beginDoStatement();
    expect(Token.DO);
    DartStatement body = parseLoopStatement();
    expect(Token.WHILE);
    expect(Token.LPAREN);
    DartExpression condition = parseExpression();
    expectCloseParen();
    expectStatmentTerminator();
    return done(new DartDoWhileStatement(condition, body));
  }

  /**
   * Use this wrapper to parse the body of a loop
   *
   * Sets up flag variables to make sure continue and break are properly
   * marked as errors when in wrong context.
   */
  private DartStatement parseLoopStatement() {
    boolean oldInLoop = inLoopStatement;
    inLoopStatement = true;
    try {
      return parseStatement();
    } finally {
      inLoopStatement = oldInLoop;
    }
  }

  /**
   * <pre>
   * iterationStatement
   *     : WHILE '(' expression ')' statement
   *     | DO statement WHILE '(' expression ')' ';'
   *     | FOR '(' forLoopParts ')' statement
   *     ;
   *
   * forLoopParts
   *     : forInitializerStatement expression? ';' expressionList?
   *     | constVarOrType? identifier IN expression
   *     ;
   *
   * forInitializerStatement
   *     : initializedVariableDeclaration ';'
   *     | expression? ';'
   *     ;
   * </pre>
   */
  private DartStatement parseForStatement() {
    beginForStatement();
    expect(Token.FOR);
    expect(Token.LPAREN);

    // Setup
    DartStatement setup = null;
    if (peek(0) != Token.SEMICOLON) {
      // Found a setup expression/statement
      beginForInitialization();
      Modifiers modifiers = Modifiers.NONE;
      if (optional(Token.VAR)) {
        setup = done(new DartVariableStatement(parseInitializedVariableList(), null, modifiers));
      } else {
        if (optional(Token.FINAL)) {
          modifiers = modifiers.makeFinal();
        }
        DartTypeNode type = (peek(1) == Token.IDENTIFIER || peek(1) == Token.LT || peek(1) == Token.PERIOD)
            ? tryTypeAnnotation() : null;
        if (modifiers.isFinal() || type != null) {
          setup = done(new DartVariableStatement(parseInitializedVariableList(), type, modifiers));
        } else {
          setup = done(new DartExprStmt(parseExpression()));
        }
      }
    }

    if (optional(Token.IN)) {
      if (setup instanceof DartVariableStatement) {
        DartVariableStatement variableStatement = (DartVariableStatement) setup;
        List<DartVariable> variables = variableStatement.getVariables();
        if (variables.size() != 1) {
          reportError(variables.get(1), ParserErrorCode.FOR_IN_WITH_MULTIPLE_VARIABLES);
        }
        DartExpression initializer = variables.get(0).getValue();
        if (initializer != null) {
          reportError(initializer, ParserErrorCode.FOR_IN_WITH_VARIABLE_INITIALIZER);
        }
      } else {
        DartExpression expression = ((DartExprStmt) setup).getExpression();
        if (!(expression instanceof DartIdentifier)) {
          reportError(setup, ParserErrorCode.FOR_IN_WITH_COMPLEX_VARIABLE);
        }
      }

      DartExpression iterable = parseExpression();
      expectCloseParen();
      int closeParenOffset = ctx.getTokenLocation().getBegin();

      DartStatement body = parseLoopStatement();
      return done(new DartForInStatement(setup, iterable, closeParenOffset, body));

    } else if (optional(Token.SEMICOLON)) {

      // Condition
      DartExpression condition = null;
      if (peek(0) != Token.SEMICOLON) {
        condition = parseExpression();
      }
      expect(Token.SEMICOLON);

      // Next
      DartExpression next = null;
      if (peek(0) != Token.RPAREN) {
        next = parseExpressionList();
      }
      expectCloseParen();
      int closeParenOffset = ctx.getTokenLocation().getBegin();

      DartStatement body = parseLoopStatement();
      return done(new DartForStatement(setup, condition, next, closeParenOffset, body));
    } else {
      reportUnexpectedToken(position(), null, peek(0));
      return done(parseErrorStatement());
    }
  }

  /**
   * <pre>
   * selectionStatement
   *    : IF '(' expression ')' statement ((ELSE)=> ELSE statement)?
   *    | SWITCH '(' expression ')' '{' switchCase* defaultCase? '}'
   *    ;
   * </pre>
   */
  private DartIfStatement parseIfStatement() {
    beginIfStatement();
    expect(Token.IF);
    expect(Token.LPAREN);
    DartExpression condition = parseExpression();
    expectCloseParen();
    int closeParenOffset = ctx.getTokenLocation().getBegin();
    DartStatement yes = parseStatement();
    DartStatement no = null;
    int elseTokenOffset = 0;
    if (optional(Token.ELSE)) {
      elseTokenOffset = ctx.getTokenLocation().getBegin();
      no = parseStatement();
    }
    return done(new DartIfStatement(condition, closeParenOffset, yes, elseTokenOffset, no));
  }

  /**
   * <pre>
   * caseStatements
   *    : normalCompletingStatement* abruptCompletingStatement
   *    ;
   * </pre>
   */
  private List<DartStatement> parseCaseStatements() {
    List<DartStatement> statements = new ArrayList<DartStatement>();
    DartStatement statement = null;
    boolean endOfCaseFound = false;
    boolean warnedUnreachable = false;
    while (true) {
      switch (peek(0)) {
        case CASE:
        case DEFAULT:
        case RBRACE:
        case EOS:
          return statements;
        case IDENTIFIER:
          // Handle consecutively labeled case statements
          if (isCaseOrDefault()) {
            return statements;
          }
        default:
          boolean oldInCaseStatement = inCaseStatement;
          inCaseStatement = true;
          try {
            if (endOfCaseFound && !warnedUnreachable) {
              reportErrorWithoutAdvancing(ParserErrorCode.UNREACHABLE_CODE_IN_CASE);
              warnedUnreachable = true;
            }
            statement = parseStatement();
          } finally {
            inCaseStatement = oldInCaseStatement;
          }
          if (statement == null) {
            return statements;
          }

          // Don't add unreachable code to the list of statements.
          if (!endOfCaseFound) {
            statements.add(statement);
            if (statement.isAbruptCompletingStatement()) {
              endOfCaseFound = true;
            }
          }
      }
    }
  }

  private boolean isCaseOrDefault() {
    int index = 0;
    while (peek(index) == Token.IDENTIFIER && peek(index + 1) == Token.COLON) {
      index += 2;
    }
    Token next = peek(index);
    return next == Token.CASE || next == Token.DEFAULT;
  }

  /**
   * <pre>
   * switchCase
   *    : label? (CASE expression ':')+ caseStatements
   *    ;
   * </pre>
   */
  private DartSwitchMember parseCaseMember(List<DartLabel> labels) {
    // The begin() associated with the done() in this method is in the method
    // parseSwitchStatement(), called by beginSwitchMember().
    expect(Token.CASE);
    DartExpression caseExpr = parseExpression();
    expect(Token.COLON);
    return done(new DartCase(caseExpr, labels, parseCaseStatements()));
  }

  /**
   * <pre>
   * defaultCase
   *    : label? (CASE expression ':')* DEFAULT ':' caseStatements
   *    ;
   * </pre>
   */
  private DartSwitchMember parseDefaultMember(List<DartLabel> labels) {
    // The begin() associated with the done() in this method is in the method
    // parseSwitchStatement(), called by beginSwitchMember().
    expect(Token.DEFAULT);
    expect(Token.COLON);
    return done(new DartDefault(labels, parseCaseStatements()));
  }


  /**
   * <pre>
   * selectionStatement
   *    : IF '(' expression ')' statement ((ELSE)=> ELSE statement)?
   *    | SWITCH '(' expression ')' '{' switchCase* defaultCase? '}'
   *    ;
   * </pre>
   */
  private DartStatement parseSwitchStatement() {
    beginSwitchStatement();
    expect(Token.SWITCH);

    expect(Token.LPAREN);
    DartExpression expr = parseExpression();
    expectCloseParen();

    List<DartSwitchMember> members = new ArrayList<DartSwitchMember>();
    if (peek(0) != Token.LBRACE) {
      reportUnexpectedToken(position(), Token.LBRACE, peek(0));
      return done(new DartSwitchStatement(expr, members));
    }
    boolean foundOpenBrace = expect(Token.LBRACE);

    boolean done = optional(Token.RBRACE);
    while (!done) {
      List<DartLabel> labels = new ArrayList<DartLabel>();
      beginSwitchMember(); // switch member
      while (peek(0) == Token.IDENTIFIER && peek(1) == Token.COLON) {
        beginLabel();
        DartIdentifier identifier = parseIdentifier();
        expect(Token.COLON);
        labels.add(done(new DartLabel(identifier, null)));
        if (peek(0) == Token.RBRACE) {
          reportError(position(), ParserErrorCode.LABEL_NOT_FOLLOWED_BY_CASE_OR_DEFAULT);
          expectCloseBrace(foundOpenBrace);
          return done(new DartSwitchStatement(expr, members));
        }
      }
      if (peek(0) == Token.CASE) {
        members.add(parseCaseMember(labels));
      } else if (optional(Token.RBRACE)) {
        if (!labels.isEmpty()) {
          reportError(position(), ParserErrorCode.EXPECTED_CASE_OR_DEFAULT);
        }
        done = true;
        done(null);
      } else {
        if (peek(0) == Token.DEFAULT) {
          members.add(parseDefaultMember(labels));
        }
        expectCloseBrace(foundOpenBrace);
        done = true; // Ensure termination.
      }
    }
    return done(new DartSwitchStatement(expr, members));
  }

  /**
   * <pre>
   * catchParameter
   *    : FINAL type? identifier
   *    | VAR identifier
   *    | type identifier
   *    ;
   *  </pre>
   */
  private DartParameter parseCatchParameter() {
    beginCatchParameter();
    List<DartAnnotation> metadata = parseMetadata();
    DartTypeNode type = null;
    Modifiers modifiers = Modifiers.NONE;
    boolean isDeclared = false;
    if (optional(Token.VAR)) {
      isDeclared = true;
    } else {
      if (optional(Token.FINAL)) {
        modifiers = modifiers.makeFinal();
        isDeclared = true;
      }
      if (peek(1) != Token.COMMA && peek(1) != Token.RPAREN) {
        type = parseTypeAnnotation();
        isDeclared = true;
      }
    }
    DartIdentifier name = parseIdentifier();
    if (!isDeclared) {
      reportError(name, ParserErrorCode.EXPECTED_VAR_FINAL_OR_TYPE);
    }
    DartParameter parameter = done(new DartParameter(name, type, null, null, modifiers));
    setMetadata(parameter, metadata);
    return parameter;
  }

  /**
   * Parse either the old try statement syntax:
   * <pre>
   * tryStatement
   *     : TRY block (catchPart+ finallyPart? | finallyPart)
   *     ;
   *
   * catchPart
   *     : CATCH '(' declaredIdentifier (',' declaredIdentifier)? ')' block
   *     ;
   *
   * finallyPart
   *     : FINALLY block
   *     ;
   * </pre>
   * or the new syntax:
   * <pre>
   * tryStatement
   *     : TRY block (onPart+ finallyPart? | finallyPart)
   *     ;
   *
   * onPart
   *     : catchPart block
   *     | ON qualified catchPart? block
   *
   * catchPart
   *     : CATCH '(' identifier (',' identifier)? ')'
   *     ;
   *
   * finallyPart
   *     : FINALLY block
   *     ;
   * </pre>
   */
  private DartTryStatement parseTryStatement() {
    beginTryStatement();
    // Try.
    expect(Token.TRY);
    // TODO(zundel): It would be nice here to setup 'ON', 'CATCH' and 'FINALLY' as tokens for recovery
    DartBlock tryBlock = parseBlock();

    List<DartCatchBlock> catches = new ArrayList<DartCatchBlock>();
    while (peekPseudoKeyword(0, ON_KEYWORD) || match(Token.CATCH)) {
      // TODO(zundel): It would be nice here to setup 'FINALLY' as token for recovery
      if (peekPseudoKeyword(0, ON_KEYWORD)) {
        beginCatchClause();
        next();
        DartTypeNode exceptionType = parseTypeAnnotation();
        DartParameter exception = null;
        DartParameter stackTrace = null;
        if (optional(Token.CATCH)) {
          expect(Token.LPAREN);
          beginCatchParameter();
          List<DartAnnotation> metadata = parseMetadata();
          DartIdentifier exceptionName = parseIdentifier();
          exception = done(new DartParameter(exceptionName, exceptionType, null, null, Modifiers.NONE));
          setMetadata(exception, metadata);
          if (optional(Token.COMMA)) {
            beginCatchParameter();
            DartIdentifier stackName = parseIdentifier();
            stackTrace = done(new DartParameter(stackName, null, null, null, Modifiers.NONE));
          }
          expectCloseParen();
        } else {
          // Create a dummy identifier that the user cannot reliably reference.
          beginCatchParameter();
          List<DartAnnotation> metadata = parseMetadata();
          beginIdentifier();
          DartIdentifier exceptionName = done(new DartIdentifier("e" + Long.toHexString(System.currentTimeMillis())));
          exception = done(new DartParameter(exceptionName, exceptionType, null, null, Modifiers.NONE));
          setMetadata(exception, metadata);
        }
        DartBlock block = parseBlock();
        catches.add(done(new DartCatchBlock(block, exception, stackTrace)));
      } else {
        beginCatchClause();
        next();
        expect(Token.LPAREN);
        DartParameter exception;
        if (match(Token.IDENTIFIER) && (peek(1) == Token.COMMA || peek(1) == Token.RPAREN)) {
          beginCatchParameter();
          List<DartAnnotation> metadata = parseMetadata();
          DartIdentifier exceptionName = parseIdentifier();
          exception = done(new DartParameter(exceptionName, null , null, null, Modifiers.NONE));
          setMetadata(exception, metadata);
        } else {
          // Old-style parameter
          reportError(position(), ParserErrorCode.DEPRECATED_CATCH);
          exception = parseCatchParameter();
        }
        DartParameter stackTrace = null;
        if (optional(Token.COMMA)) {
          if (match(Token.IDENTIFIER) && peek(1) == Token.RPAREN) {
            beginCatchParameter();
            List<DartAnnotation> metadata = parseMetadata();
            DartIdentifier stackName = parseIdentifier();
            stackTrace = done(new DartParameter(stackName, null, null, null, Modifiers.NONE));
            setMetadata(stackTrace, metadata);
          } else {
            // Old-style parameter
            reportError(position(), ParserErrorCode.DEPRECATED_CATCH);
            stackTrace = parseCatchParameter();
          }
        }
        expectCloseParen();
        DartBlock block = parseBlock();
        catches.add(done(new DartCatchBlock(block, exception, stackTrace)));
      }
    }

    // Finally.
    DartBlock finallyBlock = null;
    if (optional(Token.FINALLY)) {
      finallyBlock = parseBlock();
    }

    if ( catches.size() == 0 && finallyBlock == null) {
      reportError(new DartCompilationError(tryBlock.getSourceInfo().getSource(), new Location(position()),
        ParserErrorCode.CATCH_OR_FINALLY_EXPECTED));
    }

    return done(new DartTryStatement(tryBlock, catches, finallyBlock));
  }

  /**
   * <pre>
   * unaryExpression
   *     : postfixExpression
   *     | prefixOperator unaryExpression
   *     | incrementOperator assignableExpression
   *     ;
   *
   *  @return an expression or null if noFail is true and the next tokens could not be parsed as an
   *      expression, leaving the state unchanged.
   *  </pre>
   */
  private DartExpression parseUnaryExpression() {
    // There is no unary plus operator in Dart.
    // However, we allow a leading plus in decimal numeric literals.
    if (optional(Token.ADD)) {
      if (peek(0) != Token.INTEGER_LITERAL && peek(0) != Token.DOUBLE_LITERAL) {
        reportError(position(), ParserErrorCode.NO_UNARY_PLUS_OPERATOR);
      } else if (position() + 1 != peekTokenLocation(0).getBegin()) {
        reportError(position(), ParserErrorCode.NO_SPACE_AFTER_PLUS);
      }
    }
    // Check for unary minus operator.
    Token token = peek(0);
    if (token.isUnaryOperator() || token == Token.SUB) {
      if (token == Token.DEC && peek(1) == Token.SUPER) {
        beginUnaryExpression();
        beginUnaryExpression();
        consume(token);
        int tokenOffset = ctx.getTokenLocation().getBegin();
        DartExpression unary = parseUnaryExpression();
        DartUnaryExpression unary2 = new DartUnaryExpression(Token.SUB, tokenOffset, unary, true);
        return done(new DartUnaryExpression(Token.SUB, tokenOffset, done(unary2), true));
      } else {
        beginUnaryExpression();
        consume(token);
        int tokenOffset = ctx.getTokenLocation().getBegin();
        DartExpression unary = parseUnaryExpression();
        if (token.isCountOperator()) {
          ensureAssignable(unary);
        }
        return done(new DartUnaryExpression(token, tokenOffset, unary, true));
      }
    } else {
      return parsePostfixExpression();
    }
  }

  /**
   * <pre>
   * type
   *     : qualified typeArguments?
   *     ;
   * </pre>
   */
  private DartTypeNode parseTypeAnnotation() {
    beginTypeAnnotation();
    return done(new DartTypeNode(parseQualified(false), parseTypeArgumentsOpt()));
  }

  /**
   * <pre>
   * type
   *     : qualified typeArguments? ('.' identifier)?
   *     ;
   * </pre>
   */
  private DartTypeNode parseTypeAnnotationPossiblyFollowedByName() {
    beginTypeAnnotation();
    boolean canBeFollowedByPeriod = true;
    if (peek(Token.IDENTIFIER, Token.LT) || peek(Token.IDENTIFIER, Token.PERIOD, Token.IDENTIFIER, Token.LT)) {
      canBeFollowedByPeriod = false;
    }
    return done(new DartTypeNode(parseQualified(canBeFollowedByPeriod), parseTypeArgumentsOpt()));
  }

  private boolean peek(Token... tokens) {
    int index = 0;
    for (Token token : tokens) {
      if (peek(index++) != token) {
        return false;
      }
    }
    return true;
  }

  /**
   * <pre>
   * typeArguments
   *     : '<' typeList '>'
   *     ;
   *
   * typeList
   *     : type (',' type)*
   *     ;
   * </pre>
   */
  @Terminals(tokens={Token.GT, Token.COMMA})
  private List<DartTypeNode> parseTypeArguments() {
    consume(Token.LT);
    List<DartTypeNode> arguments = new ArrayList<DartTypeNode>();
    do {
      arguments.add(parseTypeAnnotation());
    } while (optional(Token.COMMA));
    if (!tryParameterizedTypeEnd()) {
      expect(Token.GT);
    }
    return arguments;
  }

  /**
   * <pre>
   * typeArguments?
   * </pre>
   */
  private List<DartTypeNode> parseTypeArgumentsOpt() {
    return (peek(0) == Token.LT)
        ? parseTypeArguments()
        : Collections.<DartTypeNode>emptyList();
  }

  /**
   * <pre>
   * qualified
   *     : identifier ('.' identifier)?
   *     ;
   * </pre>
   */
  private DartExpression parseQualified(boolean canBeFollowedByPeriod) {
    beginQualifiedIdentifier();
    DartIdentifier identifier = parseIdentifier();
    if (!prefixes.contains(identifier.getName())) {
      if (canBeFollowedByPeriod && !(peek(0) == Token.PERIOD && peek(1) == Token.IDENTIFIER && peek(2) == Token.PERIOD)) {
        return done(identifier);
      }
    }
    DartExpression qualified = identifier;
    if (optional(Token.PERIOD)) {
      // The previous identifier was a prefix.
      qualified = new DartPropertyAccess(qualified, parseIdentifier());
    }
    return done(qualified);
  }

  private boolean tryParameterizedTypeEnd() {
    switch (peek(0)) {
      case GT:
        consume(Token.GT);
        return true;
      case SAR:
        setPeek(0, Token.GT);
        return true;
      default:
        return false;
    }
  }

  private DartTypeNode tryTypeAnnotation() {
    if (peek(0) != Token.IDENTIFIER && peek(0) != Token.AS) {
      return null;
    }
    List<DartTypeNode> typeArguments = new ArrayList<DartTypeNode>();
    beginTypeAnnotation(); // to allow roll-back in case we're not at a type

    DartNode qualified = parseQualified(false);

    if (optional(Token.LT)) {
      if (peek(0) != Token.IDENTIFIER && peek(0) != Token.AS) {
        rollback();
        return null;
      }
      beginTypeArguments();
      DartNode qualified2 = parseQualified(false);
      DartTypeNode argument;
      switch (peek(0)) {
        case LT:
          // qualified < qualified2 <
          argument = done(new DartTypeNode(qualified2, parseTypeArguments()));
          break;

        case GT:
        case SAR:
          // qualified < qualified2 >
        case COMMA:
          // qualified < qualified2 ,
          argument = done(new DartTypeNode(qualified2, Collections.<DartTypeNode>emptyList()));
          break;

        default:
          done(null);
          rollback();
          return null;
      }
      typeArguments.add(argument);

      while (optional(Token.COMMA)) {
        typeArguments.add(parseTypeAnnotation());
      }
      if (!tryParameterizedTypeEnd()) {
        expect(Token.GT);
      }
    }

    return done(new DartTypeNode(qualified, typeArguments));
  }

  private DartIdentifier parseIdentifier() {
    beginIdentifier();
    if (peek(0) == Token.AS) {
      next();
      return done(new DartIdentifier("as"));
    }
    if (looksLikeTopLevelKeyword()) {
      reportErrorWithoutAdvancing(ParserErrorCode.EXPECTED_IDENTIFIER);
      return done(new DartSyntheticErrorIdentifier());
    }
    DartIdentifier identifier;
    if (expect(Token.IDENTIFIER) && ctx.getTokenString() != null) {
      identifier = new DartIdentifier(new String(ctx.getTokenString()));
    } else {
      identifier = new DartSyntheticErrorIdentifier();
    }
    return done(identifier);
  }

  public DartExpression parseEntryPoint() {
    beginEntryPoint();
    DartExpression entry = parseIdentifier();
    while (!EOS()) {
      expect(Token.PERIOD);
      entry = doneWithoutConsuming(new DartPropertyAccess(entry, parseIdentifier()));
    }
    return done(entry);
  }

  private void ensureAssignable(DartExpression expression) {
    if (expression != null && !expression.isAssignable()) {
      reportError(position(), ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE);
    }
  }

  /**
   * Increment the number of errors encountered while parsing this compilation unit. Returns whether
   * the current error should be reported.
   * 
   * @return whether the current error should be reported
   */
  private boolean incErrorCount(ErrorCode errorCode) {
    // count only errors, but not warnings (such as "abstract")
    if (errorCode.getErrorSeverity() == ErrorSeverity.ERROR) {
      errorCount++;
    }
    
    if (errorCount >= MAX_DEFAULT_ERRORS) {
      if (errorCount == MAX_DEFAULT_ERRORS) {
        // Create a 'too many errors' error.
        DartCompilationError dartError = new DartCompilationError(ctx.getSource(),
            ctx.getTokenLocation(), ParserErrorCode.NO_SOUP_FOR_YOU);
        ctx.error(dartError);
      }
      
      // Consume the rest of the input stream. Throwing an exception - as suggested elsewhere in
      // this file - is not ideal.
      Token next = next();
      
      while (next != null && next != Token.EOS) {
        next = next();
      }
    }
    
    return errorCount < MAX_DEFAULT_ERRORS;
  }
  
  private void reportDeprecatedError(int position, ErrorCode errorCode) {
    // TODO(scheglov) remove after http://code.google.com/p/dart/issues/detail?id=6508
    if (!Elements.isCoreLibrarySource(source) &&
        !Elements.isLibrarySource(source, "/isolate/isolate.dart")
      &&  !Elements.isLibrarySource(source, "/json/json.dart")
      &&  !Elements.isLibrarySource(source, "/math/math.dart")
      &&  !Elements.isLibrarySource(source, "/html/dartium/nativewrappers.dart")
      &&  !Elements.isLibrarySource(source, "/io/io.dart")
      &&  !Elements.isLibrarySource(source, "/crypto/crypto.dart")
      &&  !Elements.isLibrarySource(source, "/uri/uri.dart")
      &&  !Elements.isLibrarySource(source, "/utf/utf.dart")
      &&  !Elements.isLibrarySource(source, "/scalarlist/scalarlist.dart")
        ) {
      super.reportError(position, errorCode);
    }
  }
  
  @Override
  protected void reportError(int position, ErrorCode errorCode, Object... arguments) {
    // TODO(devoncarew): we're not correctly identifying dart:html as a core library
    if (incErrorCount(errorCode)) {
      super.reportError(position, errorCode, arguments);
    }
  }

  @Override
  protected void reportErrorAtPosition(int startPosition, int endPosition,
      ErrorCode errorCode, Object... arguments) {
    if (incErrorCount(errorCode)) {
      super.reportErrorAtPosition(startPosition, endPosition, errorCode, arguments);
    }
  }

  private void reportError(DartCompilationError dartError) {
    if (incErrorCount(dartError.getErrorCode())) {
      ctx.error(dartError);
      errorHistory.add(dartError.hashCode());
    }
  }

  private void reportError(DartNode node, ErrorCode errorCode, Object... arguments) {
    if (node != null) {
      reportError(new DartCompilationError(node, errorCode, arguments));
    }
  }

  private boolean currentlyParsingToplevel() {
    return   !(isParsingInterface || isTopLevelAbstract || isParsingClass);
  }
}
