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

#include "vm/parser.h"

#include "vm/bigint_operations.h"
#include "vm/class_finalizer.h"
#include "vm/compiler.h"
#include "vm/compiler_stats.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
#include "vm/longjump.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/resolver.h"
#include "vm/scopes.h"

namespace dart {

DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements.");
DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks.");
DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors.");
DEFINE_FLAG(bool, silent_warnings, true, "Silence warnings.");
DEFINE_FLAG(bool, warn_params, false, "Report legacy parameter syntax");

// All references to Dart names are listed here.
static const char* kAssertErrorName = "AssertError";
static const char* kFallThroughErrorName = "FallThroughError";
static const char* kThrowNewName = "throwNew";
static const char* kGrowableObjectArrayFromArrayName =
    "GrowableObjectArray._usingArray";
static const char* kGrowableObjectArrayName = "GrowableObjectArray";
static const char* kMutableMapName = "MutableMap";
static const char* kMutableMapFromLiteralName = "fromLiteral";
static const char* kImmutableMapName = "ImmutableMap";
static const char* kImmutableMapConstructorName = "ImmutableMap.";
static const char* kStringClassName = "StringBase";
static const char* kInterpolateName = "_interpolate";
static const char* kThisName = "this";
static const char* kGetIteratorName = "iterator";

#if defined(DEBUG)

class TraceParser : public ValueObject {
 public:
  TraceParser(intptr_t token_index, const Script& script, const char* msg) {
    if (FLAG_trace_parser) {
      intptr_t line, column;
      script.GetTokenLocation(token_index, &line, &column);
      PrintIndent();
      OS::Print("%s (line %d, col %d, token %d)\n",
                msg, line, column, token_index);
      indent_++;
    }
  }
  ~TraceParser() { indent_--; }
 private:
  void PrintIndent() {
    for (int i = 0; i < indent_; i++) { OS::Print(". "); }
  }
  static int indent_;
};

int TraceParser::indent_ = 0;

#define TRACE_PARSER(s) \
  TraceParser __p__(this->token_index_, this->script_, s)

#else  // not DEBUG
#define TRACE_PARSER(s)
#endif  // DEBUG


static const char* kManglePrefix = "this:";

static RawString* MangledInitParamName(const String& field_name) {
  return String::Concat(String::Handle(String::New(kManglePrefix)),
                        field_name);
}


template<typename T>
static RawArray* NewArray(const GrowableArray<T*>& objs) {
  Array& a = Array::Handle(Array::New(objs.length(), Heap::kOld));
  for (int i = 0; i < objs.length(); i++) {
    a.SetAt(i, *objs[i]);
  }
  return a.raw();
}


static RawTypeArray* NewTypeArray(const GrowableArray<Type*>& objs) {
  TypeArray& a = TypeArray::Handle(TypeArray::New(objs.length()));
  for (int i = 0; i < objs.length(); i++) {
    a.SetTypeAt(i, *objs[i]);
  }
  return a.raw();
}


struct Parser::Block : public ZoneAllocated {
  Block(Block* outer_block, LocalScope* local_scope, SequenceNode* seq)
    : parent(outer_block), scope(local_scope), statements(seq) {
    ASSERT(scope != NULL);
    ASSERT(statements != NULL);
  }
  Block* parent;  // Enclosing block, or NULL if outermost.
  LocalScope* scope;
  SequenceNode* statements;
};


// Class which describes an inlined finally block which is used to generate
// inlined code for the finally blocks when there is an exit from a try
// block using 'return', 'break' or 'continue'.
class Parser::TryBlocks : public ZoneAllocated {
 public:
  TryBlocks(Block* try_block, TryBlocks* outer_try_block)
      : try_block_(try_block),
        inlined_finally_nodes_(),
        outer_try_block_(outer_try_block) { }

  TryBlocks* outer_try_block() const { return outer_try_block_; }
  Block* try_block() const { return try_block_; }

  void AddNodeForFinallyInlining(AstNode* node);
  AstNode* GetNodeToInlineFinally(int index) {
    if (0 <= index && index < inlined_finally_nodes_.length()) {
      return inlined_finally_nodes_[index];
    }
    return NULL;
  }

 private:
  Block* try_block_;
  GrowableArray<AstNode*> inlined_finally_nodes_;
  TryBlocks* outer_try_block_;

  DISALLOW_COPY_AND_ASSIGN(TryBlocks);
};


void Parser::TryBlocks::AddNodeForFinallyInlining(AstNode* node) {
  inlined_finally_nodes_.Add(node);
}


Parser::Parser(const Script& script, const Library& library)
    : script_(script),
      tokens_(TokenStream::Handle(script.tokens())),
      token_index_(0),
      current_block_(NULL),
      is_top_level_(false),
      current_member_(NULL),
      allow_function_literals_(true),
      current_function_(Function::Handle()),
      current_class_(Class::Handle()),
      library_(library),
      try_blocks_list_(NULL) {
  SetPosition(0);
}


Parser::Parser(const Script& script,
               const Function& function,
               intptr_t token_index)
    : script_(script),
      tokens_(TokenStream::Handle(script.tokens())),
      token_index_(0),
      current_block_(NULL),
      is_top_level_(false),
      current_member_(NULL),
      allow_function_literals_(true),
      current_function_(function),
      current_class_(Class::Handle(current_function_.owner())),
      library_(Library::Handle(current_class_.library())),
      try_blocks_list_(NULL) {
  SetPosition(token_index);
}


bool Parser::SetAllowFunctionLiterals(bool value) {
  bool current_value = allow_function_literals_;
  allow_function_literals_ = value;
  return current_value;
}


const Function& Parser::current_function() const {
  return current_function_;
}


const Class& Parser::current_class() const {
  return current_class_;
}


void Parser::set_current_class(const Class& value) {
  current_class_ = value.raw();
}


void Parser::SetPosition(intptr_t position) {
  if (position < token_index_ && position != 0) {
    CompilerStats::num_tokens_rewind += (token_index_ - position);
  }
  token_index_ = position;
  token_kind_ = Token::kILLEGAL;
}


void Parser::ParseCompilationUnit(const Library& library,
                                  const Script& script) {
  Parser parser(script, library);
  if (FLAG_compiler_stats) {
    CompilerStats::parser_timer.Start();
  }
  parser.ParseTopLevel();
  if (FLAG_compiler_stats) {
    CompilerStats::parser_timer.Stop();
    CompilerStats::num_tokens_total += parser.tokens_.Length();
  }
}


Token::Kind Parser::CurrentToken() {
  if (token_kind_ == Token::kILLEGAL) {
    token_kind_ = tokens_.KindAt(token_index_);
    if (token_kind_ == Token::kERROR) {
      ErrorMsg(token_index_, CurrentLiteral()->ToCString());
    }
    if (Token::IsPseudoKeyword(token_kind_) && !is_top_level_) {
      token_kind_ = Token::kIDENT;
    }
  }
  CompilerStats::num_token_checks++;
  return token_kind_;
}


Token::Kind Parser::LookaheadToken(int num_tokens) {
  CompilerStats::num_tokens_lookahead++;
  CompilerStats::num_token_checks++;
  return tokens_.KindAt(token_index_ + num_tokens);
}


String* Parser::CurrentLiteral() const {
  String& result = String::ZoneHandle();
  result ^= tokens_.LiteralAt(token_index_);
  return &result;
}


// A QualIdent is an optionally qualified identifier.
struct QualIdent {
  QualIdent() {
    Clear();
  }
  void Clear() {
    local_scope_ident = false;
    lib_prefix = NULL;
    qualifier = NULL;
    ident_pos = 0;
    ident = NULL;
  }
  bool local_scope_ident;
  LibraryPrefix* lib_prefix;
  String* qualifier;
  intptr_t ident_pos;
  String* ident;
};


struct ParamDesc {
  ParamDesc()
      : type(NULL),
        name_pos(0),
        name(NULL),
        default_value(NULL),
        is_final(false),
        is_field_initializer(false) { }
  const Type* type;
  intptr_t name_pos;
  const String* name;
  const Object* default_value;  // NULL if not an optional parameter.
  bool is_final;
  bool is_field_initializer;
};


struct ParamList {
  ParamList() {
    Clear();
  }

  void Clear() {
    num_fixed_parameters = 0;
    num_optional_parameters = 0;
    has_named_optional_parameters = false;
    has_field_initializer = false;
    implicitly_final = false;
    this->parameters = new ZoneGrowableArray<ParamDesc>();
  }

  void AddFinalParameter(intptr_t name_pos,
                         const char* name,
                         const Type* type) {
    this->num_fixed_parameters++;
    ParamDesc param;
    param.name_pos = name_pos;
    param.name = &String::ZoneHandle(String::NewSymbol(name));
    param.is_final = true;
    param.type = type;
    this->parameters->Add(param);
  }

  void AddReceiver(intptr_t name_pos) {
    ASSERT(this->parameters->length() == 0);
    // The receiver does not need to be type checked.
    AddFinalParameter(name_pos, kThisName, &Type::ZoneHandle(Type::VarType()));
  }

  void SetImplicitlyFinal() {
    implicitly_final = true;
  }

  int num_fixed_parameters;
  int num_optional_parameters;
  bool has_named_optional_parameters;  // Indicates use of the new syntax.
  bool has_field_initializer;
  bool implicitly_final;
  ZoneGrowableArray<ParamDesc>* parameters;
};


struct MemberDesc {
  MemberDesc() {
    Clear();
  }
  void Clear() {
    has_abstract = false;
    has_final = false;
    has_const = false;
    has_static = false;
    has_var = false;
    has_factory = false;
    type = NULL;
    name_pos = 0;
    name = NULL;
    redirect_name = NULL;
    params.Clear();
    kind = RawFunction::kFunction;
  }
  bool IsConstructor() const {
    return (kind == RawFunction::kConstructor) && !has_static;
  }
  bool IsFactory() const {
    return (kind == RawFunction::kConstructor) && has_static;
  }
  bool IsFactoryOrConstructor() const {
    return (kind == RawFunction::kConstructor);
  }
  bool IsGetter() const {
    return kind == RawFunction::kGetterFunction;
  }
  bool IsSetter() const {
    return kind == RawFunction::kSetterFunction;
  }
  bool has_abstract;
  bool has_final;
  bool has_const;
  bool has_static;
  bool has_var;
  bool has_factory;
  const Type* type;
  intptr_t name_pos;
  String* name;
  String* redirect_name;  // For constructors: NULL or redirected constructor.
  ParamList params;
  RawFunction::Kind kind;
};


class ClassDesc : public ValueObject {
 public:
  ClassDesc(const Class& cls,
            const String& cls_name,
            bool is_interface,
            intptr_t token_pos)
      : clazz_(cls),
        class_name_(cls_name),
        is_interface_(is_interface),
        token_pos_(token_pos),
        functions_(4),
        fields_(4) {
  }

  bool FunctionNameExists(const String& name, RawFunction::Kind kind) const {
    // First check if a function or field of same name exists.
    if (NameExists<Function>(functions_, name) ||
        NameExists<Field>(fields_, name)) {
      return true;
    }
    String& accessor_name = String::Handle();
    if (kind != RawFunction::kSetterFunction) {
      // Check if a getter function of same name exists.
      accessor_name = Field::GetterName(name);
      if (NameExists<Function>(functions_, accessor_name)) {
        return true;
      }
    }
    if (kind != RawFunction::kGetterFunction) {
      // Check if a setter function of same name exists.
      accessor_name = Field::SetterName(name);
      if (NameExists<Function>(functions_, accessor_name)) {
        return true;
      }
    }
    return false;
  }

  bool FieldNameExists(const String& name) const {
    // First check if a function or field of same name exists.
    if (NameExists<Function>(functions_, name) ||
        NameExists<Field>(fields_, name)) {
      return true;
    }
    // Now check if a getter/setter function of same name exists.
    String& getter_name = String::Handle(Field::GetterName(name));
    String& setter_name = String::Handle(Field::SetterName(name));
    if (NameExists<Function>(functions_, getter_name) ||
        NameExists<Function>(functions_, setter_name)) {
      return true;
    }
    return false;
  }

  void AddFunction(Function* function) {
    ASSERT(!NameExists<Function>(functions_, String::Handle(function->name())));
    functions_.Add(function);
  }

  const GrowableArray<Function*>& functions() const {
    return functions_;
  }

  void AddField(Field* field) {
    ASSERT(!NameExists<Field>(fields_, String::Handle(field->name())));
    fields_.Add(field);
  }

  const GrowableArray<Field*>& fields() const {
    return fields_;
  }

  RawClass* clazz() const {
    return clazz_.raw();
  }

  const String& class_name() const {
    return class_name_;
  }

  bool is_interface() const {
    return is_interface_;
  }

  bool has_constructor() const {
    for (int i = 0; i < functions_.length(); i++) {
      if (functions_[i]->kind() == RawFunction::kConstructor) {
        return true;
      }
    }
    return false;
  }

  intptr_t token_pos() const {
    return token_pos_;
  }

  void AddMember(const MemberDesc& member) {
    members_.Add(member);
  }

  const GrowableArray<MemberDesc>& members() const {
    return members_;
  }

  MemberDesc* LookupMember(const String& name) const {
    for (int i = 0; i < members_.length(); i++) {
      if (name.Equals(*members_[i].name)) {
        return &members_[i];
      }
    }
    return NULL;
  }

 private:
  template<typename T>
  bool NameExists(const GrowableArray<T*>& list, const String& name) const {
    String& test_name = String::Handle();
    for (int i = 0; i < list.length(); i++) {
      test_name = list[i]->name();
      if (name.Equals(test_name)) {
        return true;
      }
    }
    return false;
  }

  const Class& clazz_;
  const String& class_name_;
  const bool is_interface_;
  intptr_t token_pos_;   // Token index of "class" keyword.
  GrowableArray<Function*> functions_;
  GrowableArray<Field*> fields_;
  GrowableArray<MemberDesc> members_;
};


struct TopLevel {
  TopLevel() : fields(4), functions(4) { }

  GrowableArray<Field*> fields;
  GrowableArray<Function*> functions;
};


void Parser::ParseFunction(ParsedFunction* parsed_function) {
  Isolate* isolate = Isolate::Current();
  // Compilation can be nested, preserve the ast node id.
  const int prev_ast_node_id = isolate->ast_node_id();
  isolate->set_ast_node_id(0);
  ASSERT(parsed_function != NULL);
  const Function& func = parsed_function->function();
  const Class& cls = Class::Handle(func.owner());
  const Script& script = Script::Handle(cls.script());
  Parser parser(script, func, func.token_index());
  if (FLAG_compiler_stats) {
    CompilerStats::parser_timer.Start();
  }
  SequenceNode* node_sequence = NULL;
  Array& default_parameter_values = Array::Handle();
  switch (func.kind()) {
    case RawFunction::kFunction:
    case RawFunction::kClosureFunction:
    case RawFunction::kGetterFunction:
    case RawFunction::kSetterFunction:
    case RawFunction::kConstructor:
      node_sequence = parser.ParseFunc(func, default_parameter_values);
      break;
    case RawFunction::kImplicitGetter:
      ASSERT(!func.is_static());
      node_sequence = parser.ParseInstanceGetter(func);
      break;
    case RawFunction::kImplicitSetter:
      ASSERT(!func.is_static());
      node_sequence = parser.ParseInstanceSetter(func);
      break;
    case RawFunction::kConstImplicitGetter:
      node_sequence = parser.ParseStaticConstGetter(func);
      break;
    default:
      UNREACHABLE();
  }

  if ((node_sequence->length() == 0) ||
      !node_sequence->NodeAt(node_sequence->length() - 1)->IsReturnNode()) {
    // Add implicit return node.
    node_sequence->Add(new ReturnNode(parser.token_index_));
  }
  parsed_function->set_node_sequence(node_sequence);

  // The instantiator may be required at run time for generic type checks or
  // allocation of generic types.
  if (parser.current_class().IsParameterized() &&
      (!parser.current_function().IsInStaticScope() ||
       parser.current_function().IsInFactoryScope())) {
    // In the case of a local function, only set the instantiator if the
    // receiver was captured.
    const bool kTestOnly = true;
    LocalVariable* receiver =
        parser.LookupReceiver(node_sequence->scope(),
                              kTestOnly);
    if (!parser.current_function().IsLocalFunction() ||
        ((receiver != NULL) && receiver->is_captured())) {
      parsed_function->set_instantiator(
          new LoadLocalNode(node_sequence->token_index(), *receiver));
    }
  }

  parsed_function->set_default_parameter_values(default_parameter_values);
  if (FLAG_compiler_stats) {
    CompilerStats::parser_timer.Stop();
  }
  isolate->set_ast_node_id(prev_ast_node_id);
}


SequenceNode* Parser::ParseStaticConstGetter(const Function& func) {
  ParamList params;
  ASSERT(func.num_fixed_parameters() == 0);  // static.
  ASSERT(func.num_optional_parameters() == 0);
  ASSERT(Type::Handle(func.result_type()).IsResolved());

  // Build local scope for function and populate with the formal parameters.
  OpenFunctionBlock(func);
  AddFormalParamsToScope(&params, current_block_->scope);

  // Static const fields must have an initializer.
  ExpectToken(Token::kIDENT);
  ExpectToken(Token::kASSIGN);

  // We don't want to use ParseConstExpr() here because we don't want
  // the constant folding code to create, compile and execute a code
  // fragment to evaluate the expression. Instead, we just make sure
  // the static const field initializer is a constant expression and
  // leave the evaluation to the getter function.
  intptr_t expr_pos = token_index_;
  AstNode* expr = ParseExpr(kAllowConst);
  if (expr->EvalConstExpr() == NULL) {
    ErrorMsg(expr_pos, "initializer must be a compile time constant");
  }
  ReturnNode* return_node = new ReturnNode(token_index_, expr);
  current_block_->statements->Add(return_node);
  return CloseBlock();
}


// Create AstNodes for an implicit instance getter method:
//   LoadLocalNode 0 ('this');
//   LoadInstanceFieldNode (field_name);
//   ReturnNode (field's value);
SequenceNode* Parser::ParseInstanceGetter(const Function& func) {
  TRACE_PARSER("ParseInstanceGetter");
  ParamList params;
  params.AddReceiver(token_index_);
  ASSERT(func.num_fixed_parameters() == 1);  // receiver.
  ASSERT(func.num_optional_parameters() == 0);
  ASSERT(Type::Handle(func.result_type()).IsResolved());

  // Build local scope for function and populate with the formal parameters.
  OpenFunctionBlock(func);
  AddFormalParamsToScope(&params, current_block_->scope);

  // Receiver is local 0.
  LocalVariable* receiver = current_block_->scope->VariableAt(0);
  LoadLocalNode* load_receiver = new LoadLocalNode(token_index_, *receiver);
  // token_index_ is the function's token position which points to the name of
  // the field;
  ASSERT(CurrentToken() == Token::kIDENT);
  const String& field_name = *CurrentLiteral();
  const Class& field_class = Class::Handle(func.owner());
  const Field& field =
      Field::ZoneHandle(field_class.LookupInstanceField(field_name));

  LoadInstanceFieldNode* load_field =
      new LoadInstanceFieldNode(token_index_, load_receiver, field);

  ReturnNode* return_node = new ReturnNode(token_index_, load_field);
  current_block_->statements->Add(return_node);
  return CloseBlock();
}


// Create AstNodes for an implicit instance setter method:
//   LoadLocalNode 0 ('this')
//   LoadLocalNode 1 ('value')
//   SetInstanceField (field_name);
//   ReturnNode (void);
SequenceNode* Parser::ParseInstanceSetter(const Function& func) {
  TRACE_PARSER("ParseInstanceSetter");
  // token_index_ is the function's token position which points to the name of
  // the field; we can use it to form the field_name.
  const String& field_name = *CurrentLiteral();
  const Class& field_class = Class::ZoneHandle(func.owner());
  const Field& field =
      Field::ZoneHandle(field_class.LookupInstanceField(field_name));
  const Type& field_type = Type::ZoneHandle(field.type());

  ParamList params;
  params.AddReceiver(token_index_);
  params.AddFinalParameter(token_index_, "value", &field_type);
  ASSERT(func.num_fixed_parameters() == 2);  // receiver, value.
  ASSERT(func.num_optional_parameters() == 0);
  ASSERT(Type::Handle(func.result_type()).IsVoidType());

  // Build local scope for function and populate with the formal parameters.
  OpenFunctionBlock(func);
  AddFormalParamsToScope(&params, current_block_->scope);

  LoadLocalNode* receiver =
      new LoadLocalNode(token_index_, *current_block_->scope->VariableAt(0));
  LoadLocalNode* value =
      new LoadLocalNode(token_index_, *current_block_->scope->VariableAt(1));

  StoreInstanceFieldNode* store_field =
      new StoreInstanceFieldNode(token_index_, receiver, field, value);

  current_block_->statements->Add(store_field);
  current_block_->statements->Add(new ReturnNode(token_index_));
  return CloseBlock();
}


void Parser::SkipBlock() {
  ASSERT(CurrentToken() == Token::kLBRACE);
  GrowableArray<Token::Kind> token_stack(8);
  intptr_t block_start_pos = token_index_;
  bool is_match = true;
  bool unexpected_token_found = false;
  Token::Kind token;
  intptr_t token_index;
  do {
    token = CurrentToken();
    token_index = token_index_;
    switch (token) {
      case Token::kLBRACE:
      case Token::kLPAREN:
      case Token::kLBRACK:
        token_stack.Add(token);
        break;
      case Token::kRBRACE:
        is_match = token_stack.Last() == Token::kLBRACE;
        token_stack.RemoveLast();
        break;
      case Token::kRPAREN:
        is_match = token_stack.Last() == Token::kLPAREN;
        token_stack.RemoveLast();
        break;
      case Token::kRBRACK:
        is_match = token_stack.Last() == Token::kLBRACK;
        token_stack.RemoveLast();
        break;
      case Token::kEOS:
        unexpected_token_found = true;
        break;
      default:
        // nothing.
        break;
    }
    ConsumeToken();
  } while (!token_stack.is_empty() && is_match && !unexpected_token_found);
  if (!is_match) {
    ErrorMsg(token_index, "unbalanced '%s'", Token::Str(token));
  } else if (unexpected_token_found) {
    ErrorMsg(block_start_pos, "unterminated block");
  }
}


void Parser::ParseFormalParameter(bool allow_explicit_default_value,
                                  ParamList* params) {
  TRACE_PARSER("ParseFormalParameter");
  ParamDesc parameter;
  bool var_seen = false;
  bool this_seen = false;

  if (CurrentToken() == Token::kFINAL) {
    ConsumeToken();
    parameter.is_final = true;
  } else if (CurrentToken() == Token::kVAR) {
    ConsumeToken();
    var_seen = true;
    // The parameter type is the 'var' type.
    parameter.type = &Type::ZoneHandle(Type::VarType());
  }
  if (CurrentToken() == Token::kTHIS) {
    ConsumeToken();
    ExpectToken(Token::kPERIOD);
    this_seen = true;
    parameter.is_field_initializer = true;
  }
  if (params->implicitly_final) {
    parameter.is_final = true;
  }
  if ((parameter.type == NULL) && (CurrentToken() == Token::kVOID)) {
    ConsumeToken();
    // This must later be changed to a closure type if we recognize
    // a closure/function type parameter. We check this at the end
    // of ParseFormalParameter.
    parameter.type = &Type::ZoneHandle(Type::VoidType());
  }
  if (parameter.type == NULL) {
    // At this point, we must see an identifier for the type or the
    // function parameter.
    if (CurrentToken() != Token::kIDENT) {
      ErrorMsg("parameter name or type expected");
    }
    // We have not seen a parameter type yet, so we check if the next
    // identifier could represent a type before parsing it.
    Token::Kind follower = LookaheadToken(1);
    // We have an identifier followed by a 'follower' token.
    // We either parse a type or assume that no type is specified.
    if ((follower == Token::kLT) ||  // Parameterized type.
        (follower == Token::kPERIOD) ||  // Qualified class name of type.
        (follower == Token::kIDENT) ||  // Parameter name following a type.
        (follower == Token::kTHIS)) {  // Field parameter following a type.
      parameter.type = &Type::ZoneHandle(
          ParseType(is_top_level_ ? kCanResolve : kMustResolve));
    } else {
      parameter.type = &Type::ZoneHandle(Type::VarType());
    }
  }
  if (!this_seen && (CurrentToken() == Token::kTHIS)) {
    ConsumeToken();
    ExpectToken(Token::kPERIOD);
    this_seen = true;
    parameter.is_field_initializer = true;
  }
  // At this point, we must see an identifier for the parameter name.
  if (CurrentToken() != Token::kIDENT) {
    ErrorMsg("parameter name expected");
  }
  parameter.name = CurrentLiteral();
  parameter.name_pos = token_index_;
  ConsumeToken();
  if (parameter.is_field_initializer) {
    params->has_field_initializer = true;
  }

  if (CurrentToken() == Token::kLPAREN) {
    // This parameter is probably a closure. If we saw the keyword 'var'
    // or 'final', a closure is not legal here and we ignore the
    // opening parens.
    if (!var_seen && !parameter.is_final) {
      // The parsed parameter type is actually the function result type.
      const Type& result_type = Type::Handle(parameter.type->raw());
      // Finish parsing the function type parameter.
      ParamList func_params;
      const bool no_explicit_default_values = false;
      ParseFormalParameterList(no_explicit_default_values, &func_params);
      // Change the name of the parameter type to be the signature of the
      // function type.
      // Note that the function type signature may involve parameters of a type
      // that is a type parameter of the enclosing class, so we parameterize the
      // signature with the type parameters of the enclosing class, if any.
      // TODO(regis): Revisit if this is not the right thing to do.
      const bool is_static =
          current_function().IsNull() || current_function().IsInStaticScope();
      const Function& signature_function = Function::Handle(
          Function::New(*parameter.name,
                        RawFunction::kSignatureFunction,
                        is_static,
                        /* is_const = */ false,
                        parameter.name_pos));
      signature_function.set_owner(current_class());
      signature_function.set_result_type(result_type);
      AddFormalParamsToFunction(&func_params, signature_function);
      const String& signature = String::Handle(signature_function.Signature());
      // Lookup the class named signature and only create a new class if it does
      // not exist yet.
      Class& signature_class = Class::ZoneHandle(LookupClass(signature));
      if (signature_class.IsNull()) {
        signature_class = Class::NewSignatureClass(signature,
                                                   signature_function,
                                                   script_,
                                                   parameter.name_pos);
        // Record the function signature class in the library.
        library_.AddClass(signature_class);
      }
      ASSERT(!Function::Handle(signature_class.signature_function()).IsNull());
      ASSERT(Class::Handle(signature_function.signature_class()).IsNull());
      signature_function.set_signature_class(signature_class);
      // The type of the parameter is now the signature class.
      // TODO(regis): What are the type arguments?
      parameter.type = &Type::ZoneHandle(Type::NewRawType(signature_class));
      if (!is_top_level_) {
        const String& errmsg = String::Handle(
            ClassFinalizer::FinalizeTypeWhileParsing(*parameter.type));
        if (!errmsg.IsNull()) {
          ErrorMsg(errmsg.ToCString());
        }
      }
    }
  }

  if (CurrentToken() == Token::kASSIGN) {
    if (!allow_explicit_default_value) {
      // TODO(regis): Remove support for legacy optional parameters:
      // The if guard below needs to be removed, i.e. the error must
      // be reported for both positional and named optional parameters.
      if (params->has_named_optional_parameters) {
        ErrorMsg("parameter must not specify a default value");
      }
    }
    if (FLAG_warn_params && !params->has_named_optional_parameters) {
      // Turn on warnings automagically.
      bool save_silent = FLAG_silent_warnings;
      FLAG_silent_warnings = false;
      Warning("legacy optional parameter '%s'", parameter.name->ToCString());
      FLAG_silent_warnings = save_silent;
    }
    ConsumeToken();
    params->num_optional_parameters++;
    if (is_top_level_) {
      // Skip default value parsing.
      SkipExpr();
    } else {
      const Object& const_value = ParseConstExpr()->literal();
      parameter.default_value = &const_value;
    }
  } else {
    if (params->has_named_optional_parameters) {
      // Implicit default value is null.
      params->num_optional_parameters++;
      parameter.default_value = &Object::ZoneHandle();
    } else {
      // TODO(regis): Remove support of legacy syntax.
      params->num_fixed_parameters++;
      if (params->num_optional_parameters > 0) {
        ErrorMsg("optional parameters must be last");
      }
    }
  }
  if (parameter.type->IsVoidType()) {
    ErrorMsg("parameter '%s' may not be 'void'", parameter.name->ToCString());
  }
  params->parameters->Add(parameter);
}


void Parser::ParseFormalParameterList(bool allow_explicit_default_values,
                                      ParamList* params) {
  TRACE_PARSER("ParseFormalParameterList");
  ASSERT(CurrentToken() == Token::kLPAREN);

  if (LookaheadToken(1) != Token::kRPAREN) {
    // Parse positional parameters.
    ParseFormalParameters(allow_explicit_default_values,
                          params);
    if (CurrentToken() == Token::kLBRACK) {
      ASSERT(!params->has_named_optional_parameters);
      params->has_named_optional_parameters = true;
      // Parse named optional parameters.
      ParseFormalParameters(allow_explicit_default_values,
                            params);
      if (CurrentToken() != Token::kRBRACK) {
        ErrorMsg("',' or ']' expected");
      }
      ExpectToken(Token::kRBRACK);
    }
    if ((CurrentToken() != Token::kRPAREN) &&
        !params->has_named_optional_parameters) {
      ErrorMsg("',' or ')' expected");
    }
  } else {
    ConsumeToken();
  }
  ExpectToken(Token::kRPAREN);
}


// Parses a sequence of normal or named formal parameters.
void Parser::ParseFormalParameters(bool allow_explicit_default_values,
                                   ParamList* params) {
  TRACE_PARSER("ParseFormalParameters");
  do {
    ConsumeToken();
    if (!params->has_named_optional_parameters &&
        (CurrentToken() == Token::kLBRACK)) {
      // End of normal parameters, start of named parameters.
      return;
    }
    ParseFormalParameter(allow_explicit_default_values, params);
  } while (CurrentToken() == Token::kCOMMA);
}


String& Parser::ParseNativeDeclaration() {
  TRACE_PARSER("ParseNativeDeclaration");
  ASSERT(IsLiteral("native"));
  ConsumeToken();
  if (CurrentToken() != Token::kSTRING) {
    ErrorMsg("string literal expected");
  }
  String& native_name = *CurrentLiteral();
  ConsumeToken();
  ExpectSemicolon();
  return native_name;
}


void Parser::CheckFunctionIsCallable(intptr_t token_index,
                                     const Function& function) {
  if (Class::Handle(function.owner()).is_interface()) {
    ErrorMsg(token_index, "cannot call function of interface '%s'",
        function.ToFullyQualifiedCString());
  }
}


static RawFunction* ResolveDynamicFunction(const Class& cls,
                                           const String& name) {
  Function& func = Function::Handle(cls.LookupDynamicFunction(name));
  if (func.IsNull()) {
    Class& super_cls = Class::Handle(cls.SuperClass());
    while (!super_cls.IsNull()) {
      func = super_cls.LookupDynamicFunction(name);
      if (!func.IsNull()) {
        return func.raw();
      }
      super_cls = super_cls.SuperClass();
    }
  }
  return func.raw();
}


AstNode* Parser::ParseSuperCall(const String& function_name) {
  TRACE_PARSER("ParseSuperCall");
  ASSERT(CurrentToken() == Token::kLPAREN);
  const intptr_t supercall_pos = token_index_;
  const Class& super_class = Class::Handle(current_class().SuperClass());
  if (super_class.IsNull()) {
    ErrorMsg("class '%s' does not have a superclass",
             String::Handle(current_class().Name()).ToCString());
  }
  // 'this' parameter is the first argument to super call.
  AstNode* implicit_argument = LoadReceiver();
  ArgumentListNode* arguments =
      ParseActualParameters(implicit_argument, kAllowConst);
  // Resolve the function.
  const Function& super_function = Function::ZoneHandle(
      ResolveDynamicFunction(super_class, function_name));
  if (super_function.IsNull()) {
    ErrorMsg(supercall_pos,
             "function '%s' not found in super class",
             function_name.ToCString());
  }
  CheckFunctionIsCallable(supercall_pos, super_function);
  return new StaticCallNode(supercall_pos, super_function, arguments);
}


AstNode* Parser::CreateImplicitClosureNode(const Function& func,
                                           intptr_t token_pos,
                                           AstNode* receiver) {
  Function& implicit_closure_function =
      Function::ZoneHandle(func.ImplicitClosureFunction());
  ASSERT(!implicit_closure_function.IsNull());
  ASSERT(implicit_closure_function.is_static());  // TODO(regis): For now.
  AstNode* node;
  if (receiver == NULL) {
    ASSERT(func.is_static());
    node = new StaticImplicitClosureNode(token_pos, implicit_closure_function);
  } else {
    ASSERT(!func.is_static());
    node = new ImplicitClosureNode(token_pos,
                                   implicit_closure_function,
                                   receiver);
  }
  return node;
}


AstNode* Parser::ParseSuperFieldAccess(const String& field_name) {
  const intptr_t field_pos = token_index_;
  const Class& super_class = Class::Handle(current_class().SuperClass());
  if (super_class.IsNull()) {
    ErrorMsg("class '%s' does not have a superclass",
             String::Handle(current_class().Name()).ToCString());
  }
  AstNode* implicit_argument = LoadReceiver();

  const String& getter_name =
      String::ZoneHandle(Field::GetterName(field_name));
  const Function& super_getter = Function::ZoneHandle(
      ResolveDynamicFunction(super_class, getter_name));
  if (super_getter.IsNull()) {
    // Check if this is an access to an implicit closure using 'super'.
    // If a function exists of the specified field_name then try
    // accessing it as a getter, at runtime we will handle this by
    // creating an implicit closure of the function and returning it.
    const Function& super_function = Function::ZoneHandle(
        ResolveDynamicFunction(super_class, field_name));
    if (super_function.IsNull()) {
      ErrorMsg(field_pos, "field or getter '%s' not found in superclass",
               field_name.ToCString());
    }
    return CreateImplicitClosureNode(super_function,
                                     field_pos,
                                     implicit_argument);
  }
  // All dynamic getters take one argument and no named arguments.
  ASSERT(super_getter.AreValidArgumentCounts(1, 0));
  ArgumentListNode* getter_arguments = new ArgumentListNode(field_pos);
  getter_arguments->Add(implicit_argument);
  AstNode* super_field =
      new StaticCallNode(field_pos, super_getter, getter_arguments);

  if (Token::IsAssignmentOperator(CurrentToken())) {
    const String& setter_name =
        String::ZoneHandle(Field::SetterName(field_name));
    const Function& super_setter = Function::ZoneHandle(
        ResolveDynamicFunction(super_class, setter_name));
    if (super_setter.IsNull()) {
      ErrorMsg(field_pos,
               "field '%s' not assignable in superclass",
               field_name.ToCString());
    }
    // All dynamic setters take two arguments and no named arguments.
    ASSERT(super_setter.AreValidArgumentCounts(2, 0));

    Token::Kind assignment_op = CurrentToken();
    ConsumeToken();
    AstNode* value = ParseExpr(kAllowConst);
    value = ExpandAssignableOp(field_pos, assignment_op, super_field, value);

    ArgumentListNode* setter_arguments = new ArgumentListNode(field_pos);
    setter_arguments->Add(implicit_argument);
    setter_arguments->Add(value);
    super_field = new StaticCallNode(field_pos, super_setter, setter_arguments);
  }
  return super_field;
}


AstNode* Parser::ParseSuperInitializer(const Class& cls,
                                       LocalVariable* receiver) {
  TRACE_PARSER("ParseSuperInitializer");
  ASSERT(CurrentToken() == Token::kSUPER);
  const intptr_t supercall_pos = token_index_;
  ConsumeToken();
  const Class& super_class = Class::Handle(cls.SuperClass());
  ASSERT(!super_class.IsNull());
  String& ctor_name = String::Handle(super_class.Name());
  String& ctor_suffix = String::Handle(String::NewSymbol("."));
  if (CurrentToken() == Token::kPERIOD) {
    ConsumeToken();
    ctor_suffix = String::Concat(
        ctor_suffix, *ExpectIdentifier("constructor name expected"));
  }
  ctor_name = String::Concat(ctor_name, ctor_suffix);
  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg("parameter list expected");
  }
  // 'this' parameter is the first argument to super class constructor.
  AstNode* implicit_argument = new LoadLocalNode(supercall_pos, *receiver);
  ArgumentListNode* arguments =
      ParseActualParameters(implicit_argument, kAllowConst);
  // Resolve the constructor.
  const Function& super_ctor = Function::ZoneHandle(
      super_class.LookupConstructor(ctor_name));
  if (super_ctor.IsNull() ||
      !super_ctor.AreValidArguments(arguments->length(),
                                    arguments->names())) {
    ErrorMsg(supercall_pos,
             "super class constructor '%s' not found",
             ctor_name.ToCString());
  }
  CheckFunctionIsCallable(supercall_pos, super_ctor);
  return new StaticCallNode(supercall_pos, super_ctor, arguments);
}


