// 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.

import 'dart:collection' show IterableMixin;

import '../common.dart';
import '../tokens/precedence_constants.dart' as Precedence show FUNCTION_INFO;
import '../tokens/token.dart' show BeginGroupToken, Token;
import '../tokens/token_constants.dart' as Tokens
    show IDENTIFIER_TOKEN, KEYWORD_TOKEN, PLUS_TOKEN;
import '../util/util.dart';
import '../util/characters.dart';
import '../resolution/secret_tree_element.dart'
    show NullTreeElementMixin, StoredTreeElementMixin;
import '../elements/elements.dart' show MetadataAnnotation;
import 'dartstring.dart';
import 'prettyprint.dart';
import 'unparser.dart';

abstract class Visitor<R> {
  const Visitor();

  R visitNode(Node node);

  R visitAssert(Assert node) => visitStatement(node);
  R visitAsyncForIn(AsyncForIn node) => visitForIn(node);
  R visitAsyncModifier(AsyncModifier node) => visitNode(node);
  R visitAwait(Await node) => visitExpression(node);
  R visitBlock(Block node) => visitStatement(node);
  R visitBreakStatement(BreakStatement node) => visitGotoStatement(node);
  R visitCascade(Cascade node) => visitExpression(node);
  R visitCascadeReceiver(CascadeReceiver node) => visitExpression(node);
  R visitCaseMatch(CaseMatch node) => visitNode(node);
  R visitCatchBlock(CatchBlock node) => visitNode(node);
  R visitClassNode(ClassNode node) => visitNode(node);
  R visitCombinator(Combinator node) => visitNode(node);
  R visitConditional(Conditional node) => visitExpression(node);
  R visitConditionalUri(ConditionalUri node) => visitNode(node);
  R visitContinueStatement(ContinueStatement node) => visitGotoStatement(node);
  R visitDottedName(DottedName node) => visitExpression(node);
  R visitDoWhile(DoWhile node) => visitLoop(node);
  R visitEmptyStatement(EmptyStatement node) => visitStatement(node);
  R visitEnum(Enum node) => visitNode(node);
  R visitExport(Export node) => visitLibraryDependency(node);
  R visitExpression(Expression node) => visitNode(node);
  R visitExpressionStatement(ExpressionStatement node) => visitStatement(node);
  R visitFor(For node) => visitLoop(node);
  R visitForIn(ForIn node) => visitLoop(node);
  R visitFunctionDeclaration(FunctionDeclaration node) => visitStatement(node);
  R visitFunctionExpression(FunctionExpression node) => visitExpression(node);
  R visitGotoStatement(GotoStatement node) => visitStatement(node);
  R visitIdentifier(Identifier node) => visitExpression(node);
  R visitImport(Import node) => visitLibraryDependency(node);
  R visitIf(If node) => visitStatement(node);
  R visitLabel(Label node) => visitNode(node);
  R visitLabeledStatement(LabeledStatement node) => visitStatement(node);
  R visitLibraryDependency(LibraryDependency node) => visitLibraryTag(node);
  R visitLibraryName(LibraryName node) => visitLibraryTag(node);
  R visitLibraryTag(LibraryTag node) => visitNode(node);
  R visitLiteral(Literal node) => visitExpression(node);
  R visitLiteralBool(LiteralBool node) => visitLiteral(node);
  R visitLiteralDouble(LiteralDouble node) => visitLiteral(node);
  R visitLiteralInt(LiteralInt node) => visitLiteral(node);
  R visitLiteralList(LiteralList node) => visitExpression(node);
  R visitLiteralMap(LiteralMap node) => visitExpression(node);
  R visitLiteralMapEntry(LiteralMapEntry node) => visitNode(node);
  R visitLiteralNull(LiteralNull node) => visitLiteral(node);
  R visitLiteralString(LiteralString node) => visitStringNode(node);
  R visitStringJuxtaposition(StringJuxtaposition node) => visitStringNode(node);
  R visitSyncForIn(SyncForIn node) => visitForIn(node);
  R visitLoop(Loop node) => visitStatement(node);
  R visitMetadata(Metadata node) => visitNode(node);
  R visitMixinApplication(MixinApplication node) => visitNode(node);
  R visitModifiers(Modifiers node) => visitNode(node);
  R visitNamedArgument(NamedArgument node) => visitExpression(node);
  R visitNamedMixinApplication(NamedMixinApplication node) {
    return visitMixinApplication(node);
  }

  R visitNewExpression(NewExpression node) => visitExpression(node);
  R visitNodeList(NodeList node) => visitNode(node);
  R visitOperator(Operator node) => visitIdentifier(node);
  R visitParenthesizedExpression(ParenthesizedExpression node) {
    return visitExpression(node);
  }

  R visitPart(Part node) => visitLibraryTag(node);
  R visitPartOf(PartOf node) => visitNode(node);
  R visitPostfix(Postfix node) => visitNodeList(node);
  R visitPrefix(Prefix node) => visitNodeList(node);
  R visitRedirectingFactoryBody(RedirectingFactoryBody node) {
    return visitStatement(node);
  }

  R visitRethrow(Rethrow node) => visitStatement(node);
  R visitReturn(Return node) => visitStatement(node);
  R visitSend(Send node) => visitExpression(node);
  R visitSendSet(SendSet node) => visitSend(node);
  R visitStatement(Statement node) => visitNode(node);
  R visitStringNode(StringNode node) => visitExpression(node);
  R visitStringInterpolation(StringInterpolation node) => visitStringNode(node);
  R visitStringInterpolationPart(StringInterpolationPart node) {
    return visitNode(node);
  }

  R visitSwitchCase(SwitchCase node) => visitNode(node);
  R visitSwitchStatement(SwitchStatement node) => visitStatement(node);
  R visitLiteralSymbol(LiteralSymbol node) => visitExpression(node);
  R visitThrow(Throw node) => visitExpression(node);
  R visitTryStatement(TryStatement node) => visitStatement(node);
  R visitTypeAnnotation(TypeAnnotation node) => visitNode(node);
  R visitTypedef(Typedef node) => visitNode(node);
  R visitTypeVariable(TypeVariable node) => visitNode(node);
  R visitVariableDefinitions(VariableDefinitions node) => visitStatement(node);
  R visitWhile(While node) => visitLoop(node);
  R visitYield(Yield node) => visitStatement(node);
}

/// Visitor for [Node]s that take an additional argument of type [A] and returns
/// a value of type [R].
abstract class Visitor1<R, A> {
  const Visitor1();

  R visitNode(Node node, A arg);

  R visitAssert(Assert node, A arg) => visitStatement(node, arg);
  R visitAsyncForIn(AsyncForIn node, A arg) => visitForIn(node, arg);
  R visitAsyncModifier(AsyncModifier node, A arg) => visitNode(node, arg);
  R visitAwait(Await node, A arg) => visitExpression(node, arg);
  R visitBlock(Block node, A arg) => visitStatement(node, arg);
  R visitBreakStatement(BreakStatement node, A arg) {
    return visitGotoStatement(node, arg);
  }

  R visitCascade(Cascade node, A arg) => visitExpression(node, arg);
  R visitCascadeReceiver(CascadeReceiver node, A arg) {
    return visitExpression(node, arg);
  }

  R visitCaseMatch(CaseMatch node, A arg) => visitNode(node, arg);
  R visitCatchBlock(CatchBlock node, A arg) => visitNode(node, arg);
  R visitClassNode(ClassNode node, A arg) => visitNode(node, arg);
  R visitCombinator(Combinator node, A arg) => visitNode(node, arg);
  R visitConditional(Conditional node, A arg) => visitExpression(node, arg);
  R visitConditionalUri(ConditionalUri node, A arg) {
    return visitNode(node, arg);
  }

  R visitContinueStatement(ContinueStatement node, A arg) {
    return visitGotoStatement(node, arg);
  }

  R visitDottedName(DottedName node, A arg) {
    return visitExpression(node, arg);
  }

  R visitDoWhile(DoWhile node, A arg) => visitLoop(node, arg);
  R visitEmptyStatement(EmptyStatement node, A arg) {
    return visitStatement(node, arg);
  }

  R visitEnum(Enum node, A arg) => visitNode(node, arg);
  R visitExport(Export node, A arg) => visitLibraryDependency(node, arg);
  R visitExpression(Expression node, A arg) => visitNode(node, arg);
  R visitExpressionStatement(ExpressionStatement node, A arg) {
    return visitStatement(node, arg);
  }

  R visitFor(For node, A arg) => visitLoop(node, arg);
  R visitForIn(ForIn node, A arg) => visitLoop(node, arg);
  R visitFunctionDeclaration(FunctionDeclaration node, A arg) {
    return visitStatement(node, arg);
  }

  R visitFunctionExpression(FunctionExpression node, A arg) {
    return visitExpression(node, arg);
  }

  R visitGotoStatement(GotoStatement node, A arg) {
    return visitStatement(node, arg);
  }

  R visitIdentifier(Identifier node, A arg) {
    return visitExpression(node, arg);
  }

  R visitImport(Import node, A arg) {
    return visitLibraryDependency(node, arg);
  }

  R visitIf(If node, A arg) => visitStatement(node, arg);
  R visitLabel(Label node, A arg) => visitNode(node, arg);
  R visitLabeledStatement(LabeledStatement node, A arg) {
    return visitStatement(node, arg);
  }

  R visitLibraryDependency(LibraryDependency node, A arg) {
    return visitLibraryTag(node, arg);
  }

  R visitLibraryName(LibraryName node, A arg) => visitLibraryTag(node, arg);
  R visitLibraryTag(LibraryTag node, A arg) => visitNode(node, arg);
  R visitLiteral(Literal node, A arg) => visitExpression(node, arg);
  R visitLiteralBool(LiteralBool node, A arg) => visitLiteral(node, arg);
  R visitLiteralDouble(LiteralDouble node, A arg) => visitLiteral(node, arg);
  R visitLiteralInt(LiteralInt node, A arg) => visitLiteral(node, arg);
  R visitLiteralList(LiteralList node, A arg) => visitExpression(node, arg);
  R visitLiteralMap(LiteralMap node, A arg) => visitExpression(node, arg);
  R visitLiteralMapEntry(LiteralMapEntry node, A arg) => visitNode(node, arg);
  R visitLiteralNull(LiteralNull node, A arg) => visitLiteral(node, arg);
  R visitLiteralString(LiteralString node, A arg) => visitStringNode(node, arg);
  R visitStringJuxtaposition(StringJuxtaposition node, A arg) {
    return visitStringNode(node, arg);
  }

  R visitSyncForIn(SyncForIn node, A arg) => visitForIn(node, arg);
  R visitLoop(Loop node, A arg) => visitStatement(node, arg);
  R visitMetadata(Metadata node, A arg) => visitNode(node, arg);
  R visitMixinApplication(MixinApplication node, A arg) => visitNode(node, arg);
  R visitModifiers(Modifiers node, A arg) => visitNode(node, arg);
  R visitNamedArgument(NamedArgument node, A arg) => visitExpression(node, arg);
  R visitNamedMixinApplication(NamedMixinApplication node, A arg) {
    return visitMixinApplication(node, arg);
  }

  R visitNewExpression(NewExpression node, A arg) => visitExpression(node, arg);
  R visitNodeList(NodeList node, A arg) => visitNode(node, arg);
  R visitOperator(Operator node, A arg) => visitIdentifier(node, arg);
  R visitParenthesizedExpression(ParenthesizedExpression node, A arg) {
    return visitExpression(node, arg);
  }

