// Copyright (c) 2015, 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.

library dart2js.parser.node_listener;

import 'package:front_end/src/fasta/parser.dart'
    show FormalParameterKind, IdentifierContext, MemberKind;
import 'package:front_end/src/fasta/scanner.dart' show Token;
import 'package:front_end/src/scanner/token.dart' show TokenType;

import '../common.dart';
import '../elements/elements.dart' show CompilationUnitElement;
import '../tree/tree.dart';
import '../util/util.dart' show Link;
import 'element_listener.dart' show ElementListener, ScannerOptions;

import 'package:front_end/src/fasta/parser.dart' as fasta show Assert;

class NodeListener extends ElementListener {
  int invalidTopLevelDeclarationCount = 0;
  int invalidMemberCount = 0;

  NodeListener(ScannerOptions scannerOptions, DiagnosticReporter reporter,
      CompilationUnitElement element)
      : super(scannerOptions, reporter, element, null);

  @override
  void addLibraryTag(LibraryTag tag) {
    pushNode(tag);
  }

  @override
  void addPartOfTag(PartOf tag) {
    pushNode(tag);
  }

  @override
  void endLibraryName(Token libraryKeyword, Token semicolon) {
    Expression name = popNode();
    pushNode(new LibraryName(
        libraryKeyword,
        name,
        // TODO(sigmund): Import AST nodes have pointers to MetadataAnnotation
        // (element) instead of Metatada (node).
        null));
  }

  @override
  void endImport(Token importKeyword, Token semicolon) {
    NodeList combinators = popNode();
    Flag flag = popNode();
    bool isDeferred = flag == Flag.TRUE;
    Identifier prefix = popNode();
    NodeList conditionalUris = popNode();
    StringNode uri = popLiteralString();
    pushNode(new Import(
        importKeyword,
        uri,
        conditionalUris,
        prefix,
        combinators,
        // TODO(sigmund): Import AST nodes have pointers to MetadataAnnotation
        // (element) instead of Metatada (node).
        null,
        isDeferred: isDeferred));
  }

  @override
  void endExport(Token exportKeyword, Token semicolon) {
    NodeList combinators = popNode();
    NodeList conditionalUris = popNode();
    StringNode uri = popLiteralString();
    pushNode(new Export(
        exportKeyword,
        uri,
        conditionalUris,
        combinators,
        // TODO(sigmund): Import AST nodes have pointers to MetadataAnnotation
        // (element) instead of Metatada (node).
        null));
  }

  @override
  void endPart(Token partKeyword, Token semicolon) {
    StringNode uri = popLiteralString();
    pushNode(new Part(
        partKeyword,
        uri,
        // TODO(sigmund): Import AST nodes have pointers to MetadataAnnotation
        // (element) instead of Metatada (node).
        null));
  }

  @override
  void endPartOf(
      Token partKeyword, Token ofKeyword, Token semicolon, bool hasName) {
    Expression name = popNode(); // name
    pushNode(new PartOf(
        partKeyword,
        name,
        // TODO(sigmund): Import AST nodes have pointers to MetadataAnnotation
        // (element) instead of Metatada (node).
        null));
  }

  @override
  void handleClassExtends(Token extendsKeyword) {
    pushNode(new TokenNode(extendsKeyword));
  }

  @override
  void handleClassImplements(Token implementsKeyword, int interfacesCount) {
    pushNode(makeNodeList(interfacesCount, implementsKeyword, null, ","));
  }

  @override
  void handleRecoverClassHeader() {
    popNode(); // interfaces
    popNode(); // extendsNode
    popNode(); // supertype
  }

  @override
  void endClassDeclaration(Token beginToken, Token endToken) {
    NodeList body = popNode();
    NodeList interfaces = popNode();
    TokenNode extendsNode = popNode();
    Node supertype = popNode();
    NodeList typeParameters = popNode();
    Identifier name = popNode();
    Modifiers modifiers = popNode();
    // TODO(danrubel): can we remove the extends keyword from ClassNode ?
    pushNode(new ClassNode(modifiers, name, typeParameters, supertype,
        interfaces, beginToken, extendsNode.token, body, endToken));
  }

  @override
  void handleInvalidTopLevelDeclaration(Token endToken) {
    ++invalidTopLevelDeclarationCount;
  }

  @override
  void endTopLevelDeclaration(Token token) {
    // TODO(sigmund): consider moving metadata into each declaration
    // element instead.
    Node node = popNode(); // top-level declaration
    popNode(); // Discard metadata
    pushNode(node);
    super.endTopLevelDeclaration(token);
  }

