Revert "Traitify ParserBase and move functions there."
authormarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 10 Feb 2014 16:21:11 +0000 (16:21 +0000)
committermarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 10 Feb 2014 16:21:11 +0000 (16:21 +0000)
This reverts commit r19230.

Reason: Build failures on NaCl.

BUG=
TBR=marja@chromium.org,mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/158873006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19234 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/parser.cc
src/parser.h
src/preparser.cc
src/preparser.h
test/cctest/test-parsing.cc

index f03ec02..5e7680e 100644 (file)
@@ -533,78 +533,8 @@ Parser::FunctionState::~FunctionState() {
 // ----------------------------------------------------------------------------
 // Implementation of Parser
 
-bool ParserTraits::is_classic_mode() const {
-  return parser_->top_scope_->is_classic_mode();
-}
-
-
-bool ParserTraits::is_generator() const {
-  return parser_->current_function_state_->is_generator();
-}
-
-
-bool ParserTraits::IsEvalOrArguments(Handle<String> identifier) const {
-  return identifier.is_identical_to(
-             parser_->isolate()->factory()->eval_string()) ||
-         identifier.is_identical_to(
-             parser_->isolate()->factory()->arguments_string());
-}
-
-
-void ParserTraits::ReportMessageAt(Scanner::Location source_location,
-                                   const char* message,
-                                   Vector<const char*> args) {
-  MessageLocation location(parser_->script_,
-                           source_location.beg_pos,
-                           source_location.end_pos);
-  Factory* factory = parser_->isolate()->factory();
-  Handle<FixedArray> elements = factory->NewFixedArray(args.length());
-  for (int i = 0; i < args.length(); i++) {
-    Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
-    elements->set(i, *arg_string);
-  }
-  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
-  Handle<Object> result = factory->NewSyntaxError(message, array);
-  parser_->isolate()->Throw(*result, &location);
-}
-
-
-void ParserTraits::ReportMessage(const char* message,
-                                 Vector<Handle<String> > args) {
-  Scanner::Location source_location = parser_->scanner().location();
-  ReportMessageAt(source_location, message, args);
-}
-
-
-void ParserTraits::ReportMessageAt(Scanner::Location source_location,
-                                   const char* message,
-                                   Vector<Handle<String> > args) {
-  MessageLocation location(parser_->script_,
-                           source_location.beg_pos,
-                           source_location.end_pos);
-  Factory* factory = parser_->isolate()->factory();
-  Handle<FixedArray> elements = factory->NewFixedArray(args.length());
-  for (int i = 0; i < args.length(); i++) {
-    elements->set(i, *args[i]);
-  }
-  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
-  Handle<Object> result = factory->NewSyntaxError(message, array);
-  parser_->isolate()->Throw(*result, &location);
-}
-
-
-Handle<String> ParserTraits::GetSymbol() {
-  int symbol_id = -1;
-  if (parser_->pre_parse_data() != NULL) {
-    symbol_id = parser_->pre_parse_data()->GetSymbolIdentifier();
-  }
-  return parser_->LookupSymbol(symbol_id);
-}
-
 Parser::Parser(CompilationInfo* info)
-    : ParserBase(&scanner_,
-                 info->isolate()->stack_guard()->real_climit(),
-                 this),
+    : ParserBase(&scanner_, info->isolate()->stack_guard()->real_climit()),
       isolate_(info->isolate()),
       symbol_cache_(0, info->zone()),
       script_(info->script()),
@@ -863,6 +793,62 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
 }
 
 
+Handle<String> Parser::GetSymbol() {
+  int symbol_id = -1;
+  if (pre_parse_data() != NULL) {
+    symbol_id = pre_parse_data()->GetSymbolIdentifier();
+  }
+  return LookupSymbol(symbol_id);
+}
+
+
+void Parser::ReportMessage(const char* message, Vector<const char*> args) {
+  Scanner::Location source_location = scanner().location();
+  ReportMessageAt(source_location, message, args);
+}
+
+
+void Parser::ReportMessage(const char* message, Vector<Handle<String> > args) {
+  Scanner::Location source_location = scanner().location();
+  ReportMessageAt(source_location, message, args);
+}
+
+
+void Parser::ReportMessageAt(Scanner::Location source_location,
+                             const char* message,
+                             Vector<const char*> args) {
+  MessageLocation location(script_,
+                           source_location.beg_pos,
+                           source_location.end_pos);
+  Factory* factory = isolate()->factory();
+  Handle<FixedArray> elements = factory->NewFixedArray(args.length());
+  for (int i = 0; i < args.length(); i++) {
+    Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
+    elements->set(i, *arg_string);
+  }
+  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
+  Handle<Object> result = factory->NewSyntaxError(message, array);
+  isolate()->Throw(*result, &location);
+}
+
+
+void Parser::ReportMessageAt(Scanner::Location source_location,
+                             const char* message,
+                             Vector<Handle<String> > args) {
+  MessageLocation location(script_,
+                           source_location.beg_pos,
+                           source_location.end_pos);
+  Factory* factory = isolate()->factory();
+  Handle<FixedArray> elements = factory->NewFixedArray(args.length());
+  for (int i = 0; i < args.length(); i++) {
+    elements->set(i, *args[i]);
+  }
+  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
+  Handle<Object> result = factory->NewSyntaxError(message, array);
+  isolate()->Throw(*result, &location);
+}
+
+
 void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
                                   int end_token,
                                   bool is_eval,
@@ -1095,8 +1081,8 @@ Module* Parser::ParseModuleLiteral(bool* ok) {
        !it.done(); it.Advance()) {
     if (scope->LocalLookup(it.name()) == NULL) {
       Handle<String> name(it.name());
-      ParserTraits::ReportMessage("module_export_undefined",
-                                  Vector<Handle<String> >(&name, 1));
+      ReportMessage("module_export_undefined",
+                    Vector<Handle<String> >(&name, 1));
       *ok = false;
       return NULL;
     }
@@ -1135,8 +1121,7 @@ Module* Parser::ParseModulePath(bool* ok) {
         member->interface()->Print();
       }
 #endif
-      ParserTraits::ReportMessage("invalid_module_path",
-                                  Vector<Handle<String> >(&name, 1));
+      ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1));
       return NULL;
     }
     result = member;
@@ -1246,8 +1231,7 @@ Block* Parser::ParseImportDeclaration(bool* ok) {
         module->interface()->Print();
       }
 #endif
-      ParserTraits::ReportMessage("invalid_module_path",
-                                  Vector<Handle<String> >(&name, 1));
+      ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1));
       return NULL;
     }
     VariableProxy* proxy = NewUnresolved(names[i], LET, interface);
@@ -1455,7 +1439,8 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
       // Statement:
       //    GeneratorDeclaration
       if (!top_scope_->is_classic_mode()) {
-        ReportMessageAt(scanner().peek_location(), "strict_function");
+        ReportMessageAt(scanner().peek_location(), "strict_function",
+                        Vector<const char*>::empty());
         *ok = false;
         return NULL;
       }
@@ -1634,8 +1619,7 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
           var->interface()->Print();
         }
 #endif
-        ParserTraits::ReportMessage("module_type_error",
-                                    Vector<Handle<String> >(&name, 1));
+        ReportMessage("module_type_error", Vector<Handle<String> >(&name, 1));
       }
     }
   }
@@ -1793,6 +1777,12 @@ Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
 }
 
 
+bool Parser::IsEvalOrArguments(Handle<String> string) {
+  return string.is_identical_to(isolate()->factory()->eval_string()) ||
+      string.is_identical_to(isolate()->factory()->arguments_string());
+}
+
+
 // If the variable declaration declares exactly one non-const
 // variable, then *out is set to that variable. In all other cases,
 // *out is untouched; in particular, it is the caller's responsibility
@@ -1938,7 +1928,8 @@ Block* Parser::ParseVariableDeclarations(
     Declare(declaration, mode != VAR, CHECK_OK);
     nvars++;
     if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
-      ReportMessageAt(scanner().location(), "too_many_variables");
+      ReportMessageAt(scanner().location(), "too_many_variables",
+                      Vector<const char*>::empty());
       *ok = false;
       return NULL;
     }
@@ -2241,7 +2232,7 @@ Statement* Parser::ParseContinueStatement(bool* ok) {
       message = "unknown_label";
       args = Vector<Handle<String> >(&label, 1);
     }
-    ParserTraits::ReportMessageAt(scanner().location(), message, args);
+    ReportMessageAt(scanner().location(), message, args);
     *ok = false;
     return NULL;
   }
@@ -2279,7 +2270,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
       message = "unknown_label";
       args = Vector<Handle<String> >(&label, 1);
     }
-    ParserTraits::ReportMessageAt(scanner().location(), message, args);
+    ReportMessageAt(scanner().location(), message, args);
     *ok = false;
     return NULL;
   }
@@ -3022,6 +3013,14 @@ Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
 }
 
 
+int ParserBase::Precedence(Token::Value tok, bool accept_IN) {
+  if (tok == Token::IN && !accept_IN)
+    return 0;  // 0 precedence will terminate binary expression parsing
+
+  return Token::Precedence(tok);
+}
+
+
 // Precedence >= 4
 Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
   ASSERT(prec >= 4);
@@ -3864,7 +3863,8 @@ ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
     Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
     result->Add(argument, zone());
     if (result->length() > Code::kMaxArguments) {
-      ReportMessageAt(scanner().location(), "too_many_arguments");
+      ReportMessageAt(scanner().location(), "too_many_arguments",
+                      Vector<const char*>::empty());
       *ok = false;
       return NULL;
     }
@@ -4095,7 +4095,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
       top_scope_->DeclareParameter(param_name, VAR);
       num_parameters++;
       if (num_parameters > Code::kMaxArguments) {
-        ReportMessageAt(scanner().location(), "too_many_parameters");
+        ReportMessageAt(scanner().location(), "too_many_parameters",
+                        Vector<const char*>::empty());
         *ok = false;
         return NULL;
       }
@@ -4186,10 +4187,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
           if (arg != NULL) {
             args = Vector<const char*>(&arg, 1);
           }
-          ParserTraits::ReportMessageAt(
-              Scanner::Location(logger.start(), logger.end()),
-              logger.message(),
-              args);
+          ReportMessageAt(Scanner::Location(logger.start(), logger.end()),
+                          logger.message(), args);
           *ok = false;
           return NULL;
         }
@@ -4263,27 +4262,33 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
     // since the function can declare itself strict.
     if (!top_scope_->is_classic_mode()) {
       if (IsEvalOrArguments(function_name)) {
-        ReportMessageAt(function_name_location, "strict_eval_arguments");
+        ReportMessageAt(function_name_location,
+                        "strict_eval_arguments",
+                        Vector<const char*>::empty());
         *ok = false;
         return NULL;
       }
       if (name_is_strict_reserved) {
-        ReportMessageAt(function_name_location, "unexpected_strict_reserved");
+        ReportMessageAt(function_name_location, "unexpected_strict_reserved",
+                        Vector<const char*>::empty());
         *ok = false;
         return NULL;
       }
       if (eval_args_error_log.IsValid()) {
-        ReportMessageAt(eval_args_error_log, "strict_eval_arguments");
+        ReportMessageAt(eval_args_error_log, "strict_eval_arguments",
+                        Vector<const char*>::empty());
         *ok = false;
         return NULL;
       }
       if (dupe_error_loc.IsValid()) {
-        ReportMessageAt(dupe_error_loc, "strict_param_dupe");
+        ReportMessageAt(dupe_error_loc, "strict_param_dupe",
+                        Vector<const char*>::empty());
         *ok = false;
         return NULL;
       }
       if (reserved_loc.IsValid()) {
-        ReportMessageAt(reserved_loc, "unexpected_strict_reserved");
+        ReportMessageAt(reserved_loc, "unexpected_strict_reserved",
+                        Vector<const char*>::empty());
         *ok = false;
         return NULL;
       }
@@ -4392,8 +4397,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
 
   // Check that the function is defined if it's an inline runtime call.
   if (function == NULL && name->Get(0) == '_') {
-    ParserTraits::ReportMessage("not_defined",
-                                Vector<Handle<String> >(&name, 1));
+    ReportMessage("not_defined", Vector<Handle<String> >(&name, 1));
     *ok = false;
     return NULL;
   }
@@ -4403,6 +4407,88 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
 }
 
 
+bool ParserBase::peek_any_identifier() {
+  Token::Value next = peek();
+  return next == Token::IDENTIFIER ||
+         next == Token::FUTURE_RESERVED_WORD ||
+         next == Token::FUTURE_STRICT_RESERVED_WORD ||
+         next == Token::YIELD;
+}
+
+
+bool ParserBase::CheckContextualKeyword(Vector<const char> keyword) {
+  if (peek() == Token::IDENTIFIER &&
+      scanner()->is_next_contextual_keyword(keyword)) {
+    Consume(Token::IDENTIFIER);
+    return true;
+  }
+  return false;
+}
+
+
+void ParserBase::ExpectSemicolon(bool* ok) {
+  // Check for automatic semicolon insertion according to
+  // the rules given in ECMA-262, section 7.9, page 21.
+  Token::Value tok = peek();
+  if (tok == Token::SEMICOLON) {
+    Next();
+    return;
+  }
+  if (scanner()->HasAnyLineTerminatorBeforeNext() ||
+      tok == Token::RBRACE ||
+      tok == Token::EOS) {
+    return;
+  }
+  Expect(Token::SEMICOLON, ok);
+}
+
+
+void ParserBase::ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
+  Expect(Token::IDENTIFIER, ok);
+  if (!*ok) return;
+  if (!scanner()->is_literal_contextual_keyword(keyword)) {
+    ReportUnexpectedToken(scanner()->current_token());
+    *ok = false;
+  }
+}
+
+
+void ParserBase::ReportUnexpectedToken(Token::Value token) {
+  // We don't report stack overflows here, to avoid increasing the
+  // stack depth even further.  Instead we report it after parsing is
+  // over, in ParseProgram.
+  if (token == Token::ILLEGAL && stack_overflow()) {
+    return;
+  }
+  Scanner::Location source_location = scanner()->location();
+
+  // Four of the tokens are treated specially
+  switch (token) {
+  case Token::EOS:
+    return ReportMessageAt(source_location, "unexpected_eos");
+  case Token::NUMBER:
+    return ReportMessageAt(source_location, "unexpected_token_number");
+  case Token::STRING:
+    return ReportMessageAt(source_location, "unexpected_token_string");
+  case Token::IDENTIFIER:
+    return ReportMessageAt(source_location,
+                           "unexpected_token_identifier");
+  case Token::FUTURE_RESERVED_WORD:
+    return ReportMessageAt(source_location, "unexpected_reserved");
+  case Token::YIELD:
+  case Token::FUTURE_STRICT_RESERVED_WORD:
+    return ReportMessageAt(source_location,
+                           is_classic_mode() ? "unexpected_token_identifier"
+                                             : "unexpected_strict_reserved");
+  default:
+    const char* name = Token::String(token);
+    ASSERT(name != NULL);
+    ReportMessageAt(
+        source_location, "unexpected_token", Vector<const char*>(&name, 1));
+  }
+}
+
+
 Literal* Parser::GetLiteralUndefined(int position) {
   return factory()->NewLiteral(
       isolate()->factory()->undefined_value(), position);
@@ -4415,6 +4501,68 @@ Literal* Parser::GetLiteralTheHole(int position) {
 }
 
 
+// Parses an identifier that is valid for the current scope, in particular it
+// fails on strict mode future reserved keywords in a strict scope. If
+// allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
+// "arguments" as identifier even in strict mode (this is needed in cases like
+// "var foo = eval;").
+Handle<String> Parser::ParseIdentifier(
+    AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments,
+    bool* ok) {
+  Token::Value next = Next();
+  if (next == Token::IDENTIFIER) {
+    Handle<String> name = GetSymbol();
+    if (allow_eval_or_arguments == kDontAllowEvalOrArguments &&
+        !top_scope_->is_classic_mode() && IsEvalOrArguments(name)) {
+      ReportMessage("strict_eval_arguments", Vector<const char*>::empty());
+      *ok = false;
+    }
+    return name;
+  } else if (top_scope_->is_classic_mode() &&
+             (next == Token::FUTURE_STRICT_RESERVED_WORD ||
+              (next == Token::YIELD && !is_generator()))) {
+    return GetSymbol();
+  } else {
+    ReportUnexpectedToken(next);
+    *ok = false;
+    return Handle<String>();
+  }
+}
+
+
+// Parses and identifier or a strict mode future reserved word, and indicate
+// whether it is strict mode future reserved.
+Handle<String> Parser::ParseIdentifierOrStrictReservedWord(
+    bool* is_strict_reserved, bool* ok) {
+  Token::Value next = Next();
+  if (next == Token::IDENTIFIER) {
+    *is_strict_reserved = false;
+  } else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
+             (next == Token::YIELD && !is_generator())) {
+    *is_strict_reserved = true;
+  } else {
+    ReportUnexpectedToken(next);
+    *ok = false;
+    return Handle<String>();
+  }
+  return GetSymbol();
+}
+
+
+Handle<String> Parser::ParseIdentifierName(bool* ok) {
+  Token::Value next = Next();
+  if (next != Token::IDENTIFIER &&
+      next != Token::FUTURE_RESERVED_WORD &&
+      next != Token::FUTURE_STRICT_RESERVED_WORD &&
+      !Token::IsKeyword(next)) {
+    ReportUnexpectedToken(next);
+    *ok = false;
+    return Handle<String>();
+  }
+  return GetSymbol();
+}
+
+
 void Parser::MarkAsLValue(Expression* expression) {
   VariableProxy* proxy = expression != NULL
       ? expression->AsVariableProxy()
@@ -4440,6 +4588,18 @@ void Parser::CheckStrictModeLValue(Expression* expression,
 }
 
 
+// Checks whether an octal literal was last seen between beg_pos and end_pos.
+// If so, reports an error. Only called for strict mode.
+void ParserBase::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
+  Scanner::Location octal = scanner()->octal_position();
+  if (octal.IsValid() && beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
+    ReportMessageAt(octal, "strict_octal_literal");
+    scanner()->clear_octal_position();
+    *ok = false;
+  }
+}
+
+
 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
   Declaration* decl = scope->CheckConflictingVarDeclarations();
   if (decl != NULL) {
@@ -4453,12 +4613,28 @@ void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
     Scanner::Location location = position == RelocInfo::kNoPosition
         ? Scanner::Location::invalid()
         : Scanner::Location(position, position + 1);
-    ParserTraits::ReportMessageAt(location, "redeclaration", args);
+    ReportMessageAt(location, "redeclaration", args);
     *ok = false;
   }
 }
 
 