AstNode* Parser::ParseInitializer(const Class& cls, LocalVariable* receiver) {
  TRACE_PARSER("ParseInitializer");
  const intptr_t field_pos = token_index_;
  if (CurrentToken() == Token::kTHIS) {
    ConsumeToken();
    ExpectToken(Token::kPERIOD);
  }
  const String& field_name = *ExpectIdentifier("field name expected");
  ExpectToken(Token::kASSIGN);

  // TODO(5412278): Need to check or ensure that the initializer expression
  // does not have access to the instance fields of the object.
  const bool saved_mode = SetAllowFunctionLiterals(false);
  AstNode* init_expr = ParseConditionalExpr();
  SetAllowFunctionLiterals(saved_mode);
  Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name));
  if (field.IsNull()) {
    ErrorMsg(field_pos, "unresolved reference to instance field '%s'",
             field_name.ToCString());
  }
  AstNode* instance = new LoadLocalNode(field_pos, *receiver);
  return new StoreInstanceFieldNode(field_pos, instance, field, init_expr);
}


void Parser::CheckConstFieldsInitialized(const Class& cls) {
  const Array& fields = Array::Handle(cls.fields());
  Field& field = Field::Handle();
  SequenceNode* initializers = current_block_->statements;
  for (int field_num = 0; field_num < fields.Length(); field_num++) {
    field ^= fields.At(field_num);
    if (field.is_static() || !field.is_final()) {
      continue;
    }
    bool found = false;
    for (int i = 0; i < initializers->length(); i++) {
      found = false;
      if (initializers->NodeAt(i)->IsStoreInstanceFieldNode()) {
        StoreInstanceFieldNode* initializer =
            initializers->NodeAt(i)->AsStoreInstanceFieldNode();
        if (initializer->field().raw() == field.raw()) {
          found = true;
          break;
        }
      }
    }
    if (!found) {
      ErrorMsg("const field '%s' not initialized",
               String::Handle(field.name()).ToCString());
    }
  }
}


struct FieldInitExpression {
  Field* inst_field;
  AstNode* expr;
};


void Parser::ParseInitializedInstanceFields(const Class& cls,
                 GrowableArray<FieldInitExpression>* initializers) {
  const Array& fields = Array::Handle(cls.fields());
  Field& f = Field::Handle();
  intptr_t saved_pos = token_index_;
  for (int i = 0; i < fields.Length(); i++) {
    f ^= fields.At(i);
    if (!f.is_static() && f.has_initializer()) {
      Field& field = Field::ZoneHandle();
      field ^= fields.At(i);
      intptr_t field_pos = field.token_index();
      SetPosition(field_pos);
      ASSERT(CurrentToken() == Token::kIDENT);
      ConsumeToken();
      ExpectToken(Token::kASSIGN);
      AstNode* init_expr = ParseConstExpr();
      ASSERT(init_expr != NULL);
      FieldInitExpression initializer;
      initializer.inst_field = &field;
      initializer.expr = init_expr;
      initializers->Add(initializer);
    }
  }
  SetPosition(saved_pos);
}


void Parser::ParseInitializers(const Class& cls, LocalVariable* receiver) {
  TRACE_PARSER("ParseInitializers");
  AstNode* init_statement = NULL;
  AstNode* super_init_statement = NULL;
  // TODO(4995181): Allow super initializer to appear in any position
  // of the initializer list.
  if (CurrentToken() == Token::kSUPER) {
    super_init_statement = ParseSuperInitializer(cls, receiver);
  } else {
    init_statement = ParseInitializer(cls, receiver);
    current_block_->statements->Add(init_statement);
  }
  while (CurrentToken() == Token::kCOMMA) {
    ConsumeToken();
    init_statement = ParseInitializer(cls, receiver);
    current_block_->statements->Add(init_statement);
  }
  // The call to super constructor is to be done after all initializers.
  if (super_init_statement != NULL) {
    current_block_->statements->Add(super_init_statement);
  }
}


void Parser::ParseConstructorRedirection(const Class& cls,
                                         LocalVariable* receiver) {
  ASSERT(CurrentToken() == Token::kTHIS);
  intptr_t call_pos = token_index_;
  ConsumeToken();
  String& ctor_name = String::Handle(cls.Name());
  String& ctor_suffix = String::Handle(String::NewSymbol("."));

  if (CurrentToken() == Token::kPERIOD) {
    ConsumeToken();
    ctor_suffix = String::Concat(
        ctor_suffix, *ExpectIdentifier("constructor name expected"));
  }
  ctor_name = String::Concat(ctor_name, ctor_suffix);
  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg("parameter list expected");
  }
  // 'this' parameter is the first argument to super class constructor.
  AstNode* implicit_argument = new LoadLocalNode(call_pos, *receiver);
  ArgumentListNode* arguments =
      ParseActualParameters(implicit_argument, kAllowConst);

  // Resolve the constructor.
  const Function& redirect_ctor = Function::ZoneHandle(
      cls.LookupConstructor(ctor_name));
  if (redirect_ctor.IsNull() ||
      !redirect_ctor.AreValidArguments(arguments->length(),
                                       arguments->names())) {
    ErrorMsg(call_pos, "constructor '%s' not found",
             ctor_name.ToCString());
  }
  CheckFunctionIsCallable(call_pos, redirect_ctor);
  current_block_->statements->Add(
      new StaticCallNode(call_pos, redirect_ctor, arguments));
}


SequenceNode* Parser::MakeImplicitConstructor(const Function& func) {
  ASSERT(func.IsConstructor());
  intptr_t ctor_pos = token_index_;

  // Implicit 'this' is the only parameter/local variable.
  OpenFunctionBlock(func);


  // Parse expressions of instance fields that have an explicit
  // initializers.
  GrowableArray<FieldInitExpression> initializers;
  Class& cls = Class::Handle(func.owner());
  ParseInitializedInstanceFields(cls, &initializers);

  LocalVariable* receiver = new LocalVariable(
      ctor_pos,
      String::ZoneHandle(String::NewSymbol(kThisName)),
      Type::ZoneHandle(Type::VarType()));
  current_block_->scope->AddVariable(receiver);

  // Now that the "this" parameter is in scope, we can generate the code
  // to strore the initializer expressions in the respective instance fields.
  for (int i = 0; i < initializers.length(); i++) {
    const Field* field = initializers[i].inst_field;
    AstNode* instance = new LoadLocalNode(field->token_index(), *receiver);
    AstNode* field_init =
        new StoreInstanceFieldNode(field->token_index(),
                                   instance,
                                   *field,
                                   initializers[i].expr);
    current_block_->statements->Add(field_init);
  }

  // Super call to constructor of super class.
  const Class& super_class = Class::Handle(cls.SuperClass());
  ASSERT(!super_class.IsNull());
  String& ctor_name = String::Handle(super_class.Name());
  String& ctor_suffix = String::Handle(String::NewSymbol("."));
  ctor_name = String::Concat(ctor_name, ctor_suffix);
  ctor_name = String::NewSymbol(ctor_name);
  ArgumentListNode* arguments = new ArgumentListNode(ctor_pos);
  AstNode* implicit_argument = new LoadLocalNode(ctor_pos, *receiver);
  arguments->Add(implicit_argument);
  const Function& super_ctor = Function::ZoneHandle(
      super_class.LookupConstructor(ctor_name));
  if (super_ctor.IsNull() ||
      !super_ctor.AreValidArgumentCounts(arguments->length(), 0)) {
    ErrorMsg(ctor_pos,
             "super class constructor '%s' not found",
             ctor_name.ToCString());
  }
  current_block_->statements->Add(
      new StaticCallNode(ctor_pos, super_ctor, arguments));

  CheckConstFieldsInitialized(cls);

  // Empty constructor body.
  SequenceNode* statements = CloseBlock();
  return statements;
}


// Parser is at the opening parenthesis of the formal parameter declaration
// of function. Parse the formal parameters and code.
SequenceNode* Parser::ParseFunc(const Function& func,
                                Array& default_parameter_values) {
  if (IsLiteral("class")) {
    // Special case: implicit constructor. There is no source text to
    // parse. We just build the sequence node by hand.
    return MakeImplicitConstructor(func);
  }

  // Build local scope for function.
  OpenFunctionBlock(func);

  ParamList params;
  // The first parameter of a factory is the TypeArguments vector of the type
  // of the instance to be allocated. We name this hidden parameter 'this'.
  const bool has_receiver =
      !func.is_static() || func.IsConstructor() || func.IsFactory();
  const bool are_implicitly_final = func.is_const() && func.IsConstructor();
  const bool allow_explicit_default_values = true;
  ASSERT(CurrentToken() == Token::kLPAREN);
  if (has_receiver) {
    params.AddReceiver(token_index_);
  }
  if (are_implicitly_final) {
    params.SetImplicitlyFinal();
  }
  ParseFormalParameterList(allow_explicit_default_values, &params);

  // The number of parameters and their type are not yet set in local functions,
  // since they are not 'top-level' parsed.
  if (func.IsLocalFunction()) {
    AddFormalParamsToFunction(&params, func);
  }
  SetupDefaultsForOptionalParams(&params, default_parameter_values);
  ASSERT(Type::Handle(func.result_type()).IsResolved());
  ASSERT(func.NumberOfParameters() == params.parameters->length());

  // If this is a constructor, initialize instance fields that have an
  // explicit initializer expression. This has to be done before code
  // for field initializer parameters are is generated.
  // NB: the instance field initializers have to be compiled before
  // the parameters are added to the scope, so that a parameter
  // name cannot shadow a name used in the field initializer expression.

  GrowableArray<FieldInitExpression> initializers;
  if (func.IsConstructor()) {
    Class& cls = Class::Handle(func.owner());
    ParseInitializedInstanceFields(cls, &initializers);
  }

  // Now populate function scope with the formal parameters.
  AddFormalParamsToScope(&params, current_block_->scope);

  // Now that the "this" parameter is in scope, we can generate the code
  // to strore the initializer expressions in the respective instance fields.
  // We do this before the field parameters and the initializers from the
  // constuctor's initializer list get compiled.
  if (initializers.length() > 0) {
    LocalVariable* receiver = current_block_->scope->VariableAt(0);
    for (int i = 0; i < initializers.length(); i++) {
      const Field* field = initializers[i].inst_field;
      AstNode* instance = new LoadLocalNode(field->token_index(), *receiver);
      AstNode* field_init =
          new StoreInstanceFieldNode(field->token_index(),
                                     instance,
                                     *field,
                                     initializers[i].expr);
      current_block_->statements->Add(field_init);
    }
  }

  // Turn formal field parameters into field initializers or report error
  // if the function is not a constructor
  if (params.has_field_initializer) {
    LocalVariable* receiver = current_block_->scope->VariableAt(0);
    Class& cls = Class::ZoneHandle(func.owner());
    for (int i = 0; i < params.parameters->length(); i++) {
      ParamDesc& param = (*params.parameters)[i];
      if (param.is_field_initializer) {
        if (!func.IsConstructor()) {
          ErrorMsg(param.name_pos,
                   "field initializer only allowed in constructors");
        }

        const String& field_name = *param.name;
        Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name));
        if (field.IsNull()) {
          ErrorMsg(param.name_pos,
                   "unresolved reference to instance field '%s'",
                   field_name.ToCString());
        }
        const String& mangled_name =
            String::ZoneHandle(MangledInitParamName(field_name));
        AstNode* instance = new LoadLocalNode(param.name_pos, *receiver);
        LocalVariable* p =
            current_block_->scope->LocalLookupVariable(mangled_name);
        ASSERT(p != NULL);
        AstNode* value = new LoadLocalNode(param.name_pos, *p);
        AstNode* initializer =
            new StoreInstanceFieldNode(param.name_pos, instance, field, value);
        current_block_->statements->Add(initializer);
      }
    }
  }

  if (func.IsConstructor()) {
    Class& cls = Class::ZoneHandle(func.owner());
    bool initialized_check_needed = true;
    if (CurrentToken() == Token::kCOLON) {
      ConsumeToken();
      LocalVariable* receiver = current_block_->scope->VariableAt(0);
      ASSERT(receiver != NULL);
      if ((CurrentToken() == Token::kTHIS) &&
          ((LookaheadToken(1) == Token::kLPAREN) ||
          ((LookaheadToken(1) == Token::kPERIOD) &&
              (LookaheadToken(3) == Token::kLPAREN)))) {
        // Either we see this(...) or this.xxx(...) which is a
        // redirected constructor. We don't need to check whether
        // const fields are initialized. The other constructor will
        // guarantee that.
        initialized_check_needed = false;
        ParseConstructorRedirection(cls, receiver);
      } else {
        ParseInitializers(cls, receiver);
      }
    }
    if (initialized_check_needed) {
      CheckConstFieldsInitialized(cls);
    }
  }

  if (current_block_->scope->function_level() > 0) {
    // We are parsing, but not compiling, a local function.
    // The instantiator may be required at run time for generic type checks or
    // allocation of generic types.
    if (current_class().IsParameterized() &&
        (!current_function().IsInStaticScope() ||
         current_function().IsInFactoryScope())) {
      // Make sure that the receiver of the enclosing instance function
      // (or implicit first parameter of an enclosing factory) is marked as
      // captured if type checks are enabled, because they may access the
      // receiver to instantiate types.
      if (FLAG_enable_type_checks) {
        CaptureReceiver();
      }
    }
  }

  if (CurrentToken() == Token::kLBRACE) {
    ConsumeToken();
    ParseStatementSequence();
    ExpectToken(Token::kRBRACE);
  } else if (CurrentToken() == Token::kARROW) {
    ConsumeToken();
    intptr_t expr_pos = token_index_;
    AstNode* expr = ParseExpr(kAllowConst);
    ASSERT(expr != NULL);
    current_block_->statements->Add(new ReturnNode(expr_pos, expr));
  } else if (IsLiteral("native")) {
    ParseNativeFunctionBlock(&params, func);
  } else if (CurrentToken() == Token::kSEMICOLON) {
    ConsumeToken();
    ASSERT(func.IsConstructor());
    // Some constructors have no function body.
  } else {
    UnexpectedToken();
  }

  SequenceNode* statements = CloseBlock();
  return statements;
}


void Parser::SkipIf(Token::Kind token) {
  if (CurrentToken() == token) {
    ConsumeToken();
  }
}


// Skips tokens up to matching closing parenthesis.
void Parser::SkipToMatchingParenthesis() {
  ASSERT(CurrentToken() == Token::kLPAREN);
  int level = 0;
  do {
    if (CurrentToken() == Token::kLPAREN) {
      level++;
    } else if (CurrentToken() == Token::kRPAREN) {
      level--;
    }
    ConsumeToken();
  } while ((level > 0) && (CurrentToken() != Token::kEOS));
}


void Parser::SkipInitializers() {
  if (CurrentToken() == Token::kSUPER) {
    ConsumeToken();
    if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      ExpectIdentifier("identifier expected");
    }
    if (CurrentToken() != Token::kLPAREN) {
      ErrorMsg("'(' expected");
    }
    SkipToMatchingParenthesis();
  } else {
    SkipIf(Token::kTHIS);
    SkipIf(Token::kPERIOD);
    ExpectIdentifier("identifier expected");
    ExpectToken(Token::kASSIGN);
    SetAllowFunctionLiterals(false);
    SkipExpr();
    SetAllowFunctionLiterals(true);
  }
  while (CurrentToken() == Token::kCOMMA) {
    ConsumeToken();
    SkipIf(Token::kTHIS);
    SkipIf(Token::kPERIOD);
    ExpectIdentifier("instance field expected");
    ExpectToken(Token::kASSIGN);
    SetAllowFunctionLiterals(false);
    SkipExpr();
    SetAllowFunctionLiterals(true);
  }
}


void Parser::ParseQualIdent(QualIdent* qual_ident) {
  ASSERT(CurrentToken() == Token::kIDENT);
  if (!is_top_level_) {
    bool local_ident = ResolveIdentInLocalScope(token_index_,
                                                *CurrentLiteral(),
                                                NULL);
    qual_ident->ident_pos = token_index_;
    qual_ident->ident = CurrentLiteral();
    qual_ident->lib_prefix = NULL;
    qual_ident->qualifier = NULL;
    qual_ident->local_scope_ident = local_ident;
    ConsumeToken();
    if (!local_ident && (CurrentToken() == Token::kPERIOD)) {
      LibraryPrefix& lib_prefix = LibraryPrefix::ZoneHandle();
      lib_prefix = current_class().LookupLibraryPrefix(*(qual_ident->ident));
      if (!lib_prefix.IsNull()) {
        // We have a library prefix qualified identifier.
        ConsumeToken();  // Consume the kPERIOD token.
        qual_ident->lib_prefix = &lib_prefix;
        qual_ident->qualifier = qual_ident->ident;
        qual_ident->ident_pos = token_index_;
        qual_ident->ident = ExpectIdentifier("identifier expected after '.'");
      }
    }
  } else {
    qual_ident->ident_pos = token_index_;
    qual_ident->ident = CurrentLiteral();
    qual_ident->lib_prefix = NULL;
    qual_ident->qualifier = NULL;
    qual_ident->local_scope_ident = false;
    ConsumeToken();
    if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();  // Consume the kPERIOD token.
      qual_ident->qualifier = qual_ident->ident;
      qual_ident->ident_pos = token_index_;
      qual_ident->ident = ExpectIdentifier("identifier expected after '.'");
    }
  }
}


void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) {
  ASSERT(CurrentToken() == Token::kLPAREN);
  intptr_t method_pos = this->token_index_;
  ASSERT(method->type != NULL);
  ASSERT(method->name_pos > 0);
  ASSERT(current_member_ == method);

  if (method->has_var) {
    ErrorMsg(method->name_pos, "keyword var not allowed for methods");
  }
  if (method->has_final) {
    ErrorMsg(method->name_pos, "'final' not allowed for methods");
  }
  if (method->has_abstract && method->has_static) {
    ErrorMsg(method->name_pos,
             "static method '%s' cannot be abstract",
             method->name->ToCString());
  }
  if (method->has_const && !(method->IsConstructor() || method->IsFactory())) {
    ErrorMsg(method->name_pos, "'const' not allowed for methods");
  }
  if (method->IsConstructor() && method->has_static) {
    ErrorMsg(method->name_pos, "constructor cannot be 'static'");
  }
  if (method->IsConstructor() && method->has_const) {
    Class& cls = Class::ZoneHandle(LookupClass(members->class_name()));
    cls.set_is_const();
  }
  if (method->has_abstract && members->is_interface()) {
    ErrorMsg(method->name_pos,
             "'abstract' method only allowed in class definition");
  }

  if (members->FunctionNameExists(*method->name, method->kind)) {
    ErrorMsg(method->name_pos,
             "field or method '%s' already defined", method->name->ToCString());
  }

  // Parse the formal parameters.
  // The first parameter of factory methods is an implicit parameter called
  // 'this' of type TypeArguments.
  const bool has_this_param =
      !method->has_static || method->IsConstructor() || method->has_factory;
  const bool are_implicitly_final = method->has_const;
  const bool allow_explicit_default_values =
      (!method->has_abstract && !members->is_interface());
  const intptr_t formal_param_pos = token_index_;
  method->params.Clear();
  if (has_this_param) {
    method->params.AddReceiver(formal_param_pos);
  }
  if (are_implicitly_final) {
    method->params.SetImplicitlyFinal();
  }
  ParseFormalParameterList(allow_explicit_default_values, &method->params);
  if (method->IsGetter() || method->IsSetter()) {
    int expected_num_parameters = 0;
    if (method->IsGetter()) {
      expected_num_parameters = (method->has_static) ? 0 : 1;
      method->name = &String::ZoneHandle(Field::GetterName(*method->name));
    } else {
      ASSERT(method->IsSetter());
      expected_num_parameters = (method->has_static) ? 1 : 2;
      method->name = &String::ZoneHandle(Field::SetterName(*method->name));
    }
    if ((method->params.num_fixed_parameters != expected_num_parameters) ||
        (method->params.num_optional_parameters != 0)) {
      ErrorMsg(method->name_pos, "illegal %s parameters",
               method->IsGetter() ? "getter" : "setter");
    }
  }

  // Parse initializers.
  if (CurrentToken() == Token::kCOLON) {
    if (!method->IsConstructor()) {
      ErrorMsg("initializers only allowed on constructors");
    }
    ConsumeToken();
    if ((CurrentToken() == Token::kTHIS) &&
        ((LookaheadToken(1) == Token::kLPAREN) ||
         LookaheadToken(3) == Token::kLPAREN)) {
      // Redirected constructor: either this(...) or this.xxx(...).
      if (method->params.has_field_initializer) {
        // Constructors that redirect to another constructor must not
        // initialize any fields using field initializer parameters.
        ErrorMsg(formal_param_pos, "Redirecting constructor "
                 "may not use field initializer parameters");
      }
      ExpectToken(Token::kTHIS);
      String& redir_name = String::ZoneHandle(
          String::Concat(members->class_name(),
                         String::Handle(String::NewSymbol("."))));
      if (CurrentToken() == Token::kPERIOD) {
        ConsumeToken();
        redir_name = String::Concat(redir_name,
            *ExpectIdentifier("constructor name expected"));
      }
      method->redirect_name = &redir_name;
      if (CurrentToken() != Token::kLPAREN) {
        ErrorMsg("'(' expected");
      }
      SkipToMatchingParenthesis();
    } else {
      SkipInitializers();
    }
  }

  // Only constructors can redirect to another method.
  ASSERT((method->redirect_name == NULL) || method->IsConstructor());

  if ((CurrentToken() == Token::kLBRACE) ||
      (CurrentToken() == Token::kARROW)) {
    if (method->has_abstract) {
      ErrorMsg(method->name_pos,
               "abstract method '%s' may not have function body",
               method->name->ToCString());
    } else if (method->IsConstructor() && method->has_const) {
      ErrorMsg(method->name_pos,
               "const constructor '%s' may not have function body",
               method->name->ToCString());
    } else if (method->IsFactory() && method->has_const) {
      ErrorMsg(method->name_pos,
               "const factory '%s' may not have function body",
               method->name->ToCString());
    } else if (members->is_interface()) {
      ErrorMsg(method->name_pos,
               "function body not allowed in interface declaration");
    }
    if (CurrentToken() == Token::kLBRACE) {
      SkipBlock();
    } else {
      ConsumeToken();
      SkipExpr();
      ExpectSemicolon();
    }
  } else if (IsLiteral("native")) {
    if (method->has_abstract) {
      ErrorMsg(method->name_pos,
               "abstract method '%s' may not have function body",
               method->name->ToCString());
    } else if (members->is_interface()) {
      ErrorMsg(method->name_pos,
               "function body not allowed in interface declaration");
    } else if (method->IsConstructor() && method->has_const) {
      ErrorMsg(method->name_pos,
               "const constructor '%s' may not have function body",
               method->name->ToCString());
    }
    ParseNativeDeclaration();
  } else if (CurrentToken() == Token::kSEMICOLON) {
    if (members->is_interface() ||
        method->has_abstract ||
        (method->redirect_name != NULL) ||
        method->IsConstructor()) {
      ConsumeToken();
    } else {
      ErrorMsg(method->name_pos,
               "function body expected for method '%s'",
               method->name->ToCString());
    }
  } else {
    if (members->is_interface() ||
        method->has_abstract ||
        (method->redirect_name != NULL) ||
        (method->IsConstructor() && method->has_const)) {
      ExpectSemicolon();
    } else {
      ErrorMsg(method->name_pos,
               "function body expected for method '%s'",
               method->name->ToCString());
    }
  }

  RawFunction::Kind function_kind;
  if (method->IsFactoryOrConstructor()) {
    function_kind = RawFunction::kConstructor;
  } else if (method->has_abstract) {
    function_kind = RawFunction::kAbstract;
  } else if (method->IsGetter()) {
    function_kind = RawFunction::kGetterFunction;
  } else if (method->IsSetter()) {
    function_kind = RawFunction::kSetterFunction;
  } else {
    function_kind = RawFunction::kFunction;
  }
  Function& func = Function::ZoneHandle(
      Function::New(*method->name,
                    function_kind,
                    method->has_static,
                    method->has_const,
                    method_pos));
  func.set_result_type(*method->type);

  // No need to resolve parameter types yet, or add parameters to local scope.
  ASSERT(is_top_level_);
  AddFormalParamsToFunction(&method->params, func);
  members->AddFunction(&func);
}


void Parser::ParseFieldDefinition(ClassDesc* members, MemberDesc* field) {
  // The parser has read the first field name and is now at the token
  // after the field name.
  ASSERT(CurrentToken() == Token::kSEMICOLON ||
         CurrentToken() == Token::kCOMMA ||
         CurrentToken() == Token::kASSIGN);
  ASSERT(field->type != NULL);
  ASSERT(field->name_pos > 0);
  ASSERT(current_member_ == field);

  if (field->has_const) {
    ErrorMsg("keyword 'const' not allowed in field declaration");
  }
  if (field->has_abstract) {
    ErrorMsg("keyword 'abstract' not allowed in field declaration");
  }
  if (field->has_factory) {
    ErrorMsg("keyword 'factory' not allowed in field declaration");
  }
  if (members->FieldNameExists(*field->name)) {
    ErrorMsg(field->name_pos,
             "'%s' field/method already defined\n", field->name->ToCString());
  }
  while (true) {
    bool has_initializer = CurrentToken() == Token::kASSIGN;
    if (has_initializer) {
      ConsumeToken();
      // For static final fields, the initialization expression
      // will be parsed through the kConstImplicitGetter method
      // invocation/compilation.
      // For instance fields, the expression is parsed when a constructor
      // is compiled.
      SkipExpr();
    } else {
      if (field->has_static && field->has_final) {
        ErrorMsg(field->name_pos,
                 "static final field '%s' must have an initializer expression",
                 field->name->ToCString());
      }
    }

    // Create the field object.
    Field& class_field = Field::ZoneHandle(
         Field::New(*field->name,
                    field->has_static,
                    field->has_final,
                    field->name_pos));
    class_field.set_type(*field->type);
    class_field.set_has_initializer(has_initializer);
    members->AddField(&class_field);

    // For static final fields, set value to "uninitialized" and
    // create a kConstImplicitGetter getter method.
    if (field->has_static && has_initializer) {
      class_field.set_value(Instance::Handle(Object::sentinel()));
      String& getter_name = String::ZoneHandle(Field::GetterName(*field->name));
      Function& getter = Function::ZoneHandle(
          Function::New(getter_name, RawFunction::kConstImplicitGetter,
                        field->has_static, field->has_final,
                        field->name_pos));
      getter.set_result_type(*field->type);
      members->AddFunction(&getter);
    }

    // For instance fields, we create implicit getter and setter methods.
    if (!field->has_static) {
      String& getter_name =
          String::ZoneHandle(Field::GetterName(*field->name));
      Function& getter = Function::ZoneHandle(
          Function::New(getter_name, RawFunction::kImplicitGetter,
                        field->has_static, field->has_final,
                        field->name_pos));
      ParamList params;
      params.AddReceiver(token_index_);
      getter.set_result_type(*field->type);
      AddFormalParamsToFunction(&params, getter);
      members->AddFunction(&getter);
      if (!field->has_final) {
        // Build a setter accessor for non-const fields.
        String& setter_name = String::ZoneHandle(
            Field::SetterName(*field->name));
        Function& setter = Function::ZoneHandle(
            Function::New(setter_name, RawFunction::kImplicitSetter,
                         field->has_static, field->has_final,
                         field->name_pos));
        ParamList params;
        params.AddReceiver(token_index_);
        params.AddFinalParameter(token_index_, "value", field->type);
        setter.set_result_type(Type::Handle(Type::VoidType()));
        AddFormalParamsToFunction(&params, setter);
        members->AddFunction(&setter);
      }
    }

    if (CurrentToken() != Token::kCOMMA) {
      break;
    }
    ConsumeToken();
    field->name_pos = this->token_index_;
    field->name = ExpectIdentifier("field name expected");
  }
  ExpectSemicolon();
}


void Parser::ParseClassMemberDefinition(ClassDesc* members) {
  MemberDesc member;
  current_member_ = &member;
  if (CurrentToken() == Token::kABSTRACT) {
    ConsumeToken();
    member.has_abstract = true;
  }
  if (CurrentToken() == Token::kSTATIC) {
    ConsumeToken();
    member.has_static = true;
  }
  if (CurrentToken() == Token::kCONST) {
    ConsumeToken();
    member.has_const = true;
  } else if (CurrentToken() == Token::kFINAL) {
    ConsumeToken();
    member.has_final = true;
  }
  if (CurrentToken() == Token::kVAR) {
    if (member.has_const) {
      ErrorMsg("identifier expected after 'const'");
    }
    if (member.has_final) {
      ErrorMsg("identifier expected after 'final'");
    }
    ConsumeToken();
    member.has_var = true;
    // The member type is the 'var' type.
    member.type = &Type::ZoneHandle(Type::VarType());
  } else if (CurrentToken() == Token::kFACTORY) {
    ConsumeToken();
    member.has_factory = true;
    member.has_static = true;
    // The member result type is the type of this class.
    // TODO(regis): What are the type arguments?
    member.type =
        &Type::ZoneHandle(Type::NewRawType(Class::Handle(members->clazz())));
  }
  // Optionally parse a type.
  if (CurrentToken() == Token::kVOID) {
    if (member.has_var || member.has_factory) {
      ErrorMsg("void not expected");
    }
    ConsumeToken();
    ASSERT(member.type == NULL);
    member.type = &Type::ZoneHandle(Type::VoidType());
  } else if (CurrentToken() == Token::kIDENT) {
    // This is either a type name or the name of a method/constructor/field.
    if (member.type == NULL) {
      // We have not seen a member type yet, so we check if the next
      // identifier could represent a type before parsing it.
      Token::Kind follower = LookaheadToken(1);
      // We have an identifier followed by a 'follower' token.
      // We either parse a type or assume that no type is specified.
      if ((follower == Token::kLT) ||  // Parameterized type.
          (follower == Token::kGET) ||  // Getter following a type.
          (follower == Token::kSET) ||  // Setter following a type.
          (follower == Token::kOPERATOR) ||  // Operator following a type.
          (follower == Token::kIDENT)  ||  // Member name following a type.
          ((follower == Token::kPERIOD) &&    // Qualified class name of type,
           (LookaheadToken(3) != Token::kLPAREN))) {  // but not a named constr.
        ASSERT(is_top_level_);
        member.type = &Type::ZoneHandle(ParseType(kCanResolve));
      }
    }
  }
  // Optionally parse a (possibly named) constructor name or factory.
  if ((CurrentToken() == Token::kIDENT) &&
      (CurrentLiteral()->Equals(members->class_name()) || member.has_factory)) {
    member.name = CurrentLiteral();
    member.name_pos = this->token_index_;
    // Factory result type is the same as the type name of the factory.
    // TODO(srdjan): Implement checks in class finalization when all types have
    // been resolved.
    if (member.has_factory && !member.name->Equals(members->class_name())) {
      const TypeArguments& arguments = TypeArguments::Handle();
      member.type = &Type::ZoneHandle(
          Type::NewParameterizedType(*member.name, arguments));
    }
    ConsumeToken();
    // We must be dealing with a constructor or named constructor.
    member.kind = RawFunction::kConstructor;
    String& ctor_suffix = String::ZoneHandle(String::NewSymbol("."));
    if (CurrentToken() == Token::kPERIOD) {
      // Named constructor.
      ConsumeToken();
      const String* name = ExpectIdentifier("identifier expected");
      ctor_suffix = String::Concat(ctor_suffix, *name);
    }
    *member.name = String::Concat(*member.name, ctor_suffix);
    // Ensure that names are symbols.
    *member.name = String::NewSymbol(*member.name);
    if (member.type == NULL) {
      // TODO(regis): What are the type arguments?
      member.type =
          &Type::ZoneHandle(Type::NewRawType(Class::Handle(members->clazz())));
    } else {
      // The type can only be already set in the factory case.
      if (!member.has_factory) {
        ErrorMsg(member.name_pos, "constructor must not specify return type");
      }
    }
    if (CurrentToken() != Token::kLPAREN) {
      ErrorMsg("left parenthesis expected");
    }
  } else if (CurrentToken() == Token::kGET) {
    ConsumeToken();
    member.kind = RawFunction::kGetterFunction;
    member.name_pos = this->token_index_;
    member.name = ExpectIdentifier("identifier expected");
    // If the result type was not specified, it will be set to VarType below.
  } else if (CurrentToken() == Token::kSET) {
    ConsumeToken();
    member.kind = RawFunction::kSetterFunction;
    member.name_pos = this->token_index_;
    member.name = ExpectIdentifier("identifier expected");
    // The grammar allows a return type, so member.type is not always NULL here.
    // However, the return type of a setter is ignored.
    // TODO(regis): Revisit depending on the outcome of issue 4745047.
    if (member.type == NULL) {
      member.type = &Type::ZoneHandle(Type::VoidType());
    }
  } else if (CurrentToken() == Token::kOPERATOR) {
    ConsumeToken();
    if (!Token::CanBeOverloaded(CurrentToken())) {
      ErrorMsg("invalid operator overloading");
    }
    if (member.has_static) {
      ErrorMsg("operator overloading functions cannot be static");
    }
    member.kind = RawFunction::kFunction;
    member.name_pos = this->token_index_;
    member.name =
        &String::ZoneHandle(String::NewSymbol(Token::Str(CurrentToken())));
    ConsumeToken();
  } else if (CurrentToken() == Token::kIDENT) {
    member.name = CurrentLiteral();
    member.name_pos = token_index_;
    ConsumeToken();
  } else {
    ErrorMsg("identifier expected");
  }

  ASSERT(member.name != NULL);
  if (CurrentToken() == Token::kLPAREN) {
    if (members->is_interface() && member.has_static) {
      if (member.has_factory) {
        ErrorMsg("factory constructors are not allowed in interfaces");
      } else {
        ErrorMsg("static methods are not allowed in interfaces");
      }
    }
    // Constructor or method.
    if (member.type == NULL) {
      member.type = &Type::ZoneHandle(Type::VarType());
    }
    ParseMethodOrConstructor(members, &member);
  } else if (CurrentToken() ==  Token::kSEMICOLON ||
             CurrentToken() == Token::kCOMMA ||
             CurrentToken() == Token::kASSIGN) {
    // Field definition.
    if (member.type == NULL) {
      if (member.has_final) {
        member.type = &Type::ZoneHandle(Type::VarType());
      } else {
        ErrorMsg("missing 'var', 'final' or type in field declaration");
      }
    }
    if (members->is_interface() && member.has_static && !member.has_final) {
      ErrorMsg("static non-final fields are not allowed in interfaces");
    }
    ParseFieldDefinition(members, &member);
  } else {
    UnexpectedToken();
  }
  current_member_ = NULL;
  members->AddMember(member);
}


void Parser::ParseClassDefinition(GrowableArray<const Class*>* classes) {
  TRACE_PARSER("ParseClassDefinition");
  intptr_t class_pos = token_index_;
  ExpectToken(Token::kCLASS);
  intptr_t classname_pos = token_index_;
  String& class_name = *ExpectIdentifier("class name expected");
  if (FLAG_trace_parser) {
    OS::Print("TopLevel parsing class '%s'\n", class_name.ToCString());
  }
  Class& cls = Class::ZoneHandle();
  Object& obj = Object::Handle(library_.LookupObject(class_name));
  if (obj.IsNull()) {
    cls = Class::New(class_name, script_);
    library_.AddClass(cls);
  } else {
    if (!obj.IsClass()) {
      ErrorMsg(classname_pos, "'%s' is already defined",
               class_name.ToCString());
    }
    cls ^= obj.raw();
    if (cls.is_interface()) {
      ErrorMsg(classname_pos, "'%s' is already defined as interface",
               class_name.ToCString());
    } else if (cls.functions() != Array::Empty()) {
      ErrorMsg(classname_pos, "class '%s' is already defined",
               class_name.ToCString());
    }
  }
  ASSERT(!cls.IsNull());
  ASSERT(cls.functions() == Array::Empty());
  set_current_class(cls);
  ParseTypeParameters(cls);
  Type& super_type = Type::Handle();
  if (CurrentToken() == Token::kEXTENDS) {
    ConsumeToken();
    super_type = ParseType(kCanResolve);
    if (super_type.IsInterfaceType()) {
      ErrorMsg("class '%s' may implement, but cannot extend interface '%s'",
               class_name.ToCString(),
               String::Handle(super_type.Name()).ToCString());
    }
  } else {
    // No extends clause: Implicitly extend Object.
    super_type = Type::ObjectType();
  }
  ASSERT(!super_type.IsNull());
  cls.set_super_type(super_type);

  if (CurrentToken() == Token::kIMPLEMENTS) {
    Array& interfaces = Array::Handle();
    const intptr_t interfaces_pos = token_index_;
    interfaces = ParseInterfaceList();
    AddInterfaces(interfaces_pos, cls, interfaces);
  }

  ExpectToken(Token::kLBRACE);
  ClassDesc members(cls, class_name, false, class_pos);
  while (CurrentToken() != Token::kRBRACE) {
    ParseClassMemberDefinition(&members);
  }
  ExpectToken(Token::kRBRACE);

  CheckConstructors(&members);
  cls.SetFields(Array::Handle(NewArray<Field>(members.fields())));
  // Creating a new array for functions marks the class as parsed.
  cls.SetFunctions(Array::Handle(NewArray<Function>(members.functions())));
  classes->Add(&cls);
}


// 1. Add an implicit constructor if no explicit constructor is present.
// 2. Check for cycles in constructor redirection.
void Parser::CheckConstructors(ClassDesc* class_desc) {
  // Add an implicit constructor if no explicit constructor is present.
  if (!class_desc->has_constructor()) {
    // The implicit constructor is unnamed, has no parameter, and contains
    // a supercall in the initializer list.
    String& ctor_name = String::ZoneHandle(
        String::Concat(class_desc->class_name(),
                       String::Handle(String::NewSymbol("."))));
    ctor_name = String::NewSymbol(ctor_name);
    Function& ctor = Function::ZoneHandle(
        Function::New(ctor_name,
                      RawFunction::kConstructor,
                      /* is_static = */ false,
                      /* is_const = */ false,
                      class_desc->token_pos()));
    ParamList params;
    params.AddReceiver(token_index_);
    AddFormalParamsToFunction(&params, ctor);
    // TODO(regis): What are the type arguments?
    Type& result_type = Type::ZoneHandle(
        Type::NewRawType(Class::Handle(class_desc->clazz())));
    ctor.set_result_type(result_type);
    class_desc->AddFunction(&ctor);
  }

  // Check for cycles in constructor redirection.
  const GrowableArray<MemberDesc>& members = class_desc->members();
  for (int i = 0; i < members.length(); i++) {
    MemberDesc* member = &members[i];
    GrowableArray<MemberDesc*> ctors;
    while ((member != NULL) && (member->redirect_name != NULL)) {
      ASSERT(member->IsConstructor());
      // Check whether we have already seen this member.
      for (int i = 0; i < ctors.length(); i++) {
        if (ctors[i] == member) {
          ErrorMsg(member->name_pos,
                   "cyclic reference in constructor redirection");
        }
      }
      // We haven't seen this member. Add it to the list and follow
      // the next redirection. If we can't find the constructor to
      // which the current one redirects, we ignore the unresolved
      // reference. We'll catch it later when the constructor gets
      // compiled.
      ctors.Add(member);
      member = class_desc->LookupMember(*member->redirect_name);
    }
  }
}


// Look ahead to detect if we are seeing ident [ TypeParameters ] "(".
// We need this lookahead to distinguish between the optional return type
// and the alias name of a function type alias.
// Token position remains unchanged.
bool Parser::IsFunctionTypeAliasName() {
  if ((CurrentToken() == Token::kIDENT) &&
      (LookaheadToken(1) == Token::kLPAREN)) {
    return true;
  }
  const intptr_t saved_pos = token_index_;
  bool is_alias_name = false;
  if ((CurrentToken() == Token::kIDENT)  &&
      (LookaheadToken(1) == Token::kLT)) {
    ConsumeToken();
    if (IsTypeParameter() && (CurrentToken() == Token::kLPAREN)) {
      is_alias_name = true;
    }
  }
  SetPosition(saved_pos);
  return is_alias_name;
}


void Parser::ParseFunctionTypeAlias(GrowableArray<const Class*>* classes) {
  TRACE_PARSER("ParseFunctionTypeAlias");
  ExpectToken(Token::kTYPEDEF);

  Type& result_type = Type::Handle(Type::VarType());
  intptr_t result_type_pos = token_index_;
  if (CurrentToken() == Token::kVOID) {
    ConsumeToken();
    result_type = Type::VoidType();
  } else if (!IsFunctionTypeAliasName()) {
    result_type = ParseType(kDoNotResolve);  // No owner class yet.
  }

  if (CurrentToken() != Token::kIDENT) {
    ErrorMsg("function alias name expected");
  }
  const intptr_t alias_name_pos = token_index_;
  const String* alias_name = CurrentLiteral();
  ConsumeToken();

  // Allocate a class to hold the type parameters and their 'extends'
  // constraints. Make it the owner of the function type descriptor.
  const Class& alias_owner = Class::Handle(
      Class::New(String::Handle(String::NewSymbol("")), Script::Handle()));
  set_current_class(alias_owner);
  ParseTypeParameters(alias_owner);
  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg("formal parameter list expected");
  }

  // At this point, the type parameters have been parsed, so we can resolve the
  // result type.
  if (!result_type.IsNull() && !result_type.IsResolved()) {
    ResolveTypeFromClass(result_type_pos, alias_owner, &result_type);
  }
  ParamList func_params;
  const bool no_explicit_default_values = false;
  ParseFormalParameterList(no_explicit_default_values, &func_params);
  // TODO(regis): If no type parameters were specified, the function could be
  // static. Revisit.
  Function& signature_function = Function::Handle(
      Function::New(*alias_name,
                    RawFunction::kSignatureFunction,
                    /* is_static = */ false,
                    /* is_const = */ false,
                    alias_name_pos));
  signature_function.set_owner(alias_owner);
  signature_function.set_result_type(result_type);
  AddFormalParamsToFunction(&func_params, signature_function);
  const String& signature = String::Handle(signature_function.Signature());
  if (FLAG_trace_parser) {
    OS::Print("TopLevel parsing function type alias '%s'\n",
              signature.ToCString());
  }
  // Lookup the class by its signature and only create a new canonical signature
  // class if it does not exist yet.
  Class& signature_class = Class::ZoneHandle(LookupClass(signature));
  if (signature_class.IsNull()) {
    signature_class = Class::NewSignatureClass(signature,
                                               signature_function,
                                               script_,
                                               alias_name_pos);
    // Record the function signature class in the library.
    library_.AddClass(signature_class);
    ASSERT(Class::Handle(signature_function.signature_class()).IsNull());
    signature_function.set_signature_class(signature_class);
  } else {
    // Forget the just created function type desc and use the existing one.
    signature_function = signature_class.signature_function();
    ASSERT(signature_function.signature_class() == signature_class.raw());
  }
  // Lookup the class by its alias name and report an error if it exists.
  Class& function_type_alias = Class::ZoneHandle(LookupClass(*alias_name));
  if (function_type_alias.IsNull()) {
    // Create the function type alias, but share the signature function of the
    // canonical signature class.
    function_type_alias = Class::NewSignatureClass(*alias_name,
                                                   signature_function,
                                                   script_,
                                                   alias_name_pos);
    library_.AddClass(function_type_alias);
  } else {
    const char* format = function_type_alias.is_interface() ?
        "'%s' is already defined" : "'%s' is already defined as class";
    ErrorMsg(alias_name_pos, format, alias_name->ToCString());
  }
  ExpectSemicolon();
  classes->Add(&function_type_alias);
}


void Parser::ParseInterfaceDefinition(GrowableArray<const Class*>* classes) {
  TRACE_PARSER("ParseInterfaceDefinition");
  intptr_t interface_pos = token_index_;
  ExpectToken(Token::kINTERFACE);
  intptr_t interfacename_pos = token_index_;
  String& interface_name = *ExpectIdentifier("interface name expected");
  if (FLAG_trace_parser) {
    OS::Print("TopLevel parsing interface '%s'\n", interface_name.ToCString());
  }
  Class& interface = Class::ZoneHandle();
  Object& obj = Object::Handle(library_.LookupObject(interface_name));
  if (obj.IsNull()) {
    interface = Class::NewInterface(interface_name, script_);
    library_.AddClass(interface);
  } else {
    if (!obj.IsClass()) {
      ErrorMsg(interfacename_pos, "'%s' is already defined",
               interface_name.ToCString());
    }
    interface ^= obj.raw();
    if (!interface.is_interface()) {
      ErrorMsg(interfacename_pos,
               "'%s' is already defined as class",
               interface_name.ToCString());
    } else if (interface.functions() != Array::Empty()) {
      ErrorMsg(interfacename_pos,
               "interface '%s' is already defined",
               interface_name.ToCString());
    }
  }
  ASSERT(!interface.IsNull());
  ASSERT(interface.functions() == Array::Empty());
  set_current_class(interface);
  ParseTypeParameters(interface);

  if (CurrentToken() == Token::kEXTENDS) {
    Array& interfaces = Array::Handle();
    const intptr_t interfaces_pos = token_index_;
    interfaces = ParseInterfaceList();
    AddInterfaces(interfaces_pos, interface, interfaces);
  }

  if (CurrentToken() == Token::kFACTORY) {
    ConsumeToken();
    Type& factory_type = Type::Handle();
    const intptr_t factory_type_pos = token_index_;
    factory_type = ParseType(kCanResolve);
    if (factory_type.IsInterfaceType()) {
      ErrorMsg(factory_type_pos,
               "interface '%s' must have a factory class "
               "but '%s' is an interface",
               interface_name.ToCString(),
               String::Handle(factory_type.Name()).ToCString());
    }
    interface.set_factory_type(factory_type);
  }

  ExpectToken(Token::kLBRACE);
  ClassDesc members(interface, interface_name, true, interface_pos);
  while (CurrentToken() != Token::kRBRACE) {
    ParseClassMemberDefinition(&members);
  }
  ExpectToken(Token::kRBRACE);

  interface.SetFields(Array::Handle(NewArray<Field>(members.fields())));
  // Creating a new array for functions marks the interface as parsed.
  interface.SetFunctions(
      Array::Handle(NewArray<Function>(members.functions())));
  ASSERT(interface.is_interface());
  classes->Add(&interface);
}


// Consumes exactly one right angle bracket. If the current token is a single
// bracket token, it is consumed normally. However, if it is a double or triple
// bracket, it is replaced by a single or double bracket token without
// incrementing the token index.
void Parser::ConsumeRightAngleBracket() {
  if (token_kind_ == Token::kGT) {
    ConsumeToken();
  } else if (token_kind_ == Token::kSAR) {
    token_kind_ = Token::kGT;
  } else if (token_kind_ == Token::kSHR) {
    token_kind_ = Token::kSAR;
  } else {
    UNREACHABLE();
  }
}


void Parser::SkipTypeArguments() {
  if (CurrentToken() == Token::kLT) {
    do {
      ConsumeToken();
      SkipType(false);
    } while (CurrentToken() == Token::kCOMMA);
    Token::Kind token = CurrentToken();
    if ((token == Token::kGT) ||
        (token == Token::kSAR) ||
        (token == Token::kSHR)) {
      ConsumeRightAngleBracket();
    } else {
      ErrorMsg("right angle bracket expected");
    }
  }
}


void Parser::SkipType(bool allow_void) {
  if (CurrentToken() == Token::kVOID) {
    if (!allow_void) {
      ErrorMsg("'void' not allowed here");
    }
    ConsumeToken();
  } else {
    ExpectIdentifier("type name expected");
    if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      ExpectIdentifier("name expected");
    }
    SkipTypeArguments();
  }
}


void Parser::ParseTypeParameters(const Class& cls) {
  if (CurrentToken() == Token::kLT) {
    GrowableArray<String*> type_parameters;
    GrowableArray<Type*> type_parameter_extends;
    do {
      ConsumeToken();
      if (CurrentToken() != Token::kIDENT) {
        ErrorMsg("type parameter name expected");
      }
      String& type_parameter_name = *CurrentLiteral();
      ConsumeToken();
      Type& type_extends = Type::ZoneHandle(Type::VarType());
      if (CurrentToken() == Token::kEXTENDS) {
        ConsumeToken();
        type_extends = ParseType(kCanResolve);
      }
      type_parameters.Add(&type_parameter_name);
      type_parameter_extends.Add(&type_extends);
    } while (CurrentToken() == Token::kCOMMA);
    Token::Kind token = CurrentToken();
    if ((token == Token::kGT) ||
        (token == Token::kSAR) ||
        (token == Token::kSHR)) {
      ConsumeRightAngleBracket();
    } else {
      ErrorMsg("right angle bracket expected");
    }
    cls.set_type_parameters(Array::Handle(NewArray<String>(type_parameters)));
    cls.set_type_parameter_extends(
        TypeArray::Handle(NewTypeArray(type_parameter_extends)));
  }
}


RawTypeArguments* Parser::ParseTypeArguments(TypeResolution type_resolution) {
  if (CurrentToken() == Token::kLT) {
    GrowableArray<Type*> types;
    do {
      ConsumeToken();
      Type& type = Type::ZoneHandle(ParseType(type_resolution));
      types.Add(&type);
    } while (CurrentToken() == Token::kCOMMA);
    Token::Kind token = CurrentToken();
    if ((token == Token::kGT) ||
        (token == Token::kSAR) ||
        (token == Token::kSHR)) {
      ConsumeRightAngleBracket();
    } else {
      ErrorMsg("right angle bracket expected");
    }
    return NewTypeArray(types);
  }
  return TypeArguments::null();
}


// Parse and return an array of interface types.
RawArray* Parser::ParseInterfaceList() {
  ASSERT((CurrentToken() == Token::kIMPLEMENTS) ||
         (CurrentToken() == Token::kEXTENDS));
  GrowableArray<Type*> interfaces;
  do {
    ConsumeToken();
    // TODO(regis): The way we handle unresolved classes is not going to fly.
    // We are currently not able to provide a token position for errors occuring
    // after parsing, as in the class finalizer. We need to introduce an
    // 'unresolved class' class consisting of a string, a token position, and a
    // script, maybe a library too.
    Type& interface = Type::ZoneHandle(ParseType(kCanResolve));
    interfaces.Add(&interface);
  } while (CurrentToken() == Token::kCOMMA);
  return NewArray<Type>(interfaces);
}


void Parser::AddInterfaces(intptr_t interfaces_pos,
                           const Class& cls,
                           const Array& interfaces) {
  GrowableArray<Type*> all_interfaces;
  // First get all the interfaces already implemented by class.
  Array& cls_interfaces = Array::Handle(cls.interfaces());
  for (intptr_t i = 0; i < cls_interfaces.Length(); i++) {
    Type& interface = Type::ZoneHandle();
    interface ^= cls_interfaces.At(i);
    all_interfaces.Add(&interface);
  }
  // Now add the new interfaces.
  Type& conflicting = Type::Handle();
  for (intptr_t i = 0; i < interfaces.Length(); i++) {
    Type& interface = Type::ZoneHandle();
    interface ^= interfaces.At(i);
    if (!ClassFinalizer::AddInterfaceIfUnique(&all_interfaces,
                                              &interface,
                                              &conflicting)) {
      ASSERT(!conflicting.IsNull());
      ErrorMsg(interfaces_pos,
               "interface '%s' conflicts with interface '%s'",
               String::Handle(interface.Name()).ToCString(),
               String::Handle(conflicting.Name()).ToCString());
    }
  }
  cls_interfaces = NewArray<Type>(all_interfaces);
  cls.set_interfaces(cls_interfaces);
}


void Parser::ParseTopLevelVariable(TopLevel* top_level) {
  const bool is_final = (CurrentToken() == Token::kFINAL);
  const bool is_static = true;
  const Type& type = Type::ZoneHandle(
      ParseFinalVarOrType(kIsMandatory, kCanResolve));

  while (true) {
    const intptr_t name_pos = token_index_;
    String& var_name = *ExpectIdentifier("variable name expected");

    if (library_.LookupObject(var_name) != Object::null()) {
      ErrorMsg(name_pos, "'%s' is already defined", var_name.ToCString());
    }
    Field& field = Field::ZoneHandle(
        Field::New(var_name, is_static, is_final, name_pos));
    field.set_type(type);
    field.set_value(Instance::Handle(Instance::null()));
    top_level->fields.Add(&field);
    library_.AddObject(field, var_name);
    if (CurrentToken() == Token::kASSIGN) {
      ConsumeToken();
      SkipExpr();
      field.set_value(Instance::Handle(Object::sentinel()));
      // Create a static const getter.
      String& getter_name = String::ZoneHandle(Field::GetterName(var_name));
      Function& getter = Function::ZoneHandle(
          Function::New(getter_name, RawFunction::kConstImplicitGetter,
                        is_static, is_final, name_pos));
      getter.set_result_type(type);
      top_level->functions.Add(&getter);
    } else if (is_final) {
      ErrorMsg(name_pos, "missing initializer for final variable");
    }

    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
    } else if (CurrentToken() == Token::kSEMICOLON) {
      ConsumeToken();
      break;
    } else {
      ExpectSemicolon();  // Reports error.
    }
  }
}


void Parser::ParseTopLevelFunction(TopLevel* top_level) {
  Type& result_type = Type::Handle(Type::VarType());
  const bool is_static = true;
  if (CurrentToken() == Token::kVOID) {
    ConsumeToken();
    result_type = Type::VoidType();
  } else {
    // Parse optional type.
    if ((CurrentToken() == Token::kIDENT) &&
        (LookaheadToken(1) != Token::kLPAREN)) {
      result_type = ParseType(kCanResolve);
    }
  }
  const intptr_t name_pos = token_index_;
  const String& func_name = *ExpectIdentifier("function name expected");

  if (library_.LookupObject(func_name) != Object::null()) {
    ErrorMsg(name_pos, "'%s' is already defined", func_name.ToCString());
  }

  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg("'(' expected");
  }
  const intptr_t function_pos = token_index_;
  ParamList params;
  const bool allow_explicit_default_values = true;
  ParseFormalParameterList(allow_explicit_default_values, &params);

  if (CurrentToken() == Token::kLBRACE) {
    SkipBlock();
  } else if (CurrentToken() == Token::kARROW) {
    ConsumeToken();
    SkipExpr();
    ExpectSemicolon();
  } else if (IsLiteral("native")) {
    ParseNativeDeclaration();
  } else {
    ErrorMsg("function block expected");
  }
  Function& func = Function::ZoneHandle(
      Function::New(func_name, RawFunction::kFunction,
                    is_static, false, function_pos));
  func.set_result_type(result_type);
  AddFormalParamsToFunction(&params, func);
  top_level->functions.Add(&func);
  library_.AddObject(func, func_name);
}


void Parser::ParseTopLevelAccessor(TopLevel* top_level) {
  const bool is_static = true;
  Type& result_type = Type::Handle();
  bool is_getter = (CurrentToken() == Token::kGET);
  if (CurrentToken() == Token::kGET ||
      CurrentToken() == Token::kSET) {
    ConsumeToken();
    // TODO(regis): Revisit, see issue 4745047.
    result_type = Type::VarType();
  } else {
    if (CurrentToken() == Token::kVOID) {
      ConsumeToken();
      result_type = Type::VoidType();
    } else {
      result_type = ParseType(kCanResolve);
    }
    is_getter = (CurrentToken() == Token::kGET);
    if (CurrentToken() == Token::kGET || CurrentToken() == Token::kSET) {
      ConsumeToken();
    } else {
      UnexpectedToken();
    }
  }
  intptr_t name_pos = token_index_;
  const String* field_name = ExpectIdentifier("accessor name expected");

  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg("'(' expected");
  }
  intptr_t accessor_pos = token_index_;
  ParamList params;
  const bool allow_explicit_default_values = true;
  ParseFormalParameterList(allow_explicit_default_values, &params);
  String& accessor_name = String::ZoneHandle();
  int expected_num_parameters = -1;
  if (is_getter) {
    expected_num_parameters = 0;
    accessor_name = Field::GetterName(*field_name);
  } else {
    expected_num_parameters = 1;
    accessor_name = Field::SetterName(*field_name);
  }
  if ((params.num_fixed_parameters != expected_num_parameters) ||
      (params.num_optional_parameters != 0)) {
    ErrorMsg(name_pos, "illegal %s parameters",
             is_getter ? "getter" : "setter");
  }

  if (CurrentToken() == Token::kLBRACE) {
    SkipBlock();
  } else if (CurrentToken() == Token::kARROW) {
    ConsumeToken();
    SkipExpr();
    ExpectSemicolon();
  } else if (IsLiteral("native")) {
    ParseNativeDeclaration();
  } else {
    ErrorMsg("function block expected");
  }
  Function& func = Function::ZoneHandle(
      Function::New(accessor_name,
                    is_getter? RawFunction::kGetterFunction :
                               RawFunction::kSetterFunction,
                    is_static, false, accessor_pos));
  func.set_result_type(result_type);
  AddFormalParamsToFunction(&params, func);
  top_level->functions.Add(&func);
  library_.AddObject(func, accessor_name);
}


void Parser::ParseLibraryName() {
  if ((script_.kind() == RawScript::kLibrary) &&
      (CurrentToken() != Token::kLIBRARY)) {
    // Handle error case early to get consistent error message.
    ExpectToken(Token::kLIBRARY);
  }
  if (CurrentToken() == Token::kLIBRARY) {
    ConsumeToken();
    ExpectToken(Token::kLPAREN);
    if (CurrentToken() != Token::kSTRING) {
      ErrorMsg("library name expected");
    }
    const String& name = *CurrentLiteral();
    ConsumeToken();
    ExpectToken(Token::kRPAREN);
    ExpectToken(Token::kSEMICOLON);
    library_.SetName(name);
  }
}


Dart_Result Parser::CallLibraryTagHandler(Dart_LibraryTag tag,
                                   intptr_t token_pos,
                                   const String& url) {
  Dart_LibraryTagHandler handler = Isolate::Current()->library_tag_handler();
  if (handler == NULL) {
    ErrorMsg(token_pos, "no library handler registered");
  }
  Dart_Result result = handler(tag,
                               Api::NewLocalHandle(library_),
                               Api::NewLocalHandle(url));
  if (!Dart_IsValidResult(result)) {
    ErrorMsg(token_pos, "library handler failed: %s",
             Dart_GetErrorCString(result));
  }
  return result;
}


void Parser::ParseLibraryImport() {
  while (CurrentToken() == Token::kIMPORT) {
    intptr_t import_pos = token_index_;
    ConsumeToken();
    ExpectToken(Token::kLPAREN);
    if (CurrentToken() != Token::kSTRING) {
      ErrorMsg("library url expected");
    }
    const String& url = *CurrentLiteral();
    ConsumeToken();
    String& prefix = String::Handle();
    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
      const String& kPrefix = String::Handle(String::NewSymbol("prefix"));
      if ((CurrentToken() != Token::kIDENT) ||
          !kPrefix.Equals(*CurrentLiteral())) {
        ErrorMsg("prefix: expected");
      }
      ConsumeToken();
      ExpectToken(Token::kCOLON);
      if (CurrentToken() != Token::kSTRING) {
        ErrorMsg("prefix expected");
      }
      prefix = CurrentLiteral()->raw();
      ConsumeToken();
    }
    ExpectToken(Token::kRPAREN);
    ExpectToken(Token::kSEMICOLON);
    Dart_Result result = CallLibraryTagHandler(kCanonicalizeUrl,
                                               import_pos,
                                               url);
    Dart_Handle handle = Dart_GetResult(result);
    const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle));
    // Lookup the library URL.
    Library& library = Library::Handle(Library::LookupLibrary(canon_url));
    if (library.IsNull()) {
      // Create a new library object and call the library tag handler.
      library = Library::New(canon_url);
      library.Register();
      // The tag handler expects the importing library as a parameter.
      CallLibraryTagHandler(kImportTag, import_pos, canon_url);
    }
    // Add the import to the library.
    if (prefix.IsNull() || (prefix.Length() == 0)) {
      library_.AddImport(library);
    } else {
      if (library_.LookupLocalObject(prefix) != Object::null()) {
        ErrorMsg(token_index_, "'%s' is already defined", prefix.ToCString());
      }
      prefix = String::NewSymbol(prefix);
      const LibraryPrefix& library_prefix =
          LibraryPrefix::Handle(LibraryPrefix::New(prefix, library));
      library_.AddObject(library_prefix, prefix);
    }
  }
}


void Parser::ParseLibraryInclude() {
  while (CurrentToken() == Token::kSOURCE) {
    intptr_t source_pos = token_index_;
    ConsumeToken();
    ExpectToken(Token::kLPAREN);
    if (CurrentToken() != Token::kSTRING) {
      ErrorMsg("source url expected");
    }
    const String& url = *CurrentLiteral();
    ConsumeToken();
    ExpectToken(Token::kRPAREN);
    ExpectToken(Token::kSEMICOLON);
    Dart_Result result = CallLibraryTagHandler(kCanonicalizeUrl,
                                               source_pos,
                                               url);
    Dart_Handle handle = Dart_GetResult(result);
    const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle));
    CallLibraryTagHandler(kSourceTag, source_pos, canon_url);
  }
}


void Parser::ParseLibraryDefinition() {
  // Handle the script tag.
  if (CurrentToken() == Token::kSCRIPTTAG) {
    // Nothing to do for script tags except to skip them.
    ConsumeToken();
  }

  ParseLibraryName();
  ParseLibraryImport();
  ParseLibraryInclude();
}


void Parser::ParseTopLevel() {
  // Collect the classes found at the top level in this growable array.
  // They need to be registered with class finalization after parsing
  // has been completed.
  GrowableArray<const Class*> classes;
  SetPosition(0);
  is_top_level_ = true;
  TopLevel top_level;
  Class& toplevel_class = Class::ZoneHandle(
      Class::New(String::ZoneHandle(String::NewSymbol("")), script_));
  toplevel_class.set_library(library_);

  if (is_library_source()) {
    ParseLibraryDefinition();
  }

  while (true) {
    set_current_class(Class::Handle());  // No current class.
    if (CurrentToken() == Token::kCLASS) {
      ParseClassDefinition(&classes);
    } else if (CurrentToken() == Token::kTYPEDEF) {
      ParseFunctionTypeAlias(&classes);
    } else if (CurrentToken() == Token::kINTERFACE) {
      ParseInterfaceDefinition(&classes);
    } else if (IsVariableDeclaration()) {
      set_current_class(toplevel_class);
      ParseTopLevelVariable(&top_level);
    } else if (IsTopLevelFunction()) {
      set_current_class(toplevel_class);
      ParseTopLevelFunction(&top_level);
    } else if (IsTopLevelAccessor()) {
      set_current_class(toplevel_class);
      ParseTopLevelAccessor(&top_level);
    } else if (CurrentToken() == Token::kEOS) {
      break;
    } else {
      UnexpectedToken();
    }
  }
  if ((top_level.fields.length() > 0) || (top_level.functions.length() > 0)) {
    toplevel_class.SetFields(
        Array::Handle(NewArray<Field>(top_level.fields)));
    toplevel_class.SetFunctions(
        Array::Handle(NewArray<Function>(top_level.functions)));
    library_.AddAnonymousClass(toplevel_class);
    classes.Add(&toplevel_class);
  }
  ClassFinalizer::AddPendingClasses(classes);
}


void Parser::ChainNewBlock(LocalScope* outer_scope) {
  Block* block = new Block(current_block_,
                           outer_scope,
                           new SequenceNode(token_index_, outer_scope));
  current_block_ = block;
}


void Parser::OpenBlock() {
  ASSERT(current_block_ != NULL);
  LocalScope* outer_scope = current_block_->scope;
  ChainNewBlock(new LocalScope(outer_scope,
                               outer_scope->function_level(),
                               outer_scope->loop_level()));
}


void Parser::OpenLoopBlock() {
  ASSERT(current_block_ != NULL);
  LocalScope* outer_scope = current_block_->scope;
  ChainNewBlock(new LocalScope(outer_scope,
                               outer_scope->function_level(),
                               outer_scope->loop_level() + 1));
}


void Parser::OpenFunctionBlock(const Function& func) {
  LocalScope* outer_scope;
  if (current_block_ == NULL) {
    if (!func.IsLocalFunction()) {
      // We are compiling a non-nested function.
      outer_scope = new LocalScope(NULL, 0, 0);
    } else {
      // We are compiling the function of an invoked closure.
      // Restore the outer scope containing all captured variables.
      const ContextScope& context_scope =
          ContextScope::Handle(func.context_scope());
      ASSERT(!context_scope.IsNull());
      outer_scope =
          new LocalScope(LocalScope::RestoreOuterScope(context_scope), 0, 0);
    }
  } else {
    // We are parsing a nested function while compiling the enclosing function.
    outer_scope = new LocalScope(current_block_->scope,
                                 current_block_->scope->function_level() + 1,
                                 0);
  }
  ChainNewBlock(outer_scope);
}


SequenceNode* Parser::CloseBlock() {
  SequenceNode* statements = current_block_->statements;
  current_block_ = current_block_->parent;
  return statements;
}


// Set up default values for all optional parameters to the function.
void Parser::SetupDefaultsForOptionalParams(const ParamList* params,
                                            Array& default_values) {
  if (params->num_optional_parameters > 0) {
    // Build array of default parameter values.
    ParamDesc* param =
      params->parameters->data() + params->num_fixed_parameters;
    default_values = Array::New(params->num_optional_parameters);
    for (int i = 0; i < params->num_optional_parameters; i++) {
      ASSERT(param->default_value != NULL);
      default_values.SetAt(i, *param->default_value);
      param++;
    }
  }
}


// Populate the parameter type array and parameter name array of the function
// with the formal parameter types and names.
void Parser::AddFormalParamsToFunction(const ParamList* params,
                                       const Function& func) {
  ASSERT((params != NULL) && (params->parameters != NULL));
  func.set_num_fixed_parameters(params->num_fixed_parameters);
  func.set_num_optional_parameters(params->num_optional_parameters);
  const int num_parameters = params->parameters->length();
  ASSERT(num_parameters == func.NumberOfParameters());
  func.set_parameter_types(Array::Handle(Array::New(num_parameters,
                                                    Heap::kOld)));
  func.set_parameter_names(Array::Handle(Array::New(num_parameters,
                                                    Heap::kOld)));
  for (int i = 0; i < num_parameters; i++) {
    ParamDesc& param_desc = (*params->parameters)[i];
    ASSERT(is_top_level_ || param_desc.type->IsResolved());
    func.SetParameterTypeAt(i, *param_desc.type);
    func.SetParameterNameAt(i, *param_desc.name);
  }
}


// Populate local scope with the formal parameters.
void Parser::AddFormalParamsToScope(const ParamList* params,
                                    LocalScope* scope) {
  ASSERT((params != NULL) && (params->parameters != NULL));
  ASSERT(scope != NULL);
  const int num_parameters = params->parameters->length();
  for (int i = 0; i < num_parameters; i++) {
    ParamDesc& param_desc = (*params->parameters)[i];
    ASSERT(!is_top_level_ || param_desc.type->IsResolved());
    const String* name = param_desc.name;
    if (param_desc.is_field_initializer) {
      name = &String::ZoneHandle(MangledInitParamName(*name));
    }
    LocalVariable* parameter = new LocalVariable(
        param_desc.name_pos, *name, *param_desc.type);
    if (!scope->AddVariable(parameter)) {
      ErrorMsg(param_desc.name_pos,
               "name '%s' already exists in scope",
               param_desc.name->ToCString());
    }
    if (param_desc.is_final) {
      parameter->set_is_final();
    }
  }
}


// Builds ReturnNode/NativeBodyNode for a native function.
void Parser::ParseNativeFunctionBlock(const ParamList* params,
                                      const Function& func) {
  const Class& cls = Class::Handle(func.owner());
  const int num_parameters = params->parameters->length();

  // Parse the function name out.
  intptr_t native_pos = token_index_;
  const String& native_name = ParseNativeDeclaration();

  // Now resolve the native function to the corresponding native entrypoint.
  NativeFunction native_function = NativeEntry::ResolveNative(cls,
                                                              native_name,
                                                              num_parameters);
  if (native_function == NULL) {
    ErrorMsg(native_pos, "native function '%s' cannot be found",
        native_name.ToCString());
  }

  const bool has_opt_params = (params->num_optional_parameters > 0);

  // Now add the NativeBodyNode and return statement.
  current_block_->statements->Add(
      new ReturnNode(token_index_, new NativeBodyNode(token_index_,
                                                      native_name,
                                                      native_function,
                                                      num_parameters,
                                                      has_opt_params)));
}


LocalVariable* Parser::LookupReceiver(LocalScope* from_scope,
                                      bool test_only) {
  const String& this_name = String::Handle(String::NewSymbol(kThisName));
  return from_scope->LookupVariable(this_name, test_only);
}


void Parser::CaptureReceiver() {
  ASSERT(current_block_->scope->function_level() > 0);
  const bool kTestOnly = false;
  // Side effect of lookup captures the receiver variable.
  LocalVariable* receiver = LookupReceiver(current_block_->scope, kTestOnly);
  ASSERT(receiver != NULL);
}


AstNode* Parser::LoadReceiver() {
  // A nested function may access 'this', referring to the receiver of the
  // outermost enclosing function.
  // We should not be loading the receiver from a static scope.
  ASSERT(!current_function().IsInStaticScope() ||
         current_function().IsInFactoryScope());
  const bool kTestOnly = false;
  LocalVariable* receiver = LookupReceiver(current_block_->scope, kTestOnly);
  if (receiver == NULL) {
    ErrorMsg("illegal access to 'this'");
  }
  return new LoadLocalNode(token_index_, *receiver);
}


AstNode* Parser::CallGetter(intptr_t token_index,
                            AstNode* object,
                            const String& name) {
  return new InstanceGetterNode(token_index_, object, name);
}


// Returns ast nodes of the variable initialization.
AstNode* Parser::ParseVariableDeclaration(const Type& type, bool is_final) {
  TRACE_PARSER("ParseVariableDeclaration");
  ASSERT(CurrentToken() == Token::kIDENT);
  const intptr_t ident_pos = token_index_;
  LocalVariable* variable =
      new LocalVariable(ident_pos, *CurrentLiteral(), type);
  ASSERT(current_block_ != NULL);
  ASSERT(current_block_->scope != NULL);
  ConsumeToken();  // Variable identifier.
  AstNode* initialization = NULL;
  if (CurrentToken() == Token::kASSIGN) {
    // Variable initialization.
    const intptr_t assign_pos = token_index_;
    ConsumeToken();
    AstNode* expr = ParseExpr(kAllowConst);
    initialization = new StoreLocalNode(assign_pos, *variable, expr);
  } else if (is_final) {
    ErrorMsg(ident_pos, "missing initialization of 'final' variable");
  } else {
    // Initialize variable with null.
    AstNode* null_expr = new LiteralNode(ident_pos, Instance::ZoneHandle());
    initialization = new StoreLocalNode(ident_pos, *variable, null_expr);
  }
  // Add variable to cope after parsing the initalizer expression.
  // The expression must not be able to refer to the variable.
  if (!current_block_->scope->AddVariable(variable)) {
    ErrorMsg(ident_pos, "identifier '%s' already defined",
             variable->name().ToCString());
  }
  if (is_final) {
    variable->set_is_final();
  }
  return initialization;
}


// Parses ('var' | 'final' [type] | type).
// The presence of 'final' must be detected and remembered before the call.
// If type_specification is kIsOptional, and no type can be parsed, then return
// the VarType.
// If a type is parsed, it is resolved (or not) according to type_resolution.
RawType* Parser::ParseFinalVarOrType(TypeSpecification type_specification,
                                     TypeResolution type_resolution) {
  if (CurrentToken() == Token::kVAR) {
    ConsumeToken();
    return Type::VarType();
  }
  if (CurrentToken() == Token::kFINAL) {
    ConsumeToken();
    type_specification = kIsOptional;
  }
  if (CurrentToken() != Token::kIDENT) {
    if (type_specification == kIsOptional) {
      return Type::VarType();
    } else {
      ErrorMsg("identifier expected");
    }
  }
  if (type_specification == kIsOptional) {
    Token::Kind follower = LookaheadToken(1);
    // We have an identifier followed by a 'follower' token.
    // We either parse a type or return now.
    if ((follower != Token::kLT) &&  // Parameterized type.
        (follower != Token::kPERIOD) &&  // Qualified class name of type.
        (follower != Token::kIDENT) &&  // Variable name following a type.
        (follower != Token::kTHIS)) {  // Field parameter following a type.
      return Type::VarType();
    }
  }
  return ParseType(type_resolution);
}


// Returns ast nodes of the variable initialization, or NULL if variables
// are not initialized. If several variables are declared and initialized,
// the individual initializers are collected in a sequence node.
AstNode* Parser::ParseVariableDeclarationList() {
  TRACE_PARSER("ParseVariableDeclarationList");
  bool is_final = (CurrentToken() == Token::kFINAL);
  const Type& type = Type::ZoneHandle(
      ParseFinalVarOrType(kIsMandatory, kMustResolve));
  if (CurrentToken() != Token::kIDENT) {
    ErrorMsg("identifier expected");
  }

  AstNode* initializers = ParseVariableDeclaration(type, is_final);
  while (CurrentToken() == Token::kCOMMA) {
    ConsumeToken();
    if (CurrentToken() != Token::kIDENT) {
      ErrorMsg("identifier expected after comma");
    }
    AstNode* right = ParseVariableDeclaration(type, is_final);
    if (right != NULL) {
      if (initializers == NULL) {
        initializers = right;
      } else {
        // We have a second initializer. Allocate a sequence node now.
        SequenceNode* sequence = NodeAsSequenceNode(initializers->token_index(),
                                                    initializers,
                                                    current_block_->scope);
        sequence->Add(right);
        initializers = sequence;
      }
    }
  }
  return initializers;
}


AstNode* Parser::ParseFunctionStatement(bool is_literal) {
  TRACE_PARSER("ParseFunctionStatement");
  Type& result_type = Type::Handle();
  const String* variable_name = NULL;
  const String* function_name = NULL;

  result_type = Type::VarType();
  if (CurrentToken() == Token::kVOID) {
    ConsumeToken();
    result_type = Type::VoidType();
  } else if ((CurrentToken() == Token::kIDENT) &&
             (LookaheadToken(1) != Token::kLPAREN)) {
    result_type = ParseType(kMustResolve);
  }
  intptr_t ident_pos = token_index_;
  if (CurrentToken() == Token::kIDENT) {
    variable_name = CurrentLiteral();
    function_name = variable_name;
    ConsumeToken();
  } else {
    if (!is_literal) {
      ErrorMsg("function name expected");
    }
    const String& anonymous_function_name =
        String::ZoneHandle(String::NewSymbol("function"));
    function_name = &anonymous_function_name;
  }
  ASSERT(ident_pos >= 0);

  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg("'(' expected");
  }
  Function& function = Function::ZoneHandle(
      Function::NewClosureFunction(*function_name,
                                   current_function(),
                                   token_index_));
  function.set_result_type(result_type);
  LocalVariable* function_variable = NULL;
  ParameterizedType& function_type = ParameterizedType::ZoneHandle();
  if (variable_name != NULL) {
    // Add the function variable to the scope before parsing the function in
    // order to allow self reference from inside the function.
    // The type of the implicitly declared const variable is defined by the
    // local function signature class and the type arguments of the current
    // receiver (if in a non-static scope). However, the signature is not yet
    // known, since the formal parameter list is not parsed yet. Therefore, we
    // set the type to a new parameterized type to be patched after the actual
    // type is known. We temporarily use the class of the Function interface.
    const Class& unknown_signature_class = Class::Handle(
        Type::Handle(Type::FunctionInterface()).type_class());
    function_type = ParameterizedType::New(unknown_signature_class,
                                           TypeArguments::Handle());
    function_type.set_is_finalized();  // No real finalization needed.
    function_variable = new LocalVariable(ident_pos,
                                          *variable_name,
                                          function_type);
    function_variable->set_is_final();
    ASSERT(current_block_ != NULL);
    ASSERT(current_block_->scope != NULL);
    if (!current_block_->scope->AddVariable(function_variable)) {
      ErrorMsg(ident_pos, "identifier '%s' already defined",
               function_variable->name().ToCString());
    }
  }

  // Parse the local function.
  Array& default_parameter_values = Array::Handle();
  SequenceNode* statements = Parser::ParseFunc(function,
                                               default_parameter_values);

  // Now that the local function has formal parameters, lookup or create a new
  // signature class for it.
  const String& signature = String::Handle(function.Signature());
  Class& signature_class = Class::Handle(LookupClass(signature));
  if (signature_class.IsNull()) {
    signature_class = Class::NewSignatureClass(signature,
                                               function,
                                               script_,
                                               ident_pos);
    // Record the function signature class in the library.
    library_.AddClass(signature_class);
  }
  ASSERT(!Function::Handle(signature_class.signature_function()).IsNull());
  ASSERT(Class::Handle(function.signature_class()).IsNull());
  function.set_signature_class(signature_class);

  // Local functions are not registered in the enclosing class, which is already
  // finalized.
  ASSERT(current_class().is_finalized());

  if (function_variable != NULL) {
    ASSERT(function_variable->type().raw() == function_type.raw());
    // Patch the function variable type now that the signature is known.
    // We need to create a new type for proper finalization, since the existing
    // type is already marked as finalized.
    // TODO(regis): Set proper signature_type_arguments if in non-static scope
    // and if the signature involves generic types.
    const TypeArguments& signature_type_arguments = TypeArguments::Handle();
    const String& errmsg = String::Handle(
        ClassFinalizer::FinalizeTypeWhileParsing(ParameterizedType::Handle(
            ParameterizedType::New(signature_class,
                                   signature_type_arguments))));
    if (!errmsg.IsNull()) {
      ErrorMsg(errmsg.ToCString());
    }
    function_type.set_type_class(signature_class);
    function_type.set_arguments(signature_type_arguments);
  }

  // The code generator does not compile the closure function when visiting
  // a ClosureNode. The generated code allocates a new Closure object containing
  // the current context. The type of the Closure object refers to the closure
  // function, which will be compiled on first invocation of the closure object.
  // Therefore, we ignore the parsed default_parameter_values and the
  // node_sequence representing the body of the closure function, which will be
  // parsed again when compiled later.
  // The only purpose of parsing the function now (besides reporting obvious
  // errors) is to mark referenced variables of the enclosing scopes as
  // captured. The captured variables will be recorded along with their
  // allocation information in a Scope object stored in the function object.
  // This Scope object is then provided to the compiler when compiling the local
  // function. It would be too early to record the captured variables here,
  // since further closure functions may capture more variables.
  // This Scope object is constructed after all variables have been allocated.
  // The local scope of the parsed function can be pruned, since contained
  // variables are not relevant for the compilation of the enclosing function.
  // This pruning is done by omitting to hook the local scope in its parent
  // scope in the constructor of LocalScope.
  AstNode* closure = new ClosureNode(ident_pos, function, statements->scope());

  if (function_variable == NULL) {
    ASSERT(is_literal);
    return closure;
  } else {
    AstNode* initialization =
        new StoreLocalNode(ident_pos, *function_variable, closure);
    return initialization;
  }
}


// Returns true if the current and next tokens can be parsed as type
// parameters. Current token position is not saved and restored.
bool Parser::IsTypeParameter() {
  if (CurrentToken() == Token::kLT) {
    // We are possibly looking at type parameters. Find closing ">".
    int nesting_level = 0;
    do {
      if (CurrentToken() == Token::kLT) {
        nesting_level++;
      } else if (CurrentToken() == Token::kGT) {
        nesting_level--;
      } else if (CurrentToken() == Token::kSAR) {
        nesting_level -= 2;
      } else if (CurrentToken() == Token::kSHR) {
        nesting_level -= 3;
      } else if (CurrentToken() != Token::kCOMMA &&
                 CurrentToken() != Token::kIDENT &&
                 CurrentToken() != Token::kEXTENDS) {
        // We are looking at something other than type parameters.
        return false;
      }
      ConsumeToken();
    } while (nesting_level > 0);
    if (nesting_level < 0) {
      return false;
    }
  }
  return true;
}


// Returns true if the next tokens can be parsed as a type with optional
// type parameters. Current token position is not restored.
bool Parser::IsOptionalType() {
  if (CurrentToken() == Token::kIDENT) {
    QualIdent type_name;
    ParseQualIdent(&type_name);
    // Check if the type_name has been defined as a variable in a local scope,
    // hiding the type.
    if (type_name.local_scope_ident) {
      return false;
    }
    if (CurrentToken() == Token::kLT && !IsTypeParameter()) {
      return false;
    }
  }
  return true;
}


// Returns true if the next tokens can be parsed as a type with optional
// type parameters, or keyword "void".
// Current token position is not restored.
bool Parser::IsReturnType() {
  if (CurrentToken() == Token::kVOID) {
    ConsumeToken();
    return true;
  } else if (CurrentToken() == Token::kIDENT) {
    return IsOptionalType();
  }
  return false;
}


// Look ahead to detect whether the next tokens should be parsed as
// a variable declaration. Returns true if we detect the token pattern:
// ('var' | 'final' | type ident (';' | '=' | ','))
// Token position remains unchanged.
bool Parser::IsVariableDeclaration() {
  if ((CurrentToken() == Token::kVAR) ||
      (CurrentToken() == Token::kFINAL)) {
    return true;
  }
  if (CurrentToken() != Token::kIDENT) {
    return false;
  }
  intptr_t saved_pos = token_index_;
  bool is_var_decl = false;
  if (IsOptionalType()) {
    if (CurrentToken() == Token::kIDENT) {
      ConsumeToken();
      if ((CurrentToken() == Token::kSEMICOLON) ||
          (CurrentToken() == Token::kCOMMA) ||
          (CurrentToken() == Token::kASSIGN)) {
        is_var_decl = true;
      }
    }
  }
  SetPosition(saved_pos);
  return is_var_decl;
}


bool Parser::IsFunctionDeclaration() {
  // A function declaration is like a function literal but it must have
  // a name.
  return (CurrentToken() != Token::kLPAREN) && IsFunctionLiteral();
}


bool Parser::IsTopLevelFunction() {
  // Top-level function declarations can omit the return type. Check for
  // that case separately.
  return ((CurrentToken() == Token::kIDENT) &&
      (LookaheadToken(1) == Token::kLPAREN)) ||
      IsFunctionDeclaration();
}


bool Parser::IsTopLevelAccessor() {
  if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) {
    return true;
  }
  intptr_t saved_pos = token_index_;
  if (IsReturnType()) {
    if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) {
      if (LookaheadToken(1) == Token::kIDENT) {  // Accessor name.
        SetPosition(saved_pos);
        return true;
      }
    }
  }
  SetPosition(saved_pos);
  return false;
}


bool Parser::IsFunctionLiteral() {
  if (!allow_function_literals_) {
    return false;
  }
  intptr_t saved_pos = token_index_;
  bool is_function_literal = false;
  if ((CurrentToken() == Token::kIDENT) &&
      (LookaheadToken(1) == Token::kLPAREN)) {
    ConsumeToken();  // Consume function identifier.
  } else if (IsReturnType()) {
    if (CurrentToken() != Token::kIDENT) {
      SetPosition(saved_pos);
      return false;
    }
    ConsumeToken();  // Comsume function identifier.
  }
  if (CurrentToken() == Token::kLPAREN) {
    SkipToMatchingParenthesis();
    if ((CurrentToken() == Token::kLBRACE) ||
        (CurrentToken() == Token::kARROW)) {
      is_function_literal = true;
    }
  }
  SetPosition(saved_pos);
  return is_function_literal;
}


// Current token position is the token after the opening ( of the for
// statement. Returns true if we recognize a for ( .. in expr)
// statement.
bool Parser::IsForInStatement() {
  intptr_t saved_pos = token_index_;
  bool result = false;
  if (CurrentToken() == Token::kVAR || CurrentToken() == Token::kFINAL) {
    ConsumeToken();
  }
  if (CurrentToken() == Token::kIDENT) {
    if (LookaheadToken(1) == Token::kIN) {
      result = true;
    } else if (IsOptionalType()) {
      if (CurrentToken() == Token::kIDENT) {
        ConsumeToken();
      }
      result = (CurrentToken() == Token::kIN);
    }
  }
  SetPosition(saved_pos);
  return result;
}