  R visitPart(Part node, A arg) => visitLibraryTag(node, arg);
  R visitPartOf(PartOf node, A arg) => visitNode(node, arg);
  R visitPostfix(Postfix node, A arg) => visitNodeList(node, arg);
  R visitPrefix(Prefix node, A arg) => visitNodeList(node, arg);
  R visitRedirectingFactoryBody(RedirectingFactoryBody node, A arg) {
    return visitStatement(node, arg);
  }

  R visitRethrow(Rethrow node, A arg) => visitStatement(node, arg);
  R visitReturn(Return node, A arg) => visitStatement(node, arg);
  R visitSend(Send node, A arg) => visitExpression(node, arg);
  R visitSendSet(SendSet node, A arg) => visitSend(node, arg);
  R visitStatement(Statement node, A arg) => visitNode(node, arg);
  R visitStringNode(StringNode node, A arg) => visitExpression(node, arg);
  R visitStringInterpolation(StringInterpolation node, A arg) {
    return visitStringNode(node, arg);
  }

  R visitStringInterpolationPart(StringInterpolationPart node, A arg) {
    return visitNode(node, arg);
  }

  R visitSwitchCase(SwitchCase node, A arg) => visitNode(node, arg);
  R visitSwitchStatement(SwitchStatement node, A arg) {
    return visitStatement(node, arg);
  }

  R visitLiteralSymbol(LiteralSymbol node, A arg) => visitExpression(node, arg);
  R visitThrow(Throw node, A arg) => visitExpression(node, arg);
  R visitTryStatement(TryStatement node, A arg) => visitStatement(node, arg);
  R visitTypeAnnotation(TypeAnnotation node, A arg) => visitNode(node, arg);
  R visitTypedef(Typedef node, A arg) => visitNode(node, arg);
  R visitTypeVariable(TypeVariable node, A arg) => visitNode(node, arg);
  R visitVariableDefinitions(VariableDefinitions node, A arg) {
    return visitStatement(node, arg);
  }

  R visitWhile(While node, A arg) => visitLoop(node, arg);
  R visitYield(Yield node, A arg) => visitStatement(node, arg);
}

Token firstBeginToken(Node first, Node second) {
  Token token = null;
  if (first != null) {
    token = first.getBeginToken();
  }
  if (token == null && second != null) {
    // [token] might be null even when [first] is not, e.g. for empty Modifiers.
    token = second.getBeginToken();
  }
  return token;
}

/**
 * A node in a syntax tree.
 *
 * The abstract part of "abstract syntax tree" is invalidated when
 * supporting tools such as code formatting. These tools need concrete
 * syntax such as parentheses and no constant folding.
 *
 * We support these tools by storing additional references back to the
 * token stream. These references are stored in fields ending with
 * "Token".
 */
abstract class Node extends NullTreeElementMixin implements Spannable {
  final int hashCode;
  static int _HASH_COUNTER = 0;

  Node() : hashCode = ++_HASH_COUNTER;

  accept(Visitor visitor);

  accept1(Visitor1 visitor, arg);

  visitChildren(Visitor visitor);

  visitChildren1(Visitor1 visitor, arg);

  /**
   * Returns this node unparsed to Dart source string.
   */
  toString() => unparse(this);

  /**
   * Returns Xml-like tree representation of this node.
   */
  toDebugString() {
    return PrettyPrinter.prettyPrint(this);
  }

  String getObjectDescription() => super.toString();

  Token getBeginToken();

  /// Returns the token that ends the 'prefix' of this node.
  ///
  /// For instance the end of the parameters in a [FunctionExpression] or the
  /// last token before the start of a class body for a [ClassNode].
  Token getPrefixEndToken() => getEndToken();

  Token getEndToken();

  Assert asAssert() => null;
  AsyncModifier asAsyncModifier() => null;
  Await asAwait() => null;
  Block asBlock() => null;
  BreakStatement asBreakStatement() => null;
  Cascade asCascade() => null;
  CascadeReceiver asCascadeReceiver() => null;
  CaseMatch asCaseMatch() => null;
  CatchBlock asCatchBlock() => null;
  ClassNode asClassNode() => null;
  Combinator asCombinator() => null;
  Conditional asConditional() => null;
  ConditionalUri asConditionalUri() => null;
  ContinueStatement asContinueStatement() => null;
  DottedName asDottedName() => null;
  DoWhile asDoWhile() => null;
  EmptyStatement asEmptyStatement() => null;
  Enum asEnum() => null;
  ErrorExpression asErrorExpression() => null;
  Export asExport() => null;
  Expression asExpression() => null;
  ExpressionStatement asExpressionStatement() => null;
  For asFor() => null;
  SyncForIn asSyncForIn() => null;
  AsyncForIn asAsyncForIn() => null;
  ForIn asForIn() => null;
  FunctionDeclaration asFunctionDeclaration() => null;
  FunctionExpression asFunctionExpression() => null;
  Identifier asIdentifier() => null;
  If asIf() => null;
  Import asImport() => null;
  Label asLabel() => null;
  LabeledStatement asLabeledStatement() => null;
  LibraryName asLibraryName() => null;
  LibraryDependency asLibraryDependency() => null;
  LiteralBool asLiteralBool() => null;
  LiteralDouble asLiteralDouble() => null;
  LiteralInt asLiteralInt() => null;
  LiteralList asLiteralList() => null;
  LiteralMap asLiteralMap() => null;
  LiteralMapEntry asLiteralMapEntry() => null;
  LiteralNull asLiteralNull() => null;
  LiteralString asLiteralString() => null;
  LiteralSymbol asLiteralSymbol() => null;
  Metadata asMetadata() => null;
  MixinApplication asMixinApplication() => null;
  Modifiers asModifiers() => null;
  NamedArgument asNamedArgument() => null;
  NamedMixinApplication asNamedMixinApplication() => null;
  NewExpression asNewExpression() => null;
  NodeList asNodeList() => null;
  Operator asOperator() => null;
  ParenthesizedExpression asParenthesizedExpression() => null;
  Part asPart() => null;
  PartOf asPartOf() => null;
  RedirectingFactoryBody asRedirectingFactoryBody() => null;
  Rethrow asRethrow() => null;
  Return asReturn() => null;
  Send asSend() => null;
  SendSet asSendSet() => null;
  Statement asStatement() => null;
  StringInterpolation asStringInterpolation() => null;
  StringInterpolationPart asStringInterpolationPart() => null;
  StringJuxtaposition asStringJuxtaposition() => null;
  StringNode asStringNode() => null;
  SwitchCase asSwitchCase() => null;
  SwitchStatement asSwitchStatement() => null;
  Throw asThrow() => null;
  TryStatement asTryStatement() => null;
  TypeAnnotation asTypeAnnotation() => null;
  TypeVariable asTypeVariable() => null;
  Typedef asTypedef() => null;
  VariableDefinitions asVariableDefinitions() => null;
  While asWhile() => null;
  Yield asYield() => null;

  bool isValidBreakTarget() => false;
  bool isValidContinueTarget() => false;
  bool isThis() => false;
  bool isSuper() => false;

  bool get isErroneous => false;
}

class ClassNode extends Node {
  final Modifiers modifiers;
  final Identifier name;
  final Node superclass;
  final NodeList interfaces;
  final NodeList typeParameters;
  final NodeList body;

  final Token beginToken;
  final Token extendsKeyword;
  final Token endToken;

  ClassNode(
      this.modifiers,
      this.name,
      this.typeParameters,
      this.superclass,
      this.interfaces,
      this.beginToken,
      this.extendsKeyword,
      this.body,
      this.endToken);

  ClassNode asClassNode() => this;

  accept(Visitor visitor) => visitor.visitClassNode(this);

  accept1(Visitor1 visitor, arg) => visitor.visitClassNode(this, arg);

  visitChildren(Visitor visitor) {
    if (name != null) name.accept(visitor);
    if (typeParameters != null) typeParameters.accept(visitor);
    if (superclass != null) superclass.accept(visitor);
    if (interfaces != null) interfaces.accept(visitor);
    if (body != null) body.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (name != null) name.accept1(visitor, arg);
    if (typeParameters != null) typeParameters.accept1(visitor, arg);
    if (superclass != null) superclass.accept1(visitor, arg);
    if (interfaces != null) interfaces.accept1(visitor, arg);
    if (body != null) body.accept1(visitor, arg);
  }

  Token getBeginToken() => beginToken;

  @override
  Token getPrefixEndToken() {
    Token token;
    if (interfaces != null) {
      token = interfaces.getEndToken();
    }
    if (token == null && superclass != null) {
      token = superclass.getEndToken();
    }
    if (token == null && typeParameters != null) {
      token == typeParameters.getEndToken();
    }
    if (token == null) {
      token = name.getEndToken();
    }
    assert(invariant(beginToken, token != null));
    return token;
  }

  Token getEndToken() => endToken;
}

class MixinApplication extends Node {
  final TypeAnnotation superclass;
  final NodeList mixins;

  MixinApplication(this.superclass, this.mixins);

  MixinApplication asMixinApplication() => this;

  accept(Visitor visitor) => visitor.visitMixinApplication(this);

  accept1(Visitor1 visitor, arg) => visitor.visitMixinApplication(this, arg);

  visitChildren(Visitor visitor) {
    if (superclass != null) superclass.accept(visitor);
    if (mixins != null) mixins.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (superclass != null) superclass.accept1(visitor, arg);
    if (mixins != null) mixins.accept1(visitor, arg);
  }

  Token getBeginToken() => superclass.getBeginToken();
  Token getEndToken() => mixins.getEndToken();
}

// TODO(kasperl): Let this share some structure with the typedef for function
// type aliases?
class NamedMixinApplication extends Node implements MixinApplication {
  final Identifier name;
  final NodeList typeParameters;

  final Modifiers modifiers;
  final MixinApplication mixinApplication;
  final NodeList interfaces;

  final Token classKeyword;
  final Token endToken;

  NamedMixinApplication(this.name, this.typeParameters, this.modifiers,
      this.mixinApplication, this.interfaces, this.classKeyword, this.endToken);

  TypeAnnotation get superclass => mixinApplication.superclass;
  NodeList get mixins => mixinApplication.mixins;

  MixinApplication asMixinApplication() => this;
  NamedMixinApplication asNamedMixinApplication() => this;

  accept(Visitor visitor) => visitor.visitNamedMixinApplication(this);

  accept1(Visitor1 visitor, arg) {
    return visitor.visitNamedMixinApplication(this, arg);
  }

  visitChildren(Visitor visitor) {
    name.accept(visitor);
    if (typeParameters != null) typeParameters.accept(visitor);
    if (modifiers != null) modifiers.accept(visitor);
    if (interfaces != null) interfaces.accept(visitor);
    mixinApplication.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    name.accept1(visitor, arg);
    if (typeParameters != null) typeParameters.accept1(visitor, arg);
    if (modifiers != null) modifiers.accept1(visitor, arg);
    if (interfaces != null) interfaces.accept1(visitor, arg);
    mixinApplication.accept1(visitor, arg);
  }

  Token getBeginToken() => classKeyword;
  Token getEndToken() => endToken;
}

abstract class Expression extends Node {
  Expression();

  Expression asExpression() => this;
}

abstract class Statement extends Node {
  Statement();

  Statement asStatement() => this;

  bool isValidBreakTarget() => true;
}

/// Erroneous expression that behaves as a literal null.
class ErrorExpression extends LiteralNull {
  ErrorExpression(token) : super(token);

  ErrorExpression asErrorExpression() => this;

  bool get isErroneous => true;
}

/**
 * A message send aka method invocation. In Dart, most operations can
 * (and should) be considered as message sends. Getters and setters
 * are just methods with a special syntax. Consequently, we model
 * property access, assignment, operators, and method calls with this
 * one node.
 */
