Commit cd50687b authored by marja@chromium.org's avatar marja@chromium.org

(Pre)Parser: Move ParsePrimaryExpression to ParserBase.

Notes:
- To be able to move the recursive descent functions to ParserBase one at a
time, we temporarily need routing functions from traits to Parser/PreParser,
since the recursive descent functions form a cyclic structure.
- PreParser used to always allow intrinsic syntax. After this CL, it depends on
allow_natives_syntax() which was already in ParserBase.
- This CL also decouples (Pre)ParserTraits better from (Pre)Parser, passing more
information as parameters, so that the Traits don't need to get it from
(Pre)Parser.
R=ulan@chromium.org
BUG=v8:3126
LOG=N

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19374 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4c2626a0
...@@ -535,7 +535,7 @@ void ParserTraits::ReportMessageAt(Scanner::Location source_location, ...@@ -535,7 +535,7 @@ void ParserTraits::ReportMessageAt(Scanner::Location source_location,
} }
Handle<String> ParserTraits::GetSymbol() { Handle<String> ParserTraits::GetSymbol(Scanner* scanner) {
int symbol_id = -1; int symbol_id = -1;
if (parser_->pre_parse_data() != NULL) { if (parser_->pre_parse_data() != NULL) {
symbol_id = parser_->pre_parse_data()->GetSymbolIdentifier(); symbol_id = parser_->pre_parse_data()->GetSymbolIdentifier();
...@@ -544,21 +544,99 @@ Handle<String> ParserTraits::GetSymbol() { ...@@ -544,21 +544,99 @@ Handle<String> ParserTraits::GetSymbol() {
} }
Handle<String> ParserTraits::NextLiteralString(PretenureFlag tenured) { Handle<String> ParserTraits::NextLiteralString(Scanner* scanner,
Scanner& scanner = parser_->scanner(); PretenureFlag tenured) {
if (scanner.is_next_literal_ascii()) { if (scanner->is_next_literal_ascii()) {
return parser_->isolate_->factory()->NewStringFromAscii( return parser_->isolate_->factory()->NewStringFromAscii(
scanner.next_literal_ascii_string(), tenured); scanner->next_literal_ascii_string(), tenured);
} else { } else {
return parser_->isolate_->factory()->NewStringFromTwoByte( return parser_->isolate_->factory()->NewStringFromTwoByte(
scanner.next_literal_utf16_string(), tenured); 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);
}
Expression* ParserTraits::ParseArrayLiteral(bool* ok) {
return parser_->ParseArrayLiteral(ok);
}
Expression* ParserTraits::ParseObjectLiteral(bool* ok) {
return parser_->ParseObjectLiteral(ok);
}
Expression* ParserTraits::ParseExpression(bool accept_IN, bool* ok) {
return parser_->ParseExpression(accept_IN, ok);
}
Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
return parser_->ParseV8Intrinsic(ok);
}
Parser::Parser(CompilationInfo* info) Parser::Parser(CompilationInfo* info)
: ParserBase<ParserTraits>(&scanner_, : ParserBase<ParserTraits>(&scanner_,
info->isolate()->stack_guard()->real_climit(), info->isolate()->stack_guard()->real_climit(),
info->extension(),
this), this),
isolate_(info->isolate()), isolate_(info->isolate()),
symbol_cache_(0, info->zone()), symbol_cache_(0, info->zone()),
...@@ -567,7 +645,6 @@ Parser::Parser(CompilationInfo* info) ...@@ -567,7 +645,6 @@ Parser::Parser(CompilationInfo* info)
reusable_preparser_(NULL), reusable_preparser_(NULL),
original_scope_(NULL), original_scope_(NULL),
target_stack_(NULL), target_stack_(NULL),
extension_(info->extension()),
pre_parse_data_(NULL), pre_parse_data_(NULL),
fni_(NULL), fni_(NULL),
zone_(info->zone()), zone_(info->zone()),
...@@ -3430,124 +3507,6 @@ void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) { ...@@ -3430,124 +3507,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(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: {
// Using eval or arguments in this context is OK even in strict mode.
Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, 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 = 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) { Expression* Parser::ParseArrayLiteral(bool* ok) {
// ArrayLiteral :: // ArrayLiteral ::
// '[' Expression? (',' Expression?)* ']' // '[' Expression? (',' Expression?)* ']'
......
...@@ -463,8 +463,26 @@ class ParserTraits { ...@@ -463,8 +463,26 @@ class ParserTraits {
} }
// Producing data during the recursive descent. // Producing data during the recursive descent.
Handle<String> GetSymbol(); Handle<String> GetSymbol(Scanner* scanner = NULL);
Handle<String> NextLiteralString(PretenureFlag tenured); Handle<String> NextLiteralString(Scanner* scanner,
PretenureFlag tenured);
Expression* ThisExpression(Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory);
Expression* ExpressionFromLiteral(
Token::Value token, int pos, Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory);
Expression* ExpressionFromIdentifier(
Handle<String> name, int pos, Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory);
Expression* ExpressionFromString(
int pos, Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory);
// Temporary glue; these functions will move to ParserBase.
Expression* ParseArrayLiteral(bool* ok);
Expression* ParseObjectLiteral(bool* ok);
Expression* ParseExpression(bool accept_IN, bool* ok);
Expression* ParseV8Intrinsic(bool* ok);
private: private:
Parser* parser_; Parser* parser_;
...@@ -626,7 +644,6 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -626,7 +644,6 @@ class Parser : public ParserBase<ParserTraits> {
Expression* ParseNewPrefix(PositionStack* stack, bool* ok); Expression* ParseNewPrefix(PositionStack* stack, bool* ok);
Expression* ParseMemberWithNewPrefixesExpression(PositionStack* stack, Expression* ParseMemberWithNewPrefixesExpression(PositionStack* stack,
bool* ok); bool* ok);
Expression* ParsePrimaryExpression(bool* ok);
Expression* ParseArrayLiteral(bool* ok); Expression* ParseArrayLiteral(bool* ok);
Expression* ParseObjectLiteral(bool* ok); Expression* ParseObjectLiteral(bool* ok);
...@@ -735,7 +752,6 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -735,7 +752,6 @@ class Parser : public ParserBase<ParserTraits> {
PreParser* reusable_preparser_; PreParser* reusable_preparser_;
Scope* original_scope_; // for ES5 function declarations in sloppy eval Scope* original_scope_; // for ES5 function declarations in sloppy eval
Target* target_stack_; // for break, continue statements Target* target_stack_; // for break, continue statements
v8::Extension* extension_;
ScriptDataImpl* pre_parse_data_; ScriptDataImpl* pre_parse_data_;
FuncNameInferrer* fni_; FuncNameInferrer* fni_;
......
...@@ -81,8 +81,7 @@ void PreParserTraits::ReportMessageAt(int start_pos, ...@@ -81,8 +81,7 @@ void PreParserTraits::ReportMessageAt(int start_pos,
} }
PreParserIdentifier PreParserTraits::GetSymbol() { PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
Scanner* scanner = pre_parser_->scanner();
pre_parser_->LogSymbol(); pre_parser_->LogSymbol();
if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) { if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) {
return PreParserIdentifier::FutureReserved(); return PreParserIdentifier::FutureReserved();
...@@ -107,6 +106,42 @@ PreParserIdentifier PreParserTraits::GetSymbol() { ...@@ -107,6 +106,42 @@ PreParserIdentifier PreParserTraits::GetSymbol() {
} }
PreParserExpression PreParserTraits::ExpressionFromString(
int pos, Scanner* scanner, PreParserFactory* factory) {
const int kUseStrictLength = 10;
const char* kUseStrictChars = "use strict";
pre_parser_->LogSymbol();
if (scanner->is_literal_ascii() &&
scanner->literal_length() == kUseStrictLength &&
!scanner->literal_contains_escapes() &&
!strncmp(scanner->literal_ascii_string().start(), kUseStrictChars,
kUseStrictLength)) {
return PreParserExpression::UseStrictStringLiteral();
}
return PreParserExpression::StringLiteral();
}
PreParserExpression PreParserTraits::ParseArrayLiteral(bool* ok) {
return pre_parser_->ParseArrayLiteral(ok);
}
PreParserExpression PreParserTraits::ParseObjectLiteral(bool* ok) {
return pre_parser_->ParseObjectLiteral(ok);
}
PreParserExpression PreParserTraits::ParseExpression(bool accept_IN, bool* ok) {
return pre_parser_->ParseExpression(accept_IN, ok);
}
PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
return pre_parser_->ParseV8Intrinsic(ok);
}
PreParser::PreParseResult PreParser::PreParseLazyFunction( PreParser::PreParseResult PreParser::PreParseLazyFunction(
LanguageMode mode, bool is_generator, ParserRecorder* log) { LanguageMode mode, bool is_generator, ParserRecorder* log) {
log_ = log; log_ = log;
...@@ -1111,90 +1146,6 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( ...@@ -1111,90 +1146,6 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
} }
PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
// PrimaryExpression ::
// 'this'
// 'null'
// 'true'
// 'false'
// Identifier
// Number
// String
// ArrayLiteral
// ObjectLiteral
// RegExpLiteral
// '(' Expression ')'
Expression result = Expression::Default();
switch (peek()) {
case Token::THIS: {
Next();
result = Expression::This();
break;
}
case Token::FUTURE_RESERVED_WORD:
case Token::FUTURE_STRICT_RESERVED_WORD:
case Token::YIELD:
case Token::IDENTIFIER: {
// Using eval or arguments in this context is OK even in strict mode.
Identifier id = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
result = Expression::FromIdentifier(id);
break;
}
case Token::NULL_LITERAL:
case Token::TRUE_LITERAL:
case Token::FALSE_LITERAL:
case Token::NUMBER: {
Next();
break;
}
case Token::STRING: {
Next();
result = GetStringSymbol();
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);
parenthesized_function_ = (peek() == Token::FUNCTION);
result = ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
break;
case Token::MOD:
result = ParseV8Intrinsic(CHECK_OK);
break;
default: {
Token::Value next = Next();
ReportUnexpectedToken(next);
*ok = false;
return Expression::Default();
}
}
return result;
}
PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) { PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
// ArrayLiteral :: // ArrayLiteral ::
// '[' Expression? (',' Expression?)* ']' // '[' Expression? (',' Expression?)* ']'
...@@ -1266,7 +1217,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { ...@@ -1266,7 +1217,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
case Token::STRING: case Token::STRING:
Consume(next); Consume(next);
checker.CheckProperty(next, kValueProperty, CHECK_OK); checker.CheckProperty(next, kValueProperty, CHECK_OK);
GetStringSymbol(); LogSymbol();
break; break;
case Token::NUMBER: case Token::NUMBER:
Consume(next); Consume(next);
...@@ -1475,19 +1426,4 @@ void PreParser::LogSymbol() { ...@@ -1475,19 +1426,4 @@ void PreParser::LogSymbol() {
} }
PreParser::Expression PreParser::GetStringSymbol() {
const int kUseStrictLength = 10;
const char* kUseStrictChars = "use strict";
LogSymbol();
if (scanner()->is_literal_ascii() &&
scanner()->literal_length() == kUseStrictLength &&
!scanner()->literal_contains_escapes() &&
!strncmp(scanner()->literal_ascii_string().start(), kUseStrictChars,
kUseStrictLength)) {
return Expression::UseStrictStringLiteral();
}
return Expression::StringLiteral();
}
} } // v8::internal } } // v8::internal
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "scopes.h" #include "scopes.h"
#include "token.h" #include "token.h"
#include "scanner.h" #include "scanner.h"
#include "v8.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -41,11 +42,13 @@ template <typename Traits> ...@@ -41,11 +42,13 @@ template <typename Traits>
class ParserBase : public Traits { class ParserBase : public Traits {
public: public:
ParserBase(Scanner* scanner, uintptr_t stack_limit, ParserBase(Scanner* scanner, uintptr_t stack_limit,
v8::Extension* extension,
typename Traits::Type::Parser this_object) typename Traits::Type::Parser this_object)
: Traits(this_object), : Traits(this_object),
parenthesized_function_(false), parenthesized_function_(false),
scope_(NULL), scope_(NULL),
function_state_(NULL), function_state_(NULL),
extension_(extension),
scanner_(scanner), scanner_(scanner),
stack_limit_(stack_limit), stack_limit_(stack_limit),
stack_overflow_(false), stack_overflow_(false),
...@@ -331,6 +334,8 @@ class ParserBase : public Traits { ...@@ -331,6 +334,8 @@ class ParserBase : public Traits {
typename Traits::Type::Expression ParseRegExpLiteral(bool seen_equal, typename Traits::Type::Expression ParseRegExpLiteral(bool seen_equal,
bool* ok); bool* ok);
typename Traits::Type::Expression ParsePrimaryExpression(bool* ok);
// Used to detect duplicates in object literals. Each of the values // Used to detect duplicates in object literals. Each of the values
// kGetterProperty, kSetterProperty and kValueProperty represents // kGetterProperty, kSetterProperty and kValueProperty represents
// a type of object literal property. When parsing a property, its // a type of object literal property. When parsing a property, its
...@@ -393,6 +398,7 @@ class ParserBase : public Traits { ...@@ -393,6 +398,7 @@ class ParserBase : public Traits {
typename Traits::Type::Scope* scope_; // Scope stack. typename Traits::Type::Scope* scope_; // Scope stack.
FunctionState* function_state_; // Function state stack. FunctionState* function_state_; // Function state stack.
v8::Extension* extension_;
private: private:
Scanner* scanner_; Scanner* scanner_;
...@@ -641,11 +647,39 @@ class PreParserTraits { ...@@ -641,11 +647,39 @@ class PreParserTraits {
} }
// Producing data during the recursive descent. // Producing data during the recursive descent.
PreParserIdentifier GetSymbol(); PreParserIdentifier GetSymbol(Scanner* scanner);
static PreParserIdentifier NextLiteralString(PretenureFlag tenured) { static PreParserIdentifier NextLiteralString(Scanner* scanner,
PretenureFlag tenured) {
return PreParserIdentifier::Default(); return PreParserIdentifier::Default();
} }
static PreParserExpression ThisExpression(PreParserScope* scope,
PreParserFactory* factory) {
return PreParserExpression::This();
}
static PreParserExpression ExpressionFromLiteral(
Token::Value token, int pos, Scanner* scanner,
PreParserFactory* factory) {
return PreParserExpression::Default();
}
static PreParserExpression ExpressionFromIdentifier(
PreParserIdentifier name, int pos, PreParserScope* scope,
PreParserFactory* factory) {
return PreParserExpression::FromIdentifier(name);
}
PreParserExpression ExpressionFromString(int pos,
Scanner* scanner,
PreParserFactory* factory = NULL);
// Temporary glue; these functions will move to ParserBase.
PreParserExpression ParseArrayLiteral(bool* ok);
PreParserExpression ParseObjectLiteral(bool* ok);
PreParserExpression ParseExpression(bool accept_IN, bool* ok);
PreParserExpression ParseV8Intrinsic(bool* ok);
private: private:
PreParser* pre_parser_; PreParser* pre_parser_;
}; };
...@@ -676,7 +710,7 @@ class PreParser : public ParserBase<PreParserTraits> { ...@@ -676,7 +710,7 @@ class PreParser : public ParserBase<PreParserTraits> {
PreParser(Scanner* scanner, PreParser(Scanner* scanner,
ParserRecorder* log, ParserRecorder* log,
uintptr_t stack_limit) uintptr_t stack_limit)
: ParserBase<PreParserTraits>(scanner, stack_limit, this), : ParserBase<PreParserTraits>(scanner, stack_limit, NULL, this),
log_(log) {} log_(log) {}
// Pre-parse the program from the character stream; returns true on // Pre-parse the program from the character stream; returns true on
...@@ -823,7 +857,6 @@ class PreParser : public ParserBase<PreParserTraits> { ...@@ -823,7 +857,6 @@ class PreParser : public ParserBase<PreParserTraits> {
Expression ParseNewExpression(bool* ok); Expression ParseNewExpression(bool* ok);
Expression ParseMemberExpression(bool* ok); Expression ParseMemberExpression(bool* ok);
Expression ParseMemberWithNewPrefixesExpression(unsigned new_count, bool* ok); Expression ParseMemberWithNewPrefixesExpression(unsigned new_count, bool* ok);
Expression ParsePrimaryExpression(bool* ok);
Expression ParseArrayLiteral(bool* ok); Expression ParseArrayLiteral(bool* ok);
Expression ParseObjectLiteral(bool* ok); Expression ParseObjectLiteral(bool* ok);
Expression ParseV8Intrinsic(bool* ok); Expression ParseV8Intrinsic(bool* ok);
...@@ -922,7 +955,7 @@ typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifier( ...@@ -922,7 +955,7 @@ typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifier(
bool* ok) { bool* ok) {
Token::Value next = Next(); Token::Value next = Next();
if (next == Token::IDENTIFIER) { if (next == Token::IDENTIFIER) {
typename Traits::Type::Identifier name = this->GetSymbol(); typename Traits::Type::Identifier name = this->GetSymbol(scanner());
if (allow_eval_or_arguments == kDontAllowEvalOrArguments && if (allow_eval_or_arguments == kDontAllowEvalOrArguments &&
!is_classic_mode() && this->IsEvalOrArguments(name)) { !is_classic_mode() && this->IsEvalOrArguments(name)) {
ReportMessageAt(scanner()->location(), "strict_eval_arguments"); ReportMessageAt(scanner()->location(), "strict_eval_arguments");
...@@ -931,7 +964,7 @@ typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifier( ...@@ -931,7 +964,7 @@ typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifier(
return name; return name;
} else if (is_classic_mode() && (next == Token::FUTURE_STRICT_RESERVED_WORD || } else if (is_classic_mode() && (next == Token::FUTURE_STRICT_RESERVED_WORD ||
(next == Token::YIELD && !is_generator()))) { (next == Token::YIELD && !is_generator()))) {
return this->GetSymbol(); return this->GetSymbol(scanner());
} else { } else {
this->ReportUnexpectedToken(next); this->ReportUnexpectedToken(next);
*ok = false; *ok = false;
...@@ -955,7 +988,7 @@ typename Traits::Type::Identifier ParserBase< ...@@ -955,7 +988,7 @@ typename Traits::Type::Identifier ParserBase<
*ok = false; *ok = false;
return Traits::EmptyIdentifier(); return Traits::EmptyIdentifier();
} }
return this->GetSymbol(); return this->GetSymbol(scanner());
} }
...@@ -969,7 +1002,7 @@ typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifierName( ...@@ -969,7 +1002,7 @@ typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifierName(
*ok = false; *ok = false;
return Traits::EmptyIdentifier(); return Traits::EmptyIdentifier();
} }
return this->GetSymbol(); return this->GetSymbol(scanner());
} }
...@@ -1004,7 +1037,7 @@ ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) { ...@@ -1004,7 +1037,7 @@ ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) {
int literal_index = function_state_->NextMaterializedLiteralIndex(); int literal_index = function_state_->NextMaterializedLiteralIndex();
typename Traits::Type::Identifier js_pattern = typename Traits::Type::Identifier js_pattern =
this->NextLiteralString(TENURED); this->NextLiteralString(scanner(), TENURED);
if (!scanner()->ScanRegExpFlags()) { if (!scanner()->ScanRegExpFlags()) {
Next(); Next();
ReportMessageAt(scanner()->location(), "invalid_regexp_flags"); ReportMessageAt(scanner()->location(), "invalid_regexp_flags");
...@@ -1012,12 +1045,115 @@ ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) { ...@@ -1012,12 +1045,115 @@ ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) {
return Traits::EmptyExpression(); return Traits::EmptyExpression();
} }
typename Traits::Type::Identifier js_flags = typename Traits::Type::Identifier js_flags =
this->NextLiteralString(TENURED); this->NextLiteralString(scanner(), TENURED);
Next(); Next();
return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos); return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
} }
#define CHECK_OK ok); \
if (!*ok) return this->EmptyExpression(); \
((void)0
#define DUMMY ) // to make indentation work
#undef DUMMY
template <class Traits>
typename Traits::Type::Expression ParserBase<Traits>::ParsePrimaryExpression(
bool* ok) {
// PrimaryExpression ::
// 'this'
// 'null'
// 'true'
// 'false'
// Identifier
// Number
// String
// ArrayLiteral
// ObjectLiteral
// RegExpLiteral
// '(' Expression ')'
int pos = peek_position();
typename Traits::Type::Expression result = this->EmptyExpression();
Token::Value token = peek();
switch (token) {
case Token::THIS: {
Consume(Token::THIS);
result = this->ThisExpression(scope_, factory());
break;
}
case Token::NULL_LITERAL:
case Token::TRUE_LITERAL:
case Token::FALSE_LITERAL:
case Token::NUMBER:
Next();
result = this->ExpressionFromLiteral(token, pos, scanner(), factory());
break;
case Token::IDENTIFIER:
case Token::YIELD:
case Token::FUTURE_STRICT_RESERVED_WORD: {
// Using eval or arguments in this context is OK even in strict mode.
typename Traits::Type::Identifier name =
ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
result =
this->ExpressionFromIdentifier(name, pos, scope_, factory());
break;
}
case Token::STRING: {
Consume(Token::STRING);
result = this->ExpressionFromString(pos, scanner(), factory());
break;
}
case Token::ASSIGN_DIV:
result = this->ParseRegExpLiteral(true, CHECK_OK);
break;
case Token::DIV:
result = this->ParseRegExpLiteral(false, CHECK_OK);
break;
case Token::LBRACK:
result = this->ParseArrayLiteral(CHECK_OK);
break;
case Token::LBRACE:
result = this->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 = this->ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
break;
case Token::MOD:
if (allow_natives_syntax() || extension_ != NULL) {
result = this->ParseV8Intrinsic(CHECK_OK);
break;
}
// If we're not allowing special syntax we fall-through to the
// default case.
default: {
Next();
ReportUnexpectedToken(token);
*ok = false;
}
}
return result;
}
#undef CHECK_OK
template <typename Traits> template <typename Traits>
void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
Token::Value property, Token::Value property,
......
...@@ -1391,7 +1391,7 @@ void RunParserSyncTest(const char* context_data[][2], ...@@ -1391,7 +1391,7 @@ void RunParserSyncTest(const char* context_data[][2],
static const ParserFlag flags[] = { static const ParserFlag flags[] = {
kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators, kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators,
kAllowForOf kAllowForOf, kAllowNativesSyntax
}; };
for (int i = 0; context_data[i][0] != NULL; ++i) { for (int i = 0; context_data[i][0] != NULL; ++i) {
for (int j = 0; statement_data[j] != NULL; ++j) { for (int j = 0; statement_data[j] != NULL; ++j) {
...@@ -2046,3 +2046,20 @@ TEST(NoErrorsRegexpLiteral) { ...@@ -2046,3 +2046,20 @@ TEST(NoErrorsRegexpLiteral) {
RunParserSyncTest(context_data, statement_data, kSuccess); RunParserSyncTest(context_data, statement_data, kSuccess);
} }
TEST(Intrinsics) {
const char* context_data[][2] = {
{"", ""},
{ NULL, NULL }
};
const char* statement_data[] = {
"%someintrinsic(arg)",
NULL
};
// Parsing will fail or succeed depending on whether we allow natives syntax
// or not.
RunParserSyncTest(context_data, statement_data, kSuccessOrError);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment