Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Unified Diff: src/parser.cc

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser.h ('k') | src/platform.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index 149de4dcf0c5effc3b607a1ec3e53dd279b9a0cd..68823e6c1f708a84cbba432187eac0972c397b43 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -46,49 +46,6 @@
namespace v8 {
namespace internal {
-// PositionStack is used for on-stack allocation of token positions for
-// new expressions. Please look at ParseNewExpression.
-
-class PositionStack {
- public:
- explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
- ~PositionStack() {
- ASSERT(!*ok_ || is_empty());
- USE(ok_);
- }
-
- class Element {
- public:
- Element(PositionStack* stack, int value) {
- previous_ = stack->top();
- value_ = value;
- stack->set_top(this);
- }
-
- private:
- Element* previous() { return previous_; }
- int value() { return value_; }
- friend class PositionStack;
- Element* previous_;
- int value_;
- };
-
- bool is_empty() { return top_ == NULL; }
- int pop() {
- ASSERT(!is_empty());
- int result = top_->value();
- top_ = top_->previous();
- return result;
- }
-
- private:
- Element* top() { return top_; }
- void set_top(Element* value) { top_ = value; }
- Element* top_;
- bool* ok_;
-};
-
-
RegExpBuilder::RegExpBuilder(Zone* zone)
: zone_(zone),
pending_empty_(false),
@@ -250,13 +207,19 @@ void RegExpBuilder::AddQuantifierToAtom(
Handle<String> Parser::LookupSymbol(int symbol_id) {
- // Length of symbol cache is the number of identified symbols.
- // If we are larger than that, or negative, it's not a cached symbol.
- // This might also happen if there is no preparser symbol data, even
- // if there is some preparser data.
- if (static_cast<unsigned>(symbol_id)
- >= static_cast<unsigned>(symbol_cache_.length())) {
- return scanner().GetLiteralSymbol();
+ // If there is no preparser symbol data, a negative number will be passed. In
+ // that case, we'll just read the literal from Scanner. This also guards
+ // against corrupt preparse data where the symbol id is larger than the symbol
+ // count.
+ if (symbol_id < 0 ||
+ (pre_parse_data_ && symbol_id >= pre_parse_data_->symbol_count())) {
+ if (scanner()->is_literal_ascii()) {
+ return isolate()->factory()->InternalizeOneByteString(
+ Vector<const uint8_t>::cast(scanner()->literal_ascii_string()));
+ } else {
+ return isolate()->factory()->InternalizeTwoByteString(
+ scanner()->literal_utf16_string());
+ }
}
return LookupCachedSymbol(symbol_id);
}
@@ -271,7 +234,13 @@ Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
}
Handle<String> result = symbol_cache_.at(symbol_id);
if (result.is_null()) {
- result = scanner().GetLiteralSymbol();
+ if (scanner()->is_literal_ascii()) {
+ result = isolate()->factory()->InternalizeOneByteString(
+ Vector<const uint8_t>::cast(scanner()->literal_ascii_string()));
+ } else {
+ result = isolate()->factory()->InternalizeTwoByteString(
+ scanner()->literal_utf16_string());
+ }
symbol_cache_.at(symbol_id) = result;
return result;
}
@@ -360,10 +329,10 @@ const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
}
-ScannerBase::Location ScriptDataImpl::MessageLocation() {
+Scanner::Location ScriptDataImpl::MessageLocation() {
int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
int end_pos = Read(PreparseDataConstants::kMessageEndPos);
- return ScannerBase::Location(beg_pos, end_pos);
+ return Scanner::Location(beg_pos, end_pos);
}
@@ -451,56 +420,6 @@ class TargetScope BASE_EMBEDDED {
// ----------------------------------------------------------------------------
-// FunctionState and BlockState together implement the parser's scope stack.
-// The parser's current scope is in top_scope_. The BlockState and
-// FunctionState constructors push on the scope stack and the destructors
-// pop. They are also used to hold the parser's per-function and per-block
-// state.
-
-class Parser::BlockState BASE_EMBEDDED {
- public:
- BlockState(Parser* parser, Scope* scope)
- : parser_(parser),
- outer_scope_(parser->top_scope_) {
- parser->top_scope_ = scope;
- }
-
- ~BlockState() { parser_->top_scope_ = outer_scope_; }
-
- private:
- Parser* parser_;
- Scope* outer_scope_;
-};
-
-
-Parser::FunctionState::FunctionState(Parser* parser,
- Scope* scope,
- Isolate* isolate)
- : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
- next_handler_index_(0),
- expected_property_count_(0),
- generator_object_variable_(NULL),
- parser_(parser),
- outer_function_state_(parser->current_function_state_),
- outer_scope_(parser->top_scope_),
- saved_ast_node_id_(isolate->ast_node_id()),
- factory_(isolate, parser->zone()) {
- parser->top_scope_ = scope;
- parser->current_function_state_ = this;
- isolate->set_ast_node_id(BailoutId::FirstUsable().ToInt());
-}
-
-
-Parser::FunctionState::~FunctionState() {
- parser_->top_scope_ = outer_scope_;
- parser_->current_function_state_ = outer_function_state_;
- if (outer_function_state_ != NULL) {
- parser_->isolate()->set_ast_node_id(saved_ast_node_id_);
- }
-}
-
-
-// ----------------------------------------------------------------------------
// The CHECK_OK macro is a convenient macro to enforce error
// handling for functions that may fail (by returning !*ok).
//
@@ -523,26 +442,176 @@ Parser::FunctionState::~FunctionState() {
// ----------------------------------------------------------------------------
// Implementation of Parser
+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(Scanner* scanner) {
+ int symbol_id = -1;
+ if (parser_->pre_parse_data() != NULL) {
+ symbol_id = parser_->pre_parse_data()->GetSymbolIdentifier();
+ }
+ return parser_->LookupSymbol(symbol_id);
+}
+
+
+Handle<String> ParserTraits::NextLiteralString(Scanner* scanner,
+ PretenureFlag tenured) {
+ if (scanner->is_next_literal_ascii()) {
+ return parser_->isolate_->factory()->NewStringFromAscii(
+ scanner->next_literal_ascii_string(), tenured);
+ } else {
+ return parser_->isolate_->factory()->NewStringFromTwoByte(
+ scanner->next_literal_utf16_string(), tenured);
+ }
+}
+
+
+Expression* ParserTraits::ThisExpression(
+ Scope* scope,
+ AstNodeFactory<AstConstructionVisitor>* factory) {
+ return factory->NewVariableProxy(scope->receiver());
+}
+
+
+Expression* ParserTraits::ExpressionFromLiteral(
+ Token::Value token, int pos,
+ Scanner* scanner,
+ AstNodeFactory<AstConstructionVisitor>* factory) {
+ Factory* isolate_factory = parser_->isolate()->factory();
+ switch (token) {
+ case Token::NULL_LITERAL:
+ return factory->NewLiteral(isolate_factory->null_value(), pos);
+ case Token::TRUE_LITERAL:
+ return factory->NewLiteral(isolate_factory->true_value(), pos);
+ case Token::FALSE_LITERAL:
+ return factory->NewLiteral(isolate_factory->false_value(), pos);
+ case Token::NUMBER: {
+ ASSERT(scanner->is_literal_ascii());
+ double value = StringToDouble(parser_->isolate()->unicode_cache(),
+ scanner->literal_ascii_string(),
+ ALLOW_HEX | ALLOW_OCTAL |
+ ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
+ return factory->NewNumberLiteral(value, pos);
+ }
+ default:
+ ASSERT(false);
+ }
+ return NULL;
+}
+
+
+Expression* ParserTraits::ExpressionFromIdentifier(
+ Handle<String> name, int pos, Scope* scope,
+ AstNodeFactory<AstConstructionVisitor>* factory) {
+ if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
+ // The name may refer to a module instance object, so its type is unknown.
+#ifdef DEBUG
+ if (FLAG_print_interface_details)
+ PrintF("# Variable %s ", name->ToAsciiArray());
+#endif
+ Interface* interface = Interface::NewUnknown(parser_->zone());
+ return scope->NewUnresolved(factory, name, interface, pos);
+}
+
+
+Expression* ParserTraits::ExpressionFromString(
+ int pos, Scanner* scanner,
+ AstNodeFactory<AstConstructionVisitor>* factory) {
+ Handle<String> symbol = GetSymbol(scanner);
+ if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
+ return factory->NewLiteral(symbol, pos);
+}
+
+
+Literal* ParserTraits::GetLiteralTheHole(
+ int position, AstNodeFactory<AstConstructionVisitor>* factory) {
+ return factory->NewLiteral(parser_->isolate()->factory()->the_hole_value(),
+ RelocInfo::kNoPosition);
+}
+
+
+Expression* ParserTraits::ParseObjectLiteral(bool* ok) {
+ return parser_->ParseObjectLiteral(ok);
+}
+
+
+Expression* ParserTraits::ParseAssignmentExpression(bool accept_IN, bool* ok) {
+ return parser_->ParseAssignmentExpression(accept_IN, ok);
+}
+
+
+Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
+ return parser_->ParseV8Intrinsic(ok);
+}
+
+
Parser::Parser(CompilationInfo* info)
- : ParserBase(NULL, info->isolate()->stack_guard()->real_climit()),
+ : ParserBase<ParserTraits>(&scanner_,
+ info->isolate()->stack_guard()->real_climit(),
+ info->extension(),
+ info->zone(),
+ this),
isolate_(info->isolate()),
symbol_cache_(0, info->zone()),
script_(info->script()),
+ scanner_(isolate_->unicode_cache()),
reusable_preparser_(NULL),
- top_scope_(NULL),
original_scope_(NULL),
- current_function_state_(NULL),
target_stack_(NULL),
- extension_(info->extension()),
pre_parse_data_(NULL),
fni_(NULL),
- parenthesized_function_(false),
- zone_(info->zone()),
info_(info) {
ASSERT(!script_.is_null());
isolate_->set_ast_node_id(0);
- set_allow_harmony_scoping(!info_->is_native() && FLAG_harmony_scoping);
- set_allow_modules(!info_->is_native() && FLAG_harmony_modules);
+ set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
+ set_allow_modules(!info->is_native() && FLAG_harmony_modules);
set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native());
set_allow_lazy(false); // Must be explicitly enabled.
set_allow_generators(FLAG_harmony_generators);
@@ -564,18 +633,21 @@ FunctionLiteral* Parser::ParseProgram() {
fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
// Initialize parser state.
- source = FlattenGetString(source);
+ source->TryFlatten();
FunctionLiteral* result;
- delete reusable_preparser_;
- delete scanner_;
- if (source->IsTwoByteRepresentation()) {
- scanner_ = new ExperimentalScanner<uint16_t>(source, isolate());
+ if (source->IsExternalTwoByteString()) {
+ // Notice that the stream is destroyed at the end of the branch block.
+ // The last line of the blocks can't be moved outside, even though they're
+ // identical calls.
+ ExternalTwoByteStringUtf16CharacterStream stream(
+ Handle<ExternalTwoByteString>::cast(source), 0, source->length());
+ scanner_.Initialize(&stream);
+ result = DoParseProgram(info(), source);
} else {
- scanner_ = new ExperimentalScanner<uint8_t>(source, isolate());
+ GenericStringUtf16CharacterStream stream(source, 0, source->length());
+ scanner_.Initialize(&stream);
+ result = DoParseProgram(info(), source);
}
- SetScannerFlags();
- scanner_->Init();
- result = DoParseProgram(info(), source);
if (FLAG_trace_parse && result != NULL) {
double ms = timer.Elapsed().InMillisecondsF();
@@ -596,14 +668,14 @@ FunctionLiteral* Parser::ParseProgram() {
FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
Handle<String> source) {
- ASSERT(top_scope_ == NULL);
+ ASSERT(scope_ == NULL);
ASSERT(target_stack_ == NULL);
if (pre_parse_data_ != NULL) pre_parse_data_->Initialize();
Handle<String> no_name = isolate()->factory()->empty_string();
FunctionLiteral* result = NULL;
- { Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
+ { Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
info->SetGlobalScope(scope);
if (!info->context().is_null()) {
scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
@@ -629,19 +701,19 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
ParsingModeScope parsing_mode(this, mode);
// Enters 'scope'.
- FunctionState function_state(this, scope, isolate());
+ FunctionState function_state(&function_state_, &scope_, scope, zone());
- top_scope_->SetLanguageMode(info->language_mode());
+ scope_->SetLanguageMode(info->language_mode());
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
bool ok = true;
- int beg_pos = scanner().location().beg_pos;
+ int beg_pos = scanner()->location().beg_pos;
ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok);
- if (ok && !top_scope_->is_classic_mode()) {
- CheckOctalLiteral(beg_pos, scanner().location().end_pos, &ok);
+ if (ok && !scope_->is_classic_mode()) {
+ CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
}
if (ok && is_extended_mode()) {
- CheckConflictingVarDeclarations(top_scope_, &ok);
+ CheckConflictingVarDeclarations(scope_, &ok);
}
if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
@@ -657,7 +729,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
if (ok) {
result = factory()->NewFunctionLiteral(
no_name,
- top_scope_,
+ scope_,
body,
function_state.materialized_literal_count(),
function_state.expected_property_count(),
@@ -670,6 +742,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
FunctionLiteral::kNotGenerator,
0);
result->set_ast_properties(factory()->visitor()->ast_properties());
+ result->set_slot_processor(factory()->visitor()->slot_processor());
result->set_dont_optimize_reason(
factory()->visitor()->dont_optimize_reason());
} else if (stack_overflow()) {
@@ -692,10 +765,24 @@ FunctionLiteral* Parser::ParseLazy() {
if (FLAG_trace_parse) {
timer.Start();
}
- // Initialize parser state.
Handle<SharedFunctionInfo> shared_info = info()->shared_info();
- FunctionLiteral* result = ParseLazy(
- source, shared_info->start_position(), shared_info->end_position());
+
+ // Initialize parser state.
+ source->TryFlatten();
+ FunctionLiteral* result;
+ if (source->IsExternalTwoByteString()) {
+ ExternalTwoByteStringUtf16CharacterStream stream(
+ Handle<ExternalTwoByteString>::cast(source),
+ shared_info->start_position(),
+ shared_info->end_position());
+ result = ParseLazy(&stream);
+ } else {
+ GenericStringUtf16CharacterStream stream(source,
+ shared_info->start_position(),
+ shared_info->end_position());
+ result = ParseLazy(&stream);
+ }
+
if (FLAG_trace_parse && result != NULL) {
double ms = timer.Elapsed().InMillisecondsF();
SmartArrayPointer<char> name_chars = result->debug_name()->ToCString();
@@ -705,22 +792,10 @@ FunctionLiteral* Parser::ParseLazy() {
}
-FunctionLiteral* Parser::ParseLazy(Handle<String> source, int start, int end) {
- source = FlattenGetString(source);
- delete reusable_preparser_;
- delete scanner_;
- if (source->IsTwoByteRepresentation()) {
- scanner_ = new ExperimentalScanner<uint16_t>(source, isolate());
- } else {
- scanner_ = new ExperimentalScanner<uint8_t>(source, isolate());
- }
- SetScannerFlags();
- // We don't need to Init() if we immediately SeekForward.
- scanner_->SeekForward(start);
- scanner_->SetEnd(end);
-
+FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
Handle<SharedFunctionInfo> shared_info = info()->shared_info();
- ASSERT(top_scope_ == NULL);
+ scanner_.Initialize(source);
+ ASSERT(scope_ == NULL);
ASSERT(target_stack_ == NULL);
Handle<String> name(String::cast(shared_info->name()));
@@ -734,14 +809,14 @@ FunctionLiteral* Parser::ParseLazy(Handle<String> source, int start, int end) {
{
// Parse the function literal.
- Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
+ Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
info()->SetGlobalScope(scope);
if (!info()->closure().is_null()) {
scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope,
zone());
}
original_scope_ = scope;
- FunctionState function_state(this, scope, isolate());
+ FunctionState function_state(&function_state_, &scope_, scope, zone());
ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode());
ASSERT(scope->language_mode() != EXTENDED_MODE ||
info()->is_extended_mode());
@@ -754,6 +829,7 @@ FunctionLiteral* Parser::ParseLazy(Handle<String> source, int start, int end) {
: FunctionLiteral::DECLARATION;
bool ok = true;
result = ParseFunctionLiteral(name,
+ Scanner::Location::invalid(),
false, // Strict mode name already checked.
shared_info->is_generator(),
RelocInfo::kNoPosition,
@@ -776,62 +852,6 @@ FunctionLiteral* Parser::ParseLazy(Handle<String> source, int start, int end) {
}
-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) {
- ScannerBase::Location source_location = scanner().location();
- ReportMessageAt(source_location, message, args);
-}
-
-
-void Parser::ReportMessage(const char* message, Vector<Handle<String> > args) {
- ScannerBase::Location source_location = scanner().location();
- ReportMessageAt(source_location, message, args);
-}
-
-
-void Parser::ReportMessageAt(ScannerBase::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(ScannerBase::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,
@@ -854,7 +874,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
directive_prologue = false;
}
- ScannerBase::Location token_loc = scanner().peek_location();
+ Scanner::Location token_loc = scanner()->peek_location();
Statement* stat;
if (is_global && !is_eval) {
stat = ParseModuleElement(NULL, CHECK_OK);
@@ -877,7 +897,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
Handle<String> directive = Handle<String>::cast(literal->value());
// Check "use strict" directive (ES5 14.1).
- if (top_scope_->is_classic_mode() &&
+ if (scope_->is_classic_mode() &&
directive->Equals(isolate()->heap()->use_strict_string()) &&
token_loc.end_pos - token_loc.beg_pos ==
isolate()->heap()->use_strict_string()->length() + 2) {
@@ -886,16 +906,16 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
// add this scope in DoParseProgram(), but that requires adaptations
// all over the code base, so we go with a quick-fix for now.
// In the same manner, we have to patch the parsing mode.
- if (is_eval && !top_scope_->is_eval_scope()) {
- ASSERT(top_scope_->is_global_scope());
- Scope* scope = NewScope(top_scope_, EVAL_SCOPE);
- scope->set_start_position(top_scope_->start_position());
- scope->set_end_position(top_scope_->end_position());
- top_scope_ = scope;
+ if (is_eval && !scope_->is_eval_scope()) {
+ ASSERT(scope_->is_global_scope());
+ Scope* scope = NewScope(scope_, EVAL_SCOPE);
+ scope->set_start_position(scope_->start_position());
+ scope->set_end_position(scope_->end_position());
+ scope_ = scope;
mode_ = PARSE_EAGERLY;
}
// TODO(ES6): Fix entering extended mode, once it is specified.
- top_scope_->SetLanguageMode(allow_harmony_scoping()
+ scope_->SetLanguageMode(allow_harmony_scoping()
? EXTENDED_MODE : STRICT_MODE);
// "use strict" is the only directive for now.
directive_prologue = false;
@@ -944,14 +964,14 @@ Statement* Parser::ParseModuleElement(ZoneStringList* labels,
// Handle 'module' as a context-sensitive keyword.
if (FLAG_harmony_modules &&
peek() == Token::IDENTIFIER &&
- !scanner().HasAnyLineTerminatorBeforeNext() &&
+ !scanner()->HasAnyLineTerminatorBeforeNext() &&
stmt != NULL) {
ExpressionStatement* estmt = stmt->AsExpressionStatement();
if (estmt != NULL &&
estmt->expression()->AsVariableProxy() != NULL &&
estmt->expression()->AsVariableProxy()->name()->Equals(
isolate()->heap()->module_string()) &&
- !scanner().literal_contains_escapes()) {
+ !scanner()->literal_contains_escapes()) {
return ParseModuleDeclaration(NULL, ok);
}
}
@@ -966,7 +986,7 @@ Statement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) {
// 'module' Identifier Module
int pos = peek_position();
- Handle<String> name = ParseIdentifier(CHECK_OK);
+ Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
#ifdef DEBUG
if (FLAG_print_interface_details)
@@ -976,7 +996,7 @@ Statement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) {
Module* module = ParseModule(CHECK_OK);
VariableProxy* proxy = NewUnresolved(name, MODULE, module->interface());
Declaration* declaration =
- factory()->NewModuleDeclaration(proxy, module, top_scope_, pos);
+ factory()->NewModuleDeclaration(proxy, module, scope_, pos);
Declare(declaration, true, CHECK_OK);
#ifdef DEBUG
@@ -1034,14 +1054,14 @@ Module* Parser::ParseModuleLiteral(bool* ok) {
#ifdef DEBUG
if (FLAG_print_interface_details) PrintF("# Literal ");
#endif
- Scope* scope = NewScope(top_scope_, MODULE_SCOPE);
+ Scope* scope = NewScope(scope_, MODULE_SCOPE);
Expect(Token::LBRACE, CHECK_OK);
- scope->set_start_position(scanner().location().beg_pos);
+ scope->set_start_position(scanner()->location().beg_pos);
scope->SetLanguageMode(EXTENDED_MODE);
{
- BlockState block_state(this, scope);
+ BlockState block_state(&scope_, scope);
TargetCollector collector(zone());
Target target(&this->target_stack_, &collector);
Target target_body(&this->target_stack_, body);
@@ -1055,7 +1075,7 @@ Module* Parser::ParseModuleLiteral(bool* ok) {
}
Expect(Token::RBRACE, CHECK_OK);
- scope->set_end_position(scanner().location().end_pos);
+ scope->set_end_position(scanner()->location().end_pos);
body->set_scope(scope);
// Check that all exports are bound.
@@ -1064,8 +1084,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));
+ ParserTraits::ReportMessage("module_export_undefined",
+ Vector<Handle<String> >(&name, 1));
*ok = false;
return NULL;
}
@@ -1104,7 +1124,8 @@ Module* Parser::ParseModulePath(bool* ok) {
member->interface()->Print();
}
#endif
- ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1));
+ ParserTraits::ReportMessage("invalid_module_path",
+ Vector<Handle<String> >(&name, 1));
return NULL;
}
result = member;
@@ -1119,14 +1140,14 @@ Module* Parser::ParseModuleVariable(bool* ok) {
// Identifier
int pos = peek_position();
- Handle<String> name = ParseIdentifier(CHECK_OK);
+ Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
#ifdef DEBUG
if (FLAG_print_interface_details)
PrintF("# Module variable %s ", name->ToAsciiArray());
#endif
- VariableProxy* proxy = top_scope_->NewUnresolved(
+ VariableProxy* proxy = scope_->NewUnresolved(
factory(), name, Interface::NewModule(zone()),
- scanner().location().beg_pos);
+ scanner()->location().beg_pos);
return factory()->NewModuleVariable(proxy, pos);
}
@@ -1148,7 +1169,7 @@ Module* Parser::ParseModuleUrl(bool* ok) {
// Create an empty literal as long as the feature isn't finished.
USE(symbol);
- Scope* scope = NewScope(top_scope_, MODULE_SCOPE);
+ Scope* scope = NewScope(scope_, MODULE_SCOPE);
Block* body = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
body->set_scope(scope);
Interface* interface = scope->interface();
@@ -1214,12 +1235,13 @@ Block* Parser::ParseImportDeclaration(bool* ok) {
module->interface()->Print();
}
#endif
- ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1));
+ ParserTraits::ReportMessage("invalid_module_path",
+ Vector<Handle<String> >(&name, 1));
return NULL;
}
VariableProxy* proxy = NewUnresolved(names[i], LET, interface);
Declaration* declaration =
- factory()->NewImportDeclaration(proxy, module, top_scope_, pos);
+ factory()->NewImportDeclaration(proxy, module, scope_, pos);
Declare(declaration, true, CHECK_OK);
}
@@ -1244,13 +1266,14 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
switch (peek()) {
case Token::IDENTIFIER: {
int pos = position();
- Handle<String> name = ParseIdentifier(CHECK_OK);
+ Handle<String> name =
+ ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
// Handle 'module' as a context-sensitive keyword.
if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("module"))) {
names.Add(name, zone());
while (peek() == Token::COMMA) {
Consume(Token::COMMA);
- name = ParseIdentifier(CHECK_OK);
+ name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
names.Add(name, zone());
}
ExpectSemicolon(CHECK_OK);
@@ -1273,12 +1296,12 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
default:
*ok = false;
- ReportUnexpectedToken(scanner().current_token());
+ ReportUnexpectedToken(scanner()->current_token());
return NULL;
}
// Extract declared names into export declarations and interface.
- Interface* interface = top_scope_->interface();
+ Interface* interface = scope_->interface();
for (int i = 0; i < names.length(); ++i) {
#ifdef DEBUG
if (FLAG_print_interface_details)
@@ -1293,8 +1316,8 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
// TODO(rossberg): Rethink whether we actually need to store export
// declarations (for compilation?).
// ExportDeclaration* declaration =
- // factory()->NewExportDeclaration(proxy, top_scope_, position);
- // top_scope_->AddDeclaration(declaration);
+ // factory()->NewExportDeclaration(proxy, scope_, position);
+ // scope_->AddDeclaration(declaration);
}
ASSERT(result != NULL);
@@ -1420,9 +1443,8 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
// In Harmony mode, this case also handles the extension:
// Statement:
// GeneratorDeclaration
- if (!top_scope_->is_classic_mode()) {
- ReportMessageAt(scanner().peek_location(), "strict_function",
- Vector<const char*>::empty());
+ if (!scope_->is_classic_mode()) {
+ ReportMessageAt(scanner()->peek_location(), "strict_function");
*ok = false;
return NULL;
}
@@ -1601,7 +1623,8 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
var->interface()->Print();
}
#endif
- ReportMessage("module_type_error", Vector<Handle<String> >(&name, 1));
+ ParserTraits::ReportMessage("module_type_error",
+ Vector<Handle<String> >(&name, 1));
}
}
}
@@ -1615,11 +1638,12 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
Statement* Parser::ParseNativeDeclaration(bool* ok) {
int pos = peek_position();
Expect(Token::FUNCTION, CHECK_OK);
- Handle<String> name = ParseIdentifier(CHECK_OK);
+ // Allow "eval" or "arguments" for backward compatibility.
+ Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
bool done = (peek() == Token::RPAREN);
while (!done) {
- ParseIdentifier(CHECK_OK);
+ ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
done = (peek() == Token::RPAREN);
if (!done) {
Expect(Token::COMMA, CHECK_OK);
@@ -1639,7 +1663,7 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
// other functions are set up when entering the surrounding scope.
VariableProxy* proxy = NewUnresolved(name, VAR, Interface::NewValue());
Declaration* declaration =
- factory()->NewVariableDeclaration(proxy, VAR, top_scope_, pos);
+ factory()->NewVariableDeclaration(proxy, VAR, scope_, pos);
Declare(declaration, true, CHECK_OK);
NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
name, extension_, RelocInfo::kNoPosition);
@@ -1663,6 +1687,7 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
Handle<String> name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK);
FunctionLiteral* fun = ParseFunctionLiteral(name,
+ scanner()->location(),
is_strict_reserved,
is_generator,
pos,
@@ -1674,10 +1699,10 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
// In extended mode, a function behaves as a lexical binding, except in the
// global scope.
VariableMode mode =
- is_extended_mode() && !top_scope_->is_global_scope() ? LET : VAR;
+ is_extended_mode() && !scope_->is_global_scope() ? LET : VAR;
VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
Declaration* declaration =
- factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_, pos);
+ factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
Declare(declaration, true, CHECK_OK);
if (names) names->Add(name, zone());
return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
@@ -1685,7 +1710,7 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
- if (top_scope_->is_extended_mode()) return ParseScopedBlock(labels, ok);
+ if (scope_->is_extended_mode()) return ParseScopedBlock(labels, ok);
// Block ::
// '{' Statement* '}'
@@ -1718,12 +1743,12 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
// Construct block expecting 16 statements.
Block* body =
factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
- Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE);
+ Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
// Parse the statements and collect escaping labels.
Expect(Token::LBRACE, CHECK_OK);
- block_scope->set_start_position(scanner().location().beg_pos);
- { BlockState block_state(this, block_scope);
+ block_scope->set_start_position(scanner()->location().beg_pos);
+ { BlockState block_state(&scope_, block_scope);
TargetCollector collector(zone());
Target target(&this->target_stack_, &collector);
Target target_body(&this->target_stack_, body);
@@ -1736,7 +1761,7 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
}
}
Expect(Token::RBRACE, CHECK_OK);
- block_scope->set_end_position(scanner().location().end_pos);
+ block_scope->set_end_position(scanner()->location().end_pos);
block_scope = block_scope->FinalizeBlockScope();
body->set_scope(block_scope);
return body;
@@ -1757,12 +1782,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
@@ -1811,7 +1830,7 @@ Block* Parser::ParseVariableDeclarations(
// existing pages. Therefore we keep allowing const with the old
// non-harmony semantics in classic mode.
Consume(Token::CONST);
- switch (top_scope_->language_mode()) {
+ switch (scope_->language_mode()) {
case CLASSIC_MODE:
mode = CONST;
init_op = Token::INIT_CONST;
@@ -1882,16 +1901,9 @@ Block* Parser::ParseVariableDeclarations(
// Parse variable name.
if (nvars > 0) Consume(Token::COMMA);
- name = ParseIdentifier(CHECK_OK);
+ name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
if (fni_ != NULL) fni_->PushVariableName(name);
- // Strict mode variables may not be named eval or arguments
- if (!declaration_scope->is_classic_mode() && IsEvalOrArguments(name)) {
- ReportMessage("strict_var_name", Vector<const char*>::empty());
- *ok = false;
- return NULL;
- }
-
// Declare variable.
// Note that we *always* must treat the initial value via a separate init
// assignment for variables and constants because the value must be assigned
@@ -1911,12 +1923,11 @@ Block* Parser::ParseVariableDeclarations(
is_const ? Interface::NewConst() : Interface::NewValue();
VariableProxy* proxy = NewUnresolved(name, mode, interface);
Declaration* declaration =
- factory()->NewVariableDeclaration(proxy, mode, top_scope_, pos);
+ factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
Declare(declaration, mode != VAR, CHECK_OK);
nvars++;
if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
- ReportMessageAt(scanner().location(), "too_many_variables",
- Vector<const char*>::empty());
+ ReportMessageAt(scanner()->location(), "too_many_variables");
*ok = false;
return NULL;
}
@@ -1931,7 +1942,7 @@ Block* Parser::ParseVariableDeclarations(
//
// var v; v = x;
//
- // In particular, we need to re-lookup 'v' (in top_scope_, not
+ // In particular, we need to re-lookup 'v' (in scope_, not
// declaration_scope) as it may be a different 'v' than the 'v' in the
// declaration (e.g., if we are inside a 'with' statement or 'catch'
// block).
@@ -1949,7 +1960,7 @@ Block* Parser::ParseVariableDeclarations(
// one - there is no re-lookup (see the last parameter of the
// Declare() call above).
- Scope* initialization_scope = is_const ? declaration_scope : top_scope_;
+ Scope* initialization_scope = is_const ? declaration_scope : scope_;
Expression* value = NULL;
int pos = -1;
// Harmony consts have non-optional initializers.
@@ -2140,7 +2151,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
// Remove the "ghost" variable that turned out to be a label
// from the top scope. This way, we don't try to resolve it
// during the scope processing.
- top_scope_->RemoveUnresolved(var);
+ scope_->RemoveUnresolved(var);
Expect(Token::COLON, CHECK_OK);
return ParseStatement(labels, ok);
}
@@ -2150,12 +2161,12 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
// no line-terminator between the two words.
if (extension_ != NULL &&
peek() == Token::FUNCTION &&
- !scanner().HasAnyLineTerminatorBeforeNext() &&
+ !scanner()->HasAnyLineTerminatorBeforeNext() &&
expr != NULL &&
expr->AsVariableProxy() != NULL &&
expr->AsVariableProxy()->name()->Equals(
isolate()->heap()->native_string()) &&
- !scanner().literal_contains_escapes()) {
+ !scanner()->literal_contains_escapes()) {
return ParseNativeDeclaration(ok);
}
@@ -2163,11 +2174,11 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
// Only expect semicolon in the former case.
if (!FLAG_harmony_modules ||
peek() != Token::IDENTIFIER ||
- scanner().HasAnyLineTerminatorBeforeNext() ||
+ scanner()->HasAnyLineTerminatorBeforeNext() ||
expr->AsVariableProxy() == NULL ||
!expr->AsVariableProxy()->name()->Equals(
isolate()->heap()->module_string()) ||
- scanner().literal_contains_escapes()) {
+ scanner()->literal_contains_escapes()) {
ExpectSemicolon(CHECK_OK);
}
return factory()->NewExpressionStatement(expr, pos);
@@ -2204,9 +2215,10 @@ Statement* Parser::ParseContinueStatement(bool* ok) {
Expect(Token::CONTINUE, CHECK_OK);
Handle<String> label = Handle<String>::null();
Token::Value tok = peek();
- if (!scanner().HasAnyLineTerminatorBeforeNext() &&
+ if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
- label = ParseIdentifier(CHECK_OK);
+ // ECMA allows "eval" or "arguments" as labels even in strict mode.
+ label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
}
IterationStatement* target = NULL;
target = LookupContinueTarget(label, CHECK_OK);
@@ -2218,7 +2230,7 @@ Statement* Parser::ParseContinueStatement(bool* ok) {
message = "unknown_label";
args = Vector<Handle<String> >(&label, 1);
}
- ReportMessageAt(scanner().location(), message, args);
+ ParserTraits::ReportMessageAt(scanner()->location(), message, args);
*ok = false;
return NULL;
}
@@ -2235,9 +2247,10 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
Expect(Token::BREAK, CHECK_OK);
Handle<String> label;
Token::Value tok = peek();
- if (!scanner().HasAnyLineTerminatorBeforeNext() &&
+ if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
- label = ParseIdentifier(CHECK_OK);
+ // ECMA allows "eval" or "arguments" as labels even in strict mode.
+ label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
}
// Parse labeled break statements that target themselves into
// empty statements, e.g. 'l1: l2: l3: break l2;'
@@ -2255,7 +2268,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
message = "unknown_label";
args = Vector<Handle<String> >(&label, 1);
}
- ReportMessageAt(scanner().location(), message, args);
+ ParserTraits::ReportMessageAt(scanner()->location(), message, args);
*ok = false;
return NULL;
}
@@ -2277,7 +2290,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
Token::Value tok = peek();
Statement* result;
Expression* return_value;
- if (scanner().HasAnyLineTerminatorBeforeNext() ||
+ if (scanner()->HasAnyLineTerminatorBeforeNext() ||
tok == Token::SEMICOLON ||
tok == Token::RBRACE ||
tok == Token::EOS) {
@@ -2288,7 +2301,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
ExpectSemicolon(CHECK_OK);
if (is_generator()) {
Expression* generator = factory()->NewVariableProxy(
- current_function_state_->generator_object_variable());
+ function_state_->generator_object_variable());
Expression* yield = factory()->NewYield(
generator, return_value, Yield::FINAL, pos);
result = factory()->NewExpressionStatement(yield, pos);
@@ -2301,7 +2314,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
// function. See ECMA-262, section 12.9, page 67.
//
// To be consistent with KJS we report the syntax error at runtime.
- Scope* declaration_scope = top_scope_->DeclarationScope();
+ Scope* declaration_scope = scope_->DeclarationScope();
if (declaration_scope->is_global_scope() ||
declaration_scope->is_eval_scope()) {
Handle<String> message = isolate()->factory()->illegal_return_string();
@@ -2320,7 +2333,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
Expect(Token::WITH, CHECK_OK);
int pos = position();
- if (!top_scope_->is_classic_mode()) {
+ if (!scope_->is_classic_mode()) {
ReportMessage("strict_mode_with", Vector<const char*>::empty());
*ok = false;
return NULL;
@@ -2330,13 +2343,13 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
Expression* expr = ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
- top_scope_->DeclarationScope()->RecordWithStatement();
- Scope* with_scope = NewScope(top_scope_, WITH_SCOPE);
+ scope_->DeclarationScope()->RecordWithStatement();
+ Scope* with_scope = NewScope(scope_, WITH_SCOPE);
Statement* stmt;
- { BlockState block_state(this, with_scope);
- with_scope->set_start_position(scanner().peek_location().beg_pos);
+ { BlockState block_state(&scope_, with_scope);
+ with_scope->set_start_position(scanner()->peek_location().beg_pos);
stmt = ParseStatement(labels, CHECK_OK);
- with_scope->set_end_position(scanner().location().end_pos);
+ with_scope->set_end_position(scanner()->location().end_pos);
}
return factory()->NewWithStatement(with_scope, expr, stmt, pos);
}
@@ -2410,7 +2423,7 @@ Statement* Parser::ParseThrowStatement(bool* ok) {
Expect(Token::THROW, CHECK_OK);
int pos = position();
- if (scanner().HasAnyLineTerminatorBeforeNext()) {
+ if (scanner()->HasAnyLineTerminatorBeforeNext()) {
ReportMessage("newline_after_throw", Vector<const char*>::empty());
*ok = false;
return NULL;
@@ -2465,35 +2478,27 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
Consume(Token::CATCH);
Expect(Token::LPAREN, CHECK_OK);
- catch_scope = NewScope(top_scope_, CATCH_SCOPE);
- catch_scope->set_start_position(scanner().location().beg_pos);
- name = ParseIdentifier(CHECK_OK);
-
- if (!top_scope_->is_classic_mode() && IsEvalOrArguments(name)) {
- ReportMessage("strict_catch_variable", Vector<const char*>::empty());
- *ok = false;
- return NULL;
- }
+ catch_scope = NewScope(scope_, CATCH_SCOPE);
+ catch_scope->set_start_position(scanner()->location().beg_pos);
+ name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
- if (peek() == Token::LBRACE) {
- Target target(&this->target_stack_, &catch_collector);
- VariableMode mode = is_extended_mode() ? LET : VAR;
- catch_variable =
- catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
+ Target target(&this->target_stack_, &catch_collector);
+ VariableMode mode = is_extended_mode() ? LET : VAR;
+ catch_variable =
+ catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
- BlockState block_state(this, catch_scope);
- catch_block = ParseBlock(NULL, CHECK_OK);
- } else {
- Expect(Token::LBRACE, CHECK_OK);
- }
- catch_scope->set_end_position(scanner().location().end_pos);
+ BlockState block_state(&scope_, catch_scope);
+ catch_block = ParseBlock(NULL, CHECK_OK);
+
+ catch_scope->set_end_position(scanner()->location().end_pos);
tok = peek();
}
Block* finally_block = NULL;
- if (tok == Token::FINALLY || catch_block == NULL) {
+ ASSERT(tok == Token::FINALLY || catch_block != NULL);
+ if (tok == Token::FINALLY) {
Consume(Token::FINALLY);
finally_block = ParseBlock(NULL, CHECK_OK);
}
@@ -2506,7 +2511,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
if (catch_block != NULL && finally_block != NULL) {
// If we have both, create an inner try/catch.
ASSERT(catch_scope != NULL && catch_variable != NULL);
- int index = current_function_state_->NextHandlerIndex();
+ int index = function_state_->NextHandlerIndex();
TryCatchStatement* statement = factory()->NewTryCatchStatement(
index, try_block, catch_scope, catch_variable, catch_block,
RelocInfo::kNoPosition);
@@ -2520,12 +2525,12 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
if (catch_block != NULL) {
ASSERT(finally_block == NULL);
ASSERT(catch_scope != NULL && catch_variable != NULL);
- int index = current_function_state_->NextHandlerIndex();
+ int index = function_state_->NextHandlerIndex();
result = factory()->NewTryCatchStatement(
index, try_block, catch_scope, catch_variable, catch_block, pos);
} else {
ASSERT(finally_block != NULL);
- int index = current_function_state_->NextHandlerIndex();
+ int index = function_state_->NextHandlerIndex();
result = factory()->NewTryFinallyStatement(
index, try_block, finally_block, pos);
// Combine the jump targets of the try block and the possible catch block.
@@ -2605,9 +2610,9 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
if (for_of != NULL) {
Factory* heap_factory = isolate()->factory();
- Variable* iterator = top_scope_->DeclarationScope()->NewTemporary(
+ Variable* iterator = scope_->DeclarationScope()->NewTemporary(
heap_factory->dot_iterator_string());
- Variable* result = top_scope_->DeclarationScope()->NewTemporary(
+ Variable* result = scope_->DeclarationScope()->NewTemporary(
heap_factory->dot_result_string());
Expression* assign_iterator;
@@ -2674,13 +2679,13 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Statement* init = NULL;
// Create an in-between scope for let-bound iteration variables.
- Scope* saved_scope = top_scope_;
- Scope* for_scope = NewScope(top_scope_, BLOCK_SCOPE);
- top_scope_ = for_scope;
+ Scope* saved_scope = scope_;
+ Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
+ scope_ = for_scope;
Expect(Token::FOR, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
- for_scope->set_start_position(scanner().location().beg_pos);
+ for_scope->set_start_position(scanner()->location().beg_pos);
if (peek() != Token::SEMICOLON) {
if (peek() == Token::VAR || peek() == Token::CONST) {
bool is_const = peek() == Token::CONST;
@@ -2703,15 +2708,15 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Expect(Token::RPAREN, CHECK_OK);
VariableProxy* each =
- top_scope_->NewUnresolved(factory(), name, interface);
+ scope_->NewUnresolved(factory(), name, interface);
Statement* body = ParseStatement(NULL, CHECK_OK);
InitializeForEachStatement(loop, each, enumerable, body);
Block* result =
factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
result->AddStatement(variable_statement, zone());
result->AddStatement(loop, zone());
- top_scope_ = saved_scope;
- for_scope->set_end_position(scanner().location().end_pos);
+ scope_ = saved_scope;
+ for_scope->set_end_position(scanner()->location().end_pos);
for_scope = for_scope->FinalizeBlockScope();
ASSERT(for_scope == NULL);
// Parsed for-in loop w/ variable/const declaration.
@@ -2749,20 +2754,20 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Handle<String> tempstr =
heap_factory->NewConsString(heap_factory->dot_for_string(), name);
Handle<String> tempname = heap_factory->InternalizeString(tempstr);
- Variable* temp = top_scope_->DeclarationScope()->NewTemporary(tempname);
+ Variable* temp = scope_->DeclarationScope()->NewTemporary(tempname);
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
ForEachStatement* loop =
factory()->NewForEachStatement(mode, labels, pos);
Target target(&this->target_stack_, loop);
// The expression does not see the loop variable.
- top_scope_ = saved_scope;
+ scope_ = saved_scope;
Expression* enumerable = ParseExpression(true, CHECK_OK);
- top_scope_ = for_scope;
+ scope_ = for_scope;
Expect(Token::RPAREN, CHECK_OK);
VariableProxy* each =
- top_scope_->NewUnresolved(factory(), name, Interface::NewValue());
+ scope_->NewUnresolved(factory(), name, Interface::NewValue());
Statement* body = ParseStatement(NULL, CHECK_OK);
Block* body_block =
factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
@@ -2774,8 +2779,8 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
body_block->AddStatement(assignment_statement, zone());
body_block->AddStatement(body, zone());
InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
- top_scope_ = saved_scope;
- for_scope->set_end_position(scanner().location().end_pos);
+ scope_ = saved_scope;
+ for_scope->set_end_position(scanner()->location().end_pos);
for_scope = for_scope->FinalizeBlockScope();
body_block->set_scope(for_scope);
// Parsed for-in loop w/ let declaration.
@@ -2808,8 +2813,8 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Statement* body = ParseStatement(NULL, CHECK_OK);
InitializeForEachStatement(loop, expression, enumerable, body);
- top_scope_ = saved_scope;
- for_scope->set_end_position(scanner().location().end_pos);
+ scope_ = saved_scope;
+ for_scope->set_end_position(scanner()->location().end_pos);
for_scope = for_scope->FinalizeBlockScope();
ASSERT(for_scope == NULL);
// Parsed for-in loop.
@@ -2843,8 +2848,8 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Expect(Token::RPAREN, CHECK_OK);
Statement* body = ParseStatement(NULL, CHECK_OK);
- top_scope_ = saved_scope;
- for_scope->set_end_position(scanner().location().end_pos);
+ scope_ = saved_scope;
+ for_scope->set_end_position(scanner()->location().end_pos);
for_scope = for_scope->FinalizeBlockScope();
if (for_scope != NULL) {
// Rewrite a for statement of the form
@@ -2871,23 +2876,6 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
}
-// Precedence = 1
-Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
- // Expression ::
- // AssignmentExpression
- // Expression ',' AssignmentExpression
-
- Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
- while (peek() == Token::COMMA) {
- Expect(Token::COMMA, CHECK_OK);
- int pos = position();
- Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
- result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos);
- }
- return result;
-}
-
-
// Precedence = 2
Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
// AssignmentExpression ::
@@ -2919,9 +2907,9 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
expression = NewThrowReferenceError(message);
}
- if (!top_scope_->is_classic_mode()) {
+ if (!scope_->is_classic_mode()) {
// Assignment to eval or arguments is disallowed in strict mode.
- CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
+ CheckStrictModeLValue(expression, CHECK_OK);
}
MarkAsLValue(expression);
@@ -2939,7 +2927,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
property != NULL &&
property->obj()->AsVariableProxy() != NULL &&
property->obj()->AsVariableProxy()->is_this()) {
- current_function_state_->AddProperty();
+ function_state_->AddProperty();
}
// If we assign a function literal to a property we pretenure the
@@ -2975,11 +2963,11 @@ Expression* Parser::ParseYieldExpression(bool* ok) {
Yield::Kind kind =
Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND;
Expression* generator_object = factory()->NewVariableProxy(
- current_function_state_->generator_object_variable());
+ function_state_->generator_object_variable());
Expression* expression = ParseAssignmentExpression(false, CHECK_OK);
Yield* yield = factory()->NewYield(generator_object, expression, kind, pos);
if (kind == Yield::DELEGATING) {
- yield->set_index(current_function_state_->NextHandlerIndex());
+ yield->set_index(function_state_->NextHandlerIndex());
}
return yield;
}
@@ -3006,14 +2994,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);
@@ -3151,7 +3131,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
}
// "delete identifier" is a syntax error in strict mode.
- if (op == Token::DELETE && !top_scope_->is_classic_mode()) {
+ if (op == Token::DELETE && !scope_->is_classic_mode()) {
VariableProxy* operand = expression->AsVariableProxy();
if (operand != NULL && !operand->is_this()) {
ReportMessage("strict_delete", Vector<const char*>::empty());
@@ -3199,9 +3179,9 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
expression = NewThrowReferenceError(message);
}
- if (!top_scope_->is_classic_mode()) {
+ if (!scope_->is_classic_mode()) {
// Prefix expression operand in strict mode may not be eval or arguments.
- CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
+ CheckStrictModeLValue(expression, CHECK_OK);
}
MarkAsLValue(expression);
@@ -3221,7 +3201,7 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
// LeftHandSideExpression ('++' | '--')?
Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
- if (!scanner().HasAnyLineTerminatorBeforeNext() &&
+ if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
Token::IsCountOp(peek())) {
// Signal a reference error if the expression is an invalid
// left-hand side expression. We could report this as a syntax
@@ -3233,9 +3213,9 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
expression = NewThrowReferenceError(message);
}
- if (!top_scope_->is_classic_mode()) {
+ if (!scope_->is_classic_mode()) {
// Postfix expression operand in strict mode may not be eval or arguments.
- CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
+ CheckStrictModeLValue(expression, CHECK_OK);
}
MarkAsLValue(expression);
@@ -3254,12 +3234,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
// LeftHandSideExpression ::
// (NewExpression | MemberExpression) ...
- Expression* result;
- if (peek() == Token::NEW) {
- result = ParseNewExpression(CHECK_OK);
- } else {
- result = ParseMemberExpression(CHECK_OK);
- }
+ Expression* result = ParseMemberWithNewPrefixesExpression(CHECK_OK);
while (true) {
switch (peek()) {
@@ -3274,7 +3249,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
case Token::LPAREN: {
int pos;
- if (scanner().current_token() == Token::IDENTIFIER) {
+ if (scanner()->current_token() == Token::IDENTIFIER) {
// For call of an identifier we want to report position of
// the identifier as position of the call in the stack trace.
pos = position();
@@ -3304,7 +3279,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
VariableProxy* callee = result->AsVariableProxy();
if (callee != NULL &&
callee->IsVariable(isolate()->factory()->eval_string())) {
- top_scope_->DeclarationScope()->RecordEvalCall();
+ scope_->DeclarationScope()->RecordEvalCall();
}
result = factory()->NewCall(result, args, pos);
if (fni_ != NULL) fni_->RemoveLastFunction();
@@ -3328,70 +3303,73 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
}
-Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
+Expression* Parser::ParseMemberWithNewPrefixesExpression(bool* ok) {
// NewExpression ::
// ('new')+ MemberExpression
- // The grammar for new expressions is pretty warped. The keyword
- // 'new' can either be a part of the new expression (where it isn't
- // followed by an argument list) or a part of the member expression,
- // where it must be followed by an argument list. To accommodate
- // this, we parse the 'new' keywords greedily and keep track of how
- // many we have parsed. This information is then passed on to the
- // member expression parser, which is only allowed to match argument
- // lists as long as it has 'new' prefixes left
- Expect(Token::NEW, CHECK_OK);
- PositionStack::Element pos(stack, position());
-
- Expression* result;
- if (peek() == Token::NEW) {
- result = ParseNewPrefix(stack, CHECK_OK);
- } else {
- result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
- }
-
- if (!stack->is_empty()) {
- int last = stack->pop();
- result = factory()->NewCallNew(
- result, new(zone()) ZoneList<Expression*>(0, zone()), last);
- }
- return result;
-}
+ // The grammar for new expressions is pretty warped. We can have several 'new'
+ // keywords following each other, and then a MemberExpression. When we see '('
+ // after the MemberExpression, it's associated with the rightmost unassociated
+ // 'new' to create a NewExpression with arguments. However, a NewExpression
+ // can also occur without arguments.
+ // Examples of new expression:
+ // new foo.bar().baz means (new (foo.bar)()).baz
+ // new foo()() means (new foo())()
+ // new new foo()() means (new (new foo())())
+ // new new foo means new (new foo)
+ // new new foo() means new (new foo())
+ // new new foo().bar().baz means (new (new foo()).bar()).baz
-Expression* Parser::ParseNewExpression(bool* ok) {
- PositionStack stack(ok);
- return ParseNewPrefix(&stack, ok);
+ if (peek() == Token::NEW) {
+ Consume(Token::NEW);
+ int new_pos = position();
+ Expression* result = ParseMemberWithNewPrefixesExpression(CHECK_OK);
+ if (peek() == Token::LPAREN) {
+ // NewExpression with arguments.
+ ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
+ result = factory()->NewCallNew(result, args, new_pos);
+ // The expression can still continue with . or [ after the arguments.
+ result = ParseMemberExpressionContinuation(result, CHECK_OK);
+ return result;
+ }
+ // NewExpression without arguments.
+ return factory()->NewCallNew(
+ result, new(zone()) ZoneList<Expression*>(0, zone()), new_pos);
+ }
+ // No 'new' keyword.
+ return ParseMemberExpression(ok);
}
Expression* Parser::ParseMemberExpression(bool* ok) {
- return ParseMemberWithNewPrefixesExpression(NULL, ok);
-}
-
-
-Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
- bool* ok) {
// MemberExpression ::
// (PrimaryExpression | FunctionLiteral)
// ('[' Expression ']' | '.' Identifier | Arguments)*
+ // The '[' Expression ']' and '.' Identifier parts are parsed by
+ // ParseMemberExpressionContinuation, and the Arguments part is parsed by the
+ // caller.
+
// Parse the initial primary or function expression.
Expression* result = NULL;
if (peek() == Token::FUNCTION) {
- Expect(Token::FUNCTION, CHECK_OK);
+ Consume(Token::FUNCTION);
int function_token_position = position();
bool is_generator = allow_generators() && Check(Token::MUL);
Handle<String> name;
bool is_strict_reserved_name = false;
+ Scanner::Location function_name_location = Scanner::Location::invalid();
if (peek_any_identifier()) {
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
CHECK_OK);
+ function_name_location = scanner()->location();
}
FunctionLiteral::FunctionType function_type = name.is_null()
? FunctionLiteral::ANONYMOUS_EXPRESSION
: FunctionLiteral::NAMED_EXPRESSION;
result = ParseFunctionLiteral(name,
+ function_name_location,
is_strict_reserved_name,
is_generator,
function_token_position,
@@ -3401,13 +3379,22 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
result = ParsePrimaryExpression(CHECK_OK);
}
+ result = ParseMemberExpressionContinuation(result, CHECK_OK);
+ return result;
+}
+
+
+Expression* Parser::ParseMemberExpressionContinuation(Expression* expression,
+ bool* ok) {
+ // Parses this part of MemberExpression:
+ // ('[' Expression ']' | '.' Identifier)*
while (true) {
switch (peek()) {
case Token::LBRACK: {
Consume(Token::LBRACK);
int pos = position();
Expression* index = ParseExpression(true, CHECK_OK);
- result = factory()->NewProperty(result, index, pos);
+ expression = factory()->NewProperty(expression, index, pos);
if (fni_ != NULL) {
if (index->IsPropertyName()) {
fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
@@ -3423,23 +3410,17 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
Consume(Token::PERIOD);
int pos = position();
Handle<String> name = ParseIdentifierName(CHECK_OK);
- result = factory()->NewProperty(
- result, factory()->NewLiteral(name, pos), pos);
+ expression = factory()->NewProperty(
+ expression, factory()->NewLiteral(name, pos), pos);
if (fni_ != NULL) fni_->PushLiteralName(name);
break;
}
- case Token::LPAREN: {
- if ((stack == NULL) || stack->is_empty()) return result;
- // Consume one of the new prefixes (already parsed).
- ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
- int pos = stack->pop();
- result = factory()->NewCallNew(result, args, pos);
- break;
- }
default:
- return result;
+ return expression;
}
}
+ ASSERT(false);
+ return NULL;
}
@@ -3457,41 +3438,6 @@ DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
}
-void Parser::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/ParseJson.
- if (token == Token::ILLEGAL && stack_overflow()) return;
- // Four of the tokens are treated specially
- switch (token) {
- case Token::EOS:
- return ReportMessage("unexpected_eos", Vector<const char*>::empty());
- case Token::NUMBER:
- return ReportMessage("unexpected_token_number",
- Vector<const char*>::empty());
- case Token::STRING:
- return ReportMessage("unexpected_token_string",
- Vector<const char*>::empty());
- case Token::IDENTIFIER:
- return ReportMessage("unexpected_token_identifier",
- Vector<const char*>::empty());
- case Token::FUTURE_RESERVED_WORD:
- return ReportMessage("unexpected_reserved",
- Vector<const char*>::empty());
- case Token::YIELD:
- case Token::FUTURE_STRICT_RESERVED_WORD:
- return ReportMessage(top_scope_->is_classic_mode() ?
- "unexpected_token_identifier" :
- "unexpected_strict_reserved",
- Vector<const char*>::empty());
- default:
- const char* name = Token::String(token);
- ASSERT(name != NULL);
- ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
- }
-}
-
-
void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
SmartArrayPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
const char* element[1] = { name_string.get() };
@@ -3501,151 +3447,6 @@ void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
}
-Expression* Parser::ParsePrimaryExpression(bool* ok) {
- // PrimaryExpression ::
- // 'this'
- // 'null'
- // 'true'
- // 'false'
- // Identifier
- // Number
- // String
- // ArrayLiteral
- // ObjectLiteral
- // RegExpLiteral
- // '(' Expression ')'
-
- int pos = peek_position();
- Expression* result = NULL;
- switch (peek()) {
- case Token::THIS: {
- Consume(Token::THIS);
- result = factory()->NewVariableProxy(top_scope_->receiver());
- break;
- }
-
- case Token::NULL_LITERAL:
- Consume(Token::NULL_LITERAL);
- result = factory()->NewLiteral(isolate()->factory()->null_value(), pos);
- break;
-
- case Token::TRUE_LITERAL:
- Consume(Token::TRUE_LITERAL);
- result = factory()->NewLiteral(isolate()->factory()->true_value(), pos);
- break;
-
- case Token::FALSE_LITERAL:
- Consume(Token::FALSE_LITERAL);
- result = factory()->NewLiteral(isolate()->factory()->false_value(), pos);
- break;
-
- case Token::IDENTIFIER:
- case Token::YIELD:
- case Token::FUTURE_STRICT_RESERVED_WORD: {
- Handle<String> name = ParseIdentifier(CHECK_OK);
- if (fni_ != NULL) fni_->PushVariableName(name);
- // The name may refer to a module instance object, so its type is unknown.
-#ifdef DEBUG
- if (FLAG_print_interface_details)
- PrintF("# Variable %s ", name->ToAsciiArray());
-#endif
- Interface* interface = Interface::NewUnknown(zone());
- result = top_scope_->NewUnresolved(factory(), name, interface, pos);
- break;
- }
-
- case Token::NUMBER: {
- Consume(Token::NUMBER);
- ASSERT(scanner().is_literal_ascii());
- double value = StringToDouble(isolate()->unicode_cache(),
- scanner().literal_ascii_string(),
- ALLOW_HEX | ALLOW_OCTAL |
- ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
- result = factory()->NewNumberLiteral(value, pos);
- break;
- }
-
- case Token::STRING: {
- Consume(Token::STRING);
- Handle<String> symbol = GetSymbol();
- result = factory()->NewLiteral(symbol, pos);
- if (fni_ != NULL) fni_->PushLiteralName(symbol);
- break;
- }
-
- case Token::ASSIGN_DIV:
- result = ParseRegExpLiteral(true, CHECK_OK);
- break;
-
- case Token::DIV:
- result = ParseRegExpLiteral(false, CHECK_OK);
- break;
-
- case Token::LBRACK:
- result = ParseArrayLiteral(CHECK_OK);
- break;
-
- case Token::LBRACE:
- result = ParseObjectLiteral(CHECK_OK);
- break;
-
- case Token::LPAREN:
- Consume(Token::LPAREN);
- // Heuristically try to detect immediately called functions before
- // seeing the call parentheses.
- parenthesized_function_ = (peek() == Token::FUNCTION);
- result = ParseExpression(true, CHECK_OK);
- Expect(Token::RPAREN, CHECK_OK);
- break;
-
- case Token::MOD:
- if (allow_natives_syntax() || extension_ != NULL) {
- result = ParseV8Intrinsic(CHECK_OK);
- break;
- }
- // If we're not allowing special syntax we fall-through to the
- // default case.
-
- default: {
- Token::Value tok = Next();
- ReportUnexpectedToken(tok);
- *ok = false;
- return NULL;
- }
- }
-
- return result;
-}
-
-
-Expression* Parser::ParseArrayLiteral(bool* ok) {
- // ArrayLiteral ::
- // '[' Expression? (',' Expression?)* ']'
-
- int pos = peek_position();
- ZoneList<Expression*>* values = new(zone()) ZoneList<Expression*>(4, zone());
- Expect(Token::LBRACK, CHECK_OK);
- while (peek() != Token::RBRACK) {
- Expression* elem;
- if (peek() == Token::COMMA) {
- elem = GetLiteralTheHole(peek_position());
- } else {
- elem = ParseAssignmentExpression(true, CHECK_OK);
- }
- values->Add(elem, zone());
- if (peek() != Token::RBRACK) {
- Expect(Token::COMMA, CHECK_OK);
- }
- }
- Expect(Token::RBRACK, CHECK_OK);
-
- // Update the scope information before the pre-parsing bailout.
- int literal_index = current_function_state_->NextMaterializedLiteralIndex();
-
- return factory()->NewArrayLiteral(values, literal_index, pos);
-}
-
-
bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
if (expression->AsLiteral() != NULL) return true;
MaterializedLiteral* lit = expression->AsMaterializedLiteral();
@@ -3702,7 +3503,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
int number_of_boilerplate_properties = 0;
bool has_function = false;
- ObjectLiteralChecker checker(this, top_scope_->language_mode());
+ ObjectLiteralChecker checker(this, scope_->language_mode());
Expect(Token::LBRACE, CHECK_OK);
@@ -3748,6 +3549,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
: GetSymbol();
FunctionLiteral* value =
ParseFunctionLiteral(name,
+ scanner()->location(),
false, // reserved words are allowed here
false, // not a generator
RelocInfo::kNoPosition,
@@ -3788,9 +3590,9 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
}
case Token::NUMBER: {
Consume(Token::NUMBER);
- ASSERT(scanner().is_literal_ascii());
+ ASSERT(scanner()->is_literal_ascii());
double value = StringToDouble(isolate()->unicode_cache(),
- scanner().literal_ascii_string(),
+ scanner()->literal_ascii_string(),
ALLOW_HEX | ALLOW_OCTAL |
ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
key = factory()->NewNumberLiteral(value, next_pos);
@@ -3817,12 +3619,12 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
Expression* value = ParseAssignmentExpression(true, CHECK_OK);
ObjectLiteral::Property* property =
- new(zone()) ObjectLiteral::Property(key, value, isolate());
+ factory()->NewObjectLiteralProperty(key, value);
// Mark top-level object literals that contain function literals and
// pretenure the literal so it can be added as a constant function
// property.
- if (top_scope_->DeclarationScope()->is_global_scope() &&
+ if (scope_->DeclarationScope()->is_global_scope() &&
value->AsFunctionLiteral() != NULL) {
has_function = true;
value->AsFunctionLiteral()->set_pretenure();
@@ -3845,7 +3647,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
Expect(Token::RBRACE, CHECK_OK);
// Computation of literal_index must happen before pre parse bailout.
- int literal_index = current_function_state_->NextMaterializedLiteralIndex();
+ int literal_index = function_state_->NextMaterializedLiteralIndex();
return factory()->NewObjectLiteral(properties,
literal_index,
@@ -3855,26 +3657,6 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
}
-Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
- int pos = peek_position();
- if (!scanner().ScanRegExpPattern(seen_equal)) {
- Next();
- ReportMessage("unterminated_regexp", Vector<const char*>::empty());
- *ok = false;
- return NULL;
- }
-
- int literal_index = current_function_state_->NextMaterializedLiteralIndex();
-
- Handle<String> js_pattern = NextLiteralString(TENURED);
- scanner().ScanRegExpFlags();
- Handle<String> js_flags = NextLiteralString(TENURED);
- Next();
-
- return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
-}
-
-
ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
// Arguments ::
// '(' (AssignmentExpression)*[','] ')'
@@ -3886,8 +3668,7 @@ 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",
- Vector<const char*>::empty());
+ ReportMessageAt(scanner()->location(), "too_many_arguments");
*ok = false;
return NULL;
}
@@ -3994,6 +3775,7 @@ class SingletonLogger : public ParserRecorder {
FunctionLiteral* Parser::ParseFunctionLiteral(
Handle<String> function_name,
+ Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
int function_token_pos,
@@ -4043,14 +3825,14 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// one relative to the deserialized scope chain. Otherwise we must be
// compiling a function in an inner declaration scope in the eval, e.g. a
// nested function, and hoisting works normally relative to that.
- Scope* declaration_scope = top_scope_->DeclarationScope();
+ Scope* declaration_scope = scope_->DeclarationScope();
Scope* original_declaration_scope = original_scope_->DeclarationScope();
Scope* scope =
function_type == FunctionLiteral::DECLARATION && !is_extended_mode() &&
(original_scope_ == original_declaration_scope ||
declaration_scope != original_declaration_scope)
? NewScope(declaration_scope, FUNCTION_SCOPE)
- : NewScope(top_scope_, FUNCTION_SCOPE);
+ : NewScope(scope_, FUNCTION_SCOPE);
ZoneList<Statement*>* body = NULL;
int materialized_literal_count = -1;
int expected_property_count = -1;
@@ -4063,23 +3845,23 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
FunctionLiteral::IsGeneratorFlag generator = is_generator
? FunctionLiteral::kIsGenerator
: FunctionLiteral::kNotGenerator;
+ DeferredFeedbackSlotProcessor* slot_processor;
AstProperties ast_properties;
BailoutReason dont_optimize_reason = kNoReason;
// Parse function body.
- { FunctionState function_state(this, scope, isolate());
- top_scope_->SetScopeName(function_name);
+ { FunctionState function_state(&function_state_, &scope_, scope, zone());
+ scope_->SetScopeName(function_name);
if (is_generator) {
// For generators, allocating variables in contexts is currently a win
// because it minimizes the work needed to suspend and resume an
// activation.
- top_scope_->ForceContextAllocation();
+ scope_->ForceContextAllocation();
// Calling a generator returns a generator object. That object is stored
// in a temporary variable, a definition that is used by "yield"
- // expressions. Presence of a variable for the generator object in the
- // FunctionState indicates that this function is a generator.
- Variable* temp = top_scope_->DeclarationScope()->NewTemporary(
+ // expressions. This also marks the FunctionState as a generator.
+ Variable* temp = scope_->DeclarationScope()->NewTemporary(
isolate()->factory()->dot_generator_object_string());
function_state.set_generator_object_variable(temp);
}
@@ -4087,10 +3869,14 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// FormalParameterList ::
// '(' (Identifier)*[','] ')'
Expect(Token::LPAREN, CHECK_OK);
- scope->set_start_position(scanner().location().beg_pos);
- ScannerBase::Location name_loc = ScannerBase::Location::invalid();
- ScannerBase::Location dupe_loc = ScannerBase::Location::invalid();
- ScannerBase::Location reserved_loc = ScannerBase::Location::invalid();
+ scope->set_start_position(scanner()->location().beg_pos);
+
+ // We don't yet know if the function will be strict, so we cannot yet
+ // produce errors for parameter names or duplicates. However, we remember
+ // the locations of these errors if they occur and produce the errors later.
+ Scanner::Location eval_args_error_log = Scanner::Location::invalid();
+ Scanner::Location dupe_error_loc = Scanner::Location::invalid();
+ Scanner::Location reserved_loc = Scanner::Location::invalid();
bool done = (peek() == Token::RPAREN);
while (!done) {
@@ -4099,22 +3885,21 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
// Store locations for possible future error reports.
- if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
- name_loc = scanner().location();
- }
- if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
- duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
- dupe_loc = scanner().location();
+ if (!eval_args_error_log.IsValid() && IsEvalOrArguments(param_name)) {
+ eval_args_error_log = scanner()->location();
}
if (!reserved_loc.IsValid() && is_strict_reserved) {
- reserved_loc = scanner().location();
+ reserved_loc = scanner()->location();
+ }
+ if (!dupe_error_loc.IsValid() && scope_->IsDeclared(param_name)) {
+ duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
+ dupe_error_loc = scanner()->location();
}
- top_scope_->DeclareParameter(param_name, VAR);
+ scope_->DeclareParameter(param_name, VAR);
num_parameters++;
if (num_parameters > Code::kMaxArguments) {
- ReportMessageAt(scanner().location(), "too_many_parameters",
- Vector<const char*>::empty());
+ ReportMessageAt(scanner()->location(), "too_many_parameters");
*ok = false;
return NULL;
}
@@ -4136,17 +3921,20 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
if (is_extended_mode()) fvar_init_op = Token::INIT_CONST_HARMONY;
VariableMode fvar_mode = is_extended_mode() ? CONST_HARMONY : CONST;
- fvar = new(zone()) Variable(top_scope_,
+ fvar = new(zone()) Variable(scope_,
function_name, fvar_mode, true /* is valid LHS */,
Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
VariableProxy* proxy = factory()->NewVariableProxy(fvar);
VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
- proxy, fvar_mode, top_scope_, RelocInfo::kNoPosition);
- top_scope_->DeclareFunctionVar(fvar_declaration);
+ proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
+ scope_->DeclareFunctionVar(fvar_declaration);
}
- // Determine whether the function will be lazily compiled.
- // The heuristics are:
+ // Determine if the function can be parsed lazily. Lazy parsing is different
+ // from lazy compilation; we need to parse more eagerly than we compile.
+
+ // We can only parse lazily if we also compile lazily. The heuristics for
+ // lazy compilation are:
// - It must not have been prohibited by the caller to Parse (some callers
// need a full AST).
// - The outer scope must allow lazy compilation of inner functions.
@@ -4156,12 +3944,31 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// compiled.
// These are all things we can know at this point, without looking at the
// function itself.
- bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
- top_scope_->AllowsLazyCompilation() &&
- !parenthesized_function_);
+
+ // In addition, we need to distinguish between these cases:
+ // (function foo() {
+ // bar = function() { return 1; }
+ // })();
+ // and
+ // (function foo() {
+ // var a = 1;
+ // bar = function() { return a; }
+ // })();
+
+ // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
+ // parenthesis before the function means that it will be called
+ // immediately). The inner function *must* be parsed eagerly to resolve the
+ // possible reference to the variable in foo's scope. However, it's possible
+ // that it will be compiled lazily.
+
+ // To make this additional case work, both Parser and PreParser implement a
+ // logic where only top-level functions will be parsed lazily.
+ bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
+ scope_->AllowsLazyCompilation() &&
+ !parenthesized_function_);
parenthesized_function_ = false; // The bit was set for this function only.
- if (is_lazily_compiled) {
+ if (is_lazily_parsed) {
int function_block_pos = position();
FunctionEntry entry;
if (pre_parse_data_ != NULL) {
@@ -4175,7 +3982,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// to check.
ReportInvalidPreparseData(function_name, CHECK_OK);
}
- scanner().SeekForward(entry.end_pos() - 1);
+ scanner()->SeekForward(entry.end_pos() - 1);
scope->set_end_position(entry.end_pos());
Expect(Token::RBRACE, CHECK_OK);
@@ -4183,9 +3990,22 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
scope->end_position() - function_block_pos);
materialized_literal_count = entry.literal_count();
expected_property_count = entry.property_count();
- top_scope_->SetLanguageMode(entry.language_mode());
+ scope_->SetLanguageMode(entry.language_mode());
} else {
- is_lazily_compiled = false;
+ // This case happens when we have preparse data but it doesn't contain
+ // an entry for the function. As a safety net, fall back to eager
+ // parsing. It is unclear whether PreParser's laziness analysis can
+ // produce different results than the Parser's laziness analysis (see
+ // https://codereview.chromium.org/7565003 ). This safety net is
+ // guarding against the case where Parser thinks a function should be
+ // lazily parsed, but PreParser thinks it should be eagerly parsed --
+ // in that case we fall back to eager parsing in Parser, too. Note
+ // that the opposite case is worse: if PreParser thinks a function
+ // should be lazily parsed, but Parser thinks it should be eagerly
+ // parsed, it will never advance the preparse data beyond that
+ // function and all further laziness will fail (all functions will be
+ // parsed eagerly).
+ is_lazily_parsed = false;
}
} else {
// With no preparser data, we partially parse the function, without
@@ -4205,8 +4025,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
if (arg != NULL) {
args = Vector<const char*>(&arg, 1);
}
- ReportMessageAt(ScannerBase::Location(logger.start(), logger.end()),
- logger.message(), args);
+ ParserTraits::ReportMessageAt(
+ Scanner::Location(logger.start(), logger.end()),
+ logger.message(),
+ args);
*ok = false;
return NULL;
}
@@ -4216,15 +4038,17 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
scope->end_position() - function_block_pos);
materialized_literal_count = logger.literals();
expected_property_count = logger.properties();
- top_scope_->SetLanguageMode(logger.language_mode());
+ scope_->SetLanguageMode(logger.language_mode());
}
}
- if (!is_lazily_compiled) {
+ if (!is_lazily_parsed) {
+ // Everything inside an eagerly parsed function will be parsed eagerly
+ // (see comment above).
ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
body = new(zone()) ZoneList<Statement*>(8, zone());
if (fvar != NULL) {
- VariableProxy* fproxy = top_scope_->NewUnresolved(
+ VariableProxy* fproxy = scope_->NewUnresolved(
factory(), function_name, Interface::NewConst());
fproxy->BindTo(fvar);
body->Add(factory()->NewExpressionStatement(
@@ -4244,11 +4068,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject),
arguments, pos);
VariableProxy* init_proxy = factory()->NewVariableProxy(
- current_function_state_->generator_object_variable());
+ function_state_->generator_object_variable());
Assignment* assignment = factory()->NewAssignment(
Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
VariableProxy* get_proxy = factory()->NewVariableProxy(
- current_function_state_->generator_object_variable());
+ function_state_->generator_object_variable());
Yield* yield = factory()->NewYield(
get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition);
body->Add(factory()->NewExpressionStatement(
@@ -4259,7 +4083,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
if (is_generator) {
VariableProxy* get_proxy = factory()->NewVariableProxy(
- current_function_state_->generator_object_variable());
+ function_state_->generator_object_variable());
Expression *undefined = factory()->NewLiteral(
isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
Yield* yield = factory()->NewYield(
@@ -4273,48 +4097,34 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
handler_count = function_state.handler_count();
Expect(Token::RBRACE, CHECK_OK);
- scope->set_end_position(scanner().location().end_pos);
+ scope->set_end_position(scanner()->location().end_pos);
}
- // Validate strict mode.
- if (!top_scope_->is_classic_mode()) {
+ // Validate strict mode. We can do this only after parsing the function,
+ // since the function can declare itself strict.
+ if (!scope_->is_classic_mode()) {
if (IsEvalOrArguments(function_name)) {
- int start_pos = scope->start_position();
- int position = function_token_pos != RelocInfo::kNoPosition
- ? function_token_pos : (start_pos > 0 ? start_pos - 1 : start_pos);
- ScannerBase::Location location =
- ScannerBase::Location(position, start_pos);
- ReportMessageAt(location,
- "strict_function_name", Vector<const char*>::empty());
+ ReportMessageAt(function_name_location, "strict_eval_arguments");
*ok = false;
return NULL;
}
- if (name_loc.IsValid()) {
- ReportMessageAt(name_loc, "strict_param_name",
- Vector<const char*>::empty());
+ if (name_is_strict_reserved) {
+ ReportMessageAt(function_name_location, "unexpected_strict_reserved");
*ok = false;
return NULL;
}
- if (dupe_loc.IsValid()) {
- ReportMessageAt(dupe_loc, "strict_param_dupe",
- Vector<const char*>::empty());
+ if (eval_args_error_log.IsValid()) {
+ ReportMessageAt(eval_args_error_log, "strict_eval_arguments");
*ok = false;
return NULL;
}
- if (name_is_strict_reserved) {
- int start_pos = scope->start_position();
- int position = function_token_pos != RelocInfo::kNoPosition
- ? function_token_pos : (start_pos > 0 ? start_pos - 1 : start_pos);
- ScannerBase::Location location =
- ScannerBase::Location(position, start_pos);
- ReportMessageAt(location, "strict_reserved_word",
- Vector<const char*>::empty());
+ if (dupe_error_loc.IsValid()) {
+ ReportMessageAt(dupe_error_loc, "strict_param_dupe");
*ok = false;
return NULL;
}
if (reserved_loc.IsValid()) {
- ReportMessageAt(reserved_loc, "strict_reserved_word",
- Vector<const char*>::empty());
+ ReportMessageAt(reserved_loc, "unexpected_strict_reserved");
*ok = false;
return NULL;
}
@@ -4323,6 +4133,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
CHECK_OK);
}
ast_properties = *factory()->visitor()->ast_properties();
+ slot_processor = factory()->visitor()->slot_processor();
dont_optimize_reason = factory()->visitor()->dont_optimize_reason();
}
@@ -4346,6 +4157,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
pos);
function_literal->set_function_token_position(function_token_pos);
function_literal->set_ast_properties(&ast_properties);
+ function_literal->set_slot_processor(slot_processor);
function_literal->set_dont_optimize_reason(dont_optimize_reason);
if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
@@ -4356,11 +4168,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
SingletonLogger* logger) {
HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse());
- ASSERT_EQ(Token::LBRACE, scanner().current_token());
+ ASSERT_EQ(Token::LBRACE, scanner()->current_token());
if (reusable_preparser_ == NULL) {
intptr_t stack_limit = isolate()->stack_guard()->real_climit();
- reusable_preparser_ = new PreParser(scanner_, NULL, stack_limit);
+ reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit);
reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
reusable_preparser_->set_allow_modules(allow_modules());
reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax());
@@ -4371,7 +4183,7 @@ PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
allow_harmony_numeric_literals());
}
PreParser::PreParseResult result =
- reusable_preparser_->PreParseLazyFunction(top_scope_->language_mode(),
+ reusable_preparser_->PreParseLazyFunction(scope_->language_mode(),
is_generator(),
logger);
return result;
@@ -4384,13 +4196,14 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
int pos = peek_position();
Expect(Token::MOD, CHECK_OK);
- Handle<String> name = ParseIdentifier(CHECK_OK);
+ // Allow "eval" or "arguments" for backward compatibility.
+ Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
if (extension_ != NULL) {
// The extension structures are only accessible while parsing the
// very first time not when reparsing because of lazy compilation.
- top_scope_->DeclarationScope()->ForceEagerCompilation();
+ scope_->DeclarationScope()->ForceEagerCompilation();
}
const Runtime::Function* function = Runtime::FunctionForName(name);
@@ -4422,7 +4235,8 @@ 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));
+ ParserTraits::ReportMessage("not_defined",
+ Vector<Handle<String> >(&name, 1));
*ok = false;
return NULL;
}
@@ -4432,114 +4246,12 @@ 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;
- }
-}
-
-
Literal* Parser::GetLiteralUndefined(int position) {
return factory()->NewLiteral(
isolate()->factory()->undefined_value(), position);
}
-Literal* Parser::GetLiteralTheHole(int position) {
- return factory()->NewLiteral(
- isolate()->factory()->the_hole_value(), RelocInfo::kNoPosition);
-}
-
-
-// Parses an identifier that is valid for the current scope, in particular it
-// fails on strict mode future reserved keywords in a strict scope.
-Handle<String> Parser::ParseIdentifier(bool* ok) {
- Token::Value next = Next();
- if (next == Token::IDENTIFIER ||
- (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()
@@ -4552,27 +4264,14 @@ void Parser::MarkAsLValue(Expression* expression) {
// Checks LHS expression for assignment and prefix/postfix increment/decrement
// in strict mode.
void Parser::CheckStrictModeLValue(Expression* expression,
- const char* error,
bool* ok) {
- ASSERT(!top_scope_->is_classic_mode());
+ ASSERT(!scope_->is_classic_mode());
VariableProxy* lhs = expression != NULL
? expression->AsVariableProxy()
: NULL;
if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
- ReportMessage(error, 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) {
- ScannerBase::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();
+ ReportMessage("strict_eval_arguments", Vector<const char*>::empty());
*ok = false;
}
}
@@ -4588,31 +4287,15 @@ void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
const char* elms[2] = { "Variable", c_string.get() };
Vector<const char*> args(elms, 2);
int position = decl->proxy()->position();
- ScannerBase::Location location = position == RelocInfo::kNoPosition
- ? ScannerBase::Location::invalid()
- : ScannerBase::Location(position, position + 1);
- ReportMessageAt(location, "redeclaration", args);
+ Scanner::Location location = position == RelocInfo::kNoPosition
+ ? Scanner::Location::invalid()
+ : Scanner::Location(position, position + 1);
+ ParserTraits::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
@@ -5594,38 +5277,29 @@ int ScriptDataImpl::ReadNumber(byte** source) {
}
-// Create a ScannerBase for the preparser to use as input, and preparse the
-// source.
+// Create a Scanner for the preparser to use as input, and preparse the source.
ScriptDataImpl* PreParserApi::PreParse(Isolate* isolate,
- Handle<String> source) {
+ Utf16CharacterStream* source) {
CompleteParserRecorder recorder;
HistogramTimerScope timer(isolate->counters()->pre_parse());
- source = FlattenGetString(source);
- ScannerBase* scanner = NULL;
- if (source->IsTwoByteRepresentation()) {
- scanner = new ExperimentalScanner<uint16_t>(source, isolate);
- } else {
- scanner = new ExperimentalScanner<uint8_t>(source, isolate);
- }
+ Scanner scanner(isolate->unicode_cache());
intptr_t stack_limit = isolate->stack_guard()->real_climit();
- PreParser preparser(scanner, &recorder, stack_limit);
+ PreParser preparser(&scanner, &recorder, stack_limit);
preparser.set_allow_lazy(true);
preparser.set_allow_generators(FLAG_harmony_generators);
preparser.set_allow_for_of(FLAG_harmony_iteration);
preparser.set_allow_harmony_scoping(FLAG_harmony_scoping);
preparser.set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
- scanner->Init();
+ scanner.Initialize(source);
PreParser::PreParseResult result = preparser.PreParseProgram();
if (result == PreParser::kPreParseStackOverflow) {
isolate->StackOverflow();
- delete scanner;
return NULL;
}
// Extract the accumulated data from the recorder as a single
// contiguous vector that we are responsible for disposing.
Vector<unsigned> store = recorder.ExtractData();
- delete scanner;
return new ScriptDataImpl(store);
}
@@ -5667,10 +5341,10 @@ bool Parser::Parse() {
ScriptDataImpl* pre_parse_data = info()->pre_parse_data();
set_pre_parse_data(pre_parse_data);
if (pre_parse_data != NULL && pre_parse_data->has_error()) {
- ScannerBase::Location loc = pre_parse_data->MessageLocation();
+ Scanner::Location loc = pre_parse_data->MessageLocation();
const char* message = pre_parse_data->BuildMessage();
Vector<const char*> args = pre_parse_data->BuildArgs();
- ReportMessageAt(loc, message, args);
+ ParserTraits::ReportMessageAt(loc, message, args);
DeleteArray(message);
for (int i = 0; i < args.length(); i++) {
DeleteArray(args[i]);
@@ -5685,11 +5359,4 @@ bool Parser::Parse() {
return (result != NULL);
}
-
-void Parser::SetScannerFlags() {
- scanner_->SetHarmonyScoping(allow_harmony_scoping_);
- scanner_->SetHarmonyModules(allow_harmony_modules_);
- scanner_->SetHarmonyNumericLiterals(allow_harmony_numeric_literals_);
-}
-
} } // namespace v8::internal
« no previous file with comments | « src/parser.h ('k') | src/platform.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698