class Send extends Expression with StoredTreeElementMixin {
  final Node receiver;
  final Node selector;
  final NodeList argumentsNode;

  /// Whether this is a conditinal send of the form `a?.b`.
  final bool isConditional;

  Link<Node> get arguments => argumentsNode.nodes;

  Send(
      [this.receiver,
      this.selector,
      this.argumentsNode,
      this.isConditional = false]);
  Send.postfix(this.receiver, this.selector,
      [Node argument = null, this.isConditional = false])
      : argumentsNode = (argument == null)
            ? new Postfix()
            : new Postfix.singleton(argument);
  Send.prefix(this.receiver, this.selector,
      [Node argument = null, this.isConditional = false])
      : argumentsNode =
            (argument == null) ? new Prefix() : new Prefix.singleton(argument);

  Send asSend() => this;

  accept(Visitor visitor) => visitor.visitSend(this);

  accept1(Visitor1 visitor, arg) => visitor.visitSend(this, arg);

  visitChildren(Visitor visitor) {
    if (receiver != null) receiver.accept(visitor);
    if (selector != null) selector.accept(visitor);
    if (argumentsNode != null) argumentsNode.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (receiver != null) receiver.accept1(visitor, arg);
    if (selector != null) selector.accept1(visitor, arg);
    if (argumentsNode != null) argumentsNode.accept1(visitor, arg);
  }

  int argumentCount() {
    return (argumentsNode == null) ? -1 : argumentsNode.slowLength();
  }

  bool get isSuperCall {
    return receiver != null && receiver.isSuper();
  }

  bool get isOperator => selector is Operator;
  bool get isPropertyAccess => argumentsNode == null;
  bool get isFunctionObjectInvocation => selector == null;
  bool get isPrefix => argumentsNode is Prefix;
  bool get isPostfix => argumentsNode is Postfix;
  bool get isCall => !isOperator && !isPropertyAccess;
  bool get isIndex =>
      isOperator && identical(selector.asOperator().source, '[]');
  bool get isLogicalAnd =>
      isOperator && identical(selector.asOperator().source, '&&');
  bool get isLogicalOr =>
      isOperator && identical(selector.asOperator().source, '||');
  bool get isIfNull =>
      isOperator && identical(selector.asOperator().source, '??');

  bool get isTypeCast {
    return isOperator && identical(selector.asOperator().source, 'as');
  }

  bool get isTypeTest {
    return isOperator && identical(selector.asOperator().source, 'is');
  }

  bool get isIsNotCheck {
    return isTypeTest && arguments.head.asSend() != null;
  }

  TypeAnnotation get typeAnnotationFromIsCheckOrCast {
    assert(isOperator);
    assert(identical(selector.asOperator().source, 'is') ||
        identical(selector.asOperator().source, 'as'));
    return isIsNotCheck ? arguments.head.asSend().receiver : arguments.head;
  }

  Token getBeginToken() {
    if (isPrefix && !isIndex) return selector.getBeginToken();
    return firstBeginToken(receiver, selector);
  }

  Token getEndToken() {
    if (isPrefix) {
      if (receiver != null) return receiver.getEndToken();
      if (selector != null) return selector.getEndToken();
      return null;
    }
    if (!isPostfix && argumentsNode != null) {
      Token token = argumentsNode.getEndToken();
      if (token != null) return token;
    }
    if (selector != null) return selector.getEndToken();
    return getBeginToken();
  }

  Send copyWithReceiver(Node newReceiver, bool isConditional) {
    assert(receiver == null);
    return new Send(newReceiver, selector, argumentsNode, isConditional);
  }
}

class Postfix extends NodeList {
  Postfix() : super(null, const Link<Node>());
  Postfix.singleton(Node argument) : super.singleton(argument);
}

class Prefix extends NodeList {
  Prefix() : super(null, const Link<Node>());
  Prefix.singleton(Node argument) : super.singleton(argument);
}

class SendSet extends Send {
  final Operator assignmentOperator;
  SendSet(receiver, selector, this.assignmentOperator, argumentsNode,
      [bool isConditional = false])
      : super(receiver, selector, argumentsNode, isConditional);
  SendSet.postfix(receiver, selector, this.assignmentOperator,
      [Node argument = null, bool isConditional = false])
      : super.postfix(receiver, selector, argument, isConditional);
  SendSet.prefix(receiver, selector, this.assignmentOperator,
      [Node argument = null, bool isConditional = false])
      : super.prefix(receiver, selector, argument, isConditional);

  SendSet asSendSet() => this;

  accept(Visitor visitor) => visitor.visitSendSet(this);

  accept1(Visitor1 visitor, arg) => visitor.visitSendSet(this, arg);

  visitChildren(Visitor visitor) {
    super.visitChildren(visitor);
    if (assignmentOperator != null) assignmentOperator.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    super.visitChildren1(visitor, arg);
    if (assignmentOperator != null) assignmentOperator.accept1(visitor, arg);
  }

  /// `true` if this send is not a simple assignment.
  bool get isComplex => !identical(assignmentOperator.source, '=');

  /// Whether this is an if-null assignment of the form `a ??= b`.
  bool get isIfNullAssignment => identical(assignmentOperator.source, '??=');

  Send copyWithReceiver(Node newReceiver, bool isConditional) {
    assert(receiver == null);
    return new SendSet(newReceiver, selector, assignmentOperator, argumentsNode,
        isConditional);
  }

  Token getBeginToken() {
    if (isPrefix) return assignmentOperator.getBeginToken();
    return super.getBeginToken();
  }

  Token getEndToken() {
    if (isPostfix) return assignmentOperator.getEndToken();
    return super.getEndToken();
  }
}

class NewExpression extends Expression {
  /** The token NEW or CONST or `null` for metadata */
  final Token newToken;

  // Note: we expect that send.receiver is null.
  final Send send;

  NewExpression([this.newToken, this.send]);

  NewExpression asNewExpression() => this;

  accept(Visitor visitor) => visitor.visitNewExpression(this);

  accept1(Visitor1 visitor, arg) => visitor.visitNewExpression(this, arg);

  visitChildren(Visitor visitor) {
    if (send != null) send.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (send != null) send.accept1(visitor, arg);
  }

  bool get isConst {
    return newToken == null || identical(newToken.stringValue, 'const');
  }

  Token getBeginToken() => newToken != null ? newToken : send.getBeginToken();

  Token getEndToken() => send.getEndToken();
}

class NodeList extends Node with IterableMixin<Node> {
  final Link<Node> nodes;
  final Token beginToken;
  final Token endToken;
  final String delimiter;
  bool get isEmpty => nodes.isEmpty;

  NodeList([this.beginToken, this.nodes, this.endToken, this.delimiter]);

  Iterator<Node> get iterator => nodes.iterator;

  NodeList.singleton(Node node) : this(null, const Link<Node>().prepend(node));
  NodeList.empty() : this(null, const Link<Node>());

  NodeList asNodeList() => this;

  // Override [IterableMixin.toString] with same code as [Node.toString].
  toString() => unparse(this);

  get length {
    throw new UnsupportedError('use slowLength() instead of get:length');
  }

  int slowLength() {
    int result = 0;
    for (Link<Node> cursor = nodes; !cursor.isEmpty; cursor = cursor.tail) {
      result++;
    }
    return result;
  }

  accept(Visitor visitor) => visitor.visitNodeList(this);

  accept1(Visitor1 visitor, arg) => visitor.visitNodeList(this, arg);

  visitChildren(Visitor visitor) {
    if (nodes == null) return;
    for (Link<Node> link = nodes; !link.isEmpty; link = link.tail) {
      if (link.head != null) link.head.accept(visitor);
    }
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (nodes == null) return;
    for (Link<Node> link = nodes; !link.isEmpty; link = link.tail) {
      if (link.head != null) link.head.accept1(visitor, arg);
    }
  }

  Token getBeginToken() {
    if (beginToken != null) return beginToken;
    if (nodes != null) {
      for (Link<Node> link = nodes; !link.isEmpty; link = link.tail) {
        if (link.head.getBeginToken() != null) {
          return link.head.getBeginToken();
        }
        if (link.head.getEndToken() != null) {
          return link.head.getEndToken();
        }
      }
    }
    return endToken;
  }

  Token getEndToken() {
    if (endToken != null) return endToken;
    if (nodes != null) {
      Link<Node> link = nodes;
      if (link.isEmpty) return beginToken;
      while (!link.tail.isEmpty) link = link.tail;
      Node lastNode = link.head;
      if (lastNode != null) {
        if (lastNode.getEndToken() != null) return lastNode.getEndToken();
        if (lastNode.getBeginToken() != null) return lastNode.getBeginToken();
      }
    }
    return beginToken;
  }
}

class Block extends Statement {
  final NodeList statements;

  Block(this.statements);

  Block asBlock() => this;

  accept(Visitor visitor) => visitor.visitBlock(this);

  accept1(Visitor1 visitor, arg) => visitor.visitBlock(this, arg);

  visitChildren(Visitor visitor) {
    if (statements != null) statements.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (statements != null) statements.accept1(visitor, arg);
  }

  Token getBeginToken() => statements.getBeginToken();

  Token getEndToken() => statements.getEndToken();
}

class If extends Statement {
  final ParenthesizedExpression condition;
  final Statement thenPart;
  final Statement elsePart;

  final Token ifToken;
  final Token elseToken;

  If(this.condition, this.thenPart, this.elsePart, this.ifToken,
      this.elseToken);

  If asIf() => this;

  bool get hasElsePart => elsePart != null;

  accept(Visitor visitor) => visitor.visitIf(this);

  accept1(Visitor1 visitor, arg) => visitor.visitIf(this, arg);

  visitChildren(Visitor visitor) {
    if (condition != null) condition.accept(visitor);
    if (thenPart != null) thenPart.accept(visitor);
    if (elsePart != null) elsePart.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (condition != null) condition.accept1(visitor, arg);
    if (thenPart != null) thenPart.accept1(visitor, arg);
    if (elsePart != null) elsePart.accept1(visitor, arg);
  }

  Token getBeginToken() => ifToken;

  Token getEndToken() {
    if (elsePart == null) return thenPart.getEndToken();
    return elsePart.getEndToken();
  }
}

class Conditional extends Expression {
  final Expression condition;
  final Expression thenExpression;
  final Expression elseExpression;

  final Token questionToken;
  final Token colonToken;

  Conditional(this.condition, this.thenExpression, this.elseExpression,
      this.questionToken, this.colonToken);

  Conditional asConditional() => this;

  accept(Visitor visitor) => visitor.visitConditional(this);

  accept1(Visitor1 visitor, arg) => visitor.visitConditional(this, arg);

  visitChildren(Visitor visitor) {
    condition.accept(visitor);
    thenExpression.accept(visitor);
    elseExpression.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    condition.accept1(visitor, arg);
    thenExpression.accept1(visitor, arg);
    elseExpression.accept1(visitor, arg);
  }

  Token getBeginToken() => condition.getBeginToken();

  Token getEndToken() => elseExpression.getEndToken();
}

class For extends Loop {
  /** Either a variable declaration or an expression. */
  final Node initializer;
  /** Either an expression statement or an empty statement. */
  final Statement conditionStatement;
  final NodeList update;

  final Token forToken;

  For(this.initializer, this.conditionStatement, this.update, body,
      this.forToken)
      : super(body);

  For asFor() => this;

  Expression get condition {
    ExpressionStatement expressionStatement =
        conditionStatement.asExpressionStatement();
    if (expressionStatement != null) {
      return expressionStatement.expression;
    } else {
      return null;
    }
  }

  accept(Visitor visitor) => visitor.visitFor(this);

  accept1(Visitor1 visitor, arg) => visitor.visitFor(this, arg);