static bool ContainsAbruptCompletingStatement(SequenceNode *seq);

static bool IsAbruptCompleting(AstNode* statement) {
  return statement->IsReturnNode() ||
         statement->IsJumpNode()   ||
         statement->IsThrowNode()  ||
         (statement->IsSequenceNode() &&
             ContainsAbruptCompletingStatement(statement->AsSequenceNode()));
}


static bool ContainsAbruptCompletingStatement(SequenceNode *seq) {
  for (int i = 0; i < seq->length(); i++) {
    if (IsAbruptCompleting(seq->NodeAt(i))) {
      return true;
    }
  }
  return false;
}


void Parser::ParseStatementSequence() {
  TRACE_PARSER("ParseStatementSequence");
  const bool dead_code_allowed = true;
  bool abrupt_completing_seen = false;
  while (CurrentToken() != Token::kRBRACE) {
    intptr_t statement_pos = token_index_;
    AstNode* statement = ParseStatement();
    if (statement != NULL) {
      if (!dead_code_allowed && abrupt_completing_seen) {
        ErrorMsg(statement_pos, "dead code after abrupt completing statement");
      }
      current_block_->statements->Add(statement);
      abrupt_completing_seen |= IsAbruptCompleting(statement);
    }
  }
}


// Parse nested statement of if, while, for, etc. We automatically generate
// a sequence of one statement if there are no curly braces.
// The argument 'parsing_loop_body' indicates the parsing of a loop statement.
SequenceNode* Parser::ParseNestedStatement(bool parsing_loop_body,
                                           SourceLabel* label) {
  TRACE_PARSER("ParseNestedStatement");
  if (parsing_loop_body) {
    OpenLoopBlock();
  } else {
    OpenBlock();
  }
  if (label != NULL) {
    current_block_->scope->AddLabel(label);
  }
  if (CurrentToken() == Token::kLBRACE) {
    ConsumeToken();
    ParseStatementSequence();
    ExpectToken(Token::kRBRACE);
  } else {
    AstNode* statement = ParseStatement();
    if (statement != NULL) {
      current_block_->statements->Add(statement);
    }
  }
  SequenceNode* sequence = CloseBlock();
  return sequence;
}


AstNode* Parser::ParseIfStatement(String* label_name) {
  TRACE_PARSER("ParseIfStatement");
  ASSERT(CurrentToken() == Token::kIF);
  intptr_t if_pos = token_index_;
  SourceLabel* label = NULL;
  if (label_name != NULL) {
    label = SourceLabel::New(if_pos, label_name, SourceLabel::kStatement);
    OpenBlock();
    current_block_->scope->AddLabel(label);
  }
  ConsumeToken();
  ExpectToken(Token::kLPAREN);
  AstNode* cond_expr = ParseExpr(kAllowConst);
  ExpectToken(Token::kRPAREN);
  const bool parsing_loop_body = false;
  SequenceNode* true_branch = ParseNestedStatement(parsing_loop_body, NULL);
  SequenceNode* false_branch = NULL;
  if (CurrentToken() == Token::kELSE) {
    ConsumeToken();
    false_branch = ParseNestedStatement(parsing_loop_body, NULL);
  }
  AstNode* if_node = new IfNode(if_pos, cond_expr, true_branch, false_branch);
  if (label != NULL) {
    current_block_->statements->Add(if_node);
    SequenceNode* sequence = CloseBlock();
    sequence->set_label(label);
    if_node = sequence;
  }
  return if_node;
}


CaseNode* Parser::ParseCaseClause(LocalVariable* switch_expr_value,
                                  SourceLabel* case_label) {
  TRACE_PARSER("ParseCaseStatement");
  bool default_seen = false;
  intptr_t case_pos = token_index_;
  intptr_t expr_pos = 0;
  SequenceNode* case_expressions =
      new SequenceNode(case_pos, current_block_->scope);
  while (CurrentToken() == Token::kCASE || CurrentToken() == Token::kDEFAULT) {
    if (CurrentToken() == Token::kCASE) {
      if (default_seen) {
        ErrorMsg("default clause must be last case");
      }
      ConsumeToken();  // Keyword case.
      expr_pos = token_index_;
      AstNode* expr = ParseExpr(kAllowConst);
      AstNode* switch_expr_load = new LoadLocalNode(case_pos,
                                                    *switch_expr_value);
      AstNode* case_comparison = new ComparisonNode(case_pos,
                                                    Token::kEQ,
                                                    expr,
                                                    switch_expr_load);
      case_expressions->Add(case_comparison);
    } else {
      if (default_seen) {
        ErrorMsg("only one default clause is allowed");
      }
      ConsumeToken();  // Keyword default.
      expr_pos = token_index_;
      default_seen = true;
      // The default case always succeeds.
    }
    ExpectToken(Token::kCOLON);
  }

  OpenBlock();
  bool abrupt_completing_seen = false;
  while (true) {
    // Check whether the next statement still belongs to the current case
    // clause. If we see 'case' or 'default', optionally preceeded by
    // a label, or closing brace, we stop parsing statements.
    Token::Kind next_token;
    if (CurrentToken() == Token::kIDENT &&
        LookaheadToken(1) == Token::kCOLON) {
      next_token = LookaheadToken(2);
    } else {
      next_token = CurrentToken();
    }
    if (next_token == Token::kRBRACE) {
      // End of switch statement.
      break;
    }
    if ((next_token == Token::kCASE) || (next_token == Token::kDEFAULT)) {
      // End of this case clause. If there is a possible fall-through to
      // the next case clause, throw an implicit FallThroughError.
      if (!abrupt_completing_seen) {
        ArgumentListNode* arguments = new ArgumentListNode(token_index_);
        arguments->Add(new LiteralNode(
            token_index_, Integer::ZoneHandle(Integer::New(token_index_))));
        current_block_->statements->Add(
            MakeStaticCall(kFallThroughErrorName, kThrowNewName, arguments));
      }
      break;
    }
    // The next statement still belongs to this case.
    AstNode* statement = ParseStatement();
    if (statement != NULL) {
      current_block_->statements->Add(statement);
      abrupt_completing_seen |= IsAbruptCompleting(statement);
    }
  }
  SequenceNode* statements = CloseBlock();
  return new CaseNode(case_pos, case_label,
      case_expressions, default_seen, switch_expr_value, statements);
}


AstNode* Parser::ParseSwitchStatement(String* label_name) {
  TRACE_PARSER("ParseSwitchStatement");
  ASSERT(CurrentToken() == Token::kSWITCH);
  intptr_t switch_pos = token_index_;
  SourceLabel* label =
      SourceLabel::New(switch_pos, label_name, SourceLabel::kSwitch);
  ConsumeToken();
  const bool parens_are_mandatory = false;
  bool paren_found = false;
  if (CurrentToken() == Token::kLPAREN) {
    paren_found = true;
    ConsumeToken();
  } else if (parens_are_mandatory) {
    ErrorMsg("'(' expected");
  }
  intptr_t expr_pos = token_index_;
  AstNode* switch_expr = ParseExpr(kAllowConst);
  if (paren_found) {
    ExpectToken(Token::kRPAREN);
  }
  ExpectToken(Token::kLBRACE);
  OpenBlock();
  current_block_->scope->AddLabel(label);

  // Store switch expression in temporary local variable.
  LocalVariable* temp_variable =
      new LocalVariable(expr_pos,
                        String::ZoneHandle(String::NewSymbol(":switch_expr")),
                        Type::ZoneHandle(Type::VarType()));
  current_block_->scope->AddVariable(temp_variable);
  AstNode* save_switch_expr =
      new StoreLocalNode(expr_pos, *temp_variable, switch_expr);
  current_block_->statements->Add(save_switch_expr);

  // Parse case clauses
  bool default_seen = false;
  while (true) {
    // Check for statement label
    SourceLabel* case_label = NULL;
    if (CurrentToken() == Token::kIDENT &&
        LookaheadToken(1) == Token::kCOLON) {
      // Case statements start with a label.
      String* label_name = CurrentLiteral();
      intptr_t label_pos = token_index_;
      ConsumeToken();  // Consume label identifier.
      ConsumeToken();  // Consume colon.
      case_label = current_block_->scope->LocalLookupLabel(*label_name);
      if (case_label == NULL) {
        // Label does not exist yet. Add it to scope of switch statement.
        case_label =
            new SourceLabel(label_pos, *label_name, SourceLabel::kCase);
        current_block_->scope->AddLabel(case_label);
      } else if (case_label->kind() == SourceLabel::kForward) {
        // We have seen a 'continue' with this label name. Resolve
        // the forward reference.
        case_label->ResolveForwardReference();
      } else {
        ErrorMsg(label_pos, "name '%s' already exists in scope",
                 label_name->ToCString());
      }
      ASSERT(case_label->kind() == SourceLabel::kCase);
    }
    if (CurrentToken() == Token::kCASE ||
        CurrentToken() == Token::kDEFAULT) {
      if (default_seen) {
        ErrorMsg("no case clauses allowed after default clause");
      }
      CaseNode* case_clause = ParseCaseClause(temp_variable, case_label);
      default_seen = case_clause->contains_default();
      current_block_->statements->Add(case_clause);
    } else if (CurrentToken() != Token::kRBRACE) {
      ErrorMsg("'case' or '}' expected");
    } else if (case_label != NULL) {
      ErrorMsg("expecting at least one case clause after label");
    } else {
      break;
    }
  }

  // Check for unresolved label references.
  SourceLabel* unresolved_label =
      current_block_->scope->CheckUnresolvedLabels();
  if (unresolved_label != NULL) {
    ErrorMsg("unresolved reference to label '%s'",
             unresolved_label->name().ToCString());
  }

  SequenceNode* switch_body = CloseBlock();
  ExpectToken(Token::kRBRACE);
  return new SwitchNode(switch_pos, label, switch_body);
}


AstNode* Parser::ParseWhileStatement(String* label_name) {
  TRACE_PARSER("ParseWhileStatement");
  intptr_t while_pos = token_index_;
  SourceLabel* label =
      SourceLabel::New(while_pos, label_name, SourceLabel::kWhile);
  ConsumeToken();
  ExpectToken(Token::kLPAREN);
  AstNode* cond_expr = ParseExpr(kAllowConst);
  ExpectToken(Token::kRPAREN);
  const bool parsing_loop_body =  true;
  SequenceNode* while_body = ParseNestedStatement(parsing_loop_body, label);
  return new WhileNode(while_pos, label, cond_expr, while_body);
}


AstNode* Parser::ParseDoWhileStatement(String* label_name) {
  TRACE_PARSER("ParseDoWhileStatement");
  intptr_t do_pos = token_index_;
  SourceLabel* label =
      SourceLabel::New(do_pos, label_name, SourceLabel::kDoWhile);
  ConsumeToken();
  const bool parsing_loop_body =  true;
  SequenceNode* dowhile_body = ParseNestedStatement(parsing_loop_body, label);
  ExpectToken(Token::kWHILE);
  ExpectToken(Token::kLPAREN);
  AstNode* cond_expr = ParseExpr(kAllowConst);
  ExpectToken(Token::kRPAREN);
  ExpectSemicolon();
  return new DoWhileNode(do_pos, label, cond_expr, dowhile_body);
}


AstNode* Parser::ParseForInStatement(intptr_t forin_pos,
                                     SourceLabel* label) {
  bool is_final = (CurrentToken() == Token::kFINAL);
  const String* loop_var_name = NULL;
  LocalVariable* loop_var = NULL;
  intptr_t loop_var_pos = 0;
  if (LookaheadToken(1) == Token::kIN) {
    loop_var_pos = token_index_;
    loop_var_name = ExpectIdentifier("variable name expected");
  } else {
    // The case without a type is handled above, so require a type here.
    const Type& type = Type::ZoneHandle(
        ParseFinalVarOrType(kIsMandatory, kMustResolve));
    loop_var_pos = token_index_;
    loop_var_name = ExpectIdentifier("variable name expected");
    loop_var = new LocalVariable(loop_var_pos, *loop_var_name, type);
    if (is_final) {
      loop_var->set_is_final();
    }
  }
  ExpectToken(Token::kIN);
  intptr_t collection_pos = token_index_;
  AstNode* collection_expr = ParseExpr(kAllowConst);
  ExpectToken(Token::kRPAREN);

  OpenBlock();  // Implicit block around while loop.

  // Generate implicit iterator variable and add to scope.
  const String& iterator_name =
      String::ZoneHandle(String::NewSymbol(":for-in-iter"));
  // We could set the type of the implicit iterator variable to Iterator<T>
  // where T is the type of the for loop variable. However, the type error
  // would refer to the compiler generated iterator and could confuse the user.
  // It is better to leave the iterator untyped and postpone the type error
  // until the loop variable is assigned to.
  const Type& iterator_type = Type::ZoneHandle(Type::VarType());
  LocalVariable* iterator_var =
      new LocalVariable(collection_pos, iterator_name, iterator_type);
  current_block_->scope->AddVariable(iterator_var);

  // Generate initialization of iterator variable.
  const String& iterator_method_name =
      String::ZoneHandle(String::NewSymbol(kGetIteratorName));
  ArgumentListNode* no_args = new ArgumentListNode(collection_pos);
  AstNode* get_iterator = new InstanceCallNode(
      collection_pos, collection_expr, iterator_method_name, no_args);
  AstNode* iterator_init =
      new StoreLocalNode(collection_pos, *iterator_var, get_iterator);
  current_block_->statements->Add(iterator_init);

  // Generate while loop condition.
  AstNode* iterator_has_next = new InstanceCallNode(
      collection_pos,
      new LoadLocalNode(collection_pos, *iterator_var),
      String::ZoneHandle(String::NewSymbol("hasNext")),
      no_args);

  // Parse the for loop body. Ideally, we would use ParseNestedStatement()
  // here, but that does not work well because we have to insert an implicit
  // variable assignment and potentially a variable declaration in the
  // loop body.
  OpenLoopBlock();
  current_block_->scope->AddLabel(label);

  AstNode* iterator_next = new InstanceCallNode(
      collection_pos,
      new LoadLocalNode(collection_pos, *iterator_var),
      String::ZoneHandle(String::NewSymbol("next")),
      no_args);

  // Generate assignment of next iterator value to loop variable.
  AstNode* loop_var_assignment = NULL;
  if (loop_var != NULL) {
    // The for loop declares a new variable. Add it to the loop body scope.
    current_block_->scope->AddVariable(loop_var);
    loop_var_assignment =
        new StoreLocalNode(loop_var_pos, *loop_var, iterator_next);
  } else {
    AstNode* loop_var_primary = ResolveVarOrField(loop_var_pos, *loop_var_name);
    ASSERT(!loop_var_primary->IsPrimaryNode());
    loop_var_assignment =
        loop_var_primary->MakeAssignmentNode(iterator_next);
    if (loop_var_assignment == NULL) {
      ErrorMsg(loop_var_pos, "variable or field '%s' is not assignable",
               loop_var_name->ToCString());
    }
  }
  current_block_->statements->Add(loop_var_assignment);

  // Now parse the for-in loop statement or block.
  if (CurrentToken() == Token::kLBRACE) {
    ConsumeToken();
    ParseStatementSequence();
    ExpectToken(Token::kRBRACE);
  } else {
    AstNode* statement = ParseStatement();
    if (statement != NULL) {
      current_block_->statements->Add(statement);
    }
  }

  SequenceNode* for_loop_statement = CloseBlock();

  AstNode* while_statement =
      new WhileNode(forin_pos, label, iterator_has_next, for_loop_statement);
  current_block_->statements->Add(while_statement);

  return CloseBlock();  // Implicit block around while loop.
}


AstNode* Parser::ParseForStatement(String* label_name) {
  TRACE_PARSER("ParseForStatement");
  intptr_t for_pos = token_index_;
  ConsumeToken();
  ExpectToken(Token::kLPAREN);
  SourceLabel* label = SourceLabel::New(for_pos, label_name, SourceLabel::kFor);
  if (IsForInStatement()) {
    return ParseForInStatement(for_pos, label);
  }
  OpenBlock();
  // The label is added to the implicit scope that also contains
  // the loop variable declarations.
  current_block_->scope->AddLabel(label);
  AstNode* initializer = NULL;
  intptr_t init_pos = token_index_;
  LocalScope* init_scope = current_block_->scope;
  if (CurrentToken() != Token::kSEMICOLON) {
    if (IsVariableDeclaration()) {
      initializer = ParseVariableDeclarationList();
    } else {
      initializer = ParseExpr(kAllowConst);
    }
  }
  ExpectSemicolon();
  AstNode* condition = NULL;
  if (CurrentToken() != Token::kSEMICOLON) {
    condition = ParseExpr(kAllowConst);
  }
  ExpectSemicolon();
  AstNode* increment = NULL;
  intptr_t incr_pos = token_index_;
  LocalScope* incr_scope = current_block_->scope;
  if (CurrentToken() != Token::kRPAREN) {
    increment = ParseExprList();
  }
  ExpectToken(Token::kRPAREN);
  const bool parsing_loop_body =  true;
  SequenceNode* body = ParseNestedStatement(parsing_loop_body, NULL);
  CloseBlock();
  return new ForNode(for_pos,
                     label,
                     NodeAsSequenceNode(init_pos, initializer, init_scope),
                     condition,
                     NodeAsSequenceNode(incr_pos, increment, incr_scope),
                     body);
}


// Lookup class in the corelib implementation which contains various VM
// helper methods and classes.
static RawClass* LookupImplClass(const String& class_name) {
  return Library::Handle(Library::CoreImplLibrary()).LookupClass(class_name);
}


RawClass* Parser::LookupClass(const String& class_name) {
  return library_.LookupClass(class_name);
}


// Calling VM-internal helpers, uses implementation core library.
AstNode* Parser::MakeStaticCall(const char* class_name,
                                const char* function_name,
                                ArgumentListNode* arguments) {
  const String& cls_name =
      String::Handle(String::NewSymbol(class_name));
  const Class& cls = Class::Handle(LookupImplClass(cls_name));
  ASSERT(!cls.IsNull());
  const String& func_name =
      String::ZoneHandle(String::NewSymbol(function_name));
  const Function& func = Function::ZoneHandle(
      Resolver::ResolveStatic(cls,
                              func_name,
                              arguments->length(),
                              arguments->names(),
                              Resolver::kIsQualified));
  ASSERT(!func.IsNull());
  CheckFunctionIsCallable(arguments->token_index(), func);
  return new StaticCallNode(arguments->token_index(), func, arguments);
}


AstNode* Parser::MakeAssertCall(intptr_t begin, intptr_t end) {
  ArgumentListNode* arguments = new ArgumentListNode(begin);
  arguments->Add(new LiteralNode(begin,
      Integer::ZoneHandle(Integer::New(begin))));
  arguments->Add(new LiteralNode(end,
      Integer::ZoneHandle(Integer::New(end))));
  return MakeStaticCall(kAssertErrorName, kThrowNewName, arguments);
}


AstNode* Parser::ParseAssertStatement() {
  ConsumeToken();  // Consume assert keyword.
  ExpectToken(Token::kLPAREN);
  const intptr_t condition_pos = token_index_;
  if (!FLAG_enable_asserts) {  // always enable assert for now...
    SkipExpr();
    ExpectToken(Token::kRPAREN);
    return NULL;
  }
  AstNode* condition = ParseExpr(kAllowConst);
  const intptr_t condition_end = token_index_;
  ExpectToken(Token::kRPAREN);
  if (condition->IsClosureNode()) {
    // Function literal in assert implies a call.
    condition =
        new ClosureCallNode(condition_pos,
                            condition,
                            new ArgumentListNode(condition_pos));
  }
  condition = new UnaryOpNode(condition_pos, Token::kNOT, condition);
  AstNode* assert_throw = MakeAssertCall(condition_pos, condition_end);
  return new IfNode(condition_pos,
                    condition,
                    NodeAsSequenceNode(condition_pos,
                                       assert_throw,
                                       current_block_->scope),
                    NULL);
}


struct CatchParamDesc {
  CatchParamDesc()
      : token_index(0), type(NULL), var(NULL), is_final(false) { }
  intptr_t token_index;
  const Type* type;
  const String* var;
  bool is_final;
};


// Parse the parameter specified in the catch clause.
void Parser::ParseCatchParameter(CatchParamDesc* catch_param) {
  TRACE_PARSER("ParseCatchParameter");
  ASSERT(catch_param != NULL);
  catch_param->is_final = (CurrentToken() == Token::kFINAL);
  catch_param->type = &Type::ZoneHandle(
      ParseFinalVarOrType(kIsMandatory, kMustResolve));
  if (CurrentToken() != Token::kIDENT) {
    ErrorMsg("identifier expected");
  }
  catch_param->token_index = token_index_;
  catch_param->var = CurrentLiteral();
  ConsumeToken();
}


// Populate local scope of the catch block with the catch parameters.
void Parser::AddCatchParamsToScope(const CatchParamDesc& exception_param,
                                   const CatchParamDesc& stack_trace_param,
                                   LocalScope* scope) {
  ASSERT(exception_param.var != NULL);
  LocalVariable* var = new LocalVariable(exception_param.token_index,
                                         *(exception_param.var),
                                         *(exception_param.type));
  if (exception_param.is_final) {
    var->set_is_final();
  }
  bool added_to_scope = scope->AddVariable(var);
  ASSERT(added_to_scope);
  if (stack_trace_param.var != NULL) {
    var = new LocalVariable(token_index_,
                            *(stack_trace_param.var),
                            *(stack_trace_param.type));
    if (stack_trace_param.is_final) {
      var->set_is_final();
    }
    added_to_scope = scope->AddVariable(var);
    if (!added_to_scope) {
      ErrorMsg(stack_trace_param.token_index,
               "name '%s' already exists in scope",
               stack_trace_param.var->ToCString());
    }
  }
}


SequenceNode* Parser::ParseFinallyBlock() {
  OpenBlock();
  ExpectToken(Token::kLBRACE);
  ParseStatementSequence();
  ExpectToken(Token::kRBRACE);
  SequenceNode* finally_block = CloseBlock();
  return finally_block;
}


void Parser::PushTryBlock(Block* try_block) {
  TryBlocks* block = new TryBlocks(try_block, try_blocks_list_);
  try_blocks_list_ = block;
}


Parser::TryBlocks* Parser::PopTryBlock() {
  TryBlocks* innermost_try_block = try_blocks_list_;
  try_blocks_list_ = try_blocks_list_->outer_try_block();
  return innermost_try_block;
}


void Parser::AddNodeForFinallyInlining(AstNode* node) {
  if (node == NULL) {
    return;
  }
  ASSERT(node->IsReturnNode() || node->IsJumpNode());
  TryBlocks* iterator = try_blocks_list_;
  while (iterator != NULL) {
    // For continue and break node check if the target label is in scope.
    if (node->IsJumpNode()) {
      SourceLabel* label = node->AsJumpNode()->label();
      ASSERT(label != NULL);
      LocalScope* try_scope = iterator->try_block()->scope;
      // If the label is defined in a scope which is a child (nested scope)
      // of the try scope then we are not breaking out of this try block
      // so we do not need to inline the finally code. Otherwise we need
      // to inline the finally code of this try block and then move on to the
      // next outer try block.
      if (label->owner()->IsNestedWithin(try_scope)) {
        break;
      }
    }
    iterator->AddNodeForFinallyInlining(node);
    iterator = iterator->outer_try_block();
  }
}


// Add the inlined finally block to the specified node.
void Parser::AddFinallyBlockToNode(AstNode* node,
                                   InlinedFinallyNode* finally_node) {
  if (node->IsReturnNode()) {
    node->AsReturnNode()->AddInlinedFinallyNode(finally_node);
  } else {
    ASSERT(node->IsJumpNode());
    node->AsJumpNode()->AddInlinedFinallyNode(finally_node);
  }
}


AstNode* Parser::ParseTryStatement(String* label_name) {
  TRACE_PARSER("ParseTryStatement");

  // We create three stack slots for exceptions here:
  // ':saved_context_var' - Used to save the context before start of the try
  //                        block. The context register is restored from this
  //                        slot before processing the catch block handler.
  // ':exception_var' - Used to save the current exception object that was
  //                    thrown.
  // ':stacktrace_var' - Used to save the current stack trace object into which
  //                     the stack trace was copied into when an exception was
  //                     thrown.
  // :exception_var and :stacktrace_var get set with the exception object
  // and the stacktrace object when an exception is thrown.
  // These three implicit variables can never be captured variables.
  const String& context_var_name =
      String::ZoneHandle(String::NewSymbol(":saved_context_var"));
  LocalVariable* context_var =
      current_block_->scope->LocalLookupVariable(context_var_name);
  if (context_var == NULL) {
    context_var = new LocalVariable(token_index_,
                                    context_var_name,
                                    Type::ZoneHandle(Type::VarType()));
    current_block_->scope->AddVariable(context_var);
  }
  const String& catch_excp_var_name =
      String::ZoneHandle(String::NewSymbol(":exception_var"));
  LocalVariable* catch_excp_var =
      current_block_->scope->LocalLookupVariable(catch_excp_var_name);
  if (catch_excp_var == NULL) {
    catch_excp_var = new LocalVariable(token_index_,
                                       catch_excp_var_name,
                                       Type::ZoneHandle(Type::VarType()));
    current_block_->scope->AddVariable(catch_excp_var);
  }
  const String& catch_trace_var_name =
      String::ZoneHandle(String::NewSymbol(":stacktrace_var"));
  LocalVariable* catch_trace_var =
      current_block_->scope->LocalLookupVariable(catch_trace_var_name);
  if (catch_trace_var == NULL) {
    catch_trace_var = new LocalVariable(token_index_,
                                        catch_trace_var_name,
                                        Type::ZoneHandle(Type::VarType()));
    current_block_->scope->AddVariable(catch_trace_var);
  }

  intptr_t try_pos = token_index_;
  ConsumeToken();  // Consume the 'try'.

  SourceLabel* try_label = NULL;
  if (label_name != NULL) {
    try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement);
    OpenBlock();
    current_block_->scope->AddLabel(try_label);
  }

  // Now parse the 'try' block.
  OpenBlock();
  Block* current_try_block = current_block_;
  PushTryBlock(current_try_block);
  ExpectToken(Token::kLBRACE);
  ParseStatementSequence();
  ExpectToken(Token::kRBRACE);
  SequenceNode* try_block = CloseBlock();

  // Now create a label for the end of catch block processing so that we can
  // jump over the catch block code after executing the try block.
  SourceLabel* end_catch_label =
      SourceLabel::New(token_index_, NULL, SourceLabel::kCatch);

  // Now parse the 'catch' blocks if any and merge all of them into
  // an if-then sequence of the different types specified using the 'is'
  // operator.
  bool catch_seen = false;
  bool generic_catch_seen = false;
  SequenceNode* catch_handler_list = NULL;
  intptr_t handler_pos = token_index_;
  OpenBlock();  // Start the catch block sequence.
  current_block_->scope->AddLabel(end_catch_label);
  while (CurrentToken() == Token::kCATCH) {
    catch_seen = true;
    intptr_t catch_pos = token_index_;
    ConsumeToken();  // Consume the 'catch'.
    ExpectToken(Token::kLPAREN);
    CatchParamDesc exception_param;
    CatchParamDesc stack_trace_param;
    ParseCatchParameter(&exception_param);
    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
      ParseCatchParameter(&stack_trace_param);
    }
    ExpectToken(Token::kRPAREN);

    // If a generic "catch all" statement has already been seen then all
    // subsequent catch statements are dead. We issue an error for now,
    // it might make sense to turn this into a warning.
    if (generic_catch_seen) {
      ErrorMsg("A generic 'catch all' statement already exists for this "
               "try block. All subsequent catch statements are dead code");
    }
    OpenBlock();
    AddCatchParamsToScope(exception_param,
                          stack_trace_param,
                          current_block_->scope);

    SequenceNode* catch_clause;

    // Parse the individual catch handler code and add an unconditional
    // JUMP to the end of the try block.
    ExpectToken(Token::kLBRACE);
    OpenBlock();

    // Generate code to load the exception object (:exception_var) into
    // the exception variable specified in this block.
    ASSERT(exception_param.var != NULL);
    LocalVariable* var = LookupLocalScope(*exception_param.var);
    ASSERT(var != NULL);
    ASSERT(catch_excp_var != NULL);
    current_block_->statements->Add(
        new StoreLocalNode(catch_pos,
                           *var,
                           new LoadLocalNode(catch_pos, *catch_excp_var)));
    if (stack_trace_param.var != NULL) {
      // A stack trace variable is specified in this block, so generate code
      // to load the stack trace object (:stacktrace_var) into the stack trace
      // variable specified in this block.
      LocalVariable* trace = LookupLocalScope(*stack_trace_param.var);
      ASSERT(catch_trace_var != NULL);
      current_block_->statements->Add(
          new StoreLocalNode(catch_pos,
                             *trace,
                             new LoadLocalNode(catch_pos, *catch_trace_var)));
    }

    ParseStatementSequence();  // Parse the catch handler code.
    current_block_->statements->Add(
        new JumpNode(catch_pos, Token::kCONTINUE, end_catch_label));
    SequenceNode* catch_handler = CloseBlock();
    ExpectToken(Token::kRBRACE);

    if (!exception_param.type->IsVarType()) {  // Has a type specification.
      // Now form an 'if type check' as an exception type exists in
      // the catch specifier.
      if (!exception_param.type->IsInstantiated() &&
          (current_block_->scope->function_level() > 0)) {
        // Make sure that the instantiator is captured.
        CaptureReceiver();
      }
      AstNode* exception_type = new TypeNode(catch_pos, *exception_param.type);
      AstNode* exception_var = new LoadLocalNode(catch_pos, *catch_excp_var);
      AstNode* cond_expr = new ComparisonNode(
          catch_pos, Token::kIS, exception_var, exception_type);
      current_block_->statements->Add(
          new IfNode(catch_pos, cond_expr, catch_handler, NULL));
    } else {
      // No exception type exists in the catch specifier so execute the
      // catch handler code unconditionally.
      current_block_->statements->Add(catch_handler);
      generic_catch_seen = true;
    }
    catch_clause = CloseBlock();

    // Add this individual catch handler to the catch handlers list.
    current_block_->statements->Add(catch_clause);
  }
  catch_handler_list = CloseBlock();
  TryBlocks* inner_try_block = PopTryBlock();

  // Finally parse the 'finally' block.
  SequenceNode* finally_block = NULL;
  if (CurrentToken() == Token::kFINALLY) {
    current_function_.set_is_optimizable(false);
    ConsumeToken();  // Consume the 'finally'.
    intptr_t finally_pos = token_index_;
    // Add the finally block to the exit points recorded so far.
    intptr_t node_index = 0;
    AstNode* node_to_inline =
        inner_try_block->GetNodeToInlineFinally(node_index);
    while (node_to_inline != NULL) {
      finally_block = ParseFinallyBlock();
      InlinedFinallyNode* node = new InlinedFinallyNode(finally_pos,
                                                        finally_block,
                                                        *context_var);
      AddFinallyBlockToNode(node_to_inline, node);
      node_index += 1;
      node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index);
      token_index_ = finally_pos;
    }
    if (!generic_catch_seen) {
      // No generic catch handler exists so execute this finally block
      // before rethrowing the excetion.
      finally_block = ParseFinallyBlock();
      catch_handler_list->Add(finally_block);
      token_index_ = finally_pos;
    }
    finally_block = ParseFinallyBlock();
  } else {
    if (!catch_seen) {
      ErrorMsg("'catch' or 'finally' expected");
    }
  }

  if (!generic_catch_seen) {
    // No generic catch handler exists so rethrow the exception so that
    // the next catch handler can deal with it.
    catch_handler_list->Add(
        new ThrowNode(handler_pos,
                      new LoadLocalNode(handler_pos, *catch_excp_var),
                      new LoadLocalNode(handler_pos, *catch_trace_var)));
  }
  CatchClauseNode* catch_block = new CatchClauseNode(handler_pos,
                                                     catch_handler_list,
                                                     *context_var,
                                                     *catch_excp_var,
                                                     *catch_trace_var);

  // Now create the try/catch ast node and return it. If there is a label
  // on the try/catch, close the block that's embedding the try statement
  // and attach the label to it.
  AstNode* try_catch_node =
      new TryCatchNode(try_pos, try_block, end_catch_label,
                       *context_var, catch_block, finally_block);

  if (try_label != NULL) {
    current_block_->statements->Add(try_catch_node);
    SequenceNode* sequence = CloseBlock();
    sequence->set_label(try_label);
    try_catch_node = sequence;
  }
  return try_catch_node;
}


AstNode* Parser::ParseJump(String* label_name) {
  ASSERT(CurrentToken() == Token::kBREAK || CurrentToken() == Token::kCONTINUE);
  Token::Kind jump_kind = CurrentToken();
  intptr_t jump_pos = token_index_;
  SourceLabel* target = NULL;
  ConsumeToken();
  if (CurrentToken() == Token::kIDENT) {
    // Explicit label after break/continue.
    const String& target_name = *CurrentLiteral();
    ConsumeToken();
    // Handle pathological cases first.
    if (label_name != NULL && target_name.Equals(*label_name)) {
      if (jump_kind == Token::kCONTINUE) {
        ErrorMsg(jump_pos, "'continue' jump to label '%s' is illegal",
                 target_name.ToCString());
      }
      // L: break L; is a no-op.
      return NULL;
    }
    target = current_block_->scope->LookupLabel(target_name);
    if (target == NULL && jump_kind == Token::kCONTINUE) {
      // Either a reference to a non-existent label, or a forward reference
      // to a case label that we haven't seen yet. If we are inside a switch
      // statement, create a "forward reference" label in the scope of
      // the switch statement.
      LocalScope* switch_scope = current_block_->scope->LookupSwitchScope();
      if (switch_scope != NULL) {
        // We found a switch scope. Enter a forward reference to the label.
        target = new SourceLabel(
            token_index_, target_name, SourceLabel::kForward);
        switch_scope->AddLabel(target);
      }
    }
    if (target == NULL) {
      ErrorMsg(jump_pos, "label '%s' not found", target_name.ToCString());
    }
  } else {
    target = current_block_->scope->LookupInnermostLabel();
    if (target == NULL) {
      ErrorMsg(jump_pos, "'%s' is illegal here", Token::Str(jump_kind));
    }
  }
  ASSERT(target != NULL);
  if (jump_kind == Token::kCONTINUE) {
    if (target->kind() == SourceLabel::kSwitch) {
      ErrorMsg(jump_pos, "'continue' jump to switch statement is illegal");
    } else if (target->kind() == SourceLabel::kStatement) {
      ErrorMsg(jump_pos, "'continue' jump to label '%s' is illegal",
               target->name().ToCString());
    }
  }
  if (jump_kind == Token::kBREAK && target->kind() == SourceLabel::kCase) {
    ErrorMsg(jump_pos, "'break' to case clause label is illegal");
  }
  if (target->FunctionLevel() != current_block_->scope->function_level()) {
    ErrorMsg(jump_pos, "'%s' target must be in same function context",
             Token::Str(jump_kind));
  }
  return new JumpNode(jump_pos, jump_kind, target);
}


AstNode* Parser::ParseStatement() {
  TRACE_PARSER("ParseStatement");
  AstNode* statement = NULL;
  intptr_t label_pos = 0;
  String* label_name = NULL;
  if (CurrentToken() == Token::kIDENT) {
    if (LookaheadToken(1) == Token::kCOLON) {
      // Statement starts with a label.
      label_name = CurrentLiteral();
      label_pos = token_index_;
      ASSERT(label_pos > 0);
      ConsumeToken();  // Consume identifier.
      ConsumeToken();  // Consume colon.
    }
  }
  const intptr_t statement_pos = token_index_;

  if (CurrentToken() == Token::kWHILE) {
    statement = ParseWhileStatement(label_name);
  } else if (CurrentToken() == Token::kFOR) {
    statement = ParseForStatement(label_name);
  } else if (CurrentToken() == Token::kDO) {
    statement = ParseDoWhileStatement(label_name);
  } else if (CurrentToken() == Token::kSWITCH) {
    statement = ParseSwitchStatement(label_name);
  } else if (CurrentToken() == Token::kTRY) {
    statement = ParseTryStatement(label_name);
  } else if (CurrentToken() == Token::kRETURN) {
    ConsumeToken();
    if (CurrentToken() != Token::kSEMICOLON) {
      AstNode* expr = ParseExpr(kAllowConst);
      statement = new ReturnNode(statement_pos, expr);
    } else {
      statement = new ReturnNode(statement_pos);
    }
    AddNodeForFinallyInlining(statement);
    ExpectSemicolon();
  } else if (CurrentToken() == Token::kIF) {
    statement = ParseIfStatement(label_name);
  } else if (CurrentToken() == Token::kASSERT) {
    statement = ParseAssertStatement();
    ExpectSemicolon();
  } else if (IsVariableDeclaration()) {
    statement = ParseVariableDeclarationList();
    ExpectSemicolon();
  } else if (IsFunctionDeclaration()) {
    statement = ParseFunctionStatement(false);
  } else if (CurrentToken() == Token::kLBRACE) {
    SourceLabel* label = NULL;
    OpenBlock();
    if (label_name != NULL) {
      label = SourceLabel::New(label_pos, label_name, SourceLabel::kStatement);
      current_block_->scope->AddLabel(label);
    }
    ConsumeToken();
    ParseStatementSequence();
    statement = CloseBlock();
    if (label != NULL) {
      statement->AsSequenceNode()->set_label(label);
    }
    ExpectToken(Token::kRBRACE);
  } else if (CurrentToken() == Token::kBREAK) {
    statement = ParseJump(label_name);
    AddNodeForFinallyInlining(statement);
    ExpectSemicolon();
  } else if (CurrentToken() == Token::kCONTINUE) {
    statement = ParseJump(label_name);
    AddNodeForFinallyInlining(statement);
    ExpectSemicolon();
  } else if (CurrentToken() == Token::kSEMICOLON) {
    // Empty statement, nothing to do.
    ConsumeToken();
  } else if (CurrentToken() == Token::kTHROW) {
    ConsumeToken();
    AstNode* expr = NULL;
    if (CurrentToken() != Token::kSEMICOLON) {
      expr = ParseExpr(kAllowConst);
      ExpectSemicolon();
      statement = new ThrowNode(statement_pos, expr, NULL);
    } else {  // No exception object seen so must be a rethrow.
      // Check if it is ok to do a rethrow.
      SourceLabel* label = current_block_->scope->LookupInnermostCatchLabel();
      if (label == NULL ||
          label->FunctionLevel() != current_block_->scope->function_level()) {
        ErrorMsg("rethrow of an exception is not valid here");
      }
      ASSERT(label->owner() != NULL);
      LocalScope* scope = label->owner()->parent();
      ASSERT(scope != NULL);
      LocalVariable* excp_var = scope->LocalLookupVariable(
          String::ZoneHandle(String::NewSymbol(":exception_var")));
      ASSERT(excp_var != NULL);
      LocalVariable* trace_var = scope->LocalLookupVariable(
          String::ZoneHandle(String::NewSymbol(":stacktrace_var")));
      ASSERT(trace_var != NULL);
      statement = new ThrowNode(statement_pos,
                                new LoadLocalNode(statement_pos, *excp_var),
                                new LoadLocalNode(statement_pos, *trace_var));
    }
  } else {
    statement = ParseExpr(kAllowConst);
    ExpectSemicolon();
  }
  return statement;
}


// Static.
void Parser::ReportMsg(const Script& script,
                       intptr_t token_index,
                       const char* msg_type,
                       char* message,
                       const char* format, va_list args) {
  const String& script_url = String::CheckedHandle(script.url());
  const int buf_size = 256;
  static char text_buffer[buf_size];

  intptr_t line, column;
  script.GetTokenLocation(token_index, &line, &column);
  OS::VSNPrint(text_buffer, buf_size, format, args);
  intptr_t msg_len =
      OS::SNPrint(message, Parser::kErrorBuflen,
                  "'%s': %s: line %d pos %d: %s\n",
                  script_url.ToCString(), msg_type, line, column, text_buffer);
  const String& text = String::Handle(script.GetLine(line));
  ASSERT(!text.IsNull());
  if (text.Length() < buf_size) {
    OS::SNPrint(message + msg_len, Parser::kErrorBuflen - msg_len,
                "%s\n%*s\n", text.ToCString(), column, "^");
  }
}


void Parser::ErrorMsg(intptr_t token_index, const char* format, ...) {
  va_list args;
  va_start(args, format);
  ReportMsg(script_, token_index, "Error", error_msg_, format, args);
  Isolate::Current()->long_jump_base()->Jump(1, error_msg_);
  UNREACHABLE();
}


void Parser::ErrorMsg(const char* format, ...) {
  va_list args;
  va_start(args, format);
  ReportMsg(script_, token_index_, "Error", error_msg_, format, args);
  Isolate::Current()->long_jump_base()->Jump(1, error_msg_);
  UNREACHABLE();
}


void Parser::Warning(const char* format, ...) {
  if (FLAG_silent_warnings) return;
  va_list args;
  va_start(args, format);
  ReportMsg(script_, token_index_, "Warning", error_msg_, format, args);
  if (FLAG_warning_as_error) {
    Isolate::Current()->long_jump_base()->Jump(1, error_msg_);
    UNREACHABLE();
  }
}


void Parser::Unimplemented(const char* msg) {
  ErrorMsg(token_index_, msg);
}


void Parser::ExpectToken(Token::Kind token_expected) {
  if (CurrentToken() != token_expected) {
    ErrorMsg("'%s' expected", Token::Str(token_expected));
  }
  ConsumeToken();
}


void Parser::ExpectSemicolon() {
  if (CurrentToken() != Token::kSEMICOLON) {
    ErrorMsg("semicolon expected");
  }
  ConsumeToken();
}


void Parser::UnexpectedToken() {
  ErrorMsg("unexpected token '%s'",
           CurrentToken() == Token::kIDENT ?
               CurrentLiteral()->ToCString() : Token::Str(CurrentToken()));
}


String* Parser::ExpectIdentifier(const char* msg) {
  if (CurrentToken() != Token::kIDENT) {
    ErrorMsg(msg);
  }
  String* ident = CurrentLiteral();
  ConsumeToken();
  return ident;
}


bool Parser::IsLiteral(const char* literal) {
  return (CurrentToken() == Token::kIDENT)
      && CurrentLiteral()->Equals(literal, strlen(literal));
}


bool Parser::IsIncrementOperator(Token::Kind token) {
  return token == Token::kINCR || token == Token::kDECR;
}


bool Parser::IsPrefixOperator(Token::Kind token) {
  return token == Token::kADD || token == Token::kSUB
      || token == Token::kNOT || token == Token::kBIT_NOT;
}


SequenceNode* Parser::NodeAsSequenceNode(intptr_t sequence_pos,
                                         AstNode* node,
                                         LocalScope* scope) {
  if ((node == NULL) || !node->IsSequenceNode()) {
    SequenceNode* sequence = new SequenceNode(sequence_pos, scope);
    if (node != NULL) {
      sequence->Add(node);
    }
    return sequence;
  }
  return node->AsSequenceNode();
}


AstNode* Parser::ParseBinaryExpr(int min_preced) {
  TRACE_PARSER("ParseBinaryExpr");
  ASSERT(min_preced >= 4);
  AstNode* left_operand = ParseUnaryExpr();
  int current_preced = Token::Precedence(CurrentToken());
  while (current_preced >= min_preced) {
    while (Token::Precedence(CurrentToken()) == current_preced) {
      Token::Kind op_kind = CurrentToken();
      const intptr_t op_pos = token_index_;
      ConsumeToken();
      AstNode* right_operand = NULL;
      if (op_kind != Token::kIS) {
        right_operand = ParseBinaryExpr(current_preced + 1);
      } else {
        // For 'is' we expect the right operand to be a type.
        if (CurrentToken() == Token::kNOT) {
          ConsumeToken();
          op_kind = Token::kISNOT;
        }
        const intptr_t type_pos = token_index_;
        const Type& type = Type::ZoneHandle(ParseType(kMustResolve));
        if (!type.IsInstantiated() &&
            (current_block_->scope->function_level() > 0)) {
          // Make sure that the instantiator is captured.
          CaptureReceiver();
        }
        right_operand = new TypeNode(type_pos, type);
      }
      if (Token::IsRelationalOperator(op_kind)
          || Token::IsInstanceofOperator(op_kind)
          || Token::IsEqualityOperator(op_kind)) {
        left_operand = new ComparisonNode(
            op_pos, op_kind, left_operand, right_operand);
        break;  // Equality and relational operators cannot be chained.
      } else {
        StringConcatNode* str_concat = NULL;
        if (op_kind == Token::kADD) {
          if (left_operand->IsLiteralNode()) {
            LiteralNode* lit = left_operand->AsLiteralNode();
            if (lit->literal().IsString()) {
              str_concat = new StringConcatNode(lit->token_index());
              str_concat->AddExpr(lit);
            }
          } else if (left_operand->IsStringConcatNode()) {
            str_concat = left_operand->AsStringConcatNode();
          }
        }
        if (str_concat != NULL) {
          str_concat->AddExpr(right_operand);
          left_operand = str_concat;
        } else {
          left_operand = new BinaryOpNode(
              op_pos, op_kind, left_operand, right_operand);
        }
      }
    }
    current_preced--;
  }
  return left_operand;
}


bool Parser::IsAssignableExpr(AstNode* expr) {
  return expr->IsPrimaryNode()
      || expr->IsLoadLocalNode()
      || expr->IsLoadStaticFieldNode()
      || expr->IsStaticGetterNode()
      || expr->IsInstanceGetterNode()
      || expr->IsLoadIndexedNode();
}


AstNode* Parser::ParseExprList() {
  TRACE_PARSER("ParseExprList");
  AstNode* expressions = ParseExpr(kAllowConst);
  if (CurrentToken() == Token::kCOMMA) {
    // Collect comma-separated expressions in a sequence node.
    SequenceNode* list = new SequenceNode(token_index_, current_block_->scope);
    list->Add(expressions);
    while (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
      AstNode* expr = ParseExpr(kAllowConst);
      list->Add(expr);
    }
    expressions = list;
  }
  return expressions;
}


static bool IsLocalOrLiteralNode(AstNode* node) {
  return node->IsLoadLocalNode() || node->IsLiteralNode();
}


LocalVariable* Parser::CreateTempConstVariable(intptr_t token_index,
                                               intptr_t token_id,
                                               const char* s) {
  char name[64];
  OS::SNPrint(name, 64, "%s%d", s, token_id);
  LocalVariable* temp =
      new LocalVariable(token_index,
                        String::ZoneHandle(String::NewSymbol(name)),
                        Type::ZoneHandle(Type::VarType()));
  temp->set_is_final();
  current_block_->scope->AddVariable(temp);
  return temp;
}


// If 'node' can create side effects, store its result in a temporary variable
// and return a LoadLocalNode instead.
// Side effect free nodes are LoadLocalNode and LiteralNode.
AstNode* Parser::AsSideEffectFreeNode(AstNode* node) {
  if (node->IsLoadIndexedNode()) {
    LoadIndexedNode* load_indexed = node->AsLoadIndexedNode();
    intptr_t token_id = node->id();
    intptr_t token_index = node->token_index();
    node = NULL;  // Do not use it.
    if (!IsLocalOrLiteralNode(load_indexed->index_expr())) {
      LocalVariable* temp =
          CreateTempConstVariable(token_index, token_id, "lix");
      AstNode* save =
          new StoreLocalNode(token_index, *temp, load_indexed->index_expr());
      current_block_->statements->Add(save);
      AstNode* load = new LoadLocalNode(token_index, *temp);
      load_indexed = new LoadIndexedNode(token_index,
                                         load_indexed->array(),
                                         load);
    }
    // The array object access may not have side effects.
    if (!IsLocalOrLiteralNode(load_indexed->array())) {
      LocalVariable* temp =
          CreateTempConstVariable(token_index, token_id, "lia");
      AstNode* save =
          new StoreLocalNode(token_index, *temp, load_indexed->array());
      current_block_->statements->Add(save);
      AstNode* load = new LoadLocalNode(token_index, *temp);
      load_indexed = new LoadIndexedNode(token_index,
                                         load,
                                         load_indexed->index_expr());
    }
    return load_indexed;
  }
  if (node->IsInstanceGetterNode()) {
    InstanceGetterNode* getter = node->AsInstanceGetterNode();
    intptr_t token_index = node->token_index();
    intptr_t token_id = node->id();
    node = NULL;  // Do not use it.
    if (!IsLocalOrLiteralNode(getter->receiver())) {
      LocalVariable* temp =
          CreateTempConstVariable(token_index, token_id, "igr");
      AstNode* save =
          new StoreLocalNode(token_index, *temp, getter->receiver());
      current_block_->statements->Add(save);
      AstNode* load = new LoadLocalNode(token_index, *temp);
      getter = new InstanceGetterNode(token_index, load, getter->field_name());
    }
    return getter;
  }
  return node;
}


AstNode* Parser::ExpandAssignableOp(intptr_t op_pos,
                                    Token::Kind assignment_op,
                                    AstNode* lhs,
                                    AstNode* rhs) {
  TRACE_PARSER("ExpandAssignableOp");
  switch (assignment_op) {
    case Token::kASSIGN:
      return rhs;
    case Token::kASSIGN_ADD:
      return new BinaryOpNode(op_pos, Token::kADD, lhs, rhs);
    case Token::kASSIGN_SUB:
      return new BinaryOpNode(op_pos, Token::kSUB, lhs, rhs);
    case Token::kASSIGN_MUL:
      return new BinaryOpNode(op_pos, Token::kMUL, lhs, rhs);
    case Token::kASSIGN_TRUNCDIV:
      return new BinaryOpNode(op_pos, Token::kTRUNCDIV, lhs, rhs);
    case Token::kASSIGN_DIV:
      return new BinaryOpNode(op_pos, Token::kDIV, lhs, rhs);
    case Token::kASSIGN_SAR:
      return new BinaryOpNode(op_pos, Token::kSAR, lhs, rhs);
    case Token::kASSIGN_SHL:
      return new BinaryOpNode(op_pos, Token::kSHL, lhs, rhs);
    case Token::kASSIGN_OR:
      return new BinaryOpNode(op_pos, Token::kBIT_OR, lhs, rhs);
    case Token::kASSIGN_AND:
      return new BinaryOpNode(op_pos, Token::kBIT_AND, lhs, rhs);
    case Token::kASSIGN_XOR:
      return new BinaryOpNode(op_pos, Token::kBIT_XOR, lhs, rhs);
    default:
      ErrorMsg(op_pos, "Internal error: ExpandAssignableOp '%s' unimplemented",
          Token::Name(assignment_op));
      UNIMPLEMENTED();
      return NULL;
  }
}


// Evaluates the value of the compile time constant expression
// and returns a literal node for the value.
AstNode* Parser::FoldConstExpr(intptr_t expr_pos, AstNode* expr) {
  if (expr->IsLiteralNode()) {
    return expr;
  }
  if (expr->EvalConstExpr() == NULL) {
    ErrorMsg(expr_pos, "expression must be a compile time constant");
  }
  return new LiteralNode(expr_pos, EvaluateConstExpr(expr));
}


AstNode* Parser::ParseExpr(bool require_compiletime_const) {
  TRACE_PARSER("ParseExpr");
  const intptr_t expr_pos = token_index_;
  AstNode* expr = ParseConditionalExpr();
  if (!Token::IsAssignmentOperator(CurrentToken())) {
    if (require_compiletime_const) {
      expr = FoldConstExpr(expr_pos, expr);
    }
    return expr;
  }
  // Assignment expressions.
  Token::Kind assignment_op = CurrentToken();
  const intptr_t assignment_pos = token_index_;
  ConsumeToken();
  const intptr_t right_expr_pos = token_index_;
  if (require_compiletime_const && (assignment_op != Token::kASSIGN)) {
    ErrorMsg(right_expr_pos, "expression must be a compile time constant");
  }
  AstNode* right_expr = ParseExpr(require_compiletime_const);
  if (assignment_op != Token::kASSIGN) {
    expr = AsSideEffectFreeNode(expr);
  }
  right_expr =
      ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
  AstNode* assign_expr = expr->MakeAssignmentNode(right_expr);
  if (assign_expr == NULL) {
    ErrorMsg(assignment_pos,
             "Left hand side of '%s' is not assignable",
             Token::Str(assignment_op));
  }
  return assign_expr;
}


LiteralNode* Parser::ParseConstExpr() {
  TRACE_PARSER("ParseConstExpr");
  AstNode* expr = ParseExpr(kRequireConst);
  ASSERT(expr->IsLiteralNode());
  return expr->AsLiteralNode();
}


AstNode* Parser::ParseConditionalExpr() {
  TRACE_PARSER("ParseConditionalExpr");
  const intptr_t expr_pos = token_index_;
  AstNode* expr = ParseBinaryExpr(Token::Precedence(Token::kOR));
  if (CurrentToken() == Token::kCONDITIONAL) {
    ConsumeToken();
    AstNode* expr1 = ParseConditionalExpr();
    ExpectToken(Token::kCOLON);
    AstNode* expr2 = ParseConditionalExpr();
    expr = new ConditionalExprNode(expr_pos, expr, expr1, expr2);
  }
  return expr;
}


AstNode* Parser::ParseUnaryExpr() {
  TRACE_PARSER("ParseUnaryExpr");
  AstNode* expr = NULL;
  const intptr_t op_pos = token_index_;
  if (IsPrefixOperator(CurrentToken())) {
    Token::Kind unary_op = CurrentToken();
    ConsumeToken();
    expr = ParseUnaryExpr();
    expr = UnaryOpNode::UnaryOpOrLiteral(op_pos, unary_op, expr);
  } else if (IsIncrementOperator(CurrentToken())) {
    Token::Kind incr_op = CurrentToken();
    ConsumeToken();
    expr = ParseUnaryExpr();
    if (!IsAssignableExpr(expr)) {
      ErrorMsg("Expression is not assignable");
    }
    // is_prefix.
    AstNode* incr_op_node = expr->MakeIncrOpNode(op_pos, incr_op, true);
    if (incr_op_node == NULL) {
      Unimplemented("incr operation not implemented");
    }
    expr = incr_op_node;
  } else {
    expr = ParsePostfixExpr();
  }
  return expr;
}


ArgumentListNode* Parser::ParseActualParameters(AstNode* implicit_argument,
                                                bool require_const) {
  TRACE_PARSER("ParseActualParameters");
  ASSERT(CurrentToken() == Token::kLPAREN);
  const bool saved_mode = SetAllowFunctionLiterals(true);
  ArgumentListNode* arguments = new ArgumentListNode(token_index_);
  if (implicit_argument != NULL) {
    arguments->Add(implicit_argument);
  }
  GrowableArray<const String*> names;
  bool named_argument_seen = false;
  if (LookaheadToken(1) != Token::kRPAREN) {
    do {
      ASSERT((CurrentToken() == Token::kLPAREN) ||
             (CurrentToken() == Token::kCOMMA));
      ConsumeToken();
      if ((CurrentToken() == Token::kIDENT) &&
          (LookaheadToken(1) == Token::kCOLON)) {
        named_argument_seen = true;
        // The canonicalization of the argument descriptor array built in the
        // code generator requires that the names are symbols, i.e.
        // canonicalized strings.
        ASSERT(CurrentLiteral()->IsSymbol());
        for (int i = 0; i < names.length(); i++) {
          if (CurrentLiteral()->Equals(*names[i])) {
            ErrorMsg("duplicate named argument");
          }
        }
        names.Add(CurrentLiteral());
        ConsumeToken();  // ident.
        ConsumeToken();  // colon.
      } else if (named_argument_seen) {
        ErrorMsg("named argument expected");
      }
      arguments->Add(ParseExpr(require_const));
    } while (CurrentToken() == Token::kCOMMA);
  } else {
    ConsumeToken();
  }
  ExpectToken(Token::kRPAREN);
  SetAllowFunctionLiterals(saved_mode);
  if (named_argument_seen) {
    arguments->set_names(Array::Handle(NewArray<const String>(names)));
  }
  return arguments;
}


AstNode* Parser::ParseStaticCall(const Class& cls,
                                 const String& func_name,
                                 intptr_t ident_pos) {
  TRACE_PARSER("ParseStaticCall");
  const intptr_t call_pos = token_index_;
  ASSERT(CurrentToken() == Token::kLPAREN);
  ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
  const int num_arguments = arguments->length();
  const Function& func = Function::ZoneHandle(
      Resolver::ResolveStatic(cls,
                              func_name,
                              num_arguments,
                              arguments->names(),
                              Resolver::kIsQualified));
  if (func.IsNull()) {
    // Check if there is a static field of the same name, it could be a closure
    // and so we try and invoke the closure.
    AstNode* closure = NULL;
    const Field& field = Field::ZoneHandle(cls.LookupStaticField(func_name));
    Function& func = Function::ZoneHandle();
    if (field.IsNull()) {
      // No field, check if we have an explicit getter function.
      const String& getter_name =
          String::ZoneHandle(Field::GetterName(func_name));
      const int kNumArguments = 0;  // no arguments.
      const Array& kNoArgumentNames = Array::Handle();
      func = Resolver::ResolveStatic(cls,
                                     getter_name,
                                     kNumArguments,
                                     kNoArgumentNames,
                                     Resolver::kIsQualified);
      if (!func.IsNull()) {
        ASSERT(func.kind() != RawFunction::kConstImplicitGetter);
        closure = new StaticGetterNode(call_pos,
                                       Class::ZoneHandle(cls.raw()),
                                       func_name);
        return new ClosureCallNode(call_pos, closure, arguments);
      }
    } else {
      closure = GenerateStaticFieldLookup(field, call_pos);
      return new ClosureCallNode(call_pos, closure, arguments);
    }
    ErrorMsg(ident_pos, "unresolved static method '%s'", func_name.ToCString());
  }
  CheckFunctionIsCallable(call_pos, func);
  return new StaticCallNode(call_pos, func, arguments);
}


AstNode* Parser::ParseInstanceCall(AstNode* receiver, const String& func_name) {
  const intptr_t call_pos = token_index_;
  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg(call_pos, "left parenthesis expected");
  }
  ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
  return new InstanceCallNode(call_pos, receiver, func_name, arguments);
}


AstNode* Parser::ParseClosureCall(AstNode* closure) {
  const intptr_t call_pos = token_index_;
  ASSERT(CurrentToken() == Token::kLPAREN);
  ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
  return new ClosureCallNode(call_pos, closure, arguments);
}


AstNode* Parser::ParseInstanceFieldAccess(AstNode* receiver,
                                          const String& field_name) {
  TRACE_PARSER("ParseInstanceFieldAccess");
  AstNode* access = NULL;
  const intptr_t call_pos = token_index_;
  if (Token::IsAssignmentOperator(CurrentToken())) {
    Token::Kind assignment_op = CurrentToken();
    ConsumeToken();
    AstNode* value = ParseExpr(kAllowConst);
    AstNode* load_access =
        new InstanceGetterNode(call_pos, receiver, field_name);
    if (assignment_op != Token::kASSIGN) {
      load_access = AsSideEffectFreeNode(load_access);
    }
    value = ExpandAssignableOp(call_pos, assignment_op, load_access, value);
    access = load_access->MakeAssignmentNode(value);
  } else {
    access = CallGetter(call_pos, receiver, field_name);
  }
  return access;
}


AstNode* Parser::GenerateStaticFieldLookup(const Field& field,
                                           intptr_t ident_pos) {
  // Run static field initializer first if necessary.
  RunStaticFieldInitializer(field);

  // Access the field
  if (field.is_final()) {
    return new LiteralNode(ident_pos, Instance::ZoneHandle(field.value()));
  } else {
    return new LoadStaticFieldNode(ident_pos,
                                   Field::ZoneHandle(field.raw()));
  }
}