  @override
  void beginCompilationUnit(Token token) {
    invalidTopLevelDeclarationCount = 0;
  }

  @override
  void endCompilationUnit(int count, Token token) {
    pushNode(makeNodeList(
        count - invalidTopLevelDeclarationCount, null, null, '\n'));
  }

  @override
  void endFunctionTypeAlias(
      Token typedefKeyword, Token equals, Token endToken) {
    bool isGeneralizedTypeAlias;
    NodeList templateParameters;
    TypeAnnotation returnType;
    Identifier name;
    NodeList typeParameters;
    NodeList formals;
    if (equals == null) {
      isGeneralizedTypeAlias = false;
      formals = popNode();
      templateParameters = popNode();
      name = popNode();
      returnType = popNode();
    } else {
      // TODO(floitsch): keep using the `FunctionTypeAnnotation' node.
      isGeneralizedTypeAlias = true;
      Node type = popNode();
      if (type.asFunctionTypeAnnotation() == null) {
        // TODO(floitsch): The parser should diagnose this problem, not
        // this listener.
        // However, this problem goes away, when we allow aliases for
        // non-function types too.
        reportFatalError(type, 'Expected a function type.');
      }
      FunctionTypeAnnotation functionType = type;
      templateParameters = popNode();
      name = popNode();
      returnType = functionType.returnType;
      typeParameters = functionType.typeParameters;
      formals = functionType.formals;
    }
    pushNode(new Typedef(isGeneralizedTypeAlias, templateParameters, returnType,
        name, typeParameters, formals, typedefKeyword, endToken));
  }

  void handleNoName(Token token) {
    pushNode(null);
  }

  @override
  void endFunctionType(Token functionToken, Token endToken) {
    NodeList formals = popNode();
    TypeAnnotation returnType = popNode();
    NodeList typeParameters = popNode();
    pushNode(new FunctionTypeAnnotation(
        returnType, functionToken, typeParameters, formals));
  }

  @override
  void endNamedMixinApplication(Token beginToken, Token classKeyword,
      Token equals, Token implementsKeyword, Token endToken) {
    NodeList interfaces = (implementsKeyword != null) ? popNode() : null;
    Node mixinApplication = popNode();
    NodeList typeParameters = popNode();
    Identifier name = popNode();
    Modifiers modifiers = popNode();
    pushNode(new NamedMixinApplication(name, typeParameters, modifiers,
        mixinApplication, interfaces, beginToken, endToken));
  }

  @override
  void endEnum(Token enumKeyword, Token leftBrace, int count) {
    NodeList names = makeNodeList(count, leftBrace, leftBrace?.endGroup, ",");
    Identifier name = popNode();
    pushNode(new Enum(enumKeyword, name, names));
  }

  @override
  void endClassBody(int memberCount, Token beginToken, Token endToken) {
    pushNode(makeNodeList(
        memberCount - invalidMemberCount, beginToken, endToken, null));
    invalidMemberCount = 0;
  }

  @override
  void endTopLevelFields(int count, Token beginToken, Token endToken) {
    NodeList variables = makeNodeList(count, null, endToken, ",");
    TypeAnnotation type = popNode();
    Modifiers modifiers = popNode();
    pushNode(new VariableDefinitions(type, modifiers, variables));
  }