  visitChildren(Visitor visitor) {
    if (initializer != null) initializer.accept(visitor);
    if (conditionStatement != null) conditionStatement.accept(visitor);
    if (update != null) update.accept(visitor);
    if (body != null) body.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (initializer != null) initializer.accept1(visitor, arg);
    if (conditionStatement != null) conditionStatement.accept1(visitor, arg);
    if (update != null) update.accept1(visitor, arg);
    if (body != null) body.accept1(visitor, arg);
  }

  Token getBeginToken() => forToken;

  Token getEndToken() {
    return body.getEndToken();
  }
}

class FunctionDeclaration extends Statement {
  final FunctionExpression function;

  FunctionDeclaration(this.function);

  FunctionDeclaration asFunctionDeclaration() => this;

  accept(Visitor visitor) => visitor.visitFunctionDeclaration(this);

  accept1(Visitor1 visitor, arg) => visitor.visitFunctionDeclaration(this, arg);

  visitChildren(Visitor visitor) => function.accept(visitor);

  visitChildren1(Visitor1 visitor, arg) => function.accept1(visitor, arg);

  Token getBeginToken() => function.getBeginToken();

  @override
  Token getPrefixEndToken() => function.getPrefixEndToken();

  Token getEndToken() => function.getEndToken();
}

/// Node representing the method implementation modifiers `sync*`, `async`, and
/// `async*` or the invalid modifier `sync`.
class AsyncModifier extends Node {
  /// The `async` or `sync` token.
  final Token asyncToken;

  /// The `*` token.
  final Token starToken;

  AsyncModifier(this.asyncToken, this.starToken);

  AsyncModifier asAsyncModifier() => this;

  accept(Visitor visitor) => visitor.visitAsyncModifier(this);

  accept1(Visitor1 visitor, arg) => visitor.visitAsyncModifier(this, arg);

  visitChildren(Visitor visitor) {}

  visitChildren1(Visitor1 visitor, arg) {}

  Token getBeginToken() => asyncToken;

  Token getEndToken() => starToken != null ? starToken : asyncToken;

  /// Is `true` if this modifier is either `async` or `async*`.
  bool get isAsynchronous => asyncToken.value == 'async';

  /// Is `true` if this modifier is either `sync*` or `async*`.
  bool get isYielding => starToken != null;
}

class FunctionExpression extends Expression with StoredTreeElementMixin {
  final Node name;

  /**
   * List of VariableDefinitions or NodeList.
   *
   * A NodeList can only occur at the end and holds named parameters.
   */
  final NodeList parameters;

  final Statement body;
  final TypeAnnotation returnType;
  final Modifiers modifiers;
  final NodeList initializers;

  final Token getOrSet;
  final AsyncModifier asyncModifier;

  FunctionExpression(this.name, this.parameters, this.body, this.returnType,
      this.modifiers, this.initializers, this.getOrSet, this.asyncModifier) {
    assert(modifiers != null);
  }

  FunctionExpression asFunctionExpression() => this;

  accept(Visitor visitor) => visitor.visitFunctionExpression(this);

  accept1(Visitor1 visitor, arg) => visitor.visitFunctionExpression(this, arg);

  bool get isRedirectingFactory {
    return body != null && body.asRedirectingFactoryBody() != null;
  }

  visitChildren(Visitor visitor) {
    if (modifiers != null) modifiers.accept(visitor);
    if (returnType != null) returnType.accept(visitor);
    if (name != null) name.accept(visitor);
    if (parameters != null) parameters.accept(visitor);
    if (initializers != null) initializers.accept(visitor);
    if (asyncModifier != null) asyncModifier.accept(visitor);
    if (body != null) body.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (modifiers != null) modifiers.accept1(visitor, arg);
    if (returnType != null) returnType.accept1(visitor, arg);
    if (name != null) name.accept1(visitor, arg);
    if (parameters != null) parameters.accept1(visitor, arg);
    if (initializers != null) initializers.accept1(visitor, arg);
    if (asyncModifier != null) asyncModifier.accept1(visitor, arg);
    if (body != null) body.accept1(visitor, arg);
  }

  bool get hasBody => body.asEmptyStatement() == null;

  bool get hasEmptyBody {
    Block block = body.asBlock();
    if (block == null) return false;
    return block.statements.isEmpty;
  }

  Token getBeginToken() {
    Token token = firstBeginToken(modifiers, returnType);
    if (token != null) return token;
    if (getOrSet != null) return getOrSet;
    return firstBeginToken(name, parameters);
  }

  @override
  Token getPrefixEndToken() {
    return parameters != null ? parameters.getEndToken() : name.getEndToken();
  }

  Token getEndToken() {
    Token token = (body == null) ? null : body.getEndToken();
    token = (token == null) ? parameters.getEndToken() : token;
    return (token == null) ? name.getEndToken() : token;
  }
}

typedef void DecodeErrorHandler(Token token, var error);

abstract class Literal<T> extends Expression {
  final Token token;
  final DecodeErrorHandler handler;

  Literal(Token this.token, DecodeErrorHandler this.handler);

  T get value;

  visitChildren(Visitor visitor) {}

  visitChildren1(Visitor1 visitor, arg) {}

  Token getBeginToken() => token;

  Token getEndToken() => token;
}

class LiteralInt extends Literal<int> {
  LiteralInt(Token token, DecodeErrorHandler handler) : super(token, handler);

  LiteralInt asLiteralInt() => this;

  int get value {
    try {
      Token valueToken = token;
      if (identical(valueToken.kind, Tokens.PLUS_TOKEN)) {
        valueToken = valueToken.next;
      }
      return int.parse(valueToken.value);
    } on FormatException catch (ex) {
      (this.handler)(token, ex);
    }
  }

  accept(Visitor visitor) => visitor.visitLiteralInt(this);

  accept1(Visitor1 visitor, arg) => visitor.visitLiteralInt(this, arg);
}

class LiteralDouble extends Literal<double> {
  LiteralDouble(Token token, DecodeErrorHandler handler)
      : super(token, handler);

  LiteralDouble asLiteralDouble() => this;

  double get value {
    try {
      Token valueToken = token;
      if (identical(valueToken.kind, Tokens.PLUS_TOKEN)) {
        valueToken = valueToken.next;
      }
      return double.parse(valueToken.value);
    } on FormatException catch (ex) {
      (this.handler)(token, ex);
    }
  }

  accept(Visitor visitor) => visitor.visitLiteralDouble(this);

  accept1(Visitor1 visitor, arg) => visitor.visitLiteralDouble(this, arg);
}

class LiteralBool extends Literal<bool> {
  LiteralBool(Token token, DecodeErrorHandler handler) : super(token, handler);

  LiteralBool asLiteralBool() => this;

  bool get value {
    if (identical(token.stringValue, 'true')) return true;
    if (identical(token.stringValue, 'false')) return false;
    (this.handler)(token, "not a bool ${token.value}");
    throw false;
  }

  accept(Visitor visitor) => visitor.visitLiteralBool(this);

  accept1(Visitor1 visitor, arg) => visitor.visitLiteralBool(this, arg);
}

class StringQuoting {
  /// Cache of common quotings.
  static const List<StringQuoting> _mapping = const <StringQuoting>[
    const StringQuoting($SQ, raw: false, leftQuoteLength: 1),
    const StringQuoting($SQ, raw: true, leftQuoteLength: 1),
    const StringQuoting($DQ, raw: false, leftQuoteLength: 1),
    const StringQuoting($DQ, raw: true, leftQuoteLength: 1),
    // No string quotes with 2 characters.
    null,
    null,
    null,
    null,
    // Multiline quotings.
    const StringQuoting($SQ, raw: false, leftQuoteLength: 3),
    const StringQuoting($SQ, raw: true, leftQuoteLength: 3),
    const StringQuoting($DQ, raw: false, leftQuoteLength: 3),
    const StringQuoting($DQ, raw: true, leftQuoteLength: 3),
    // Leading single whitespace or espaped newline.
    const StringQuoting($SQ, raw: false, leftQuoteLength: 4),
    const StringQuoting($SQ, raw: true, leftQuoteLength: 4),
    const StringQuoting($DQ, raw: false, leftQuoteLength: 4),
    const StringQuoting($DQ, raw: true, leftQuoteLength: 4),
    // Other combinations of leading whitespace and/or escaped newline.
    const StringQuoting($SQ, raw: false, leftQuoteLength: 5),
    const StringQuoting($SQ, raw: true, leftQuoteLength: 5),
    const StringQuoting($DQ, raw: false, leftQuoteLength: 5),
    const StringQuoting($DQ, raw: true, leftQuoteLength: 5),
    const StringQuoting($SQ, raw: false, leftQuoteLength: 6),
    const StringQuoting($SQ, raw: true, leftQuoteLength: 6),
    const StringQuoting($DQ, raw: false, leftQuoteLength: 6),
    const StringQuoting($DQ, raw: true, leftQuoteLength: 6)
  ];

  final bool raw;
  final int leftQuoteCharCount;
  final int quote;
  const StringQuoting(this.quote, {this.raw, int leftQuoteLength})
      : this.leftQuoteCharCount = leftQuoteLength;
  String get quoteChar => identical(quote, $DQ) ? '"' : "'";

  int get leftQuoteLength => (raw ? 1 : 0) + leftQuoteCharCount;
  int get rightQuoteLength => (leftQuoteCharCount > 2) ? 3 : 1;
  static StringQuoting getQuoting(int quote, bool raw, int leftQuoteLength) {
    int quoteKindOffset = (quote == $DQ) ? 2 : 0;
    int rawOffset = raw ? 1 : 0;
    int index = (leftQuoteLength - 1) * 4 + rawOffset + quoteKindOffset;
    if (index < _mapping.length) return _mapping[index];
    return new StringQuoting(quote, raw: raw, leftQuoteLength: leftQuoteLength);
  }
}

/**
  * Superclass for classes representing string literals.
  */
abstract class StringNode extends Expression {
  DartString get dartString;
  bool get isInterpolation;

  StringNode asStringNode() => this;
}

class LiteralString extends StringNode {
  final Token token;
  /** Non-null on validated string literals. */
  final DartString dartString;

  LiteralString(this.token, this.dartString);

  LiteralString asLiteralString() => this;

  bool get isInterpolation => false;

  Token getBeginToken() => token;
  Token getEndToken() => token;

  accept(Visitor visitor) => visitor.visitLiteralString(this);

  accept1(Visitor1 visitor, arg) => visitor.visitLiteralString(this, arg);

  void visitChildren(Visitor visitor) {}

  void visitChildren1(Visitor1 visitor, arg) {}
}

class LiteralNull extends Literal<String> {
  LiteralNull(Token token) : super(token, null);

  LiteralNull asLiteralNull() => this;

  String get value => null;

  accept(Visitor visitor) => visitor.visitLiteralNull(this);

  accept1(Visitor1 visitor, arg) => visitor.visitLiteralNull(this, arg);
}

class LiteralList extends Expression {
  final NodeList typeArguments;
  final NodeList elements;

  final Token constKeyword;

  LiteralList(this.typeArguments, this.elements, this.constKeyword);

  bool get isConst => constKeyword != null;

  LiteralList asLiteralList() => this;
  accept(Visitor visitor) => visitor.visitLiteralList(this);

  accept1(Visitor1 visitor, arg) => visitor.visitLiteralList(this, arg);

  visitChildren(Visitor visitor) {
    if (typeArguments != null) typeArguments.accept(visitor);
    elements.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (typeArguments != null) typeArguments.accept1(visitor, arg);
    elements.accept1(visitor, arg);
  }

  Token getBeginToken() {
    if (constKeyword != null) return constKeyword;
    return firstBeginToken(typeArguments, elements);
  }