AstNode* Parser::ParseStaticFieldAccess(const Class& cls,
                                        const String& field_name,
                                        intptr_t ident_pos) {
  TRACE_PARSER("ParseStaticFieldAccess");
  AstNode* access = NULL;
  const intptr_t call_pos = token_index_;
  const Field& field = Field::ZoneHandle(cls.LookupStaticField(field_name));
  Function& func = Function::ZoneHandle();
  if (Token::IsAssignmentOperator(CurrentToken())) {
    Token::Kind assignment_op = CurrentToken();
    if (field.IsNull()) {
      // No field, check if we have an explicit setter function.
      const String& setter_name =
          String::ZoneHandle(Field::SetterName(field_name));
      const int kNumArguments = 1;  // value.
      const Array& kNoArgumentNames = Array::Handle();
      func = Resolver::ResolveStatic(cls,
                                     setter_name,
                                     kNumArguments,
                                     kNoArgumentNames,
                                     Resolver::kIsQualified);
      if (func.IsNull()) {
        // No field or explicit setter function, this is an error.
        ErrorMsg(ident_pos, "unknown static field '%s'",
                 field_name.ToCString());
        return access;
      }
    }
    ConsumeToken();
    AstNode* value = ParseExpr(kAllowConst);
    AstNode* load_access = NULL;
    if (field.IsNull()) {
      // No field found, we must have at least a setter function defined.
      ASSERT(!func.IsNull());
      // Explicit setter function for the field found, field does not exist.
      // Create a getter node first in case it is needed. If getter node
      // is used as part of, e.g., "+=", and the explicit getter does not
      // exist, and error will be reported by the code generator.
      load_access = new StaticGetterNode(call_pos,
                                         Class::ZoneHandle(cls.raw()),
                                         String::ZoneHandle(field_name.raw()));
    } else {
      // Field exists.
      if (field.is_final()) {
        // Field has been marked as final, report an error as the field
        // is not settable.
        ErrorMsg(ident_pos,
                 "field '%s' is const static, cannot assign to it",
                 field_name.ToCString());
        return access;
      }
      load_access = GenerateStaticFieldLookup(field, token_index_);
    }
    value = ExpandAssignableOp(call_pos, assignment_op, load_access, value);
    access = load_access->MakeAssignmentNode(value);
  } else {  // Not Token::IsAssignmentOperator(CurrentToken()).
    if (field.IsNull()) {
      // No field, check if we have an explicit getter function.
      const String& getter_name =
          String::ZoneHandle(Field::GetterName(field_name));
      const int kNumArguments = 0;  // no arguments.
      const Array& kNoArgumentNames = Array::Handle();
      func = Resolver::ResolveStatic(cls,
                                     getter_name,
                                     kNumArguments,
                                     kNoArgumentNames,
                                     Resolver::kIsQualified);
      if (func.IsNull()) {
        // We might be referring to an implicit closure, check to see if
        // there is a function of the same name.
        func = cls.LookupStaticFunction(field_name);
        if (func.IsNull()) {
          // No field or explicit getter function, this is an error.
          ErrorMsg(ident_pos,
                   "unknown static field '%s'", field_name.ToCString());
          return access;
        }
        access = CreateImplicitClosureNode(func, call_pos, NULL);
      } else {
        ASSERT(func.kind() != RawFunction::kConstImplicitGetter);
        access = new StaticGetterNode(call_pos,
                                      Class::ZoneHandle(cls.raw()),
                                      field_name);
      }
    } else {
      return GenerateStaticFieldLookup(field, token_index_);
    }
  }
  return access;
}


AstNode* Parser::ParsePostfixExpr() {
  TRACE_PARSER("ParsePostfixExpr");
  const intptr_t postfix_expr_pos = token_index_;
  AstNode* postfix_expr = ParsePrimary();
  while (true) {
    AstNode* selector = NULL;
    AstNode* left = postfix_expr;
    if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      const intptr_t ident_pos = token_index_;
      String* ident = ExpectIdentifier("identifier expected");
      if (CurrentToken() == Token::kLPAREN) {
        // Identifier followed by a opening paren: method call.
        if (left->IsPrimaryNode()
            && left->AsPrimaryNode()->primary().IsClass()) {
          // Static method call prefixed with class name.
          Class& cls = Class::CheckedHandle(
              left->AsPrimaryNode()->primary().raw());
          selector = ParseStaticCall(cls, *ident, ident_pos);
        } else {
          selector = ParseInstanceCall(left, *ident);
        }
      } else {
        // Field access.
        Class& cls = Class::Handle();
        if (left->IsPrimaryNode()) {
          PrimaryNode* primary_node = left->AsPrimaryNode();
          if (primary_node->primary().IsClass()) {
            // If the primary node referred to a class we are loading a
            // qualified static field.
            cls ^= primary_node->primary().raw();
          }
        }
        if (cls.IsNull()) {
          // Instance field access.
          selector = ParseInstanceFieldAccess(left, *ident);
        } else {
          // Static field access.
          selector = ParseStaticFieldAccess(cls, *ident, ident_pos);
        }
      }
    } else if (CurrentToken() == Token::kLBRACK) {
      const intptr_t bracket_pos = token_index_;
      ConsumeToken();
      const bool saved_mode = SetAllowFunctionLiterals(true);
      AstNode* index = ParseExpr(kAllowConst);
      SetAllowFunctionLiterals(saved_mode);
      ExpectToken(Token::kRBRACK);
      AstNode* array = left;
      if (left->IsPrimaryNode()) {
        PrimaryNode* primary = left->AsPrimaryNode();
        if (primary->primary().IsFunction()) {
          ErrorMsg(bracket_pos, "cannot apply index operator to function");
        } else if (primary->primary().IsClass()) {
          ErrorMsg(bracket_pos, "cannot apply index operator to class");
        } else if (primary->primary().IsString()) {
          // Primary is an unresolved name.
          String& name = String::CheckedZoneHandle(primary->primary().raw());
          if (current_function().IsInStaticScope()) {
            ErrorMsg(primary->token_index(),
                     "identifier '%s' is not declared in this scope",
                     name.ToCString());
          } else {
            // Treat as call to unresolved (instance) method.
            AstNode* receiver = LoadReceiver();
            selector = ParseInstanceCall(receiver, name);
          }
        } else {
          // Internal parser error.
          UNREACHABLE();
        }
      }
      selector = new LoadIndexedNode(bracket_pos, array, index);
    } else if (CurrentToken() == Token::kLPAREN) {
      if (left->IsPrimaryNode()) {
        PrimaryNode* primary = left->AsPrimaryNode();
        const intptr_t primary_pos = primary->token_index();
        if (primary->primary().IsFunction()) {
          Function& func = Function::CheckedHandle(primary->primary().raw());
          String& func_name = String::ZoneHandle(func.name());
          if (func.is_static()) {
            // Parse static function call.
            Class& cls = Class::Handle(func.owner());
            selector = ParseStaticCall(cls, func_name, primary_pos);
          } else {
            // Dynamic function call on implicit "this" parameter.
            if (current_function().IsInStaticScope()) {
              ErrorMsg(primary_pos,
                       "Cannot access instance method '%s' "
                       "from static function",
                       func_name.ToCString());
            }
            selector = ParseInstanceCall(LoadReceiver(), func_name);
          }
        } else if (primary->primary().IsString()) {
          // Primary is an unresolved name.
          String& name = String::CheckedZoneHandle(primary->primary().raw());
          if (current_function().IsInStaticScope()) {
            ErrorMsg(primary->token_index(),
                     "identifier '%s' is not declared in this scope",
                     name.ToCString());
          } else {
            // Treat as call to unresolved (instance) method.
            AstNode* receiver = LoadReceiver();
            selector = ParseInstanceCall(receiver, name);
          }
        } else if (primary->primary().IsClass()) {
          ErrorMsg(left->token_index(),
              "must use 'new' or 'const' to construct new instance");
        } else {
          // Internal parser error.
          UNREACHABLE();
        }
      } else {
        // Left is not a primary node; this must be a closure call.
        AstNode* closure = left;
        selector = ParseClosureCall(closure);
      }
    } else {
      // No (more) selector to parse.
      if (left->IsPrimaryNode()) {
        if (left->AsPrimaryNode()->primary().IsString()) {
          PrimaryNode* primary = left->AsPrimaryNode();
          const String& ident =
              String::CheckedZoneHandle(primary->primary().raw());
          // An unresolved identifier that is not followed by a selector token
          // . or [ or (.
          // If we are in a static method, this is an error.
          // If we are compiling an instance method, convert this into
          // a runtime lookup for a field (which may be defined in a
          // subclass.)
          if (current_function().IsInStaticScope()) {
            ErrorMsg(primary->token_index(),
                     "identifier '%s' is not declared in this scope",
                     ident.ToCString());
          } else {
            // Treat as call to unresolved (instance) field.
            AstNode* receiver = LoadReceiver();
            postfix_expr = ParseInstanceFieldAccess(receiver, ident);
          }
        } else if (left->AsPrimaryNode()->primary().IsFunction()) {
          // Treat as implicit closure.
          PrimaryNode* primary = left->AsPrimaryNode();
          const Function& func =
              Function::CheckedZoneHandle(primary->primary().raw());
          const String& funcname = String::ZoneHandle(func.name());
          if (func.is_static()) {
            // Static function access.
            postfix_expr = CreateImplicitClosureNode(func,
                                                     primary->token_index(),
                                                     NULL);
          } else {
            // Instance function access.
            if (current_function().IsInStaticScope() ||
                current_function().IsInFactoryScope()) {
              ErrorMsg(primary->token_index(),
                       "illegal use of method '%s'",
                       funcname.ToCString());
            }
            AstNode* receiver = LoadReceiver();
            postfix_expr = ParseInstanceFieldAccess(receiver, funcname);
          }
        }
      }
      // Done parsing selectors.
      break;
    }
    ASSERT(selector != NULL);
    postfix_expr = selector;
  }
  if (IsIncrementOperator(CurrentToken())) {
    TRACE_PARSER("IncrementOperator");
    Token::Kind incr_op = CurrentToken();
    if (!IsAssignableExpr(postfix_expr)) {
      ErrorMsg("expression is not assignable");
    }
    ConsumeToken();
    // Not prefix.
    AstNode* incr_op_node =
        postfix_expr->MakeIncrOpNode(postfix_expr_pos, incr_op, false);
    if (incr_op_node == NULL) {
      Unimplemented("incr op not implemented");
    }
    postfix_expr = incr_op_node;
  }
  return postfix_expr;
}


bool Parser::ResolveTypeFromClass(intptr_t type_pos,
                                  const Class& cls,
                                  Type* type) {
  ASSERT(type != NULL);
  // Resolve class.
  if (!type->HasResolvedTypeClass()) {
    const String& unresolved_type_class =
        String::Handle(type->unresolved_type_class());
    // First check if the type is a type parameter of the given class.
    const TypeParameter& type_parameter = TypeParameter::Handle(
        cls.LookupTypeParameter(unresolved_type_class));
    if (!type_parameter.IsNull()) {
      CheckTypeParameterReference(type_pos, unresolved_type_class);
      // A type parameter cannot be parameterized, so report an error if type
      // arguments have previously been parsed.
      if (type->arguments() != TypeArguments::null()) {
        ErrorMsg(type_pos, "type parameter '%s' cannot be parameterized",
                 type_parameter.ToCString());
        return false;
      }
      *type = type_parameter.raw();
      return true;
    }
    const Class& resolved_type_class =
        Class::Handle(LookupClass(unresolved_type_class));
    if (resolved_type_class.IsNull()) {
      return false;
    }
    Object& type_class = Object::Handle(resolved_type_class.raw());
    ASSERT(type->IsParameterizedType());
    // Replace unresolved type class with resolved type class.
    ParameterizedType& parameterized_type = ParameterizedType::Handle();
    parameterized_type ^= type->raw();
    parameterized_type.set_type_class(type_class);
  }
  // Resolve type arguments, if any.
  const TypeArguments& arguments = TypeArguments::Handle(type->arguments());
  if (!arguments.IsNull()) {
    intptr_t num_arguments = arguments.Length();
    for (intptr_t i = 0; i < num_arguments; i++) {
      Type& type_argument = Type::Handle(arguments.TypeAt(i));
      if (!ResolveTypeFromClass(type_pos, cls, &type_argument)) {
        return false;
      }
      arguments.SetTypeAt(i, type_argument);
    }
  }
  return true;
}


// Return class for type name. If the name cannot be resolved (yet), give an
// error (if type_resolution == kMustResolve) or return the unresolved name.
RawObject* Parser::LookupTypeClass(const QualIdent& type_name,
                                   TypeResolution type_resolution) {
  ASSERT(type_name.ident != NULL);
  Class& type_class = Class::Handle();
  if (type_name.lib_prefix != NULL) {
    Library& lib = Library::Handle(type_name.lib_prefix->library());
    type_class ^= lib.LookupLocalClass(*(type_name.ident));
  } else {
    type_class ^= LookupClass(*(type_name.ident));
  }
  if (!type_class.IsNull()) {
    return type_class.raw();
  }
  // Type name could not be resolved (yet).
  if (type_resolution == kMustResolve) {
    ErrorMsg(type_name.ident_pos, "type '%s' is not loaded",
             type_name.ident->ToCString());
    return Object::null_class();
  }
  // Return the type name.
  return type_name.ident->raw();
}


LocalVariable* Parser::LookupLocalScope(const String& ident) {
  if (current_block_ == NULL) {
    return NULL;
  }
  // A found name is treated as accessed and possibly marked as captured.
  const bool kTestOnly = false;
  return current_block_->scope->LookupVariable(ident, kTestOnly);
}


void Parser::CheckInstanceFieldAccess(intptr_t field_pos,
                                      const String& field_name) {
  // Fields are not accessible from a static function, except from a
  // constructor, which is considered as non-static by the compiler.
  if (current_function().IsInStaticScope()) {
    ErrorMsg(field_pos,
             "cannot access instance field '%s' from a static function",
             field_name.ToCString());
  }
}


void Parser::CheckTypeParameterReference(intptr_t type_parameter_pos,
                                         const String& type_parameter_name) {
  // Type parameters cannot be referred to from a static function, except from
  // a constructor or from a factory.
  // A constructor is considered as non-static by the compiler.
  if ((is_top_level_ &&
       (current_member_ != NULL) &&
       current_member_->has_static &&
       !current_member_->has_factory) ||
      (!current_function().IsNull() &&
       current_function().IsInStaticScope() &&
       !current_function().IsInFactoryScope())) {
    ErrorMsg(type_parameter_pos,
             "cannot refer to type parameter '%s' from a static function",
             type_parameter_name.ToCString());
  }
}


void Parser::RunStaticFieldInitializer(const Field& field) {
  ASSERT(field.is_static());
  const Instance& value = Instance::Handle(field.value());
  if (value.raw() == Object::transition_sentinel()) {
    ErrorMsg("Circular dependency while initializing static field '%s'",
             String::Handle(field.name()).ToCString());

  } else if (value.raw() == Object::sentinel()) {
    // This field has not been referenced yet and thus the value has
    // not been evaluated. Call the static getter method to evaluate
    // the expression and canonicalize the value.

    field.set_value(Instance::Handle(Object::transition_sentinel()));
    const String& field_name = String::Handle(field.name());
    const String& getter_name =
        String::Handle(Field::GetterName(field_name));
    const Class& cls = Class::Handle(field.owner());
    GrowableArray<const Object*> arguments;  // no arguments.
    const int kNumArguments = 0;  // no arguments.
    const Array& kNoArgumentNames = Array::Handle();
    const Function& func =
        Function::Handle(Resolver::ResolveStatic(cls,
                                                 getter_name,
                                                 kNumArguments,
                                                 kNoArgumentNames,
                                                 Resolver::kIsQualified));
    ASSERT(!func.IsNull());
    ASSERT(func.kind() == RawFunction::kConstImplicitGetter);
    Instance& const_value =
        Instance::Handle(DartEntry::InvokeStatic(func, arguments));
    if (const_value.IsUnhandledException()) {
      ErrorMsg("Exception thrown in Parser::RunStaticFieldInitializer");
    }
    if (!const_value.IsNull()) {
      const_value ^= const_value.Canonicalize();
    }
    field.set_value(const_value);
  }
}


RawInstance* Parser::EvaluateConstConstructorCall(
    const Class& type_class,
    const TypeArguments& type_arguments,
    const Function& constructor,
    ArgumentListNode* arguments) {
  GrowableArray<const Object*> arg_values(arguments->length() + 1);
  Instance& instance = Instance::Handle();
  if (!constructor.IsFactory()) {
    instance = Instance::New(type_class);
    if (!type_arguments.IsNull()) {
      // TODO(regis): Where should we check the constraints on type parameters?
      if (!type_arguments.IsInstantiated()) {
        ErrorMsg("type must be constant in const constructor");
      }
      instance.SetTypeArguments(type_arguments);
    }
    arg_values.Add(&instance);
  } else {
    // Prepend type_arguments to list of arguments to factory.
    ASSERT(type_arguments.IsZoneHandle());
    arg_values.Add(&type_arguments);
  }
  for (int i = 0; i < arguments->length(); i++) {
    AstNode* arg = arguments->NodeAt(i);
    // Arguments have been evaluated to a literal value already.
    ASSERT(arg->IsLiteralNode());
    arg_values.Add(&arg->AsLiteralNode()->literal());
  }
  const Instance& result = Instance::Handle(
      DartEntry::InvokeStatic(constructor, arg_values));
  if (result.IsUnhandledException()) {
    ErrorMsg("Exception thrown in EvaluateConstConstructorCall");
  }
  if (constructor.IsFactory()) {
    // The factory method returns the allocated object.
    instance = result.raw();
  }
  if (!instance.IsNull()) {
    instance ^= instance.Canonicalize();
  }
  return instance.raw();
}


// Do a lookup for the identifier in the block scope and the class scope
// return true if the identifier is found, false otherwise.
// If node is non NULL return an AST node corresponding to the identifier.
bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos,
                                      const String &ident,
                                      AstNode** node) {
  TRACE_PARSER("ResolveIdentInLocalScope");
  // First try to find the identifier in the nested local scopes.
  LocalVariable* local = LookupLocalScope(ident);
  if (local != NULL) {
    if (node != NULL) {
      *node = new LoadLocalNode(ident_pos, *local);
    }
    return true;
  }

  // Try to find the identifier in the class scope.
  Class& cls = Class::Handle(current_class().raw());
  Function& func = Function::Handle();
  Field& field = Field::Handle();
  while (!cls.IsNull()) {
    // First check if a field exists.
    field = cls.LookupInstanceField(ident);
    if (!field.IsNull()) {
      if (node != NULL) {
        CheckInstanceFieldAccess(ident_pos, ident);
        *node = CallGetter(ident_pos, LoadReceiver(), ident);
      }
      return true;
    }
    field = cls.LookupStaticField(ident);
    if (!field.IsNull()) {
      if (node != NULL) {
        *node = GenerateStaticFieldLookup(field, ident_pos);
      }
      return true;
    }

    // Now check if a getter/setter method exists for it in which case
    // it is still a field.
    const String& getter_name = String::Handle(Field::GetterName(ident));
    func = cls.LookupDynamicFunction(getter_name);
    if (!func.IsNull()) {
      if (node != NULL) {
        CheckInstanceFieldAccess(ident_pos, ident);
        ASSERT(Type::Handle(func.result_type()).IsResolved());
        *node = CallGetter(ident_pos, LoadReceiver(), ident);
      }
      return true;
    }
    func = cls.LookupStaticFunction(getter_name);
    if (!func.IsNull()) {
      if (node != NULL) {
        ASSERT(Type::Handle(func.result_type()).IsResolved());
        *node = new StaticGetterNode(ident_pos,
                                     Class::ZoneHandle(cls.raw()),
                                     ident);
      }
      return true;
    }
    const String& setter_name = String::Handle(Field::SetterName(ident));
    func = cls.LookupDynamicFunction(setter_name);
    if (!func.IsNull()) {
      if (node != NULL) {
        // We create a getter node even though a getter doesn't exist as
        // it could be followed by an assignment which will convert it to
        // a setter node. If there is no assignment we will get an error
        // when we try to invoke the getter.
        CheckInstanceFieldAccess(ident_pos, ident);
        ASSERT(Type::Handle(func.result_type()).IsResolved());
        *node = CallGetter(ident_pos, LoadReceiver(), ident);
      }
      return true;
    }
    func = cls.LookupStaticFunction(setter_name);
    if (!func.IsNull()) {
      if (node != NULL) {
        // We create a getter node even though a getter doesn't exist as
        // it could be followed by an assignment which will convert it to
        // a setter node. If there is no assignment we will get an error
        // when we try to invoke the getter.
        *node = new StaticGetterNode(ident_pos,
                                     Class::ZoneHandle(cls.raw()),
                                     ident);
      }
      return true;
    }

    // Check if an instance/static function exists.
    func = cls.LookupDynamicFunction(ident);
    if (func.IsNull()) {
      func = cls.LookupStaticFunction(ident);
    }
    if (!func.IsNull()) {
      if (node != NULL) {
        *node = new PrimaryNode(ident_pos, Function::ZoneHandle(func.raw()));
      }
      return true;
    }
    cls = cls.SuperClass();
  }
  if (node != NULL) {
    *node = NULL;
  }
  return false;  // Not an unqualified identifier.
}


// Do a lookup for the identifier in the library scope of the specified
// library. If resolve_locally is true the lookup does not consider
// the libraries imported by it for the lookup.
AstNode* Parser::ResolveIdentInLibraryScope(const Library& lib,
                                            const QualIdent& qual_ident,
                                            bool resolve_locally) {
  TRACE_PARSER("ResolveIdentInLibraryScope");
  Object& obj = Object::Handle();
  if (resolve_locally) {
    obj = lib.LookupLocalObject(*qual_ident.ident);
  } else {
    obj = lib.LookupObject(*qual_ident.ident);
  }
  if (obj.IsClass()) {
    Class& cls = Class::Handle();
    cls ^= obj.raw();
    return new PrimaryNode(qual_ident.ident_pos, Class::ZoneHandle(cls.raw()));
  }
  if (obj.IsField()) {
    Field& field = Field::Handle();
    field ^= obj.raw();
    ASSERT(field.is_static());
    return GenerateStaticFieldLookup(field, qual_ident.ident_pos);
  }
  Function& func = Function::Handle();
  if (obj.IsFunction()) {
    func ^= obj.raw();
    ASSERT(func.is_static());
    return new PrimaryNode(qual_ident.ident_pos,
                           Function::ZoneHandle(func.raw()));
  } else {
    ASSERT(obj.IsNull() || obj.IsLibraryPrefix());
  }

  // Check if there is a global getter or setter for qual_ident.
  // We create a getter node even if a getter doesn't exist since
  // qual_ident could be followed by an assignment which will convert it
  // to a setter node. If there is no assignment we will get an error
  // when we try to invoke the getter.
  String& accessor_name = String::Handle(Field::GetterName(*qual_ident.ident));
  if (resolve_locally) {
    obj = lib.LookupLocalObject(accessor_name);
  } else {
    obj = lib.LookupObject(accessor_name);
  }
  if (obj.IsNull()) {
    accessor_name = Field::SetterName(*qual_ident.ident);
    if (resolve_locally) {
      obj = lib.LookupLocalObject(accessor_name);
    } else {
      obj = lib.LookupObject(accessor_name);
    }
  }
  if (!obj.IsNull()) {
    ASSERT(obj.IsFunction());
    func ^= obj.raw();
    ASSERT(func.is_static());
    ASSERT(Type::Handle(func.result_type()).IsResolved());
    return new StaticGetterNode(qual_ident.ident_pos,
                                Class::ZoneHandle(func.owner()),
                                *qual_ident.ident);
  }
  if (qual_ident.qualifier != NULL) {
    // This is an unresolved prefixed primary identifier, need to report
    // an error.
    ErrorMsg(qual_ident.ident_pos, "identifier '%s.%s' cannot be resolved",
             (qual_ident.qualifier)->ToCString(),
             (qual_ident.ident)->ToCString());
  }
  // Lexically unresolved primary identifiers are referenced by their name.
  return new PrimaryNode(qual_ident.ident_pos, *qual_ident.ident);
}


// Resolve identifier, issue an error message if the name refers to
// a method or a class/interface.
// If the name cannot be resolved, turn it into an instance field access
// if we're compiling an instance method, or issue an error message
// if we're compiling a static method.
AstNode* Parser::ResolveVarOrField(intptr_t ident_pos, const String& ident) {
  TRACE_PARSER("ResolveVarOrField");
  // First try to find the variable in the local scope (block scope or
  // class scope).
  AstNode* var_or_field = NULL;
  ResolveIdentInLocalScope(ident_pos, ident, &var_or_field);
  if (var_or_field == NULL) {
    // Not found in the local scope, so try finding the variable in the
    // library scope (current library and all libraries imported by it).
    QualIdent qual_ident;
    qual_ident.qualifier = NULL;
    qual_ident.lib_prefix = NULL;
    qual_ident.ident_pos = ident_pos;
    qual_ident.ident = &(String::ZoneHandle(ident.raw()));
    var_or_field = ResolveIdentInLibraryScope(library_,
                                              qual_ident,
                                              kResolveIncludingImports);
  }
  if (var_or_field->IsPrimaryNode()) {
    PrimaryNode* primary = var_or_field->AsPrimaryNode();
    if (primary->primary().IsString()) {
      // We got an unresolved name. If we are compiling a static
      // method, this is an error. In an instance method, we convert
      // the unresolved name to an instance field access, since a
      // subclass might define a field with this name.
      if (current_function().IsInStaticScope()) {
        ErrorMsg(ident_pos, "identifier '%s' is not declared in this scope",
                 ident.ToCString());
      } else {
        // Treat as call to unresolved instance field.
        var_or_field = CallGetter(ident_pos, LoadReceiver(), ident);
      }
    } else if (primary->primary().IsFunction()) {
      ErrorMsg(ident_pos, "illegal reference to method '%s'",
               ident.ToCString());
    } else {
      ASSERT(primary->primary().IsClass());
      ErrorMsg(ident_pos, "illegal reference to class or interface '%s'",
               ident.ToCString());
    }
  }
  return var_or_field;
}


// Parses type = [ident "."] ident ["<" type { "," type } ">"].
// Returns the class object if the type can be resolved. Otherwise, either give
// an error if type resolution was required, or return the unresolved name as a
// string object.
RawType* Parser::ParseType(TypeResolution type_resolution) {
  if (CurrentToken() != Token::kIDENT) {
    ErrorMsg("type name expected");
  }
  QualIdent type_name;
  intptr_t type_pos = token_index_;
  ParseQualIdent(&type_name);
  if (type_name.local_scope_ident) {
    ErrorMsg(type_pos, "Using '%s' in this context is invalid",
             type_name.ident->ToCString());
  }
  Object& type_class = Object::Handle();
  if (type_resolution == kDoNotResolve) {
    // TODO(5072252): Figure out what should be done in this case.
    if (type_name.qualifier != NULL) {
      Unimplemented("cannot handle qualified type names yet");
    }
    type_class = type_name.ident->raw();
  } else {
    TypeParameter& type_parameter = TypeParameter::Handle();
    // Check if qualifier is a type parameter of the class we are parsing.
    if (type_name.qualifier != NULL) {
      type_parameter =
          current_class().LookupTypeParameter(*type_name.qualifier);
      if (!type_parameter.IsNull()) {
        ErrorMsg(type_pos, "Use of '%s' in this context is invalid",
                 type_name.qualifier->ToCString());
      }
    } else {
      // Check if ident is a type parameter of the class we are parsing.
      type_parameter = current_class().LookupTypeParameter(*type_name.ident);
      if (!type_parameter.IsNull()) {
        CheckTypeParameterReference(type_name.ident_pos, *type_name.ident);
        if (CurrentToken() == Token::kLT) {
          // A type parameter cannot be parameterized.
          ErrorMsg(type_pos, "type parameter '%s' cannot be parameterized",
                   String::Handle(type_parameter.Name()).ToCString());
        }
        return type_parameter.raw();
      }
    }
    // Try to resolve the type class.
    type_class = LookupTypeClass(type_name, type_resolution);
  }
  TypeArguments& type_arguments =
      TypeArguments::Handle(ParseTypeArguments(type_resolution));
  const Type& type = Type::Handle(
      Type::NewParameterizedType(type_class, type_arguments));
  if (type_resolution == kMustResolve) {
    const String& errmsg = String::Handle(
        ClassFinalizer::FinalizeTypeWhileParsing(type));
    if (!errmsg.IsNull()) {
      ErrorMsg(errmsg.ToCString());
    }
  }
  return type.raw();
}


// Parse "[" [ expr { "," expr } ["," ] "]".
// Note: if the array literal is empty and the brackets have no whitespace
// between them, the scanner recognizes the opening and closing bracket
// as one token of type Token::kINDEX.
AstNode* Parser::ParseArrayLiteral(intptr_t type_pos,
                                   bool is_const,
                                   const TypeArguments& type_arguments) {
  ASSERT(CurrentToken() == Token::kLBRACK || CurrentToken() == Token::kINDEX);
  intptr_t literal_pos = token_index_;
  bool is_empty_literal = CurrentToken() == Token::kINDEX;
  ConsumeToken();

  // If no type arguments are provided, leave them as null, which is equivalent
  // to using Array<var>. See issue 4966724.
  if (!type_arguments.IsNull()) {
    // For now, only check the number of type arguments. See issue 4975876.
    if (type_arguments.Length() != 1) {
      ASSERT(type_pos >= 0);
      ErrorMsg(type_pos, "wrong number of type arguments for Array literal");
    }
  }

  // Parse the array elements. Note: there may be an optional extra
  // comma after the last element.
  ArrayNode* array = new ArrayNode(token_index_, type_arguments);
  if (!is_empty_literal) {
    const bool saved_mode = SetAllowFunctionLiterals(true);
    while (CurrentToken() != Token::kRBRACK) {
      array->AddElement(ParseExpr(is_const));
      if (CurrentToken() == Token::kCOMMA) {
        ConsumeToken();
      } else if (CurrentToken() != Token::kRBRACK) {
        ErrorMsg("comma or ']' expected");
      }
    }
    ExpectToken(Token::kRBRACK);
    SetAllowFunctionLiterals(saved_mode);
  }

  if (is_const) {
    // Allocate and initialize the array at compile time.
    Array& lit_array =
        Array::ZoneHandle(Array::New(array->length(), Heap::kOld));
    if (!type_arguments.IsNull()) {
      // TODO(regis): Where should we check the constraints on type parameters?
      if (!type_arguments.IsInstantiated()) {
        ErrorMsg("type must be constant in const constructor");
      }
      lit_array.SetTypeArguments(type_arguments);
    }

    for (int i = 0; i < array->length(); i++) {
      AstNode* elem = array->ElementAt(i);
      // Arguments have been evaluated to a literal value already.
      ASSERT(elem->IsLiteralNode());
      lit_array.SetAt(i, elem->AsLiteralNode()->literal());
    }
    lit_array ^= lit_array.Canonicalize();
    lit_array.MakeImmutable();
    return new LiteralNode(literal_pos, lit_array);
  } else {
    if (!type_arguments.IsNull() &&
        !type_arguments.IsInstantiated() &&
        (current_block_->scope->function_level() > 0)) {
      // Make sure that the instantiator is captured.
      CaptureReceiver();
    }

    // Make a new growable array from the fixed array.
    String& growable_object_array_class_name = String::Handle(
        String::NewSymbol(kGrowableObjectArrayName));
    const Class& growable_array_class = Class::Handle(
        LookupImplClass(growable_object_array_class_name));
    String& ctor_name =
        String::Handle(String::NewSymbol(kGrowableObjectArrayFromArrayName));
    Function& array_ctor = Function::ZoneHandle(
        growable_array_class.LookupConstructor(ctor_name));
    ASSERT(!array_ctor.IsNull());
    ArgumentListNode* ctor_args = new ArgumentListNode(literal_pos);
    ctor_args->Add(array);
    return new ConstructorCallNode(
        literal_pos, type_arguments, array_ctor, ctor_args);
  }
}