+// This function reads an identifier name and determines whether or not it
+// is 'get' or 'set'.
+Handle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get,
+                                                     bool* is_set,
+                                                     bool* ok) {
+  Handle<String> result = ParseIdentifierName(ok);
+  if (!*ok) return Handle<String>();
+  if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
+    const char* token = scanner().literal_ascii_string().start();
+    *is_get = strncmp(token, "get", 3) == 0;
+    *is_set = !*is_get && strncmp(token, "set", 3) == 0;
+  }
+  return result;
+}
+
+
 // ----------------------------------------------------------------------------
 // Parser support
 
@@ -5507,7 +5683,7 @@ bool Parser::Parse() {
       Scanner::Location loc = pre_parse_data->MessageLocation();
       const char* message = pre_parse_data->BuildMessage();
       Vector<const char*> args = pre_parse_data->BuildArgs();
-      ParserTraits::ReportMessageAt(loc, message, args);
+      ReportMessageAt(loc, message, args);
       DeleteArray(message);
       for (int i = 0; i < args.length(); i++) {
         DeleteArray(args[i]);
index 64513d3..2b0995a 100644 (file)
@@ -404,44 +404,10 @@ class RegExpParser BASE_EMBEDDED {
 // ----------------------------------------------------------------------------
 // JAVASCRIPT PARSING
 
-class Parser;
+// Forward declaration.
 class SingletonLogger;
 
-class ParserTraits {
- public:
-  typedef Parser* ParserType;
-  // Return types for traversing functions.
-  typedef Handle<String> IdentifierType;
-
-  explicit ParserTraits(Parser* parser) : parser_(parser) {}
-
-  // Helper functions for recursive descent.
-  bool is_classic_mode() const;
-  bool is_generator() const;
-  bool IsEvalOrArguments(Handle<String> identifier) const;
-
-  // Reporting errors.
-  void ReportMessageAt(Scanner::Location source_location,
-                       const char* message,
-                       Vector<const char*> args);
-  void ReportMessage(const char* message, Vector<Handle<String> > args);
-  void ReportMessageAt(Scanner::Location source_location,
-                       const char* message,
-                       Vector<Handle<String> > args);
-
-  // Identifiers:
-  static IdentifierType EmptyIdentifier() {
-    return Handle<String>();
-  }
-
-  IdentifierType GetSymbol();
-
- private:
-  Parser* parser_;
-};
-
-
-class Parser : public ParserBase<ParserTraits> {
+class Parser : public ParserBase {
  public:
   explicit Parser(CompilationInfo* info);
   ~Parser() {
@@ -461,8 +427,6 @@ class Parser : public ParserBase<ParserTraits> {
   bool Parse();
 
  private:
-  friend class ParserTraits;
-
   static const int kMaxNumFunctionLocals = 131071;  // 2^17-1
 
   enum Mode {
@@ -557,6 +521,10 @@ class Parser : public ParserBase<ParserTraits> {
     Mode old_mode_;
   };
 
+  virtual bool is_classic_mode() {
+    return top_scope_->is_classic_mode();
+  }
+
   // Returns NULL if parsing failed.
   FunctionLiteral* ParseProgram();
 
@@ -573,6 +541,17 @@ class Parser : public ParserBase<ParserTraits> {
 
   // Report syntax error
   void ReportInvalidPreparseData(Handle<String> name, bool* ok);
+  void ReportMessage(const char* message, Vector<const char*> args);
+  void ReportMessage(const char* message, Vector<Handle<String> > args);
+  void ReportMessageAt(Scanner::Location location, const char* type) {
+    ReportMessageAt(location, type, Vector<const char*>::empty());
+  }
+  void ReportMessageAt(Scanner::Location loc,
+                       const char* message,
+                       Vector<const char*> args);
+  void ReportMessageAt(Scanner::Location loc,
+                       const char* message,
+                       Vector<Handle<String> > args);
 
   void set_pre_parse_data(ScriptDataImpl *data) {
     pre_parse_data_ = data;
@@ -592,6 +571,9 @@ class Parser : public ParserBase<ParserTraits> {
         ? top_scope_ : top_scope_->DeclarationScope();
   }
 
+  // Check if the given string is 'eval' or 'arguments'.
+  bool IsEvalOrArguments(Handle<String> string);
+
   // All ParseXXX functions take as the last argument an *ok parameter
   // which is set to false if parsing failed; it is unchanged otherwise.
   // By making the 'exception handling' explicit, we are forced to check
@@ -678,6 +660,8 @@ class Parser : public ParserBase<ParserTraits> {
   // Magical syntax support.
   Expression* ParseV8Intrinsic(bool* ok);
 
+  bool is_generator() const { return current_function_state_->is_generator(); }
+
   bool CheckInOrOf(bool accept_OF, ForEachStatement::VisitMode* visit_mode);
 
   Handle<String> LiteralString(PretenureFlag tenured) {
@@ -700,10 +684,20 @@ class Parser : public ParserBase<ParserTraits> {
     }
   }
 
+  Handle<String> GetSymbol();
+
   // Get odd-ball literals.
   Literal* GetLiteralUndefined(int position);
   Literal* GetLiteralTheHole(int position);
 
+  Handle<String> ParseIdentifier(AllowEvalOrArgumentsAsIdentifier, bool* ok);
+  Handle<String> ParseIdentifierOrStrictReservedWord(
+      bool* is_strict_reserved, bool* ok);
+  Handle<String> ParseIdentifierName(bool* ok);
+  Handle<String> ParseIdentifierNameOrGetOrSet(bool* is_get,
+                                               bool* is_set,
+                                               bool* ok);
+
   // Determine if the expression is a variable proxy and mark it as being used
   // in an assignment or with a increment/decrement operator. This is currently
   // used on for the statically checking assignments to harmony const bindings.
index c01acdd..fa6f217 100644 (file)
@@ -55,68 +55,6 @@ int isfinite(double value);
 namespace v8 {
 namespace internal {
 
-bool PreParserTraits::is_classic_mode() const {
-  return pre_parser_->scope_->language_mode() == CLASSIC_MODE;
-}
-
-
-bool PreParserTraits::is_generator() const {
-  return pre_parser_->scope_->is_generator();
-}
-
-
-void PreParserTraits::ReportMessageAt(Scanner::Location location,
-                                      const char* message,
-                                      Vector<const char*> args) {
-  ReportMessageAt(location.beg_pos,
-                  location.end_pos,
-                  message,
-                  args.length() > 0 ? args[0] : NULL);
-}
-
-
-void PreParserTraits::ReportMessageAt(Scanner::Location location,
-                                      const char* type,
-                                      const char* name_opt) {
-  pre_parser_->log_
-      ->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
-}
-
-
-void PreParserTraits::ReportMessageAt(int start_pos,
-                                      int end_pos,
-                                      const char* type,
-                                      const char* name_opt) {
-  pre_parser_->log_->LogMessage(start_pos, end_pos, type, name_opt);
-}
-
-
-PreParserIdentifier PreParserTraits::GetSymbol() {
-  Scanner* scanner = pre_parser_->scanner();
-  pre_parser_->LogSymbol();
-  if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) {
-    return PreParserIdentifier::FutureReserved();
-  } else if (scanner->current_token() ==
-             Token::FUTURE_STRICT_RESERVED_WORD) {
-    return PreParserIdentifier::FutureStrictReserved();
-  } else if (scanner->current_token() == Token::YIELD) {
-    return PreParserIdentifier::Yield();
-  }
-  if (scanner->is_literal_ascii()) {
-    // Detect strict-mode poison words.
-    if (scanner->literal_length() == 4 &&
-        !strncmp(scanner->literal_ascii_string().start(), "eval", 4)) {
-      return PreParserIdentifier::Eval();
-    }
-    if (scanner->literal_length() == 9 &&
-        !strncmp(scanner->literal_ascii_string().start(), "arguments", 9)) {
-      return PreParserIdentifier::Arguments();
-    }
-  }
-  return PreParserIdentifier::Default();
-}
-
-
 PreParser::PreParseResult PreParser::PreParseLazyFunction(
     LanguageMode mode, bool is_generator, ParserRecorder* log) {
   log_ = log;
@@ -297,10 +235,8 @@ PreParser::Statement PreParser::ParseStatement(bool* ok) {
       Statement statement = ParseFunctionDeclaration(CHECK_OK);
       Scanner::Location end_location = scanner()->location();
       if (!scope_->is_classic_mode()) {
-        PreParserTraits::ReportMessageAt(start_location.beg_pos,
-                                         end_location.end_pos,
-                                         "strict_function",
-                                         NULL);
+        ReportMessageAt(start_location.beg_pos, end_location.end_pos,
+                        "strict_function", NULL);
         *ok = false;
         return Statement::Default();
       } else {
@@ -416,14 +352,16 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
         break;
       case STRICT_MODE: {
         Scanner::Location location = scanner()->peek_location();
-        ReportMessageAt(location, "strict_const");
+        ReportMessageAt(location, "strict_const", NULL);
         *ok = false;
         return Statement::Default();
       }
       case EXTENDED_MODE:
         if (var_context != kSourceElement &&
             var_context != kForStatement) {
-          ReportMessageAt(scanner()->peek_location(), "unprotected_const");
+          Scanner::Location location = scanner()->peek_location();
+          ReportMessageAt(location.beg_pos, location.end_pos,
+                          "unprotected_const", NULL);
           *ok = false;
           return Statement::Default();
         }
@@ -438,14 +376,18 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
     // * It is a Syntax Error if the code that matches this production is not
     //   contained in extended code.
     if (!is_extended_mode()) {
-      ReportMessageAt(scanner()->peek_location(), "illegal_let");
+      Scanner::Location location = scanner()->peek_location();
+      ReportMessageAt(location.beg_pos, location.end_pos,
+                      "illegal_let", NULL);
       *ok = false;
       return Statement::Default();
     }
     Consume(Token::LET);
     if (var_context != kSourceElement &&
         var_context != kForStatement) {
-      ReportMessageAt(scanner()->peek_location(), "unprotected_let");
+      Scanner::Location location = scanner()->peek_location();
+      ReportMessageAt(location.beg_pos, location.end_pos,
+                      "unprotected_let", NULL);
       *ok = false;
       return Statement::Default();
     }
@@ -589,7 +531,8 @@ PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
   //   'with' '(' Expression ')' Statement
   Expect(Token::WITH, CHECK_OK);
   if (!scope_->is_classic_mode()) {
-    ReportMessageAt(scanner()->location(), "strict_mode_with");
+    Scanner::Location location = scanner()->location();
+    ReportMessageAt(location, "strict_mode_with", NULL);
     *ok = false;
     return Statement::Default();
   }
@@ -733,7 +676,8 @@ PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
 
   Expect(Token::THROW, CHECK_OK);
   if (scanner()->HasAnyLineTerminatorBeforeNext()) {
-    ReportMessageAt(scanner()->location(), "newline_after_throw");
+    Scanner::Location pos = scanner()->location();
+    ReportMessageAt(pos, "newline_after_throw", NULL);
     *ok = false;
     return Statement::Default();
   }
@@ -761,7 +705,7 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
 
   Token::Value tok = peek();
   if (tok != Token::CATCH && tok != Token::FINALLY) {
-    ReportMessageAt(scanner()->location(), "no_catch_or_finally");
+    ReportMessageAt(scanner()->location(), "no_catch_or_finally", NULL);
     *ok = false;
     return Statement::Default();
   }
@@ -844,8 +788,8 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
       expression.IsIdentifier() &&
       expression.AsIdentifier().IsEvalOrArguments()) {
     Scanner::Location after = scanner()->location();
-    PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos,
-                                     "strict_eval_arguments", NULL);
+    ReportMessageAt(before.beg_pos, after.end_pos,
+                    "strict_eval_arguments", NULL);
     *ok = false;
     return Expression::Default();
   }
@@ -938,8 +882,8 @@ PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
         expression.IsIdentifier() &&
         expression.AsIdentifier().IsEvalOrArguments()) {
       Scanner::Location after = scanner()->location();
-      PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos,
-                                       "strict_eval_arguments", NULL);
+      ReportMessageAt(before.beg_pos, after.end_pos,
+                      "strict_eval_arguments", NULL);
       *ok = false;
     }
     return Expression::Default();
@@ -961,8 +905,8 @@ PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
         expression.IsIdentifier() &&
         expression.AsIdentifier().IsEvalOrArguments()) {
       Scanner::Location after = scanner()->location();
-      PreParserTraits::ReportMessageAt(before.beg_pos, after.end_pos,
-                                       "strict_eval_arguments", NULL);
+      ReportMessageAt(before.beg_pos, after.end_pos,
+                      "strict_eval_arguments", NULL);
       *ok = false;
       return Expression::Default();
     }
@@ -1305,7 +1249,7 @@ PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
                                                     bool* ok) {
   if (!scanner()->ScanRegExpPattern(seen_equal)) {
     Next();
-    ReportMessageAt(scanner()->location(), "unterminated_regexp");
+    ReportMessageAt(scanner()->location(), "unterminated_regexp", NULL);
     *ok = false;
     return Expression::Default();
   }
@@ -1314,7 +1258,7 @@ PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
 
   if (!scanner()->ScanRegExpFlags()) {
     Next();
-    ReportMessageAt(scanner()->location(), "invalid_regexp_flags");
+    ReportMessageAt(scanner()->location(), "invalid_regexp_flags", NULL);
     *ok = false;
     return Expression::Default();
   }
@@ -1422,27 +1366,31 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
   // since the function can declare itself strict.
   if (!scope_->is_classic_mode()) {
     if (function_name.IsEvalOrArguments()) {
-      ReportMessageAt(function_name_location, "strict_eval_arguments");
+      ReportMessageAt(function_name_location, "strict_eval_arguments", NULL);
       *ok = false;
       return Expression::Default();
     }
     if (name_is_strict_reserved) {
-      ReportMessageAt(function_name_location, "unexpected_strict_reserved");
+      ReportMessageAt(
+          function_name_location, "unexpected_strict_reserved", NULL);
       *ok = false;
       return Expression::Default();
     }
     if (eval_args_error_loc.IsValid()) {
-      ReportMessageAt(eval_args_error_loc, "strict_eval_arguments");
+      ReportMessageAt(eval_args_error_loc, "strict_eval_arguments",
+                      Vector<const char*>::empty());
       *ok = false;
       return Expression::Default();
     }
     if (dupe_error_loc.IsValid()) {
-      ReportMessageAt(dupe_error_loc, "strict_param_dupe");
+      ReportMessageAt(dupe_error_loc, "strict_param_dupe",
+                      Vector<const char*>::empty());
       *ok = false;
       return Expression::Default();
     }
     if (reserved_error_loc.IsValid()) {
-      ReportMessageAt(reserved_error_loc, "unexpected_strict_reserved");
+      ReportMessageAt(reserved_error_loc, "unexpected_strict_reserved",
+                      Vector<const char*>::empty());
       *ok = false;
       return Expression::Default();
     }
@@ -1516,4 +1464,142 @@ PreParser::Expression PreParser::GetStringSymbol() {
 }
 
 
+PreParser::Identifier PreParser::GetIdentifierSymbol() {
+  LogSymbol();
+  if (scanner()->current_token() == Token::FUTURE_RESERVED_WORD) {
+    return Identifier::FutureReserved();
+  } else if (scanner()->current_token() ==
+             Token::FUTURE_STRICT_RESERVED_WORD) {
+    return Identifier::FutureStrictReserved();
+  } else if (scanner()->current_token() == Token::YIELD) {
+    return Identifier::Yield();
+  }
+  if (scanner()->is_literal_ascii()) {
+    // Detect strict-mode poison words.
+    if (scanner()->literal_length() == 4 &&
+        !strncmp(scanner()->literal_ascii_string().start(), "eval", 4)) {
+      return Identifier::Eval();
+    }
+    if (scanner()->literal_length() == 9 &&
+        !strncmp(scanner()->literal_ascii_string().start(), "arguments", 9)) {
+      return Identifier::Arguments();
+    }
+  }
+  return Identifier::Default();
+}
+
+
+// Parses an identifier that is valid for the current scope, in particular it
+// fails on strict mode future reserved keywords in a strict scope. If
+// allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
+// "arguments" as identifier even in strict mode (this is needed in cases like
+// "var foo = eval;").
+PreParser::Identifier PreParser::ParseIdentifier(
+    AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments,
+    bool* ok) {
+  Token::Value next = Next();
+  if (next == Token::IDENTIFIER) {
+    PreParser::Identifier name = GetIdentifierSymbol();
+    if (allow_eval_or_arguments == kDontAllowEvalOrArguments &&
+        !scope_->is_classic_mode() && name.IsEvalOrArguments()) {
+      ReportMessageAt(scanner()->location(), "strict_eval_arguments", NULL);
+      *ok = false;
+    }
+    return name;
+  } else if (scope_->is_classic_mode() &&
+             (next == Token::FUTURE_STRICT_RESERVED_WORD ||
+              (next == Token::YIELD && !scope_->is_generator()))) {
+    return GetIdentifierSymbol();
+  } else {
+    ReportUnexpectedToken(next);
+    *ok = false;
+    return Identifier::Default();
+  }
+}
+
+
+// Parses and identifier or a strict mode future reserved word, and indicate
+// whether it is strict mode future reserved.
+PreParser::Identifier PreParser::ParseIdentifierOrStrictReservedWord(
+    bool* is_strict_reserved, bool* ok) {
+  Token::Value next = Next();
+  if (next == Token::IDENTIFIER) {
+    *is_strict_reserved = false;
+  } else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
+             (next == Token::YIELD && !scope_->is_generator())) {
+    *is_strict_reserved = true;
+  } else {
+    ReportUnexpectedToken(next);
+    *ok = false;
+    return Identifier::Default();
+  }
+  return GetIdentifierSymbol();
+}
+
+
+PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
+  Token::Value next = Next();
+  if (next != Token::IDENTIFIER &&
+      next != Token::FUTURE_RESERVED_WORD &&
+      next != Token::FUTURE_STRICT_RESERVED_WORD &&
+      !Token::IsKeyword(next)) {
+    ReportUnexpectedToken(next);
+    *ok = false;
+    return Identifier::Default();
+  }
+  return GetIdentifierSymbol();
+}
+
+#undef CHECK_OK
+
+
+// This function reads an identifier and determines whether or not it
+// is 'get' or 'set'.
+PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get,
+                                                               bool* is_set,
+                                                               bool* ok) {
+  Identifier result = ParseIdentifierName(ok);
+  if (!*ok) return Identifier::Default();
+  if (scanner()->is_literal_ascii() &&
+      scanner()->literal_length() == 3) {
+    const char* token = scanner()->literal_ascii_string().start();
+    *is_get = strncmp(token, "get", 3) == 0;
+    *is_set = !*is_get && strncmp(token, "set", 3) == 0;
+  }
+  return result;
+}
+
+
+void PreParser::ObjectLiteralChecker::CheckProperty(Token::Value property,
+                                                    PropertyKind type,
+                                                    bool* ok) {
+  int old;
+  if (property == Token::NUMBER) {
+    old = finder_.AddNumber(scanner()->literal_ascii_string(), type);
+  } else if (scanner()->is_literal_ascii()) {
+    old = finder_.AddAsciiSymbol(scanner()->literal_ascii_string(), type);
+  } else {
+    old = finder_.AddUtf16Symbol(scanner()->literal_utf16_string(), type);
+  }
+  PropertyKind old_type = static_cast<PropertyKind>(old);
+  if (HasConflict(old_type, type)) {
+    if (IsDataDataConflict(old_type, type)) {
+      // Both are data properties.
+      if (language_mode_ == CLASSIC_MODE) return;
+      parser()->ReportMessageAt(scanner()->location(),
+                               "strict_duplicate_property");
+    } else if (IsDataAccessorConflict(old_type, type)) {
+      // Both a data and an accessor property with the same name.
+      parser()->ReportMessageAt(scanner()->location(),
+                               "accessor_data_property");
+    } else {
+      ASSERT(IsAccessorAccessorConflict(old_type, type));
+      // Both accessors of the same type.
+      parser()->ReportMessageAt(scanner()->location(),
+                               "accessor_get_set");
+    }
+    *ok = false;
+  }
+}
+
 } }  // v8::internal
index 62ac5b8..bcaab74 100644 (file)
@@ -36,19 +36,18 @@ namespace v8 {
 namespace internal {
 
 // Common base class shared between parser and pre-parser.
-template <typename Traits>
-class ParserBase : public Traits {
+class ParserBase {
  public:
-  ParserBase(Scanner* scanner, uintptr_t stack_limit,
-             typename Traits::ParserType this_object)
-      : Traits(this_object),
-        scanner_(scanner),
+  ParserBase(Scanner* scanner, uintptr_t stack_limit)
+      : scanner_(scanner),
         stack_limit_(stack_limit),
         stack_overflow_(false),
         allow_lazy_(false),
         allow_natives_syntax_(false),
         allow_generators_(false),
         allow_for_of_(false) { }
+  // TODO(mstarzinger): Only virtual until message reporting has been unified.
+  virtual ~ParserBase() { }
 
   // Getters that indicate whether certain syntactical constructs are
   // allowed to be parsed by this instance of the parser.
@@ -88,6 +87,8 @@ class ParserBase : public Traits {
   bool stack_overflow() const { return stack_overflow_; }
   void set_stack_overflow() { stack_overflow_ = true; }
 
+  virtual bool is_classic_mode() = 0;
+
   INLINE(Token::Value peek()) {
     if (stack_overflow_) return Token::ILLEGAL;
     return scanner()->peek();
@@ -131,99 +132,25 @@ class ParserBase : public Traits {
     }
   }
 
-  void ExpectSemicolon(bool* ok) {
-    // Check for automatic semicolon insertion according to
-    // the rules given in ECMA-262, section 7.9, page 21.
-    Token::Value tok = peek();
-    if (tok == Token::SEMICOLON) {
-      Next();
-      return;
-    }
-    if (scanner()->HasAnyLineTerminatorBeforeNext() ||
-        tok == Token::RBRACE ||
-        tok == Token::EOS) {
-      return;
-    }
-    Expect(Token::SEMICOLON, ok);
-  }
-
-  bool peek_any_identifier() {
-    Token::Value next = peek();
-    return next == Token::IDENTIFIER ||
-        next == Token::FUTURE_RESERVED_WORD ||
-        next == Token::FUTURE_STRICT_RESERVED_WORD ||
-        next == Token::YIELD;
-  }
+  bool peek_any_identifier();
+  void ExpectSemicolon(bool* ok);
+  bool CheckContextualKeyword(Vector<const char> keyword);
+  void ExpectContextualKeyword(Vector<const char> keyword, bool* ok);
 
-  bool CheckContextualKeyword(Vector<const char> keyword) {
-    if (peek() == Token::IDENTIFIER &&
-        scanner()->is_next_contextual_keyword(keyword)) {
-      Consume(Token::IDENTIFIER);
-      return true;
-    }
-    return false;
-  }
-
-  void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
-    Expect(Token::IDENTIFIER, ok);
-    if (!*ok) return;
-    if (!scanner()->is_literal_contextual_keyword(keyword)) {
-      ReportUnexpectedToken(scanner()->current_token());
-      *ok = false;
-    }
-  }
-
-  // Checks whether an octal literal was last seen between beg_pos and end_pos.
-  // If so, reports an error. Only called for strict mode.
-  void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
-    Scanner::Location octal = scanner()->octal_position();
-    if (octal.IsValid() && beg_pos <= octal.beg_pos &&
-        octal.end_pos <= end_pos) {
-      ReportMessageAt(octal, "strict_octal_literal");
-      scanner()->clear_octal_position();
-      *ok = false;
-    }
-  }
+  // Strict mode octal literal validation.
+  void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);
 
   // Determine precedence of given token.
-  static int Precedence(Token::Value token, bool accept_IN) {
-    if (token == Token::IN && !accept_IN)
-      return 0;  // 0 precedence will terminate binary expression parsing
-    return Token::Precedence(token);
-  }
+  static int Precedence(Token::Value token, bool accept_IN);
 
   // Report syntax errors.
-  void ReportMessage(const char* message, Vector<const char*> args) {
-    Scanner::Location source_location = scanner()->location();
-    Traits::ReportMessageAt(source_location, message, args);
-  }
-
-  void ReportMessageAt(Scanner::Location location, const char* message) {
-    Traits::ReportMessageAt(location, message, Vector<const char*>::empty());
-  }
-
   void ReportUnexpectedToken(Token::Value token);
-
-  // Recursive descent functions:
-
-  // Parses an identifier that is valid for the current scope, in particular it
-  // fails on strict mode future reserved keywords in a strict scope. If
-  // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
-  // "arguments" as identifier even in strict mode (this is needed in cases like
-  // "var foo = eval;").
-  typename Traits::IdentifierType ParseIdentifier(
-      AllowEvalOrArgumentsAsIdentifier,
-      bool* ok);
-  // Parses an identifier or a strict mode future reserved word, and indicate
-  // whether it is strict mode future reserved.
-  typename Traits::IdentifierType ParseIdentifierOrStrictReservedWord(
-      bool* is_strict_reserved,
-      bool* ok);
-  typename Traits::IdentifierType ParseIdentifierName(bool* ok);
-  // Parses an identifier and determines whether or not it is 'get' or 'set'.
-  typename Traits::IdentifierType ParseIdentifierNameOrGetOrSet(bool* is_get,
-                                                                bool* is_set,
-                                                                bool* ok);
+  void ReportMessageAt(Scanner::Location location, const char* type) {
+    ReportMessageAt(location, type, Vector<const char*>::empty());
+  }
+  virtual void ReportMessageAt(Scanner::Location source_location,
+                               const char* message,
+                               Vector<const char*> args) = 0;
 
   // Used to detect duplicates in object literals. Each of the values
   // kGetterProperty, kSetterProperty and kValueProperty represents
@@ -291,176 +218,6 @@ class ParserBase : public Traits {
 };
 
 
-class PreParserIdentifier {
- public:
-  static PreParserIdentifier Default() {
-    return PreParserIdentifier(kUnknownIdentifier);
-  }
-  static PreParserIdentifier Eval() {
-    return PreParserIdentifier(kEvalIdentifier);
-  }
-  static PreParserIdentifier Arguments() {
-    return PreParserIdentifier(kArgumentsIdentifier);
-  }
-  static PreParserIdentifier FutureReserved() {
-    return PreParserIdentifier(kFutureReservedIdentifier);
-  }
-  static PreParserIdentifier FutureStrictReserved() {
-    return PreParserIdentifier(kFutureStrictReservedIdentifier);
-  }
-  static PreParserIdentifier Yield() {
-    return PreParserIdentifier(kYieldIdentifier);
-  }
-  bool IsEval() { return type_ == kEvalIdentifier; }
-  bool IsArguments() { return type_ == kArgumentsIdentifier; }
-  bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
-  bool IsYield() { return type_ == kYieldIdentifier; }
-  bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
-  bool IsFutureStrictReserved() {
-    return type_ == kFutureStrictReservedIdentifier;
-  }
-  bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; }
-
- private:
-  enum Type {
-    kUnknownIdentifier,
-    kFutureReservedIdentifier,
-    kFutureStrictReservedIdentifier,
-    kYieldIdentifier,
-    kEvalIdentifier,
-    kArgumentsIdentifier
-  };
-  explicit PreParserIdentifier(Type type) : type_(type) {}
-  Type type_;
-
-  friend class PreParserExpression;
-};
-
-
-// Bits 0 and 1 are used to identify the type of expression:
-// If bit 0 is set, it's an identifier.
-// if bit 1 is set, it's a string literal.
-// If neither is set, it's no particular type, and both set isn't
-// use yet.
-class PreParserExpression {
- public:
-  static PreParserExpression Default() {
-    return PreParserExpression(kUnknownExpression);
-  }
-
-  static PreParserExpression FromIdentifier(PreParserIdentifier id) {
-    return PreParserExpression(kIdentifierFlag |
-                               (id.type_ << kIdentifierShift));
-  }
-
-  static PreParserExpression StringLiteral() {
-    return PreParserExpression(kUnknownStringLiteral);
-  }
-
-  static PreParserExpression UseStrictStringLiteral() {
-    return PreParserExpression(kUseStrictString);
-  }
-
-  static PreParserExpression This() {
-    return PreParserExpression(kThisExpression);
-  }
-
-  static PreParserExpression ThisProperty() {
-    return PreParserExpression(kThisPropertyExpression);
-  }
-
-  static PreParserExpression StrictFunction() {
-    return PreParserExpression(kStrictFunctionExpression);
-  }
-
-  bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; }
-
-  // Only works corretly if it is actually an identifier expression.
-  PreParserIdentifier AsIdentifier() {
-    return PreParserIdentifier(
-        static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift));
-  }
-
-  bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
-
-  bool IsUseStrictLiteral() {
-    return (code_ & kStringLiteralMask) == kUseStrictString;
-  }
-
-  bool IsThis() { return code_ == kThisExpression; }
-
-  bool IsThisProperty() { return code_ == kThisPropertyExpression; }
-
-  bool IsStrictFunction() { return code_ == kStrictFunctionExpression; }
-
- private:
-  // First two/three bits are used as flags.
-  // Bit 0 and 1 represent identifiers or strings literals, and are
-  // mutually exclusive, but can both be absent.
-  enum {
-    kUnknownExpression = 0,
-    // Identifiers
-    kIdentifierFlag = 1,  // Used to detect labels.
-    kIdentifierShift = 3,
-
-    kStringLiteralFlag = 2,  // Used to detect directive prologue.
-    kUnknownStringLiteral = kStringLiteralFlag,
-    kUseStrictString = kStringLiteralFlag | 8,
-    kStringLiteralMask = kUseStrictString,
-
-    // Below here applies if neither identifier nor string literal.
-    kThisExpression = 4,
-    kThisPropertyExpression = 8,
-    kStrictFunctionExpression = 12
-  };
-
-  explicit PreParserExpression(int expression_code) : code_(expression_code) {}
-
-  int code_;
-};
-
-class PreParser;
-
-
-class PreParserTraits {
- public:
-  typedef PreParser* ParserType;
-  // Return types for traversing functions.
-  typedef PreParserIdentifier IdentifierType;
-
-  explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
-
-  // Helper functions for recursive descent.
-  bool is_classic_mode() const;
-  bool is_generator() const;
-  static bool IsEvalOrArguments(IdentifierType identifier) {
-    return identifier.IsEvalOrArguments();
-  }
-
-  // Reporting errors.
-  void ReportMessageAt(Scanner::Location location,
-                       const char* message,
-                       Vector<const char*> args);
-  void ReportMessageAt(Scanner::Location location,
-                       const char* type,
-                       const char* name_opt);
-  void ReportMessageAt(int start_pos,
-                       int end_pos,
-                       const char* type,
-                       const char* name_opt);
-
-  // Identifiers:
-  static IdentifierType EmptyIdentifier() {
-    return PreParserIdentifier::Default();
-  }
-
-  IdentifierType GetSymbol();
-
- private:
-  PreParser* pre_parser_;
-};
-
-
 // Preparsing checks a JavaScript program and emits preparse-data that helps
 // a later parsing to be faster.
 // See preparse-data-format.h for the data format.
@@ -473,11 +230,8 @@ class PreParserTraits {
 // rather it is to speed up properly written and correct programs.
 // That means that contextual checks (like a label being declared where
 // it is used) are generally omitted.
-class PreParser : public ParserBase<PreParserTraits> {
+class PreParser : public ParserBase {
  public:
-  typedef PreParserIdentifier Identifier;
-  typedef PreParserExpression Expression;
-
   enum PreParseResult {
     kPreParseStackOverflow,
     kPreParseSuccess
@@ -486,7 +240,7 @@ class PreParser : public ParserBase<PreParserTraits> {
   PreParser(Scanner* scanner,
             ParserRecorder* log,
             uintptr_t stack_limit)
-      : ParserBase(scanner, stack_limit, this),
+      : ParserBase(scanner, stack_limit),
         log_(log),
         scope_(NULL),
         parenthesized_function_(false) { }
@@ -524,8 +278,6 @@ class PreParser : public ParserBase<PreParserTraits> {
                                       ParserRecorder* log);
 
  private:
-  friend class PreParserTraits;
-
   // These types form an algebra over syntactic categories that is just
   // rich enough to let us recognize and propagate the constructs that
   // are either being counted in the preparser data, or is important
@@ -548,6 +300,142 @@ class PreParser : public ParserBase<PreParserTraits> {
     kHasNoInitializers
   };
 
+  class Expression;
+
+  class Identifier {
+   public:
+    static Identifier Default() {
+      return Identifier(kUnknownIdentifier);
+    }
+    static Identifier Eval()  {
+      return Identifier(kEvalIdentifier);
+    }
+    static Identifier Arguments()  {
+      return Identifier(kArgumentsIdentifier);
+    }
+    static Identifier FutureReserved()  {
+      return Identifier(kFutureReservedIdentifier);
+    }
+    static Identifier FutureStrictReserved()  {
+      return Identifier(kFutureStrictReservedIdentifier);
+    }
+    static Identifier Yield()  {
+      return Identifier(kYieldIdentifier);
+    }
+    bool IsEval() { return type_ == kEvalIdentifier; }
+    bool IsArguments() { return type_ == kArgumentsIdentifier; }
+    bool IsEvalOrArguments() { return type_ >= kEvalIdentifier; }
+    bool IsYield() { return type_ == kYieldIdentifier; }
+    bool IsFutureReserved() { return type_ == kFutureReservedIdentifier; }
+    bool IsFutureStrictReserved() {
+      return type_ == kFutureStrictReservedIdentifier;
+    }
+    bool IsValidStrictVariable() { return type_ == kUnknownIdentifier; }
+
+   private:
+    enum Type {
+      kUnknownIdentifier,
+      kFutureReservedIdentifier,
+      kFutureStrictReservedIdentifier,
+      kYieldIdentifier,
+      kEvalIdentifier,
+      kArgumentsIdentifier
+    };
+    explicit Identifier(Type type) : type_(type) { }
+    Type type_;
+
+    friend class Expression;
+  };
+
+  // Bits 0 and 1 are used to identify the type of expression:
+  // If bit 0 is set, it's an identifier.
+  // if bit 1 is set, it's a string literal.
+  // If neither is set, it's no particular type, and both set isn't
+  // use yet.
+  class Expression {
+   public:
+    static Expression Default() {
+      return Expression(kUnknownExpression);
+    }
+
+    static Expression FromIdentifier(Identifier id) {
+      return Expression(kIdentifierFlag | (id.type_ << kIdentifierShift));
+    }
+
+    static Expression StringLiteral() {
+      return Expression(kUnknownStringLiteral);
+    }
+
+    static Expression UseStrictStringLiteral() {
+      return Expression(kUseStrictString);
+    }
+
+    static Expression This() {
+      return Expression(kThisExpression);
+    }
+
+    static Expression ThisProperty() {
+      return Expression(kThisPropertyExpression);
+    }
+
+    static Expression StrictFunction() {
+      return Expression(kStrictFunctionExpression);
+    }
+
+    bool IsIdentifier() {
+      return (code_ & kIdentifierFlag) != 0;
+    }
+
+    // Only works corretly if it is actually an identifier expression.
+    PreParser::Identifier AsIdentifier() {
+      return PreParser::Identifier(
+          static_cast<PreParser::Identifier::Type>(code_ >> kIdentifierShift));
+    }
+
+    bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
+
+    bool IsUseStrictLiteral() {
+      return (code_ & kStringLiteralMask) == kUseStrictString;
+    }
+
+    bool IsThis() {
+      return code_ == kThisExpression;
+    }
+
+    bool IsThisProperty() {
+      return code_ == kThisPropertyExpression;
+    }
+
+    bool IsStrictFunction() {
+      return code_ == kStrictFunctionExpression;
+    }
+
+   private:
+    // First two/three bits are used as flags.
+    // Bit 0 and 1 represent identifiers or strings literals, and are
+    // mutually exclusive, but can both be absent.
+    enum  {
+      kUnknownExpression = 0,
+      // Identifiers
+      kIdentifierFlag = 1,  // Used to detect labels.
+      kIdentifierShift = 3,
+
+      kStringLiteralFlag = 2,  // Used to detect directive prologue.
+      kUnknownStringLiteral = kStringLiteralFlag,
+      kUseStrictString = kStringLiteralFlag | 8,
+      kStringLiteralMask = kUseStrictString,
+
+      // Below here applies if neither identifier nor string literal.
+      kThisExpression = 4,
+      kThisPropertyExpression = 8,
+      kStrictFunctionExpression = 12
+    };
+
+    explicit Expression(int expression_code) : code_(expression_code) { }
+
+    int code_;
+  };
+
   class Statement {
    public:
     static Statement Default() {
@@ -658,6 +546,27 @@ class PreParser : public ParserBase<PreParserTraits> {
     bool is_generator_;
   };
 
+  // Report syntax error
+  void ReportMessageAt(Scanner::Location location,
+                       const char* message,
+                       Vector<const char*> args) {
+    ReportMessageAt(location.beg_pos,
+                    location.end_pos,
+                    message,
+                    args.length() > 0 ? args[0] : NULL);
+  }
+  void ReportMessageAt(Scanner::Location location,
+                       const char* type,
+                       const char* name_opt) {
+    log_->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
+  }
+  void ReportMessageAt(int start_pos,
+                       int end_pos,
+                       const char* type,
+                       const char* name_opt) {
+    log_->LogMessage(start_pos, end_pos, type, name_opt);
+  }
+
   // All ParseXXX functions take as the last argument an *ok parameter
   // which is set to false if parsing failed; it is unchanged otherwise.
   // By making the 'exception handling' explicit, we are forced to check
@@ -713,8 +622,18 @@ class PreParser : public ParserBase<PreParserTraits> {
       bool* ok);
   void ParseLazyFunctionLiteralBody(bool* ok);
 
+  Identifier ParseIdentifier(AllowEvalOrArgumentsAsIdentifier, bool* ok);
+  Identifier ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
+                                                 bool* ok);
+  Identifier ParseIdentifierName(bool* ok);
+  Identifier ParseIdentifierNameOrGetOrSet(bool* is_get,
+                                           bool* is_set,
+                                           bool* ok);
+
   // Logs the currently parsed literal as a symbol in the preparser data.
   void LogSymbol();
+  // Log the currently parsed identifier.
+  Identifier GetIdentifierSymbol();
   // Log the currently parsed string literal.
   Expression GetStringSymbol();
 
@@ -722,6 +641,10 @@ class PreParser : public ParserBase<PreParserTraits> {
     scope_->set_language_mode(language_mode);
   }
 
+  virtual bool is_classic_mode() {
+    return scope_->language_mode() == CLASSIC_MODE;
+  }
+
   bool is_extended_mode() {
     return scope_->language_mode() == EXTENDED_MODE;
   }
@@ -735,154 +658,6 @@ class PreParser : public ParserBase<PreParserTraits> {
   bool parenthesized_function_;
 };
 
-
-template<class Traits>
-void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) {
-  // We don't report stack overflows here, to avoid increasing the
-  // stack depth even further.  Instead we report it after parsing is
-  // over, in ParseProgram.
-  if (token == Token::ILLEGAL && stack_overflow()) {
-    return;
-  }
-  Scanner::Location source_location = scanner()->location();
-
-  // Four of the tokens are treated specially
-  switch (token) {
-    case Token::EOS:
-      return ReportMessageAt(source_location, "unexpected_eos");
-    case Token::NUMBER:
-      return ReportMessageAt(source_location, "unexpected_token_number");
-    case Token::STRING:
-      return ReportMessageAt(source_location, "unexpected_token_string");
-    case Token::IDENTIFIER:
-      return ReportMessageAt(source_location, "unexpected_token_identifier");
-    case Token::FUTURE_RESERVED_WORD:
-      return ReportMessageAt(source_location, "unexpected_reserved");
-    case Token::YIELD:
-    case Token::FUTURE_STRICT_RESERVED_WORD:
-      return ReportMessageAt(
-          source_location,
-          this->is_classic_mode() ? "unexpected_token_identifier"
-                                  : "unexpected_strict_reserved");
-    default:
-      const char* name = Token::String(token);
-      ASSERT(name != NULL);
-      Traits::ReportMessageAt(
-          source_location, "unexpected_token", Vector<const char*>(&name, 1));
-  }
-}
-
-
-template<class Traits>
-typename Traits::IdentifierType ParserBase<Traits>::ParseIdentifier(
-    AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments,
-    bool* ok) {
-  Token::Value next = Next();
-  if (next == Token::IDENTIFIER) {
-    typename Traits::IdentifierType name = this->GetSymbol();
-    if (allow_eval_or_arguments == kDontAllowEvalOrArguments &&
-        !this->is_classic_mode() && this->IsEvalOrArguments(name)) {
-      ReportMessageAt(scanner()->location(), "strict_eval_arguments");
-      *ok = false;
-    }
-    return name;
-  } else if (this->is_classic_mode() &&
-             (next == Token::FUTURE_STRICT_RESERVED_WORD ||
-              (next == Token::YIELD && !this->is_generator()))) {
-    return this->GetSymbol();
-  } else {
-    this->ReportUnexpectedToken(next);
-    *ok = false;
-    return Traits::EmptyIdentifier();
-  }
-}
-
-
-template <class Traits>
-typename Traits::IdentifierType ParserBase<
-    Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
-                                                 bool* ok) {
-  Token::Value next = Next();
-  if (next == Token::IDENTIFIER) {
-    *is_strict_reserved = false;
-  } else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
-             (next == Token::YIELD && !this->is_generator())) {
-    *is_strict_reserved = true;
-  } else {
-    ReportUnexpectedToken(next);
-    *ok = false;
-    return Traits::EmptyIdentifier();
-  }
-  return this->GetSymbol();
-}
-
-
-template <class Traits>
-typename Traits::IdentifierType ParserBase<Traits>::ParseIdentifierName(
-    bool* ok) {
-  Token::Value next = Next();
-  if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD &&
-      next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
-    this->ReportUnexpectedToken(next);
-    *ok = false;
-    return Traits::EmptyIdentifier();
-  }
-  return this->GetSymbol();
-}
-
-
-template <class Traits>
-typename Traits::IdentifierType
-ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get,
-                                                  bool* is_set,
-                                                  bool* ok) {
-  typename Traits::IdentifierType result = ParseIdentifierName(ok);
-  if (!*ok) return Traits::EmptyIdentifier();
-  if (scanner()->is_literal_ascii() &&
-      scanner()->literal_length() == 3) {
-    const char* token = scanner()->literal_ascii_string().start();
-    *is_get = strncmp(token, "get", 3) == 0;
-    *is_set = !*is_get && strncmp(token, "set", 3) == 0;
-  }
-  return result;
-}
-
-
-template <typename Traits>
-void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
-    Token::Value property,
-    PropertyKind type,
-    bool* ok) {
-  int old;
-  if (property == Token::NUMBER) {
-    old = finder_.AddNumber(scanner()->literal_ascii_string(), type);
-  } else if (scanner()->is_literal_ascii()) {
-    old = finder_.AddAsciiSymbol(scanner()->literal_ascii_string(), type);
-  } else {
-    old = finder_.AddUtf16Symbol(scanner()->literal_utf16_string(), type);
-  }
-  PropertyKind old_type = static_cast<PropertyKind>(old);
-  if (HasConflict(old_type, type)) {
-    if (IsDataDataConflict(old_type, type)) {
-      // Both are data properties.
-      if (language_mode_ == CLASSIC_MODE) return;
-      parser()->ReportMessageAt(scanner()->location(),
-                               "strict_duplicate_property");
-    } else if (IsDataAccessorConflict(old_type, type)) {
-      // Both a data and an accessor property with the same name.
-      parser()->ReportMessageAt(scanner()->location(),
-                               "accessor_data_property");
-    } else {
-      ASSERT(IsAccessorAccessorConflict(old_type, type));
-      // Both accessors of the same type.
-      parser()->ReportMessageAt(scanner()->location(),
-                               "accessor_get_set");
-    }
-    *ok = false;
-  }
-}
-
-
 } }  // v8::internal
 
 #endif  // V8_PREPARSER_H
index f3f238c..22d5056 100644 (file)
@@ -1108,9 +1108,8 @@ enum ParserSyncTestResult {
   kError
 };
 
-template <typename Traits>
-void SetParserFlags(i::ParserBase<Traits>* parser,
-                    i::EnumSet<ParserFlag> flags) {
+
+void SetParserFlags(i::ParserBase* parser, i::EnumSet<ParserFlag> flags) {
   parser->set_allow_lazy(flags.Contains(kAllowLazy));
   parser->set_allow_natives_syntax(flags.Contains(kAllowNativesSyntax));
   parser->set_allow_harmony_scoping(flags.Contains(kAllowHarmonyScoping));