  Token getEndToken() => elements.getEndToken();
}

class LiteralSymbol extends Expression {
  final Token hashToken;
  // TODO: this could be a DottedNamed.
  final NodeList identifiers;

  LiteralSymbol(this.hashToken, this.identifiers);

  LiteralSymbol asLiteralSymbol() => this;

  accept(Visitor visitor) => visitor.visitLiteralSymbol(this);

  accept1(Visitor1 visitor, arg) => visitor.visitLiteralSymbol(this, arg);

  void visitChildren(Visitor visitor) {
    if (identifiers != null) identifiers.accept(visitor);
  }

  void visitChildren1(Visitor1 visitor, arg) {
    if (identifiers != null) identifiers.accept1(visitor, arg);
  }

  Token getBeginToken() => hashToken;

  Token getEndToken() => identifiers.getEndToken();

  String get slowNameString {
    Unparser unparser = new Unparser();
    unparser.unparseNodeListOfIdentifiers(identifiers);
    return unparser.result;
  }
}

class Identifier extends Expression with StoredTreeElementMixin {
  final Token token;

  String get source => token.value;

  Identifier(Token this.token);

  bool isThis() => identical(source, 'this');

  bool isSuper() => identical(source, 'super');

  Identifier asIdentifier() => this;

  accept(Visitor visitor) => visitor.visitIdentifier(this);

  accept1(Visitor1 visitor, arg) => visitor.visitIdentifier(this, arg);

  visitChildren(Visitor visitor) {}

  visitChildren1(Visitor1 visitor, arg) {}

  Token getBeginToken() => token;

  Token getEndToken() => token;
}

// TODO(floitsch): a dotted identifier isn't really an expression. Should it
// inherit from Node instead?
class DottedName extends Expression {
  final Token token;
  final NodeList identifiers;

  DottedName(this.token, this.identifiers);

  DottedName asDottedName() => this;

  accept(Visitor visitor) => visitor.visitDottedName(this);

  accept1(Visitor1 visitor, arg) => visitor.visitDottedName(this, arg);

  void visitChildren(Visitor visitor) {
    identifiers.accept(visitor);
  }

  void visitChildren1(Visitor1 visitor, arg) {
    identifiers.accept1(visitor, arg);
  }

  Token getBeginToken() => token;
  Token getEndToken() => identifiers.getEndToken();

  String get slowNameString {
    Unparser unparser = new Unparser();
    unparser.unparseNodeListOfIdentifiers(identifiers);
    return unparser.result;
  }
}

class Operator extends Identifier {
  static const COMPLEX_OPERATORS = const [
    "--",
    "++",
    '+=',
    "-=",
    "*=",
    "/=",
    "%=",
    "&=",
    "|=",
    "~/=",
    "^=",
    ">>=",
    "<<=",
    "??="
  ];

  static const INCREMENT_OPERATORS = const <String>["++", "--"];

  Operator(Token token) : super(token);

  Operator asOperator() => this;

  accept(Visitor visitor) => visitor.visitOperator(this);

  accept1(Visitor1 visitor, arg) => visitor.visitOperator(this, arg);
}

class Return extends Statement {
  final Node expression;
  final Token beginToken;
  final Token endToken;

  Return(this.beginToken, this.endToken, this.expression);

  Return asReturn() => this;

  bool get hasExpression => expression != null;

  /// `true` if this return is of the form `=> e;`.
  bool get isArrowBody => beginToken.info == Precedence.FUNCTION_INFO;

  accept(Visitor visitor) => visitor.visitReturn(this);

  accept1(Visitor1 visitor, arg) => visitor.visitReturn(this, arg);

  visitChildren(Visitor visitor) {
    if (expression != null) expression.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (expression != null) expression.accept1(visitor, arg);
  }

  Token getBeginToken() => beginToken;

  Token getEndToken() {
    if (endToken == null) return expression.getEndToken();
    return endToken;
  }
}

class Yield extends Statement {
  final Node expression;
  final Token yieldToken;
  final Token starToken;
  final Token endToken;

  Yield(this.yieldToken, this.starToken, this.expression, this.endToken);

  Yield asYield() => this;

  bool get hasStar => starToken != null;

  accept(Visitor visitor) => visitor.visitYield(this);

  accept1(Visitor1 visitor, arg) => visitor.visitYield(this, arg);

  visitChildren(Visitor visitor) {
    expression.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    expression.accept1(visitor, arg);
  }

  Token getBeginToken() => yieldToken;

  Token getEndToken() => endToken;
}

class RedirectingFactoryBody extends Statement with StoredTreeElementMixin {
  final Node constructorReference;
  final Token beginToken;
  final Token endToken;

  RedirectingFactoryBody(
      this.beginToken, this.endToken, this.constructorReference);

  RedirectingFactoryBody asRedirectingFactoryBody() => this;

  accept(Visitor visitor) => visitor.visitRedirectingFactoryBody(this);

  accept1(Visitor1 visitor, arg) {
    return visitor.visitRedirectingFactoryBody(this, arg);
  }

  visitChildren(Visitor visitor) {
    constructorReference.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    constructorReference.accept1(visitor, arg);
  }

  Token getBeginToken() => beginToken;

  Token getEndToken() => endToken;
}

class ExpressionStatement extends Statement {
  final Expression expression;
  final Token endToken;

  ExpressionStatement(this.expression, this.endToken);

  ExpressionStatement asExpressionStatement() => this;

  accept(Visitor visitor) => visitor.visitExpressionStatement(this);

  accept1(Visitor1 visitor, arg) => visitor.visitExpressionStatement(this, arg);

  visitChildren(Visitor visitor) {
    if (expression != null) expression.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (expression != null) expression.accept1(visitor, arg);
  }

  Token getBeginToken() => expression.getBeginToken();

  Token getEndToken() => endToken;
}

class Throw extends Expression {
  final Expression expression;

  final Token throwToken;
  final Token endToken;

  Throw(this.expression, this.throwToken, this.endToken);

  Throw asThrow() => this;

  accept(Visitor visitor) => visitor.visitThrow(this);

  accept1(Visitor1 visitor, arg) => visitor.visitThrow(this, arg);

  visitChildren(Visitor visitor) {
    expression.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    expression.accept1(visitor, arg);
  }

  Token getBeginToken() => throwToken;

  Token getEndToken() => endToken;
}

class Await extends Expression {
  final Expression expression;

  final Token awaitToken;

  Await(this.awaitToken, this.expression);

  Await asAwait() => this;

  accept(Visitor visitor) => visitor.visitAwait(this);

  accept1(Visitor1 visitor, arg) => visitor.visitAwait(this, arg);

  visitChildren(Visitor visitor) {
    expression.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    expression.accept1(visitor, arg);
  }

  Token getBeginToken() => awaitToken;

  Token getEndToken() => expression.getEndToken();
}

class Assert extends Statement {
  final Token assertToken;
  final Expression condition;
  /** Message may be `null`. */
  final Expression message;
  final Token semicolonToken;

  Assert(this.assertToken, this.condition, this.message, this.semicolonToken);

  Assert asAssert() => this;

  bool get hasMessage => message != null;

  accept(Visitor visitor) => visitor.visitAssert(this);

  accept1(Visitor1 visitor, arg) => visitor.visitAssert(this, arg);

  visitChildren(Visitor visitor) {
    condition.accept(visitor);
    if (message != null) message.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    condition.accept1(visitor, arg);
    if (message != null) message.accept1(visitor, arg);
  }

  Token getBeginToken() => assertToken;
  Token getEndToken() => semicolonToken;
}

class Rethrow extends Statement {
  final Token throwToken;
  final Token endToken;

  Rethrow(this.throwToken, this.endToken);

  Rethrow asRethrow() => this;

  accept(Visitor visitor) => visitor.visitRethrow(this);

  accept1(Visitor1 visitor, arg) => visitor.visitRethrow(this, arg);

  visitChildren(Visitor visitor) {}

  visitChildren1(Visitor1 visitor, arg) {}

  Token getBeginToken() => throwToken;
  Token getEndToken() => endToken;
}

class TypeAnnotation extends Node {
  final Expression typeName;
  final NodeList typeArguments;

  TypeAnnotation(Expression this.typeName, NodeList this.typeArguments);

  TypeAnnotation asTypeAnnotation() => this;

  accept(Visitor visitor) => visitor.visitTypeAnnotation(this);

  accept1(Visitor1 visitor, arg) => visitor.visitTypeAnnotation(this, arg);

  visitChildren(Visitor visitor) {
    typeName.accept(visitor);
    if (typeArguments != null) typeArguments.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    typeName.accept1(visitor, arg);
    if (typeArguments != null) typeArguments.accept1(visitor, arg);
  }

  Token getBeginToken() => typeName.getBeginToken();

  Token getEndToken() {
    if (typeArguments != null) return typeArguments.getEndToken();
    return typeName.getEndToken();
  }
}

class TypeVariable extends Node {
  final Identifier name;
  final TypeAnnotation bound;
  TypeVariable(Identifier this.name, TypeAnnotation this.bound);

  accept(Visitor visitor) => visitor.visitTypeVariable(this);

  accept1(Visitor1 visitor, arg) => visitor.visitTypeVariable(this, arg);

  visitChildren(Visitor visitor) {
    name.accept(visitor);
    if (bound != null) {
      bound.accept(visitor);
    }
  }

  visitChildren1(Visitor1 visitor, arg) {
    name.accept1(visitor, arg);
    if (bound != null) {
      bound.accept1(visitor, arg);
    }
  }

  TypeVariable asTypeVariable() => this;

  Token getBeginToken() => name.getBeginToken();

  Token getEndToken() {
    return (bound != null) ? bound.getEndToken() : name.getEndToken();
  }
}

class VariableDefinitions extends Statement {
  final NodeList metadata;
  final TypeAnnotation type;
  final Modifiers modifiers;
  final NodeList definitions;

  VariableDefinitions(this.type, this.modifiers, this.definitions)
      : this.metadata = null {
    assert(modifiers != null);
  }

  // TODO(johnniwinther): Make this its own node type.
  VariableDefinitions.forParameter(
      this.metadata, this.type, this.modifiers, this.definitions) {
    assert(modifiers != null);
  }

  VariableDefinitions asVariableDefinitions() => this;

  accept(Visitor visitor) => visitor.visitVariableDefinitions(this);

  accept1(Visitor1 visitor, arg) => visitor.visitVariableDefinitions(this, arg);

  visitChildren(Visitor visitor) {
    if (metadata != null) metadata.accept(visitor);
    if (type != null) type.accept(visitor);
    if (definitions != null) definitions.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (metadata != null) metadata.accept1(visitor, arg);
    if (type != null) type.accept1(visitor, arg);
    if (definitions != null) definitions.accept1(visitor, arg);
  }

  Token getBeginToken() {
    var token = firstBeginToken(modifiers, type);
    if (token == null) {
      token = definitions.getBeginToken();
    }
    return token;
  }

  Token getEndToken() => definitions.getEndToken();
}

abstract class Loop extends Statement {
  Expression get condition;
  final Statement body;

  Loop(this.body);

  bool isValidContinueTarget() => true;
}

class DoWhile extends Loop {
  final Token doKeyword;
  final Token whileKeyword;
  final Token endToken;

  final Expression condition;

  DoWhile(Statement body, Expression this.condition, Token this.doKeyword,
      Token this.whileKeyword, Token this.endToken)
      : super(body);

  DoWhile asDoWhile() => this;

  accept(Visitor visitor) => visitor.visitDoWhile(this);

  accept1(Visitor1 visitor, arg) => visitor.visitDoWhile(this, arg);