  @override
  void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
    Statement body = popNode();
    AsyncModifier asyncModifier = popNode();
    NodeList formals = popNode();
    NodeList typeVariables = popNode();
    Identifier name = popNode();
    TypeAnnotation type = popNode();
    Modifiers modifiers = popNode();
    pushNode(new FunctionExpression(name, typeVariables, formals, body, type,
        modifiers, null, getOrSet, asyncModifier));
  }

  @override
  void endFormalParameter(Token thisKeyword, Token periodAfterThis,
      Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
    Expression name = popNode();
    if (thisKeyword != null) {
      Identifier thisIdentifier = new Identifier(thisKeyword);
      if (name.asSend() == null) {
        name = new Send(thisIdentifier, name);
      } else {
        name = name.asSend().copyWithReceiver(thisIdentifier, false);
      }
    }
    TypeAnnotation type = popNode();
    Modifiers modifiers = popNode();
    NodeList metadata = popNode();
    pushNode(new VariableDefinitions.forParameter(
        metadata, type, modifiers, new NodeList.singleton(name)));
  }

  @override
  void endFormalParameters(
      int count, Token beginToken, Token endToken, MemberKind kind) {
    pushNode(makeNodeList(count, beginToken, endToken, ","));
  }

  @override
  void handleNoFormalParameters(Token token, MemberKind kind) {
    pushNode(null);
  }

  @override
  void endArguments(int count, Token beginToken, Token endToken) {
    pushNode(makeNodeList(count, beginToken, endToken, ","));
  }

  @override
  void handleNoArguments(Token token) {
    pushNode(null);
  }

  @override
  void endConstructorReference(
      Token start, Token periodBeforeName, Token endToken) {
    Identifier name = null;
    if (periodBeforeName != null) {
      name = popNode();
    }
    NodeList typeArguments = popNode();
    Node classReference = popNode();
    if (typeArguments != null) {
      classReference = new NominalTypeAnnotation(classReference, typeArguments);
    } else {
      Identifier identifier = classReference.asIdentifier();
      Send send = classReference.asSend();
      if (identifier != null) {
        // TODO(ahe): Should be:
        // classReference = new Send(null, identifier);
        classReference = identifier;
      } else if (send != null) {
        classReference = send;
      } else {
        internalError(node: classReference);
      }
    }
    Node constructor = classReference;
    if (name != null) {
      // Either typeName<args>.name or x.y.name.
      constructor = new Send(classReference, name);
    }
    pushNode(constructor);
  }

  @override
  void endRedirectingFactoryBody(Token beginToken, Token endToken) {
    pushNode(new RedirectingFactoryBody(beginToken, endToken, popNode()));
  }

  @override
  void handleNativeFunctionBody(Token nativeToken, Token semicolon) {
    pushNode(new Return(nativeToken, semicolon, nativeName));
  }

  @override
  void handleEmptyFunctionBody(Token semicolon) {
    endBlockFunctionBody(0, null, semicolon);
  }

  void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
    endReturnStatement(true, arrowToken, endToken);
  }

  @override
  void endReturnStatement(
      bool hasExpression, Token beginToken, Token endToken) {
    Expression expression = hasExpression ? popNode() : null;
    pushNode(new Return(beginToken, endToken, expression));
  }

  @override
  void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
    Expression expression = popNode();
    pushNode(new Yield(yieldToken, starToken, expression, endToken));
  }

  @override
  void endExpressionStatement(Token token) {
    pushNode(new ExpressionStatement(popNode(), token));
  }

  void handleOnError(Token token, var errorInformation) {
    reporter.internalError(reporter.spanFromToken(token),
        "'${token.lexeme}': ${errorInformation}");
  }

  @override
  void handleLiteralInt(Token token) {
    pushNode(new LiteralInt(token, (t, e) => handleOnError(t, e)));
  }

  @override
  void handleLiteralDouble(Token token) {
    pushNode(new LiteralDouble(token, (t, e) => handleOnError(t, e)));
  }

  @override
  void handleLiteralBool(Token token) {
    pushNode(new LiteralBool(token, (t, e) => handleOnError(t, e)));
  }

  @override
  void handleLiteralNull(Token token) {
    pushNode(new LiteralNull(token));
  }

  @override
  void endLiteralSymbol(Token hashToken, int identifierCount) {
    NodeList identifiers = makeNodeList(identifierCount, null, null, '.');
    pushNode(new LiteralSymbol(hashToken, identifiers));
  }

  @override
  void endBinaryExpression(Token token) {
    Node argument = popNode();
    Node receiver = popNode();
    String tokenString = token.stringValue;
    if (identical(tokenString, '.') ||
        identical(tokenString, '..') ||
        identical(tokenString, '?.')) {
      Send argumentSend = argument.asSend();
      if (argumentSend == null) {
        // TODO(ahe): The parser should diagnose this problem, not
        // this listener.
        reportFatalError(
            reporter.spanFromSpannable(argument), "Expected an identifier.");
      }
      if (argumentSend.receiver != null) internalError(node: argument);
      if (argument is SendSet) internalError(node: argument);
      pushNode(argument
          .asSend()
          .copyWithReceiver(receiver, identical(tokenString, '?.')));
    } else {
      NodeList arguments = new NodeList.singleton(argument);
      pushNode(new Send(receiver, new Operator(token), arguments));
    }
    if (identical(tokenString, '===')) {
      reporter.reportErrorMessage(reporter.spanFromToken(token),
          MessageKind.UNSUPPORTED_EQ_EQ_EQ, {'lhs': receiver, 'rhs': argument});
    }
    if (identical(tokenString, '!==')) {
      reporter.reportErrorMessage(
          reporter.spanFromToken(token),
          MessageKind.UNSUPPORTED_BANG_EQ_EQ,
          {'lhs': receiver, 'rhs': argument});
    }
  }

  @override
  void beginCascade(Token token) {
    pushNode(new CascadeReceiver(popNode(), token));
  }

  @override
  void endCascade() {
    pushNode(new Cascade(popNode()));
  }

  @override
  void handleAsOperator(Token operator, Token endToken) {
    TypeAnnotation type = popNode();
    Expression expression = popNode();
    NodeList arguments = new NodeList.singleton(type);
    pushNode(new Send(expression, new Operator(operator), arguments));
  }

  @override
  void handleAssignmentExpression(Token token) {
    Node arg = popNode();
    Node node = popNode();
    Send send = node.asSend();
    if (send == null || !(send.isPropertyAccess || send.isIndex)) {
      reportNotAssignable(node);
    }
    var tokenString = token.stringValue;
    if (tokenString == '||=' || tokenString == '&&=') {
      reporter.reportErrorMessage(reporter.spanFromToken(token),
          MessageKind.UNSUPPORTED_OPERATOR, {'operator': tokenString});
      pushNode(arg);
      return;
    }
    if (send.asSendSet() != null) internalError(node: send);
    NodeList arguments;
    if (send.isIndex) {
      Link<Node> link = const Link<Node>().prepend(arg);
      link = link.prepend(send.arguments.head);
      arguments = new NodeList(null, link);
    } else {
      arguments = new NodeList.singleton(arg);
    }
    Operator op = new Operator(token);
    pushNode(new SendSet(
        send.receiver, send.selector, op, arguments, send.isConditional));
  }

  void reportNotAssignable(Node node) {
    // TODO(ahe): The parser should diagnose this problem, not this
    // listener.
    reportFatalError(reporter.spanFromSpannable(node), "Not assignable.");
  }

  @override
  void endConditionalExpression(Token question, Token colon) {
    Node elseExpression = popNode();
    Node thenExpression = popNode();
    Node condition = popNode();
    pushNode(new Conditional(
        condition, thenExpression, elseExpression, question, colon));
  }

  @override
  void handleSend(Token beginToken, Token endToken) {
    NodeList arguments = popNode();
    NodeList typeArguments = popNode();
    Node selector = popNode();
    // TODO(ahe): Handle receiver.
    pushNode(new Send(null, selector, arguments, typeArguments));
  }

  @override
  void endBlockFunctionBody(int count, Token beginToken, Token endToken) {
    if (count == 0 && beginToken == null) {
      pushNode(new EmptyStatement(endToken));
    } else {
      pushNode(new Block(makeNodeList(count, beginToken, endToken, null)));
    }
  }

  @override
  void handleAsyncModifier(Token asyncToken, Token starToken) {
    if (asyncToken != null) {
      pushNode(new AsyncModifier(asyncToken, starToken));
    } else {
      pushNode(null);
    }
  }

  @override
  void handleFunctionBodySkipped(Token token, bool isExpressionBody) {
    pushNode(new Block(new NodeList.empty()));
  }

  @override
  void handleNativeFunctionBodyIgnored(Token nativeToken, Token semicolon) {}

  @override
  void handleNativeFunctionBodySkipped(Token nativeToken, Token semicolon) {
    pushNode(new Block(new NodeList.empty()));
  }

  @override
  void handleNoFunctionBody(Token token) {
    pushNode(new EmptyStatement(token));
  }

  @override
  void endNamedFunctionExpression(Token endToken) {
    Statement body = popNode();
    AsyncModifier asyncModifier = popNode();
    NodeList initializers = popNode();
    NodeList formals = popNode();
    // The name can be an identifier or a send in case of named constructors.
    Expression name = popNode();
    TypeAnnotation type = popNode();
    Modifiers modifiers = popNode();
    NodeList typeVariables = popNode();
    pushNode(new FunctionExpression(name, typeVariables, formals, body, type,
        modifiers, initializers, null, asyncModifier));
  }

  @override
  void endLocalFunctionDeclaration(Token endToken) {
    Statement body = popNode();
    AsyncModifier asyncModifier = popNode();
    NodeList initializers = popNode();
    NodeList formals = popNode();
    // The name can be an identifier or a send in case of named constructors.
    Expression name = popNode();
    TypeAnnotation type = popNode();
    Modifiers modifiers = popNode();
    NodeList typeVariables = popNode();
    pushNode(new FunctionDeclaration(new FunctionExpression(name, typeVariables,
        formals, body, type, modifiers, initializers, null, asyncModifier)));
  }

  @override
  void endVariablesDeclaration(int count, Token endToken) {
    // TODO(ahe): Pick one name for this concept, either
    // VariablesDeclaration or VariableDefinitions.
    NodeList variables = makeNodeList(count, null, endToken, ",");
    TypeAnnotation type = popNode();
    Modifiers modifiers = popNode();
    popNode();
    pushNode(new VariableDefinitions(type, modifiers, variables));
  }

  @override
  void endVariableInitializer(Token assignmentOperator) {
    Expression initializer = popNode();
    NodeList arguments =
        initializer == null ? null : new NodeList.singleton(initializer);
    Expression name = popNode();
    Operator op = new Operator(assignmentOperator);
    pushNode(new SendSet(null, name, op, arguments));
  }

  @override
  void endFieldInitializer(Token assignmentOperator, Token token) {
    endVariableInitializer(assignmentOperator);
  }

  @override
  void endIfStatement(Token ifToken, Token elseToken) {
    Statement elsePart = (elseToken == null) ? null : popNode();
    Statement thenPart = popNode();
    ParenthesizedExpression condition = popNode();
    pushNode(new If(condition, thenPart, elsePart, ifToken, elseToken));
  }

  @override
  void endForStatement(Token forKeyword, Token leftParen, Token leftSeparator,
      int updateExpressionCount, Token endToken) {
    Statement body = popNode();
    NodeList updates = makeNodeList(updateExpressionCount, null, null, ',');
    Statement condition = popNode();
    Node initializer = popNode();
    pushNode(new For(initializer, condition, updates, body, forKeyword));
  }

  @override
  void handleNoExpression(Token token) {
    pushNode(null);
  }

  @override
  void endDoWhileStatement(
      Token doKeyword, Token whileKeyword, Token endToken) {
    Expression condition = popNode();
    Statement body = popNode();
    pushNode(new DoWhile(body, condition, doKeyword, whileKeyword, endToken));
  }

  @override
  void endWhileStatement(Token whileKeyword, Token endToken) {
    Statement body = popNode();
    Expression condition = popNode();
    pushNode(new While(condition, body, whileKeyword));
  }

  @override
  void endBlock(int count, Token beginToken, Token endToken) {
    pushNode(new Block(makeNodeList(count, beginToken, endToken, null)));
  }

  void handleInvalidTopLevelBlock(Token token) {
    popNode(); // block
  }

  @override
  void handleThrowExpression(Token throwToken, Token endToken) {
    Expression expression = popNode();
    pushNode(new Throw(expression, throwToken, endToken));
  }

  @override
  void endAwaitExpression(Token awaitToken, Token endToken) {
    Expression expression = popNode();
    pushNode(new Await(awaitToken, expression));
  }

  @override
  void endRethrowStatement(Token throwToken, Token endToken) {
    pushNode(new Rethrow(throwToken, endToken));
    if (identical(throwToken.stringValue, 'throw')) {
      reporter.reportErrorMessage(reporter.spanFromToken(throwToken),
          MessageKind.MISSING_EXPRESSION_IN_THROW);
    }
  }

  @override
  void handleUnaryPrefixExpression(Token token) {
    pushNode(new Send.prefix(popNode(), new Operator(token)));
  }

  @override
  void handleSuperExpression(Token token, IdentifierContext context) {
    pushNode(new Identifier(token));
  }

  @override
  void handleThisExpression(Token token, IdentifierContext context) {
    pushNode(new Identifier(token));
  }

  void handleUnaryAssignmentExpression(Token token, bool isPrefix) {
    Node node = popNode();
    Send send = node.asSend();
    if (send == null) {
      reportNotAssignable(node);
    }
    if (!(send.isPropertyAccess || send.isIndex)) {
      reportNotAssignable(node);
    }
    if (send.asSendSet() != null) internalError(node: send);
    Node argument = null;
    if (send.isIndex) argument = send.arguments.head;
    Operator op = new Operator(token);

    if (isPrefix) {
      pushNode(new SendSet.prefix(
          send.receiver, send.selector, op, argument, send.isConditional));
    } else {
      pushNode(new SendSet.postfix(
          send.receiver, send.selector, op, argument, send.isConditional));
    }
  }

  @override
  void handleUnaryPostfixAssignmentExpression(Token token) {
    handleUnaryAssignmentExpression(token, false);
  }

  @override
  void handleUnaryPrefixAssignmentExpression(Token token) {
    handleUnaryAssignmentExpression(token, true);
  }

  @override
  void endInitializers(int count, Token beginToken, Token endToken) {
    pushNode(makeNodeList(count, beginToken, null, ','));
  }

  @override
  void handleNoInitializers() {
    pushNode(null);
  }

  @override
  void handleInvalidMember(Token endToken) {
    popNode(); // Discard metadata
    ++invalidMemberCount;
  }

  @override
  void endMember() {
    // TODO(sigmund): consider moving metadata into each declaration
    // element instead.
    Node node = popNode(); // member
    popNode(); // Discard metadata
    pushNode(node);
    super.endMember();
  }

  @override
  void endFields(int count, Token beginToken, Token endToken) {
    NodeList variables = makeNodeList(count, null, endToken, ",");
    TypeAnnotation type = popNode();
    Modifiers modifiers = popNode();
    pushNode(new VariableDefinitions(type, modifiers, variables));
  }

  @override
  void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
      Token varFinalOrConst, Token name) {
    Link<Node> modifiers = const Link<Node>();
    if (varFinalOrConst != null) {
      modifiers = modifiers.prepend(new Identifier(varFinalOrConst));
    }
    if (covariantToken != null) {
      modifiers = modifiers.prepend(new Identifier(covariantToken));
    }
    if (staticToken != null) {
      modifiers = modifiers.prepend(new Identifier(staticToken));
    }
    if (externalToken != null) {
      modifiers = modifiers.prepend(new Identifier(externalToken));
    }
    if (modifiers.isEmpty) {
      pushNode(Modifiers.EMPTY);
    } else {
      pushNode(new Modifiers(new NodeList(null, modifiers, null, ' ')));
    }
  }

  @override
  void endMethod(
      Token getOrSet, Token beginToken, Token beginParam, Token endToken) {
    Statement body = popNode();
    AsyncModifier asyncModifier = popNode();
    NodeList initializers = popNode();
    NodeList formalParameters = popNode();
    NodeList typeVariables = popNode();
    Expression name = popNode();
    TypeAnnotation returnType = popNode();
    Modifiers modifiers = popNode();
    pushNode(new FunctionExpression(name, typeVariables, formalParameters, body,
        returnType, modifiers, initializers, getOrSet, asyncModifier));
  }

  @override
  void handleLiteralMap(
      int count, Token beginToken, Token constKeyword, Token endToken) {
    NodeList entries = makeNodeList(count, beginToken, endToken, ',');
    NodeList typeArguments = popNode();
    pushNode(new LiteralMap(typeArguments, entries, constKeyword));
  }

  @override
  void endLiteralMapEntry(Token colon, Token endToken) {
    Expression value = popNode();
    Expression key = popNode();
    pushNode(new LiteralMapEntry(key, colon, value));
  }

  @override
  void handleLiteralList(
      int count, Token beginToken, Token constKeyword, Token endToken) {
    NodeList elements = makeNodeList(count, beginToken, endToken, ',');
    pushNode(new LiteralList(popNode(), elements, constKeyword));
  }

  @override
  void handleIndexedExpression(
      Token openSquareBracket, Token closeSquareBracket) {
    NodeList arguments =
        makeNodeList(1, openSquareBracket, closeSquareBracket, null);
    Node receiver = popNode();
    Token token = new Token(TokenType.INDEX, openSquareBracket.charOffset);
    Node selector = new Operator(token);
    pushNode(new Send(receiver, selector, arguments));
  }

  @override
  void endNewExpression(Token token) {
    NodeList arguments = popNode();
    Node name = popNode();
    pushNode(new NewExpression(token, new Send(null, name, arguments)));
  }

  @override
  void endConstExpression(Token token) {
    // [token] carries the 'const' information.
    endNewExpression(token);
  }

  @override
  void handleOperator(Token token) {
    pushNode(new Operator(token));
  }

  @override
  void handleSymbolVoid(Token token) {
    logEvent('SymbolVoid');
  }

  @override
  void handleOperatorName(Token operatorKeyword, Token token) {
    Operator op = new Operator(token);
    pushNode(new Send(new Identifier(operatorKeyword), op, null));
  }

  @override
  void handleInvalidOperatorName(Token operatorKeyword, Token token) {
    Operator op = new Operator(token);
    pushNode(new Send(new Identifier(operatorKeyword), op, null));
  }

  @override
  void handleNamedArgument(Token colon) {
    Expression expression = popNode();
    Identifier name = popNode();
    pushNode(new NamedArgument(name, colon, expression));
  }

  @override
  void endOptionalFormalParameters(
      int count, Token beginToken, Token endToken) {
    pushNode(makeNodeList(count, beginToken, endToken, ','));
  }

  @override
  void handleIdentifier(Token token, IdentifierContext context) {
    if (IdentifierContext.formalParameterDeclaration == context ||
        IdentifierContext.fieldInitializer == context) {
      var typeAnnotation = popNode();
      if (typeAnnotation is FunctionExpression) {
        pushNode(null); // Signal "no type" to endFormalParameter.
        pushNode(new FunctionExpression(
            new Identifier(token),
            typeAnnotation.typeVariables,
            typeAnnotation.parameters,
            null,
            typeAnnotation.returnType,
            typeAnnotation.modifiers,
            null,
            null,
            null));
        return;
      } else {
        pushNode(typeAnnotation);
      }
    } else if (context == IdentifierContext.enumValueDeclaration) {
      popNode();
    }
    pushNode(new Identifier(token));
  }

  @override
  void endFunctionTypedFormalParameter() {
    NodeList formals = popNode();
    TypeAnnotation returnType = popNode();
    NodeList typeVariables = popNode();
    pushNode(new FunctionExpression(null, typeVariables, formals, null,
        returnType, Modifiers.EMPTY, null, null, null));
  }

  @override
  void handleValuedFormalParameter(Token equals, Token token) {
    Expression defaultValue = popNode();
    Expression parameterName = popNode();
    pushNode(new SendSet(null, parameterName, new Operator(equals),
        new NodeList.singleton(defaultValue)));
  }

  @override
  void handleFormalParameterWithoutValue(Token token) {}

  @override
  void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
    Block finallyBlock = null;
    if (finallyKeyword != null) {
      finallyBlock = popNode();
    }
    NodeList catchBlocks = makeNodeList(catchCount, null, null, null);
    Block tryBlock = popNode();
    pushNode(new TryStatement(
        tryBlock, catchBlocks, finallyBlock, tryKeyword, finallyKeyword));
  }

  @override
  void handleCaseMatch(Token caseKeyword, Token colon) {
    pushNode(new CaseMatch(caseKeyword, popNode(), colon));
  }

  @override
  void handleCatchBlock(Token onKeyword, Token catchKeyword, Token comma) {
    Block block = popNode();
    NodeList formals = catchKeyword != null ? popNode() : null;
    TypeAnnotation type = onKeyword != null ? popNode() : null;
    pushNode(new CatchBlock(type, formals, block, onKeyword, catchKeyword));
  }

  @override
  void endSwitchStatement(Token switchKeyword, Token endToken) {
    NodeList cases = popNode();
    ParenthesizedExpression expression = popNode();
    pushNode(new SwitchStatement(expression, cases, switchKeyword));
  }

  @override
  void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
    Link<Node> caseNodes = const Link<Node>();
    while (caseCount > 0) {
      SwitchCase switchCase = popNode();
      caseNodes = caseNodes.prepend(switchCase);
      caseCount--;
    }
    pushNode(new NodeList(beginToken, caseNodes, endToken, null));
  }

  @override
  void endSwitchCase(
      int labelCount,
      int caseCount,
      Token defaultKeyword,
      Token colonAfterDefault,
      int statementCount,
      Token firstToken,
      Token endToken) {
    NodeList statements = makeNodeList(statementCount, null, null, null);
    NodeList labelsAndCases =
        makeNodeList(labelCount + caseCount, null, null, null);
    pushNode(
        new SwitchCase(labelsAndCases, defaultKeyword, statements, firstToken));
  }

  @override
  void handleBreakStatement(
      bool hasTarget, Token breakKeyword, Token endToken) {
    Identifier target = null;
    if (hasTarget) {
      target = popNode();
    }
    pushNode(new BreakStatement(target, breakKeyword, endToken));
  }

  @override
  void handleContinueStatement(
      bool hasTarget, Token continueKeyword, Token endToken) {
    Identifier target = null;
    if (hasTarget) {
      target = popNode();
    }
    pushNode(new ContinueStatement(target, continueKeyword, endToken));
  }

  @override
  void handleEmptyStatement(Token token) {
    pushNode(new EmptyStatement(token));
  }

  @override
  void endFactoryMethod(
      Token beginToken, Token factoryKeyword, Token endToken) {
    super.endFactoryMethod(beginToken, factoryKeyword, endToken);
    Statement body = popNode();
    AsyncModifier asyncModifier = popNode();
    NodeList formals = popNode();
    Node name = popNode();
    Modifiers modifiers = popNode();

    // The parser does not report `factory` as a modifier,
    // but NodeListener considers it to be a modifier.
    // We cannot simply add all tokens from beginToken to factoryToken
    // inclusive because there may be invalid tokens that the parser
    // has skipped and the factoryKeyword may itself be out of order.
    // Because modifiers may be out of order, and some code relies
    // on the order of the nodes in modifiers, we must insert the factory
    // keyword in the correct place by rebuilding the modifiers.
    int modifierCount = 0;
    Identifier factoryNode = new Identifier(factoryKeyword);
    modifiers.nodes.nodes.forEach((Node node) {
      if (factoryNode != null &&
          factoryNode.token.charOffset < node.getBeginToken().charOffset) {
        pushNode(factoryNode);
        ++modifierCount;
        factoryNode = null;
      }
      pushNode(node);
      ++modifierCount;
    });
    if (factoryNode != null) {
      pushNode(factoryNode);
      ++modifierCount;
    }
    handleModifiers(modifierCount);
    modifiers = popNode();

    pushNode(new FunctionExpression(
        name, null, formals, body, null, modifiers, null, null, asyncModifier));
  }

  @override
  void endForIn(Token awaitToken, Token forToken, Token leftParenthesis,
      Token inKeyword, Token endToken) {
    Statement body = popNode();
    Expression expression = popNode();
    Node declaredIdentifier = popNode();
    if (awaitToken == null) {
      pushNode(new SyncForIn(
          declaredIdentifier, expression, body, forToken, inKeyword));
    } else {
      pushNode(new AsyncForIn(declaredIdentifier, expression, body, awaitToken,
          forToken, inKeyword));
    }
  }

  @override
  void endMetadataStar(int count) {
    if (0 == count) {
      pushNode(null);
    } else {
      pushNode(makeNodeList(count, null, null, ' '));
    }
  }

  @override
  void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
    NodeList arguments = popNode();
    if (arguments == null) {
      // This is a constant expression.
      Identifier name;
      if (periodBeforeName != null) {
        name = popNode();
      }
      NodeList typeArguments = popNode();
      Node receiver = popNode();
      if (typeArguments != null) {
        receiver = new NominalTypeAnnotation(receiver, typeArguments);
        recoverableError(typeArguments, 'Type arguments are not allowed here.');
      } else {
        Identifier identifier = receiver.asIdentifier();
        Send send = receiver.asSend();
        if (identifier != null) {
          receiver = new Send(null, identifier);
        } else if (send == null) {
          internalError(node: receiver);
        }
      }
      Send send = receiver;
      if (name != null) {
        send = new Send(receiver, name);
      }
      pushNode(new Metadata(beginToken, send));
    } else {
      // This is a const constructor call.
      endConstructorReference(beginToken, periodBeforeName, endToken);
      Node constructor = popNode();
      pushNode(new Metadata(beginToken,
          new NewExpression(null, new Send(null, constructor, arguments))));
    }
  }

  @override
  void endAssert(Token assertKeyword, fasta.Assert kind, Token leftParenthesis,
      Token commaToken, Token semicolonToken) {
    Node message;
    Node condition;
    if (commaToken != null) {
      message = popNode();
    }
    condition = popNode();
    pushNode(new Assert(assertKeyword, condition, message, semicolonToken));
  }

  @override
  void endFunctionExpression(Token beginToken, Token token) {
    Statement body = popNode();
    AsyncModifier asyncModifier = popNode();
    NodeList formals = popNode();
    NodeList typeVariables = popNode();
    pushNode(new FunctionExpression(null, typeVariables, formals, body, null,
        Modifiers.EMPTY, null, null, asyncModifier));
  }

  @override
  void handleIsOperator(Token operator, Token not, Token endToken) {
    TypeAnnotation type = popNode();
    Expression expression = popNode();
    Node argument;
    if (not != null) {
      argument = new Send.prefix(type, new Operator(not));
    } else {
      argument = type;
    }

    NodeList arguments = new NodeList.singleton(argument);
    pushNode(new Send(expression, new Operator(operator), arguments));
  }

  @override
  void handleLabel(Token colon) {
    Identifier name = popNode();
    pushNode(new Label(name, colon));
  }

  @override
  void endLabeledStatement(int labelCount) {
    Statement statement = popNode();
    NodeList labels = makeNodeList(labelCount, null, null, null);
    pushNode(new LabeledStatement(labels, statement));
  }

  @override
  void endTypeVariable(Token token, Token extendsOrSuper) {
    inTypeVariable = false;
    NominalTypeAnnotation bound = popNode();
    Identifier name = popNode();
    // TODO(paulberry): type variable metadata should not be ignored.  See
    // dartbug.com/5841.
    popNode(); // Metadata
    pushNode(new TypeVariable(name, extendsOrSuper, bound));
    rejectBuiltInIdentifier(name);
  }

  @override
  void log(message) {
    reporter.log(message);
  }

  @override
  void handleInvalidFunctionBody(Token token) {
    if (!lastErrorWasNativeFunctionBody) {
      pushNode(null);
    }
    lastErrorWasNativeFunctionBody = false;
  }

  void internalError({Token token, Node node}) {
    // TODO(ahe): This should call reporter.internalError.
    Spannable spannable = (token == null) ? node : token;
    failedAt(spannable, 'Internal error in parser.');
  }
}