static void AddKeyValuePair(ArrayNode* pairs,
                            bool is_const,
                            AstNode* key,
                            AstNode* value) {
  if (is_const) {
    ASSERT(key->IsLiteralNode());
    ASSERT(key->AsLiteralNode()->literal().IsString());
    const Instance& new_key = key->AsLiteralNode()->literal();
    for (int i = 0; i < pairs->length(); i += 2) {
      const Instance& key_i =
          pairs->ElementAt(i)->AsLiteralNode()->literal();
      ASSERT(key_i.IsString());
      if (new_key.Equals(key_i)) {
        // Duplicate key found. The new value replaces the previously
        // defined value.
        pairs->SetElementAt(i + 1, value);
        return;
      }
    }
  }
  pairs->AddElement(key);
  pairs->AddElement(value);
}


AstNode* Parser::ParseMapLiteral(intptr_t type_pos,
                                 bool is_const,
                                 const TypeArguments& type_arguments) {
  TRACE_PARSER("ParseMapLiteral");
  ASSERT(CurrentToken() == Token::kLBRACE);
  intptr_t literal_pos = token_index_;
  ConsumeToken();

  String& map_class_name = String::Handle(
      String::NewSymbol(is_const ? kImmutableMapName : kMutableMapName));
  const Class& map_class = Class::Handle(LookupImplClass(map_class_name));
  ASSERT(!map_class.IsNull());

  TypeArguments& map_type_arguments =
      TypeArguments::ZoneHandle(type_arguments.raw());
  // If no type arguments are provided, leave them as null, which is equivalent
  // to using Map<var, var>. See issue 4966724.
  if (!map_type_arguments.IsNull()) {
    // For now, only check the number of type arguments. See issue 4975876.
    if (map_type_arguments.Length() != 2) {
      ASSERT(type_pos >= 0);
      ErrorMsg(type_pos, "wrong number of type arguments for Map literal");
    }
  }

  // Parse the map entries. Note: there may be an optional extra
  // comma after the last entry.
  ArrayNode* kv_pairs =
      new ArrayNode(token_index_, TypeArguments::ZoneHandle());
  while (CurrentToken() != Token::kRBRACE) {
    AstNode* key = NULL;
    if (CurrentToken() == Token::kSTRING) {
      key = ParseStringLiteral();
    }
    if (key == NULL) {
      ErrorMsg("map entry key must be string literal");
    } else if (is_const && !key->IsLiteralNode()) {
      ErrorMsg("map entry key must be compile time constant string");
    }
    ExpectToken(Token::kCOLON);
    const bool saved_mode = SetAllowFunctionLiterals(true);
    AstNode* value = ParseExpr(is_const);
    SetAllowFunctionLiterals(saved_mode);

    AddKeyValuePair(kv_pairs, is_const, key, value);

    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
    } else if (CurrentToken() != Token::kRBRACE) {
      ErrorMsg("comma or '}' expected");
    }
  }
  ASSERT(kv_pairs->length() % 2 == 0);
  ExpectToken(Token::kRBRACE);

  if (is_const) {
    // Create the key-value pair array, canonicalize it and then create
    // the immutable map object with it. This all happens at compile time.
    // The resulting immutable map object is returned as a literal.

    // First, create the canonicalized key-value pair array.
    Array& key_value_array =
        Array::ZoneHandle(Array::New(kv_pairs->length(), Heap::kOld));
    for (int i = 0; i < kv_pairs->length(); i++) {
      AstNode* arg = kv_pairs->ElementAt(i);
      // Arguments have been evaluated to a literal value already.
      ASSERT(arg->IsLiteralNode());
      key_value_array.SetAt(i, arg->AsLiteralNode()->literal());
    }
    key_value_array ^= key_value_array.Canonicalize();
    key_value_array.MakeImmutable();

    // Construct the map object.
    ArgumentListNode* constr_args = new ArgumentListNode(token_index_);
    constr_args->Add(new LiteralNode(literal_pos, key_value_array));
    const String& constr_name =
        String::Handle(String::NewSymbol(kImmutableMapConstructorName));
    const Function& map_constr = Function::ZoneHandle(
        map_class.LookupConstructor(constr_name));
    ASSERT(!map_constr.IsNull());
    return new LiteralNode(literal_pos, Instance::ZoneHandle(
        EvaluateConstConstructorCall(
            map_class, map_type_arguments, map_constr, constr_args)));
  } else {
    // Static call at runtime.
    const String& static_factory_name =
        String::Handle(String::NewSymbol(kMutableMapFromLiteralName));
    const Function& static_factory = Function::ZoneHandle(
        map_class.LookupStaticFunction(static_factory_name));
    ASSERT(!static_factory.IsNull());
    if (!map_type_arguments.IsNull() &&
        !map_type_arguments.IsInstantiated() &&
        (current_block_->scope->function_level() > 0)) {
      // Make sure that the instantiator is captured.
      CaptureReceiver();
    }
    ArgumentListNode* factory_param = new ArgumentListNode(literal_pos);
    factory_param->Add(kv_pairs);
    return new StaticCallNode(
        literal_pos, static_factory, factory_param);
  }
}


AstNode* Parser::ParseCompoundLiteral() {
  bool is_const = false;
  if (CurrentToken() == Token::kCONST) {
    is_const = true;
    ConsumeToken();
  }
  intptr_t type_pos = token_index_;
  TypeArguments& type_arguments =
      TypeArguments::ZoneHandle(ParseTypeArguments(kMustResolve));
  AstNode* primary = NULL;
  if ((CurrentToken() == Token::kLBRACK) ||
      (CurrentToken() == Token::kINDEX)) {
    primary = ParseArrayLiteral(type_pos, is_const, type_arguments);
  } else if (CurrentToken() == Token::kLBRACE) {
    primary = ParseMapLiteral(type_pos, is_const, type_arguments);
  } else {
    ErrorMsg("Unexpected token %s", Token::Str(CurrentToken()));
  }
  return primary;
}


static const String& BuildConstructorName(const String& type_class_name,
                                          const String* named_constructor) {
  // By convention, the static function implementing a named constructor 'C'
  // for class 'A' is labeled 'A.C', and the static function implementing the
  // unnamed constructor for class 'A' is labeled 'A.'.
  // This convention prevents users from explicitly calling constructors.
  const String& period = String::Handle(String::NewSymbol("."));
  String& constructor_name =
      String::Handle(String::Concat(type_class_name, period));
  if (named_constructor != NULL) {
    constructor_name = String::Concat(constructor_name, *named_constructor);
  }
  return constructor_name;
}


AstNode* Parser::ParseNewOperator() {
  TRACE_PARSER("ParseNewOperator");
  const intptr_t new_pos = token_index_;
  ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST));
  bool is_const = (CurrentToken() == Token::kCONST);
  ConsumeToken();
  if (CurrentToken() != Token::kIDENT) {
    ErrorMsg("type name expected");
  }

  // The grammar allows for an optional ('.' identifier)?, which is a named
  // constructor. For that reason, we cannot unconditionally call
  // ParseType(kMustResolve) after we see an identifier, because the named
  // constructor would be misinterpreted as a qualified type name.
  // TODO(regis): Revisit once we correctly support qualified identifiers.
  // For now, we inline a customized version of ParseType(kMustResolve).
  Type& type = Type::Handle();
  Class& type_class = Class::ZoneHandle();
  String& type_class_name = String::Handle();
  TypeArguments& type_arguments = TypeArguments::ZoneHandle();
  String* named_constructor = NULL;
  intptr_t  type_pos = token_index_;
  QualIdent type_name;
  ParseQualIdent(&type_name);
  if (type_name.local_scope_ident) {
    ErrorMsg(type_pos, "Using '%s' in this context is invalid",
             type_name.ident->ToCString());
  }
  if (CurrentToken() == Token::kPERIOD) {
    ConsumeToken();
    named_constructor = ExpectIdentifier("identifier expected after '.'");
  }
  TypeParameter& type_parameter = TypeParameter::Handle();
  if (type_name.lib_prefix != NULL) {
    // TODO(regis): Ascertain that this check for shadowing is valid
    // See bug (490270).
    // Check if qualifier is a type parameter of the class we are parsing.
    type_parameter ^= current_class().LookupTypeParameter(*type_name.qualifier);
    if (!type_parameter.IsNull()) {
      CheckTypeParameterReference(type_pos, *type_name.qualifier);
      ErrorMsg(type_pos, "type parameter '%s' cannot be instantiated",
               String::Handle(type_parameter.Name()).ToCString());
    }
  }
  // Check if ident is a type parameter of the class we are parsing.
  type_parameter = current_class().LookupTypeParameter(*type_name.ident);
  if (!type_parameter.IsNull()) {
    CheckTypeParameterReference(type_name.ident_pos, *type_name.ident);
    ErrorMsg(type_pos, "type parameter '%s' cannot be instantiated",
             String::Handle(type_parameter.Name()).ToCString());
  }
  type_class ^= LookupTypeClass(type_name, kMustResolve);
  type_class_name = type_class.Name();
  // Type arguments are not allowed after the optional constructor name.
  if (named_constructor == NULL) {
    type_arguments = ParseTypeArguments(kMustResolve);
    type = Type::NewParameterizedType(type_class, type_arguments);
    const String& errmsg = String::Handle(
        ClassFinalizer::FinalizeTypeWhileParsing(type));
    if (!errmsg.IsNull()) {
      ErrorMsg(errmsg.ToCString());
    }
    // The type argument vector may have been expanded with the type arguments
    // of the super type when finalizing the type.
    type_arguments = type.arguments();
  }
  if ((named_constructor == NULL) && (CurrentToken() == Token::kPERIOD)) {
    ConsumeToken();
    named_constructor = ExpectIdentifier("name of constructor expected");
  }

  // Parse constructor parameters.
  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg("'(' expected");
  }
  ArgumentListNode* arguments = ParseActualParameters(NULL, is_const);

  // A constructor has an implicit 'this' parameter (instance to construct)
  // and a factory has an implicit 'this' parameter (type_arguments).
  intptr_t arguments_length = arguments->length() + 1;

  if (type_class.is_interface()) {
    // We need to make sure that an appropriate constructor is
    // declared in the interface.
    const String& constructor_name =
        BuildConstructorName(type_class_name, named_constructor);
    const String& external_constructor_name =
        (named_constructor ? constructor_name : type_class_name);
    Function& constructor = Function::ZoneHandle(
        type_class.LookupConstructor(constructor_name));
    if (constructor.IsNull()) {
      ErrorMsg(new_pos, "interface '%s' has no constructor named '%s'",
               type_class_name.ToCString(),
               external_constructor_name.ToCString());
    }
    if (!constructor.AreValidArguments(arguments_length, arguments->names())) {
      ErrorMsg(new_pos, "invalid arguments passed to constructor '%s' "
               "for interface '%s'",
               external_constructor_name.ToCString(),
               type_class_name.ToCString());
    }

    // TODO(srdjan): Evaluate if the mapping should occur during code
    // generation or here in the parser.
    const Type& factory_type = Type::Handle(type_class.factory_type());
    if (factory_type.IsNull()) {
      ErrorMsg("cannot allocate interface '%s' without factory class",
               type_class_name.ToCString());
    }
    if (!factory_type.HasResolvedTypeClass()) {
      // This error can occur only with bootstrap classes.
      const String& missing_class_name =
          String::Handle(factory_type.unresolved_type_class());
      ErrorMsg("Unresolved factory class '%s'",
               missing_class_name.ToCString());
    }

    // Only change the class of the constructor to the factory class if the
    // factory class implements the interface 'type'.
    Class& factory_type_class = Class::Handle(factory_type.type_class());
    // TODO(regis): Verify in the guide/spec that a factory class must have
    // identical type parameters as the interface.
    // TODO(regis): Do we check that in the parser?
    // Assuming that it has been checked, it is sufficient to test if the
    // raw factory type implements the raw interface type.
    if (factory_type_class.IsSubtypeOf(TypeArguments::Handle(),
                                       type_class,
                                       TypeArguments::Handle())) {
      type_class_name = factory_type_class.Name();
    }
    // Always change the result type of the constructor to the factory type.
    type_class = factory_type_class.raw();
    ASSERT(!type_class.is_interface());
  }

  // Make sure that an appropriate constructor exists.
  const String& constructor_name =
      BuildConstructorName(type_class_name, named_constructor);
  const String& external_constructor_name =
      (named_constructor ? constructor_name : type_class_name);
  Function& constructor = Function::ZoneHandle(
      type_class.LookupConstructor(constructor_name));
  if (constructor.IsNull()) {
    constructor = type_class.LookupFactory(constructor_name);
  }
  if (constructor.IsNull()) {
    ErrorMsg(new_pos, "class '%s' has no constructor or factory named '%s'",
             String::Handle(type_class.Name()).ToCString(),
             external_constructor_name.ToCString());
  }
  if (!constructor.AreValidArguments(arguments_length, arguments->names())) {
    ErrorMsg(new_pos, "invalid arguments passed to constructor '%s' "
             "for class '%s'",
             external_constructor_name.ToCString(),
             String::Handle(type_class.Name()).ToCString());
  }

  AstNode* new_object = NULL;
  if (is_const) {
    if (!constructor.is_const()) {
      ErrorMsg("'const' requires const constructor: '%s'",
          String::Handle(constructor.name()).ToCString());
    }
    const Instance& const_instance = Instance::ZoneHandle(
        EvaluateConstConstructorCall(
            type_class, type_arguments, constructor, arguments));
    new_object = new LiteralNode(new_pos, const_instance);
  } else {
    CheckFunctionIsCallable(new_pos, constructor);
    if (!type_arguments.IsNull() &&
        !type_arguments.IsInstantiated() &&
        (current_block_->scope->function_level() > 0)) {
      // Make sure that the instantiator is captured.
      CaptureReceiver();
    }
    new_object = new ConstructorCallNode(
        new_pos, type_arguments, constructor, arguments);
  }
  return new_object;
}


String& Parser::Interpolate(ArrayNode* values) {
  const String& class_name =
      String::Handle(String::NewSymbol(kStringClassName));
  const Class& cls = Class::Handle(LookupImplClass(class_name));
  ASSERT(!cls.IsNull());
  const String& func_name = String::Handle(String::NewSymbol(kInterpolateName));
  const Function& func =
      Function::Handle(cls.LookupStaticFunction(func_name));
  ASSERT(!func.IsNull());

  // Build the array of literal values to interpolate.
  const Array& value_arr = Array::Handle(Array::New(values->length()));
  for (int i = 0; i < values->length(); i++) {
    ASSERT(values->ElementAt(i)->IsLiteralNode());
    value_arr.SetAt(i, values->ElementAt(i)->AsLiteralNode()->literal());
  }

  // Build argument array to pass to the interpolation function.
  GrowableArray<const Object*> interpolate_arg;
  interpolate_arg.Add(&value_arr);

  // Call interpolation function.
  String& concatenated = String::ZoneHandle();
  concatenated ^= DartEntry::InvokeStatic(func, interpolate_arg);
  if (concatenated.IsUnhandledException()) {
    ErrorMsg("Exception thrown in Parser::Interpolate");
  }
  concatenated = String::NewSymbol(concatenated);
  return concatenated;
}


// A string literal consists of the concatenation of the next n tokens
// that satisfy the EBNF grammar:
// literal = kSTRING {{ interpol }+ kSTRING }
// interpol = kINTERPOL_VAR | (kINTERPOL_START expression kINTERPOL_END)
// In other words, the scanner breaks down interpolated strings so that
// a string literal always begins and ends with a kSTRING token, and
// there are never two kSTRING tokens next to each other.
AstNode* Parser::ParseStringLiteral() {
  AstNode* primary = NULL;
  intptr_t literal_start = token_index_;
  if ((CurrentToken() == Token::kSTRING) &&
      (LookaheadToken(1) != Token::kINTERPOL_VAR) &&
      (LookaheadToken(1) != Token::kINTERPOL_START)) {
    // Common case: no interpolation.
    primary = new LiteralNode(literal_start, *CurrentLiteral());
    ConsumeToken();
    return primary;
  }
  // String interpolation needed.
  bool is_compiletime_const = true;
  ArrayNode* values = new ArrayNode(token_index_, TypeArguments::ZoneHandle());
  GrowableArray<const Object*> arg_values;
  while (CurrentToken() == Token::kSTRING) {
    values->AddElement(new LiteralNode(token_index_, *CurrentLiteral()));
    ConsumeToken();
    if ((CurrentToken() != Token::kINTERPOL_VAR) &&
        (CurrentToken() != Token::kINTERPOL_START)) {
      break;
    }
    while ((CurrentToken() == Token::kINTERPOL_VAR) ||
        (CurrentToken() == Token::kINTERPOL_START)) {
      AstNode* expr = NULL;
      const intptr_t expr_pos = token_index_;
      if (CurrentToken() == Token::kINTERPOL_VAR) {
        expr = ResolveVarOrField(token_index_, *CurrentLiteral());
        ASSERT(!expr->IsPrimaryNode());
        ConsumeToken();
      } else {
        ASSERT(CurrentToken() == Token::kINTERPOL_START);
        ConsumeToken();
        expr = ParseExpr(kAllowConst);
        ExpectToken(Token::kINTERPOL_END);
      }

      // Check if this interpolated string is still considered a compile time
      // constant. If it is we need to evaluate if the current string part is
      // a constant or not.
      if (is_compiletime_const) {
        const Object* const_expr = expr->EvalConstExpr();
        if (const_expr != NULL) {
          // Change expr into a literal.
          expr = new LiteralNode(expr_pos, EvaluateConstExpr(expr));
        } else {
          is_compiletime_const = false;
        }
      }
      values->AddElement(expr);
    }
    // A string literal always ends with a kSTRING token.
    ASSERT(CurrentToken() == Token::kSTRING);
  }
  if (is_compiletime_const) {
    primary = new LiteralNode(literal_start, Interpolate(values));
  } else {
    ArgumentListNode* interpolate_arg =
        new ArgumentListNode(values->token_index());
    interpolate_arg->Add(values);
    primary = MakeStaticCall(kStringClassName,
                             kInterpolateName,
                             interpolate_arg);
  }
  return primary;
}


AstNode* Parser::ParsePrimary() {
  TRACE_PARSER("ParsePrimary");
  AstNode* primary = NULL;
  if (IsFunctionLiteral()) {
    // The name of a literal function is visible from inside the function, but
    // must not collide with names in the scope declaring the literal.
    OpenBlock();
    primary = ParseFunctionStatement(true);
    CloseBlock();
  } else if (CurrentToken() == Token::kIDENT) {
    QualIdent qual_ident;
    ParseQualIdent(&qual_ident);
    if (qual_ident.local_scope_ident) {
      ResolveIdentInLocalScope(qual_ident.ident_pos,
                               *qual_ident.ident,
                               &primary);
    } else {
      if (qual_ident.qualifier == NULL) {
        // This is an unqualified identifier so resolve the identifier
        // locally in the main app library and all libraries imported by it.
        primary = ResolveIdentInLibraryScope(library_,
                                             qual_ident,
                                             kResolveIncludingImports);
      } else {
        // This is a qualified identifier with a library prefix so resolve
        // the identifier locally in that library (we do not include the
        // libraries imported by that library).
        const Library& lib = Library::Handle(qual_ident.lib_prefix->library());
        primary = ResolveIdentInLibraryScope(lib,
                                             qual_ident,
                                             kResolveLocally);
      }
    }
    ASSERT(primary != NULL);
  } else if (CurrentToken() == Token::kTHIS) {
    const String& this_name = String::Handle(String::NewSymbol(kThisName));
    LocalVariable* local = LookupLocalScope(this_name);
    if (local == NULL) {
      ErrorMsg("unexpected use of 'this' in primary expression");
    }
    primary = new LoadLocalNode(token_index_, *local);
    ConsumeToken();
  } else if (CurrentToken() == Token::kINTEGER) {
    String* int_literal = CurrentLiteral();
    ASSERT(int_literal != NULL);
    ASSERT(int_literal->Length() > 0);
    const Integer& literal = Integer::ZoneHandle(Integer::New(*int_literal));
    primary = new LiteralNode(token_index_, literal);
    ConsumeToken();
  } else if (CurrentToken() == Token::kTRUE) {
    primary = new LiteralNode(token_index_, Bool::ZoneHandle(Bool::True()));
    ConsumeToken();
  } else if (CurrentToken() == Token::kFALSE) {
    primary = new LiteralNode(token_index_, Bool::ZoneHandle(Bool::False()));
    ConsumeToken();
  } else if (CurrentToken() == Token::kNULL) {
    primary = new LiteralNode(token_index_, Instance::ZoneHandle());
    ConsumeToken();
  } else if (CurrentToken() == Token::kLPAREN) {
    ConsumeToken();
    const bool saved_mode = SetAllowFunctionLiterals(true);
    primary = ParseExpr(kAllowConst);
    SetAllowFunctionLiterals(saved_mode);
    ExpectToken(Token::kRPAREN);
  } else if (CurrentToken() == Token::kDOUBLE) {
    String* double_literal = CurrentLiteral();
    ASSERT(double_literal != NULL);
    ASSERT(double_literal->Length() > 0);
    Double& double_value =
        Double::ZoneHandle(Double::New(*double_literal));
    if (double_value.IsNull()) {
      ErrorMsg("invalid double literal");
    }
    double_value ^= double_value.Canonicalize();
    primary = new LiteralNode(token_index_, double_value);
    ConsumeToken();
  } else if (CurrentToken() == Token::kSTRING) {
    primary = ParseStringLiteral();
  } else if (CurrentToken() == Token::kNEW) {
    primary = ParseNewOperator();
  } else if (CurrentToken() == Token::kCONST) {
    if ((LookaheadToken(1) == Token::kLT) ||
        (LookaheadToken(1) == Token::kLBRACK) ||
        (LookaheadToken(1) == Token::kINDEX) ||
        (LookaheadToken(1) == Token::kLBRACE)) {
      primary = ParseCompoundLiteral();
    } else {
      primary = ParseNewOperator();
    }
  } else if (CurrentToken() == Token::kLT ||
             CurrentToken() == Token::kLBRACK ||
             CurrentToken() == Token::kINDEX ||
             CurrentToken() == Token::kLBRACE) {
    primary = ParseCompoundLiteral();
  } else if (CurrentToken() == Token::kSUPER) {
    if (current_function().IsInStaticScope()) {
      ErrorMsg("cannot access superclass from static method");
    } else if (current_function().IsLocalFunction()) {
      ErrorMsg("cannot access superclass from local function");
    }
    ConsumeToken();
    if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      const String& ident = *ExpectIdentifier("identifier expected");
      if (CurrentToken() == Token::kLPAREN) {
        primary = ParseSuperCall(ident);
      } else {
        primary = ParseSuperFieldAccess(ident);
      }
    } else if (CurrentToken() == Token::kLBRACK) {
      Unimplemented("Don't know yet how to interpret super[expr]");
    } else {
      ErrorMsg("Expected '.' or '[' after super");
    }
  } else {
    UnexpectedToken();
  }
  return primary;
}


// Evaluate expression in expr and return the value. The expression must
// be a compile time constant.
const Instance& Parser::EvaluateConstExpr(AstNode* expr) {
  if (expr->IsLiteralNode()) {
    return expr->AsLiteralNode()->literal();
  } else {
    ASSERT(expr->EvalConstExpr() != NULL);
    ReturnNode* ret = new ReturnNode(expr->token_index(), expr);
    // Compile time constant expressions cannot reference anything from a
    // local scope.
    LocalScope* empty_scope = new LocalScope(NULL, 0, 0);
    SequenceNode* seq = new SequenceNode(expr->token_index(), empty_scope);
    seq->Add(ret);

    Instance& value = Instance::ZoneHandle(Compiler::ExecuteOnce(seq));
    if (value.IsNull()) {
      value ^= value.Canonicalize();
    }
    return value;
  }
}


void Parser::SkipFunctionLiteral() {
  if (CurrentToken() == Token::kIDENT) {
    if (LookaheadToken(1) != Token::kLPAREN) {
      SkipType(true);
    }
    ExpectIdentifier("function name expected");
  }
  if (CurrentToken() == Token::kLPAREN) {
    const bool allow_explicit_default_values = true;
    ParamList ignore_params;
    ParseFormalParameterList(allow_explicit_default_values, &ignore_params);
  }
  if (CurrentToken() == Token::kLBRACE) {
    SkipBlock();
  } else if (CurrentToken() == Token::kARROW) {
    ConsumeToken();
    SkipExpr();
  }
}


void Parser::SkipArrayLiteral() {
  if (CurrentToken() == Token::kINDEX) {
    // Empty array literal.
    ConsumeToken();
    return;
  }
  ExpectToken(Token::kLBRACK);
  while (CurrentToken() != Token::kRBRACK) {
    SkipNestedExpr();
    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
    }
  }
  ExpectToken(Token::kRBRACK);
}


void Parser::SkipMapLiteral() {
  ExpectToken(Token::kLBRACE);
  while (CurrentToken() == Token::kSTRING) {
    SkipStringLiteral();
    ExpectToken(Token::kCOLON);
    SkipNestedExpr();
    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
    }
  }
  ExpectToken(Token::kRBRACE);
}


void Parser::SkipActualParameters() {
  ExpectToken(Token::kLPAREN);
  while (CurrentToken() != Token::kRPAREN) {
    SkipNestedExpr();
    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
    }
  }
  ExpectToken(Token::kRPAREN);
}


void Parser::SkipCompoundLiteral() {
  if (CurrentToken() == Token::kLT) {
    SkipTypeArguments();
  }
  if ((CurrentToken() == Token::kLBRACK) ||
      (CurrentToken() == Token::kINDEX)) {
    SkipArrayLiteral();
  } else if (CurrentToken() == Token::kLBRACE) {
    SkipMapLiteral();
  }
}


void Parser::SkipNewOperator() {
  ConsumeToken();  // Skip new or const keyword.
  if (CurrentToken() == Token::kIDENT) {
    SkipType(false);
    if (CurrentToken() == Token::kLPAREN) {
      SkipActualParameters();
      return;
    }
  }
}


void Parser::SkipStringLiteral() {
  ASSERT(CurrentToken() == Token::kSTRING);
  while (CurrentToken() == Token::kSTRING) {
    ConsumeToken();
    if ((CurrentToken() != Token::kINTERPOL_VAR) &&
        (CurrentToken() != Token::kINTERPOL_START)) {
      break;
    }
    while (true) {
      if (CurrentToken() == Token::kINTERPOL_VAR) {
        ConsumeToken();
      } else if (CurrentToken() == Token::kINTERPOL_START) {
        ConsumeToken();
        SkipExpr();
        ExpectToken(Token::kINTERPOL_END);
      } else {
        break;
      }
    }
  }
}


void Parser::SkipPrimary() {
  if (IsFunctionLiteral()) {
    SkipFunctionLiteral();
    return;
  }
  switch (CurrentToken()) {
    case Token::kTHIS:
    case Token::kNULL:
    case Token::kTRUE:
    case Token::kFALSE:
    case Token::kINTEGER:
    case Token::kDOUBLE:
      ConsumeToken();
      break;
    case Token::kIDENT:
      ConsumeToken();
      break;
    case Token::kSTRING:
      SkipStringLiteral();
      break;
    case Token::kSUPER:
      Unimplemented("skipping of super not yet implemented");
      break;
    case Token::kLPAREN:
      ConsumeToken();
      SkipNestedExpr();
      ExpectToken(Token::kRPAREN);
      break;
    case Token::kNEW:
      SkipNewOperator();
      break;
    case Token::kCONST:
      if ((LookaheadToken(1) == Token::kLT) ||
          (LookaheadToken(1) == Token::kLBRACE) ||
          (LookaheadToken(1) == Token::kLBRACK) ||
          (LookaheadToken(1) == Token::kINDEX)) {
        ConsumeToken();
        SkipCompoundLiteral();
      } else {
        SkipNewOperator();
      }
      break;
    case Token::kLT:
    case Token::kLBRACE:
    case Token::kLBRACK:
    case Token::kINDEX:
      SkipCompoundLiteral();
      break;
    default:
      UnexpectedToken();
      UNREACHABLE();
      break;
  }
}


void Parser::SkipPostfixExpr() {
  SkipPrimary();
  while (true) {
    if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      ExpectIdentifier("identifier expected");
    } else if (CurrentToken() == Token::kLBRACK) {
      ConsumeToken();
      SkipNestedExpr();
      ExpectToken(Token::kRBRACK);
    } else if (CurrentToken() == Token::kLPAREN) {
      SkipActualParameters();
    } else {
      break;
    }
  }
  if (IsIncrementOperator(CurrentToken())) {
    ConsumeToken();
  }
}


void Parser::SkipUnaryExpr() {
  if (IsPrefixOperator(CurrentToken()) ||
      IsIncrementOperator(CurrentToken())) {
    ConsumeToken();
    SkipUnaryExpr();
  } else {
    SkipPostfixExpr();
  }
}


void Parser::SkipBinaryExpr() {
  SkipUnaryExpr();
  while (Token::Precedence(Token::kOR) <= Token::Precedence(CurrentToken()) &&
      Token::Precedence(CurrentToken()) <= Token::Precedence(Token::kMUL)) {
    ConsumeToken();
    SkipUnaryExpr();
  }
}


void Parser::SkipConditionalExpr() {
  SkipBinaryExpr();
  if (CurrentToken() == Token::kCONDITIONAL) {
    ConsumeToken();
    SkipConditionalExpr();
    ExpectToken(Token::kCOLON);
    SkipConditionalExpr();
  }
}


void Parser::SkipExpr() {
  SkipConditionalExpr();
  if (Token::IsAssignmentOperator(CurrentToken())) {
    ConsumeToken();
    SkipExpr();
  }
}


void Parser::SkipNestedExpr() {
  const bool saved_mode = SetAllowFunctionLiterals(true);
  SkipExpr();
  SetAllowFunctionLiterals(saved_mode);
}

}  // namespace dart