  visitChildren(Visitor visitor) {
    if (condition != null) condition.accept(visitor);
    if (body != null) body.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (condition != null) condition.accept1(visitor, arg);
    if (body != null) body.accept1(visitor, arg);
  }

  Token getBeginToken() => doKeyword;

  Token getEndToken() => endToken;
}

class While extends Loop {
  final Token whileKeyword;
  final Expression condition;

  While(Expression this.condition, Statement body, Token this.whileKeyword)
      : super(body);

  While asWhile() => this;

  accept(Visitor visitor) => visitor.visitWhile(this);

  accept1(Visitor1 visitor, arg) => visitor.visitWhile(this, arg);

  visitChildren(Visitor visitor) {
    if (condition != null) condition.accept(visitor);
    if (body != null) body.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (condition != null) condition.accept1(visitor, arg);
    if (body != null) body.accept1(visitor, arg);
  }

  Token getBeginToken() => whileKeyword;

  Token getEndToken() => body.getEndToken();
}

class ParenthesizedExpression extends Expression {
  final Expression expression;
  final BeginGroupToken beginToken;

  ParenthesizedExpression(
      Expression this.expression, BeginGroupToken this.beginToken);

  ParenthesizedExpression asParenthesizedExpression() => this;

  accept(Visitor visitor) => visitor.visitParenthesizedExpression(this);

  accept1(Visitor1 visitor, arg) {
    return visitor.visitParenthesizedExpression(this, arg);
  }

  visitChildren(Visitor visitor) {
    if (expression != null) expression.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (expression != null) expression.accept1(visitor, arg);
  }

  Token getBeginToken() => beginToken;

  Token getEndToken() => beginToken.endGroup;
}

/** Representation of modifiers such as static, abstract, final, etc. */
class Modifiers extends Node {
  /**
   * Pseudo-constant for empty modifiers.
   */
  static final Modifiers EMPTY = new Modifiers(new NodeList.empty());

  /* TODO(ahe): The following should be validated relating to modifiers:
   * 1. The nodes must come in a certain order.
   * 2. The keywords "var" and "final" may not be used at the same time.
   * 3. The keywords "abstract" and "external" may not be used at the same time.
   * 4. The type of an element must be null if isVar() is true.
   */

  final NodeList nodes;
  /** Bit pattern to easy check what modifiers are present. */
  final int flags;

  static const int FLAG_STATIC = 1;
  static const int FLAG_ABSTRACT = FLAG_STATIC << 1;
  static const int FLAG_FINAL = FLAG_ABSTRACT << 1;
  static const int FLAG_VAR = FLAG_FINAL << 1;
  static const int FLAG_CONST = FLAG_VAR << 1;
  static const int FLAG_FACTORY = FLAG_CONST << 1;
  static const int FLAG_EXTERNAL = FLAG_FACTORY << 1;

  Modifiers(NodeList nodes) : this.withFlags(nodes, computeFlags(nodes.nodes));

  Modifiers.withFlags(this.nodes, this.flags);

  static int computeFlags(Link<Node> nodes) {
    int flags = 0;
    for (; !nodes.isEmpty; nodes = nodes.tail) {
      String value = nodes.head.asIdentifier().source;
      if (identical(value, 'static'))
        flags |= FLAG_STATIC;
      else if (identical(value, 'abstract'))
        flags |= FLAG_ABSTRACT;
      else if (identical(value, 'final'))
        flags |= FLAG_FINAL;
      else if (identical(value, 'var'))
        flags |= FLAG_VAR;
      else if (identical(value, 'const'))
        flags |= FLAG_CONST;
      else if (identical(value, 'factory'))
        flags |= FLAG_FACTORY;
      else if (identical(value, 'external'))
        flags |= FLAG_EXTERNAL;
      else
        throw 'internal error: ${nodes.head}';
    }
    return flags;
  }

  Node findModifier(String modifier) {
    Link<Node> nodeList = nodes.nodes;
    for (; !nodeList.isEmpty; nodeList = nodeList.tail) {
      String value = nodeList.head.asIdentifier().source;
      if (identical(value, modifier)) {
        return nodeList.head;
      }
    }
    return null;
  }

  Modifiers asModifiers() => this;
  Token getBeginToken() => nodes.getBeginToken();
  Token getEndToken() => nodes.getEndToken();

  accept(Visitor visitor) => visitor.visitModifiers(this);

  accept1(Visitor1 visitor, arg) => visitor.visitModifiers(this, arg);

  visitChildren(Visitor visitor) => nodes.accept(visitor);

  visitChildren1(Visitor1 visitor, arg) => nodes.accept1(visitor, arg);

  bool get isStatic => (flags & FLAG_STATIC) != 0;
  bool get isAbstract => (flags & FLAG_ABSTRACT) != 0;
  bool get isFinal => (flags & FLAG_FINAL) != 0;
  bool get isVar => (flags & FLAG_VAR) != 0;
  bool get isConst => (flags & FLAG_CONST) != 0;
  bool get isFactory => (flags & FLAG_FACTORY) != 0;
  bool get isExternal => (flags & FLAG_EXTERNAL) != 0;

  Node getStatic() => findModifier('static');

  /**
   * Use this to check if the declaration is either explicitly or implicitly
   * final.
   */
  bool get isFinalOrConst => isFinal || isConst;

  String toString() {
    return modifiersToString(
        isStatic: isStatic,
        isAbstract: isAbstract,
        isFinal: isFinal,
        isVar: isVar,
        isConst: isConst,
        isFactory: isFactory,
        isExternal: isExternal);
  }
}

class StringInterpolation extends StringNode {
  final LiteralString string;
  final NodeList parts;

  StringInterpolation(this.string, this.parts);

  StringInterpolation asStringInterpolation() => this;

  DartString get dartString => null;
  bool get isInterpolation => true;

  accept(Visitor visitor) => visitor.visitStringInterpolation(this);

  accept1(Visitor1 visitor, arg) => visitor.visitStringInterpolation(this, arg);

  visitChildren(Visitor visitor) {
    string.accept(visitor);
    parts.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    string.accept1(visitor, arg);
    parts.accept1(visitor, arg);
  }

  Token getBeginToken() => string.getBeginToken();
  Token getEndToken() => parts.getEndToken();
}

class StringInterpolationPart extends Node {
  final Expression expression;
  final LiteralString string;

  StringInterpolationPart(this.expression, this.string);

  StringInterpolationPart asStringInterpolationPart() => this;

  accept(Visitor visitor) => visitor.visitStringInterpolationPart(this);

  accept1(Visitor1 visitor, arg) {
    return visitor.visitStringInterpolationPart(this, arg);
  }

  visitChildren(Visitor visitor) {
    expression.accept(visitor);
    string.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    expression.accept1(visitor, arg);
    string.accept1(visitor, arg);
  }

  Token getBeginToken() => expression.getBeginToken();

  Token getEndToken() => string.getEndToken();
}

/**
 * A class representing juxtaposed string literals.
 * The string literals can be both plain literals and string interpolations.
 */
class StringJuxtaposition extends StringNode {
  final Expression first;
  final Expression second;

  /**
   * Caches the check for whether this juxtaposition contains a string
   * interpolation
   */
  bool isInterpolationCache = null;

  /**
   * Caches a Dart string representation of the entire juxtaposition's
   * content. Only juxtapositions that don't (transitively) contains
   * interpolations have a static representation.
   */
  DartString dartStringCache = null;

  StringJuxtaposition(this.first, this.second);

  StringJuxtaposition asStringJuxtaposition() => this;

  bool get isInterpolation {
    if (isInterpolationCache == null) {
      isInterpolationCache = (first.accept(const IsInterpolationVisitor()) ||
          second.accept(const IsInterpolationVisitor()));
    }
    return isInterpolationCache;
  }

  /**
   * Retrieve a single DartString that represents this entire juxtaposition
   * of string literals.
   * Should only be called if [isInterpolation] returns false.
   */
  DartString get dartString {
    if (isInterpolation) {
      throw new SpannableAssertionFailure(
          this, "Getting dartString on interpolation;");
    }
    if (dartStringCache == null) {
      DartString firstString = first.accept(const GetDartStringVisitor());
      DartString secondString = second.accept(const GetDartStringVisitor());
      if (firstString == null || secondString == null) {
        return null;
      }
      dartStringCache = new DartString.concat(firstString, secondString);
    }
    return dartStringCache;
  }

  accept(Visitor visitor) => visitor.visitStringJuxtaposition(this);

  accept1(Visitor1 visitor, arg) => visitor.visitStringJuxtaposition(this, arg);

  void visitChildren(Visitor visitor) {
    first.accept(visitor);
    second.accept(visitor);
  }

  void visitChildren1(Visitor1 visitor, arg) {
    first.accept1(visitor, arg);
    second.accept1(visitor, arg);
  }

  Token getBeginToken() => first.getBeginToken();

  Token getEndToken() => second.getEndToken();
}

class EmptyStatement extends Statement {
  final Token semicolonToken;

  EmptyStatement(this.semicolonToken);

  EmptyStatement asEmptyStatement() => this;

  accept(Visitor visitor) => visitor.visitEmptyStatement(this);

  accept1(Visitor1 visitor, arg) => visitor.visitEmptyStatement(this, arg);

  visitChildren(Visitor visitor) {}

  visitChildren1(Visitor1 visitor, arg) {}

  Token getBeginToken() => semicolonToken;

  Token getEndToken() => semicolonToken;
}

class LiteralMap extends Expression {
  final NodeList typeArguments;
  final NodeList entries;

  final Token constKeyword;

  LiteralMap(this.typeArguments, this.entries, this.constKeyword);

  bool get isConst => constKeyword != null;

  LiteralMap asLiteralMap() => this;

  accept(Visitor visitor) => visitor.visitLiteralMap(this);

  accept1(Visitor1 visitor, arg) => visitor.visitLiteralMap(this, arg);

  visitChildren(Visitor visitor) {
    if (typeArguments != null) typeArguments.accept(visitor);
    entries.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (typeArguments != null) typeArguments.accept1(visitor, arg);
    entries.accept1(visitor, arg);
  }

  Token getBeginToken() {
    if (constKeyword != null) return constKeyword;
    return firstBeginToken(typeArguments, entries);
  }

  Token getEndToken() => entries.getEndToken();
}

class LiteralMapEntry extends Node {
  final Expression key;
  final Expression value;

  final Token colonToken;

  LiteralMapEntry(this.key, this.colonToken, this.value);

  LiteralMapEntry asLiteralMapEntry() => this;

  accept(Visitor visitor) => visitor.visitLiteralMapEntry(this);

  accept1(Visitor1 visitor, arg) => visitor.visitLiteralMapEntry(this, arg);

  visitChildren(Visitor visitor) {
    key.accept(visitor);
    value.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    key.accept1(visitor, arg);
    value.accept1(visitor, arg);
  }

  Token getBeginToken() => key.getBeginToken();

  Token getEndToken() => value.getEndToken();
}

class NamedArgument extends Expression {
  final Identifier name;
  final Expression expression;

  final Token colonToken;

  NamedArgument(this.name, this.colonToken, this.expression);

  NamedArgument asNamedArgument() => this;

  accept(Visitor visitor) => visitor.visitNamedArgument(this);

  accept1(Visitor1 visitor, arg) => visitor.visitNamedArgument(this, arg);

  visitChildren(Visitor visitor) {
    name.accept(visitor);
    expression.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    name.accept1(visitor, arg);
    expression.accept1(visitor, arg);
  }

  Token getBeginToken() => name.getBeginToken();

  Token getEndToken() => expression.getEndToken();
}

class SwitchStatement extends Statement {
  final ParenthesizedExpression parenthesizedExpression;
  final NodeList cases;

  final Token switchKeyword;

