Chromium Code Reviews| Index: src/parser.cc |
| diff --git a/src/parser.cc b/src/parser.cc |
| index 5e7680e6c19df12853d7ee850fc9bf65010f41fc..c8ce895b7e49eac51507b1ba758f80f5fa61af12 100644 |
| --- a/src/parser.cc |
| +++ b/src/parser.cc |
| @@ -533,8 +533,78 @@ 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()), |
| + : ParserBase(&scanner_, info->isolate()->stack_guard()->real_climit(), |
| + new ParserTraits(this)), |
|
Michael Starzinger
2014/02/10 13:28:03
If we make the ParserBase inherit from ParserTrait
marja
2014/02/10 15:02:07
Done.
|
| isolate_(info->isolate()), |
| symbol_cache_(0, info->zone()), |
| script_(info->script()), |
| @@ -793,62 +863,6 @@ 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, |
| @@ -1081,8 +1095,8 @@ Module* Parser::ParseModuleLiteral(bool* ok) { |
| !it.done(); it.Advance()) { |
| if (scope->LocalLookup(it.name()) == NULL) { |
| Handle<String> name(it.name()); |
| - ReportMessage("module_export_undefined", |
| - Vector<Handle<String> >(&name, 1)); |
| + traits_->ReportMessage("module_export_undefined", |
|
Michael Starzinger
2014/02/10 13:28:03
Likewise calling ReportMessage() wouldn't need an
marja
2014/02/10 15:02:07
Done.
|
| + Vector<Handle<String> >(&name, 1)); |
| *ok = false; |
| return NULL; |
| } |
| @@ -1121,7 +1135,8 @@ Module* Parser::ParseModulePath(bool* ok) { |
| member->interface()->Print(); |
| } |
| #endif |
| - ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1)); |
| + traits_->ReportMessage("invalid_module_path", |
| + Vector<Handle<String> >(&name, 1)); |
| return NULL; |
| } |
| result = member; |
| @@ -1155,7 +1170,7 @@ Module* Parser::ParseModuleUrl(bool* ok) { |
| int pos = peek_position(); |
| Expect(Token::STRING, CHECK_OK); |
| - Handle<String> symbol = GetSymbol(); |
| + Handle<String> symbol = traits_->GetSymbol(); |
| // TODO(ES6): Request JS resource from environment... |
| @@ -1231,7 +1246,8 @@ Block* Parser::ParseImportDeclaration(bool* ok) { |
| module->interface()->Print(); |
| } |
| #endif |
| - ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1)); |
| + traits_->ReportMessage("invalid_module_path", |
| + Vector<Handle<String> >(&name, 1)); |
| return NULL; |
| } |
| VariableProxy* proxy = NewUnresolved(names[i], LET, interface); |
| @@ -1619,7 +1635,8 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
| var->interface()->Print(); |
| } |
| #endif |
| - ReportMessage("module_type_error", Vector<Handle<String> >(&name, 1)); |
| + traits_->ReportMessage("module_type_error", |
| + Vector<Handle<String> >(&name, 1)); |
| } |
| } |
| } |
| @@ -1777,12 +1794,6 @@ 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 |
| @@ -2232,7 +2243,7 @@ Statement* Parser::ParseContinueStatement(bool* ok) { |
| message = "unknown_label"; |
| args = Vector<Handle<String> >(&label, 1); |
| } |
| - ReportMessageAt(scanner().location(), message, args); |
| + traits_->ReportMessageAt(scanner().location(), message, args); |
| *ok = false; |
| return NULL; |
| } |
| @@ -2270,7 +2281,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { |
| message = "unknown_label"; |
| args = Vector<Handle<String> >(&label, 1); |
| } |
| - ReportMessageAt(scanner().location(), message, args); |
| + traits_->ReportMessageAt(scanner().location(), message, args); |
| *ok = false; |
| return NULL; |
| } |
| @@ -2301,7 +2312,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) { |
| return_value = ParseExpression(true, CHECK_OK); |
| } |
| ExpectSemicolon(CHECK_OK); |
| - if (is_generator()) { |
| + if (traits_->is_generator()) { |
| Expression* generator = factory()->NewVariableProxy( |
| current_function_state_->generator_object_variable()); |
| Expression* yield = factory()->NewYield( |
| @@ -2902,7 +2913,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) { |
| // YieldExpression |
| // LeftHandSideExpression AssignmentOperator AssignmentExpression |
| - if (peek() == Token::YIELD && is_generator()) { |
| + if (peek() == Token::YIELD && traits_->is_generator()) { |
| return ParseYieldExpression(ok); |
| } |
| @@ -3013,14 +3024,6 @@ 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); |
| @@ -3543,7 +3546,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) { |
| case Token::STRING: { |
| Consume(Token::STRING); |
| - Handle<String> symbol = GetSymbol(); |
| + Handle<String> symbol = traits_->GetSymbol(); |
| result = factory()->NewLiteral(symbol, pos); |
| if (fni_ != NULL) fni_->PushLiteralName(symbol); |
| break; |
| @@ -3721,7 +3724,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { |
| checker.CheckProperty(next, type, CHECK_OK); |
| Handle<String> name = is_keyword |
| ? isolate_->factory()->InternalizeUtf8String(Token::String(next)) |
| - : GetSymbol(); |
| + : traits_->GetSymbol(); |
| FunctionLiteral* value = |
| ParseFunctionLiteral(name, |
| scanner().location(), |
| @@ -3753,7 +3756,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { |
| } |
| case Token::STRING: { |
| Consume(Token::STRING); |
| - Handle<String> string = GetSymbol(); |
| + Handle<String> string = traits_->GetSymbol(); |
| if (fni_ != NULL) fni_->PushLiteralName(string); |
| uint32_t index; |
| if (!string.is_null() && string->AsArrayIndex(&index)) { |
| @@ -3776,7 +3779,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { |
| default: |
| if (Token::IsKeyword(next)) { |
| Consume(next); |
| - Handle<String> string = GetSymbol(); |
| + Handle<String> string = traits_->GetSymbol(); |
| key = factory()->NewLiteral(string, next_pos); |
| } else { |
| // Unexpected token. |
| @@ -4081,7 +4084,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
| ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
| // Store locations for possible future error reports. |
| - if (!eval_args_error_log.IsValid() && IsEvalOrArguments(param_name)) { |
| + if (!eval_args_error_log.IsValid() && |
| + traits_->IsEvalOrArguments(param_name)) { |
| eval_args_error_log = scanner().location(); |
| } |
| if (!reserved_loc.IsValid() && is_strict_reserved) { |
| @@ -4261,7 +4265,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
| // Validate strict mode. We can do this only after parsing the function, |
| // since the function can declare itself strict. |
| if (!top_scope_->is_classic_mode()) { |
| - if (IsEvalOrArguments(function_name)) { |
| + if (traits_->IsEvalOrArguments(function_name)) { |
| ReportMessageAt(function_name_location, |
| "strict_eval_arguments", |
| Vector<const char*>::empty()); |
| @@ -4344,10 +4348,8 @@ PreParser::PreParseResult Parser::LazyParseFunctionLiteral( |
| reusable_preparser_->set_allow_harmony_numeric_literals( |
| allow_harmony_numeric_literals()); |
| } |
| - PreParser::PreParseResult result = |
| - reusable_preparser_->PreParseLazyFunction(top_scope_->language_mode(), |
| - is_generator(), |
| - logger); |
| + PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( |
| + top_scope_->language_mode(), traits_->is_generator(), logger); |
| return result; |
| } |
| @@ -4397,7 +4399,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) == '_') { |
| - ReportMessage("not_defined", Vector<Handle<String> >(&name, 1)); |
| + traits_->ReportMessage("not_defined", Vector<Handle<String> >(&name, 1)); |
| *ok = false; |
| return NULL; |
| } |
| @@ -4407,88 +4409,6 @@ 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); |
| @@ -4501,68 +4421,6 @@ 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() |
| @@ -4581,25 +4439,14 @@ void Parser::CheckStrictModeLValue(Expression* expression, |
| ? expression->AsVariableProxy() |
| : NULL; |
| - if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) { |
| + if (lhs != NULL && !lhs->is_this() && |
| + traits_->IsEvalOrArguments(lhs->name())) { |
| ReportMessage("strict_eval_arguments", Vector<const char*>::empty()); |
| *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 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) { |
| @@ -4619,22 +4466,6 @@ void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { |
| } |
| -// 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 |