  SwitchStatement(this.parenthesizedExpression, this.cases, this.switchKeyword);

  SwitchStatement asSwitchStatement() => this;

  Expression get expression => parenthesizedExpression.expression;

  accept(Visitor visitor) => visitor.visitSwitchStatement(this);

  accept1(Visitor1 visitor, arg) => visitor.visitSwitchStatement(this, arg);

  visitChildren(Visitor visitor) {
    parenthesizedExpression.accept(visitor);
    cases.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    parenthesizedExpression.accept1(visitor, arg);
    cases.accept1(visitor, arg);
  }

  Token getBeginToken() => switchKeyword;

  Token getEndToken() => cases.getEndToken();
}

class CaseMatch extends Node {
  final Token caseKeyword;
  final Expression expression;
  final Token colonToken;
  CaseMatch(this.caseKeyword, this.expression, this.colonToken);

  CaseMatch asCaseMatch() => this;
  Token getBeginToken() => caseKeyword;
  Token getEndToken() => colonToken;

  accept(Visitor visitor) => visitor.visitCaseMatch(this);

  accept1(Visitor1 visitor, arg) => visitor.visitCaseMatch(this, arg);

  visitChildren(Visitor visitor) => expression.accept(visitor);

  visitChildren1(Visitor1 visitor, arg) => expression.accept1(visitor, arg);
}

class SwitchCase extends Node {
  // The labels and case patterns are collected in [labelsAndCases].
  // The default keyword, if present, is collected in [defaultKeyword].
  // Any actual switch case must have at least one 'case' or 'default'
  // clause.
  // Notice: The labels and cases can occur interleaved in the source.
  // They are separated here, since the order is irrelevant to the meaning
  // of the switch.

  /** List of [Label] and [CaseMatch] nodes. */
  final NodeList labelsAndCases;
  /** A "default" keyword token, if applicable. */
  final Token defaultKeyword;
  /** List of statements, the body of the case. */
  final NodeList statements;

  final Token startToken;

  SwitchCase(this.labelsAndCases, this.defaultKeyword, this.statements,
      this.startToken);

  SwitchCase asSwitchCase() => this;

  bool get isDefaultCase => defaultKeyword != null;

  bool isValidContinueTarget() => true;

  accept(Visitor visitor) => visitor.visitSwitchCase(this);

  accept1(Visitor1 visitor, arg) => visitor.visitSwitchCase(this, arg);

  visitChildren(Visitor visitor) {
    labelsAndCases.accept(visitor);
    statements.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    labelsAndCases.accept1(visitor, arg);
    statements.accept1(visitor, arg);
  }

  Token getBeginToken() {
    return startToken;
  }

  Token getEndToken() {
    if (statements.nodes.isEmpty) {
      // All cases must have at least one expression or be the default.
      if (defaultKeyword != null) {
        // The colon after 'default'.
        return defaultKeyword.next;
      }
      // The colon after the last expression.
      return labelsAndCases.getEndToken();
    } else {
      return statements.getEndToken();
    }
  }
}

abstract class GotoStatement extends Statement {
  final Identifier target;
  final Token keywordToken;
  final Token semicolonToken;

  GotoStatement(this.target, this.keywordToken, this.semicolonToken);

  visitChildren(Visitor visitor) {
    if (target != null) target.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (target != null) target.accept1(visitor, arg);
  }

  Token getBeginToken() => keywordToken;

  Token getEndToken() => semicolonToken;

  // TODO(ahe): make class abstract instead of adding an abstract method.
  accept(Visitor visitor);
}

class BreakStatement extends GotoStatement {
  BreakStatement(Identifier target, Token keywordToken, Token semicolonToken)
      : super(target, keywordToken, semicolonToken);

  BreakStatement asBreakStatement() => this;

  accept(Visitor visitor) => visitor.visitBreakStatement(this);

  accept1(Visitor1 visitor, arg) => visitor.visitBreakStatement(this, arg);
}

class ContinueStatement extends GotoStatement {
  ContinueStatement(Identifier target, Token keywordToken, Token semicolonToken)
      : super(target, keywordToken, semicolonToken);

  ContinueStatement asContinueStatement() => this;

  accept(Visitor visitor) => visitor.visitContinueStatement(this);

  accept1(Visitor1 visitor, arg) => visitor.visitContinueStatement(this, arg);
}

abstract class ForIn extends Loop {
  final Node declaredIdentifier;
  final Expression expression;

  final Token forToken;
  final Token inToken;

  ForIn(this.declaredIdentifier, this.expression, Statement body, this.forToken,
      this.inToken)
      : super(body);

  Expression get condition => null;

  ForIn asForIn() => this;

  Token getEndToken() => body.getEndToken();
}

class SyncForIn extends ForIn with StoredTreeElementMixin {
  SyncForIn(declaredIdentifier, expression, Statement body, forToken, inToken)
      : super(declaredIdentifier, expression, body, forToken, inToken);

  SyncForIn asSyncForIn() => this;

  accept(Visitor visitor) => visitor.visitSyncForIn(this);

  accept1(Visitor1 visitor, arg) => visitor.visitSyncForIn(this, arg);

  visitChildren(Visitor visitor) {
    declaredIdentifier.accept(visitor);
    expression.accept(visitor);
    body.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    declaredIdentifier.accept1(visitor, arg);
    expression.accept1(visitor, arg);
    body.accept1(visitor, arg);
  }

  Token getBeginToken() => forToken;
}

class AsyncForIn extends ForIn with StoredTreeElementMixin {
  final Token awaitToken;

  AsyncForIn(declaredIdentifier, expression, Statement body, this.awaitToken,
      forToken, inToken)
      : super(declaredIdentifier, expression, body, forToken, inToken);

  AsyncForIn asAsyncForIn() => this;

  accept(Visitor visitor) => visitor.visitAsyncForIn(this);

  accept1(Visitor1 visitor, arg) => visitor.visitAsyncForIn(this, arg);

  visitChildren(Visitor visitor) {
    declaredIdentifier.accept(visitor);
    expression.accept(visitor);
    body.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    declaredIdentifier.accept1(visitor, arg);
    expression.accept1(visitor, arg);
    body.accept1(visitor, arg);
  }

  Token getBeginToken() => awaitToken;
}

class Label extends Node {
  final Identifier identifier;
  final Token colonToken;

  Label(this.identifier, this.colonToken);

  String get labelName => identifier.source;

  Label asLabel() => this;

  accept(Visitor visitor) => visitor.visitLabel(this);

  accept1(Visitor1 visitor, arg) => visitor.visitLabel(this, arg);

  void visitChildren(Visitor visitor) {
    identifier.accept(visitor);
  }

  void visitChildren1(Visitor1 visitor, arg) {
    identifier.accept1(visitor, arg);
  }

  Token getBeginToken() => identifier.token;
  Token getEndToken() => colonToken;
}

class LabeledStatement extends Statement {
  final NodeList labels;
  final Statement statement;

  LabeledStatement(this.labels, this.statement);

  LabeledStatement asLabeledStatement() => this;

  accept(Visitor visitor) => visitor.visitLabeledStatement(this);

  accept1(Visitor1 visitor, arg) => visitor.visitLabeledStatement(this, arg);

  visitChildren(Visitor visitor) {
    labels.accept(visitor);
    statement.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    labels.accept1(visitor, arg);
    statement.accept1(visitor, arg);
  }

  Token getBeginToken() => labels.getBeginToken();

  Token getEndToken() => statement.getEndToken();

  bool isValidContinueTarget() => statement.isValidContinueTarget();
}

abstract class LibraryTag extends Node {
  final List<MetadataAnnotation> metadata;

  LibraryTag(this.metadata);

  bool get isLibraryName => false;
  bool get isImport => false;
  bool get isExport => false;
  bool get isPart => false;
  bool get isPartOf => false;
}

class LibraryName extends LibraryTag {
  final Expression name;

  final Token libraryKeyword;

  LibraryName(this.libraryKeyword, this.name, List<MetadataAnnotation> metadata)
      : super(metadata);

  bool get isLibraryName => true;

  LibraryName asLibraryName() => this;

  accept(Visitor visitor) => visitor.visitLibraryName(this);

  accept1(Visitor1 visitor, arg) => visitor.visitLibraryName(this, arg);

  visitChildren(Visitor visitor) => name.accept(visitor);

  visitChildren1(Visitor1 visitor, arg) => name.accept1(visitor, arg);

  Token getBeginToken() => libraryKeyword;

  Token getEndToken() => name.getEndToken().next;
}

/**
 * This tag describes a dependency between one library and the exported
 * identifiers of another library. The other library is specified by the [uri].
 * Combinators filter away some identifiers from the other library.
 */
abstract class LibraryDependency extends LibraryTag {
  final StringNode uri;
  final NodeList conditionalUris;
  final NodeList combinators;

  LibraryDependency(this.uri, this.conditionalUris, this.combinators,
      List<MetadataAnnotation> metadata)
      : super(metadata);

  LibraryDependency asLibraryDependency() => this;

  bool get hasConditionalUris => conditionalUris != null;
}

/**
 * An [:import:] library tag.
 *
 * An import tag is dependency on another library where the exported identifiers
 * are put into the import scope of the importing library. The import scope is
 * only visible inside the library.
 */
class Import extends LibraryDependency {
  final Identifier prefix;
  final Token importKeyword;
  final bool isDeferred;

  Import(this.importKeyword, StringNode uri, NodeList conditionalUris,
      this.prefix, NodeList combinators, List<MetadataAnnotation> metadata,
      {this.isDeferred})
      : super(uri, conditionalUris, combinators, metadata);

  bool get isImport => true;

  Import asImport() => this;

  accept(Visitor visitor) => visitor.visitImport(this);

  accept1(Visitor1 visitor, arg) => visitor.visitImport(this, arg);

  visitChildren(Visitor visitor) {
    uri.accept(visitor);
    if (prefix != null) prefix.accept(visitor);
    if (combinators != null) combinators.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    uri.accept1(visitor, arg);
    if (prefix != null) prefix.accept1(visitor, arg);
    if (combinators != null) combinators.accept1(visitor, arg);
  }

  Token getBeginToken() => importKeyword;

  Token getEndToken() {
    if (combinators != null) return combinators.getEndToken().next;
    if (prefix != null) return prefix.getEndToken().next;
    if (conditionalUris != null) return conditionalUris.getEndToken().next;
    return uri.getEndToken().next;
  }
}

/**
 * A conditional uri inside an import or export clause.
 *
 * Example:
 *
 *     import 'foo.dart'
 *       if (some.condition == "someValue") 'bar.dart'
 *       if (other.condition) 'gee.dart';
 */
class ConditionalUri extends Node {
  final Token ifToken;
  final DottedName key;
  // Value may be null.
  final LiteralString value;
  final StringNode uri;

  ConditionalUri(this.ifToken, this.key, this.value, this.uri);

  ConditionalUri asConditionalUri() => this;

  accept(Visitor visitor) => visitor.visitConditionalUri(this);

  accept1(Visitor1 visitor, arg) => visitor.visitConditionalUri(this, arg);

  visitChildren(Visitor visitor) {
    key.accept(visitor);
    if (value != null) value.accept(visitor);
    uri.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    key.accept1(visitor, arg);
    if (value != null) value.accept1(visitor, arg);
    uri.accept1(visitor, arg);
  }

  Token getBeginToken() => ifToken;

  Token getEndToken() => uri.getEndToken();
}

/**
 * An `enum` declaration.
 *
 * An `enum` defines a number of named constants inside a non-extensible class
 */
class Enum extends Node {
  /** The name of the enum class. */
  final Identifier name;
  /** The names of the enum constants. */
  final NodeList names;
  final Token enumToken;

  Enum(this.enumToken, this.name, this.names);

  Enum asEnum() => this;

  accept(Visitor visitor) => visitor.visitEnum(this);

  accept1(Visitor1 visitor, arg) => visitor.visitEnum(this, arg);

  visitChildren(Visitor visitor) {
    name.accept(visitor);
    if (names != null) names.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    name.accept1(visitor, arg);
    if (names != null) names.accept1(visitor, arg);
  }

  Token getBeginToken() => enumToken;
  Token getEndToken() => names.getEndToken();
}

/**
 * An [:export:] library tag.
 *
 * An export tag is dependency on another library where the exported identifiers
 * are put into the export scope of the exporting library. The export scope is
 * not visible inside the library.
 */
class Export extends LibraryDependency {
  final Token exportKeyword;

  Export(this.exportKeyword, StringNode uri, NodeList conditionalUris,
      NodeList combinators, List<MetadataAnnotation> metadata)
      : super(uri, conditionalUris, combinators, metadata);

  bool get isExport => true;

  Export asExport() => this;

  accept(Visitor visitor) => visitor.visitExport(this);

  accept1(Visitor1 visitor, arg) => visitor.visitExport(this, arg);

  visitChildren(Visitor visitor) {
    uri.accept(visitor);
    if (combinators != null) combinators.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    uri.accept1(visitor, arg);
    if (combinators != null) combinators.accept1(visitor, arg);
  }

  Token getBeginToken() => exportKeyword;

  Token getEndToken() {
    if (combinators != null) return combinators.getEndToken().next;
    if (conditionalUris != null) return conditionalUris.getEndToken().next;
    return uri.getEndToken().next;
  }
}

class Part extends LibraryTag {
  final StringNode uri;

  final Token partKeyword;

  Part(this.partKeyword, this.uri, List<MetadataAnnotation> metadata)
      : super(metadata);

  bool get isPart => true;

  Part asPart() => this;

  accept(Visitor visitor) => visitor.visitPart(this);

  accept1(Visitor1 visitor, arg) => visitor.visitPart(this, arg);

  visitChildren(Visitor visitor) => uri.accept(visitor);

  visitChildren1(Visitor1 visitor, arg) => uri.accept1(visitor, arg);

  Token getBeginToken() => partKeyword;

  Token getEndToken() => uri.getEndToken().next;
}

class PartOf extends Node {
  final Expression name;

  final Token partKeyword;

  final List<MetadataAnnotation> metadata;

  PartOf(this.partKeyword, this.name, this.metadata);

  Token get ofKeyword => partKeyword.next;

  bool get isPartOf => true;

  PartOf asPartOf() => this;

  accept(Visitor visitor) => visitor.visitPartOf(this);

  accept1(Visitor1 visitor, arg) => visitor.visitPartOf(this, arg);

  visitChildren(Visitor visitor) => name.accept(visitor);

  visitChildren1(Visitor1 visitor, arg) => name.accept1(visitor, arg);

  Token getBeginToken() => partKeyword;

  Token getEndToken() => name.getEndToken().next;
}

class Combinator extends Node {
  final NodeList identifiers;

  final Token keywordToken;

  Combinator(this.identifiers, this.keywordToken);

  bool get isShow => identical(keywordToken.stringValue, 'show');

  bool get isHide => identical(keywordToken.stringValue, 'hide');

  Combinator asCombinator() => this;

  accept(Visitor visitor) => visitor.visitCombinator(this);

  accept1(Visitor1 visitor, arg) => visitor.visitCombinator(this, arg);

  visitChildren(Visitor visitor) => identifiers.accept(visitor);

  visitChildren1(Visitor1 visitor, arg) => identifiers.accept1(visitor, arg);

  Token getBeginToken() => keywordToken;

  Token getEndToken() => identifiers.getEndToken();
}

class Typedef extends Node {
  final TypeAnnotation returnType;
  final Identifier name;
  final NodeList typeParameters;
  final NodeList formals;

  final Token typedefKeyword;
  final Token endToken;

  Typedef(this.returnType, this.name, this.typeParameters, this.formals,
      this.typedefKeyword, this.endToken);

  Typedef asTypedef() => this;

  accept(Visitor visitor) => visitor.visitTypedef(this);

  accept1(Visitor1 visitor, arg) => visitor.visitTypedef(this, arg);

  visitChildren(Visitor visitor) {
    if (returnType != null) returnType.accept(visitor);
    name.accept(visitor);
    if (typeParameters != null) typeParameters.accept(visitor);
    formals.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (returnType != null) returnType.accept1(visitor, arg);
    name.accept1(visitor, arg);
    if (typeParameters != null) typeParameters.accept1(visitor, arg);
    formals.accept1(visitor, arg);
  }

  Token getBeginToken() => typedefKeyword;

  Token getEndToken() => endToken;
}

class TryStatement extends Statement {
  final Block tryBlock;
  final NodeList catchBlocks;
  final Block finallyBlock;

  final Token tryKeyword;
  final Token finallyKeyword;

  TryStatement(this.tryBlock, this.catchBlocks, this.finallyBlock,
      this.tryKeyword, this.finallyKeyword);

  TryStatement asTryStatement() => this;

  accept(Visitor visitor) => visitor.visitTryStatement(this);

  accept1(Visitor1 visitor, arg) => visitor.visitTryStatement(this, arg);

  visitChildren(Visitor visitor) {
    tryBlock.accept(visitor);
    catchBlocks.accept(visitor);
    if (finallyBlock != null) finallyBlock.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    tryBlock.accept1(visitor, arg);
    catchBlocks.accept1(visitor, arg);
    if (finallyBlock != null) finallyBlock.accept1(visitor, arg);
  }

  Token getBeginToken() => tryKeyword;

  Token getEndToken() {
    if (finallyBlock != null) return finallyBlock.getEndToken();
    if (!catchBlocks.isEmpty) return catchBlocks.getEndToken();
    return tryBlock.getEndToken();
  }
}

class Cascade extends Expression {
  final Expression expression;
  Cascade(this.expression);

  Cascade asCascade() => this;
  accept(Visitor visitor) => visitor.visitCascade(this);

  accept1(Visitor1 visitor, arg) => visitor.visitCascade(this, arg);

  void visitChildren(Visitor visitor) {
    expression.accept(visitor);
  }

  void visitChildren1(Visitor1 visitor, arg) {
    expression.accept1(visitor, arg);
  }

  Token getBeginToken() => expression.getBeginToken();

  Token getEndToken() => expression.getEndToken();
}

class CascadeReceiver extends Expression {
  final Expression expression;
  final Token cascadeOperator;
  CascadeReceiver(this.expression, this.cascadeOperator);

  CascadeReceiver asCascadeReceiver() => this;
  accept(Visitor visitor) => visitor.visitCascadeReceiver(this);

  accept1(Visitor1 visitor, arg) => visitor.visitCascadeReceiver(this, arg);

  void visitChildren(Visitor visitor) {
    expression.accept(visitor);
  }

  void visitChildren1(Visitor1 visitor, arg) {
    expression.accept1(visitor, arg);
  }

  Token getBeginToken() => expression.getBeginToken();

  Token getEndToken() => expression.getEndToken();
}

class CatchBlock extends Node {
  final TypeAnnotation type;
  final NodeList formals;
  final Block block;

  final Token onKeyword;
  final Token catchKeyword;

  CatchBlock(
      this.type, this.formals, this.block, this.onKeyword, this.catchKeyword);

  CatchBlock asCatchBlock() => this;

  accept(Visitor visitor) => visitor.visitCatchBlock(this);

  accept1(Visitor1 visitor, arg) => visitor.visitCatchBlock(this, arg);

  Node get exception {
    if (formals == null || formals.nodes.isEmpty) return null;
    VariableDefinitions declarations = formals.nodes.head;
    return declarations.definitions.nodes.head;
  }

  Node get trace {
    if (formals == null || formals.nodes.isEmpty) return null;
    Link<Node> declarations = formals.nodes.tail;
    if (declarations.isEmpty) return null;
    VariableDefinitions head = declarations.head;
    return head.definitions.nodes.head;
  }

  visitChildren(Visitor visitor) {
    if (type != null) type.accept(visitor);
    if (formals != null) formals.accept(visitor);
    block.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    if (type != null) type.accept1(visitor, arg);
    if (formals != null) formals.accept1(visitor, arg);
    block.accept1(visitor, arg);
  }

  Token getBeginToken() => onKeyword != null ? onKeyword : catchKeyword;

  Token getEndToken() => block.getEndToken();
}

class Metadata extends Node {
  final Token token;
  final Expression expression;

  Metadata(this.token, this.expression);

  Metadata asMetadata() => this;

  accept(Visitor visitor) => visitor.visitMetadata(this);

  accept1(Visitor1 visitor, arg) => visitor.visitMetadata(this, arg);

  visitChildren(Visitor visitor) {
    expression.accept(visitor);
  }

  visitChildren1(Visitor1 visitor, arg) {
    expression.accept1(visitor, arg);
  }

  Token getBeginToken() => token;

  Token getEndToken() => expression.getEndToken();
}

class Initializers {
  static bool isSuperConstructorCall(Send node) {
    return (node.receiver == null && node.selector.isSuper()) ||
        (node.receiver != null &&
            node.receiver.isSuper() &&
            !node.isConditional &&
            node.selector.asIdentifier() != null);
  }

  static bool isConstructorRedirect(Send node) {
    return (node.receiver == null && node.selector.isThis()) ||
        (node.receiver != null &&
            node.receiver.isThis() &&
            !node.isConditional &&
            node.selector.asIdentifier() != null);
  }
}

class GetDartStringVisitor extends Visitor<DartString> {
  const GetDartStringVisitor();
  DartString visitNode(Node node) => null;
  DartString visitStringJuxtaposition(StringJuxtaposition node) =>
      node.dartString;
  DartString visitLiteralString(LiteralString node) => node.dartString;
}

class IsInterpolationVisitor extends Visitor<bool> {
  const IsInterpolationVisitor();
  bool visitNode(Node node) => false;
  bool visitStringInterpolation(StringInterpolation node) => true;
  bool visitStringJuxtaposition(StringJuxtaposition node) =>
      node.isInterpolation;
}

/// Erroneous node used to recover from parser errors.  Implements various
/// interfaces and provides bare minimum of implementation to avoid unnecessary
/// messages.
class ErrorNode extends Node
    implements FunctionExpression, VariableDefinitions, Typedef {
  final Token token;
  final String reason;
  final Identifier name;
  final NodeList definitions;

  ErrorNode.internal(this.token, this.reason, this.name, this.definitions);

  factory ErrorNode(Token token, String reason) {
    Identifier name = new Identifier(token);
    NodeList definitions =
        new NodeList(null, const Link<Node>().prepend(name), null, null);
    return new ErrorNode.internal(token, reason, name, definitions);
  }

  Token get beginToken => token;
  Token get endToken => token;

  Token getBeginToken() => token;

  Token getEndToken() => token;

  accept(Visitor visitor) {}

  accept1(Visitor1 visitor, arg) {}

  visitChildren(Visitor visitor) {}

  visitChildren1(Visitor1 visitor, arg) {}

  bool get isErroneous => true;

  // FunctionExpression.
  get asyncModifier => null;
  get parameters => null;
  get body => null;
  get returnType => null;
  get modifiers => Modifiers.EMPTY;
  get initializers => null;
  get getOrSet => null;
  get isRedirectingFactory => false;
  bool get hasBody => false;
  bool get hasEmptyBody => false;

  // VariableDefinitions.
  get metadata => null;
  get type => null;

  // Typedef.
  get typeParameters => null;
  get formals => null;
  get typedefKeyword => null;
}
