Move new expression parsing funcs to ParserBase.
Functions moved: ParseMemberWithNewPrefixesExpression, ParseMemberExpression, ParseMemberExpressionContinuation. Now all Parse*Expression functions are in ParserBase. R=mstarzinger@chromium.org BUG= Review URL: https://codereview.chromium.org/207633003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20153 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f6f99310fe
commit
e79ff8275c
137
src/parser.cc
137
src/parser.cc
@ -439,6 +439,17 @@ bool ParserTraits::IsIdentifier(Expression* expression) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParserTraits::PushPropertyName(FuncNameInferrer* fni,
|
||||||
|
Expression* expression) {
|
||||||
|
if (expression->IsPropertyName()) {
|
||||||
|
fni->PushLiteralName(expression->AsLiteral()->AsPropertyName());
|
||||||
|
} else {
|
||||||
|
fni->PushLiteralName(
|
||||||
|
parser_->isolate()->factory()->anonymous_function_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left,
|
void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left,
|
||||||
Expression* right) {
|
Expression* right) {
|
||||||
ASSERT(left != NULL);
|
ASSERT(left != NULL);
|
||||||
@ -750,11 +761,6 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Expression* ParserTraits::ParseMemberWithNewPrefixesExpression(bool* ok) {
|
|
||||||
return parser_->ParseMemberWithNewPrefixesExpression(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(),
|
||||||
@ -3053,127 +3059,6 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Expression* Parser::ParseMemberWithNewPrefixesExpression(bool* ok) {
|
|
||||||
// NewExpression ::
|
|
||||||
// ('new')+ MemberExpression
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
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) {
|
|
||||||
// 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) {
|
|
||||||
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();
|
|
||||||
FunctionLiteral::FunctionType function_type =
|
|
||||||
FunctionLiteral::ANONYMOUS_EXPRESSION;
|
|
||||||
if (peek_any_identifier()) {
|
|
||||||
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
|
|
||||||
CHECK_OK);
|
|
||||||
function_name_location = scanner()->location();
|
|
||||||
function_type = FunctionLiteral::NAMED_EXPRESSION;
|
|
||||||
}
|
|
||||||
result = ParseFunctionLiteral(name,
|
|
||||||
function_name_location,
|
|
||||||
is_strict_reserved_name,
|
|
||||||
is_generator,
|
|
||||||
function_token_position,
|
|
||||||
function_type,
|
|
||||||
CHECK_OK);
|
|
||||||
} else {
|
|
||||||
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);
|
|
||||||
expression = factory()->NewProperty(expression, index, pos);
|
|
||||||
if (fni_ != NULL) {
|
|
||||||
if (index->IsPropertyName()) {
|
|
||||||
fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
|
|
||||||
} else {
|
|
||||||
fni_->PushLiteralName(
|
|
||||||
isolate()->factory()->anonymous_function_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Expect(Token::RBRACK, CHECK_OK);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Token::PERIOD: {
|
|
||||||
Consume(Token::PERIOD);
|
|
||||||
int pos = position();
|
|
||||||
Handle<String> name = ParseIdentifierName(CHECK_OK);
|
|
||||||
expression = factory()->NewProperty(
|
|
||||||
expression, factory()->NewLiteral(name, pos), pos);
|
|
||||||
if (fni_ != NULL) fni_->PushLiteralName(name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return expression;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ASSERT(false);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
|
DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
|
||||||
// In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
|
// In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
|
||||||
// contexts this is used as a statement which invokes the debugger as i a
|
// contexts this is used as a statement which invokes the debugger as i a
|
||||||
|
@ -475,6 +475,7 @@ class ParserTraits {
|
|||||||
static void PushLiteralName(FuncNameInferrer* fni, Handle<String> id) {
|
static void PushLiteralName(FuncNameInferrer* fni, Handle<String> id) {
|
||||||
fni->PushLiteralName(id);
|
fni->PushLiteralName(id);
|
||||||
}
|
}
|
||||||
|
void PushPropertyName(FuncNameInferrer* fni, Expression* expression);
|
||||||
|
|
||||||
static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
|
static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
|
||||||
Scope* scope, Expression* value, bool* has_function) {
|
Scope* scope, Expression* value, bool* has_function) {
|
||||||
@ -549,6 +550,7 @@ class ParserTraits {
|
|||||||
static Literal* EmptyLiteral() {
|
static Literal* EmptyLiteral() {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
// Used in error return values.
|
||||||
static ZoneList<Expression*>* NullExpressionList() {
|
static ZoneList<Expression*>* NullExpressionList() {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -589,7 +591,6 @@ class ParserTraits {
|
|||||||
int function_token_position,
|
int function_token_position,
|
||||||
FunctionLiteral::FunctionType type,
|
FunctionLiteral::FunctionType type,
|
||||||
bool* ok);
|
bool* ok);
|
||||||
Expression* ParseMemberWithNewPrefixesExpression(bool* ok);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Parser* parser_;
|
Parser* parser_;
|
||||||
@ -725,10 +726,6 @@ class Parser : public ParserBase<ParserTraits> {
|
|||||||
// Support for hamony block scoped bindings.
|
// Support for hamony block scoped bindings.
|
||||||
Block* ParseScopedBlock(ZoneStringList* labels, bool* ok);
|
Block* ParseScopedBlock(ZoneStringList* labels, bool* ok);
|
||||||
|
|
||||||
Expression* ParseMemberWithNewPrefixesExpression(bool* ok);
|
|
||||||
Expression* ParseMemberExpression(bool* ok);
|
|
||||||
Expression* ParseMemberExpressionContinuation(Expression* expression,
|
|
||||||
bool* ok);
|
|
||||||
// Initialize the components of a for-in / for-of statement.
|
// Initialize the components of a for-in / for-of statement.
|
||||||
void InitializeForEachStatement(ForEachStatement* stmt,
|
void InitializeForEachStatement(ForEachStatement* stmt,
|
||||||
Expression* each,
|
Expression* each,
|
||||||
|
110
src/preparser.cc
110
src/preparser.cc
@ -146,12 +146,6 @@ PreParserExpression PreParserTraits::ParseFunctionLiteral(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PreParserExpression PreParserTraits::ParseMemberWithNewPrefixesExpression(
|
|
||||||
bool* ok) {
|
|
||||||
return pre_parser_->ParseMemberWithNewPrefixesExpression(ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PreParser::PreParseResult PreParser::PreParseLazyFunction(
|
PreParser::PreParseResult PreParser::PreParseLazyFunction(
|
||||||
StrictMode strict_mode, bool is_generator, ParserRecorder* log) {
|
StrictMode strict_mode, bool is_generator, ParserRecorder* log) {
|
||||||
log_ = log;
|
log_ = log;
|
||||||
@ -843,110 +837,6 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
|
|||||||
#undef DUMMY
|
#undef DUMMY
|
||||||
|
|
||||||
|
|
||||||
PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
|
|
||||||
bool* ok) {
|
|
||||||
// NewExpression ::
|
|
||||||
// ('new')+ MemberExpression
|
|
||||||
|
|
||||||
// See Parser::ParseNewExpression.
|
|
||||||
|
|
||||||
if (peek() == Token::NEW) {
|
|
||||||
Consume(Token::NEW);
|
|
||||||
ParseMemberWithNewPrefixesExpression(CHECK_OK);
|
|
||||||
Expression expression = Expression::Default();
|
|
||||||
if (peek() == Token::LPAREN) {
|
|
||||||
// NewExpression with arguments.
|
|
||||||
ParseArguments(CHECK_OK);
|
|
||||||
// The expression can still continue with . or [ after the arguments. Here
|
|
||||||
// we need to transmit the "is valid left hand side" property of the
|
|
||||||
// expression.
|
|
||||||
expression =
|
|
||||||
ParseMemberExpressionContinuation(Expression::Default(), CHECK_OK);
|
|
||||||
}
|
|
||||||
return expression;
|
|
||||||
}
|
|
||||||
// No 'new' keyword.
|
|
||||||
return ParseMemberExpression(ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PreParser::Expression PreParser::ParseMemberExpression(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 = Expression::Default();
|
|
||||||
if (peek() == Token::FUNCTION) {
|
|
||||||
Consume(Token::FUNCTION);
|
|
||||||
int function_token_position = position();
|
|
||||||
bool is_generator = allow_generators() && Check(Token::MUL);
|
|
||||||
Identifier name = Identifier::Default();
|
|
||||||
bool is_strict_reserved_name = false;
|
|
||||||
Scanner::Location function_name_location = Scanner::Location::invalid();
|
|
||||||
FunctionLiteral::FunctionType function_type =
|
|
||||||
FunctionLiteral::ANONYMOUS_EXPRESSION;
|
|
||||||
if (peek_any_identifier()) {
|
|
||||||
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
|
|
||||||
CHECK_OK);
|
|
||||||
function_name_location = scanner()->location();
|
|
||||||
function_type = FunctionLiteral::NAMED_EXPRESSION;
|
|
||||||
}
|
|
||||||
result = ParseFunctionLiteral(name,
|
|
||||||
function_name_location,
|
|
||||||
is_strict_reserved_name,
|
|
||||||
is_generator,
|
|
||||||
function_token_position,
|
|
||||||
function_type,
|
|
||||||
CHECK_OK);
|
|
||||||
} else {
|
|
||||||
result = ParsePrimaryExpression(CHECK_OK);
|
|
||||||
}
|
|
||||||
result = ParseMemberExpressionContinuation(result, CHECK_OK);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PreParser::Expression PreParser::ParseMemberExpressionContinuation(
|
|
||||||
PreParserExpression expression, bool* ok) {
|
|
||||||
// Parses this part of MemberExpression:
|
|
||||||
// ('[' Expression ']' | '.' Identifier)*
|
|
||||||
while (true) {
|
|
||||||
switch (peek()) {
|
|
||||||
case Token::LBRACK: {
|
|
||||||
Consume(Token::LBRACK);
|
|
||||||
ParseExpression(true, CHECK_OK);
|
|
||||||
Expect(Token::RBRACK, CHECK_OK);
|
|
||||||
if (expression.IsThis()) {
|
|
||||||
expression = Expression::ThisProperty();
|
|
||||||
} else {
|
|
||||||
expression = Expression::Property();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Token::PERIOD: {
|
|
||||||
Consume(Token::PERIOD);
|
|
||||||
ParseIdentifierName(CHECK_OK);
|
|
||||||
if (expression.IsThis()) {
|
|
||||||
expression = Expression::ThisProperty();
|
|
||||||
} else {
|
|
||||||
expression = Expression::Property();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return expression;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ASSERT(false);
|
|
||||||
return PreParserExpression::Default();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PreParser::Expression PreParser::ParseFunctionLiteral(
|
PreParser::Expression PreParser::ParseFunctionLiteral(
|
||||||
Identifier function_name,
|
Identifier function_name,
|
||||||
Scanner::Location function_name_location,
|
Scanner::Location function_name_location,
|
||||||
|
147
src/preparser.h
147
src/preparser.h
@ -420,6 +420,10 @@ class ParserBase : public Traits {
|
|||||||
ExpressionT ParseUnaryExpression(bool* ok);
|
ExpressionT ParseUnaryExpression(bool* ok);
|
||||||
ExpressionT ParsePostfixExpression(bool* ok);
|
ExpressionT ParsePostfixExpression(bool* ok);
|
||||||
ExpressionT ParseLeftHandSideExpression(bool* ok);
|
ExpressionT ParseLeftHandSideExpression(bool* ok);
|
||||||
|
ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok);
|
||||||
|
ExpressionT ParseMemberExpression(bool* ok);
|
||||||
|
ExpressionT ParseMemberExpressionContinuation(ExpressionT expression,
|
||||||
|
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
|
||||||
@ -504,6 +508,7 @@ class ParserBase : public Traits {
|
|||||||
|
|
||||||
class PreParserIdentifier {
|
class PreParserIdentifier {
|
||||||
public:
|
public:
|
||||||
|
PreParserIdentifier() : type_(kUnknownIdentifier) {}
|
||||||
static PreParserIdentifier Default() {
|
static PreParserIdentifier Default() {
|
||||||
return PreParserIdentifier(kUnknownIdentifier);
|
return PreParserIdentifier(kUnknownIdentifier);
|
||||||
}
|
}
|
||||||
@ -791,6 +796,11 @@ class PreParserFactory {
|
|||||||
int pos) {
|
int pos) {
|
||||||
return PreParserExpression::Default();
|
return PreParserExpression::Default();
|
||||||
}
|
}
|
||||||
|
PreParserExpression NewCallNew(PreParserExpression expression,
|
||||||
|
PreParserExpressionList arguments,
|
||||||
|
int pos) {
|
||||||
|
return PreParserExpression::Default();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -860,7 +870,12 @@ class PreParserTraits {
|
|||||||
// operations interleaved with the recursive descent.
|
// operations interleaved with the recursive descent.
|
||||||
static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) {
|
static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) {
|
||||||
// PreParser should not use FuncNameInferrer.
|
// PreParser should not use FuncNameInferrer.
|
||||||
ASSERT(false);
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
static void PushPropertyName(FuncNameInferrer* fni,
|
||||||
|
PreParserExpression expression) {
|
||||||
|
// PreParser should not use FuncNameInferrer.
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
|
static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
|
||||||
@ -979,7 +994,6 @@ class PreParserTraits {
|
|||||||
int function_token_position,
|
int function_token_position,
|
||||||
FunctionLiteral::FunctionType type,
|
FunctionLiteral::FunctionType type,
|
||||||
bool* ok);
|
bool* ok);
|
||||||
PreParserExpression ParseMemberWithNewPrefixesExpression(bool* ok);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PreParser* pre_parser_;
|
PreParser* pre_parser_;
|
||||||
@ -1143,10 +1157,6 @@ class PreParser : public ParserBase<PreParserTraits> {
|
|||||||
Statement ParseTryStatement(bool* ok);
|
Statement ParseTryStatement(bool* ok);
|
||||||
Statement ParseDebuggerStatement(bool* ok);
|
Statement ParseDebuggerStatement(bool* ok);
|
||||||
Expression ParseConditionalExpression(bool accept_IN, bool* ok);
|
Expression ParseConditionalExpression(bool accept_IN, bool* ok);
|
||||||
Expression ParseMemberExpression(bool* ok);
|
|
||||||
Expression ParseMemberExpressionContinuation(PreParserExpression expression,
|
|
||||||
bool* ok);
|
|
||||||
Expression ParseMemberWithNewPrefixesExpression(bool* ok);
|
|
||||||
Expression ParseObjectLiteral(bool* ok);
|
Expression ParseObjectLiteral(bool* ok);
|
||||||
Expression ParseV8Intrinsic(bool* ok);
|
Expression ParseV8Intrinsic(bool* ok);
|
||||||
|
|
||||||
@ -1994,6 +2004,131 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class Traits>
|
||||||
|
typename ParserBase<Traits>::ExpressionT
|
||||||
|
ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
|
||||||
|
// NewExpression ::
|
||||||
|
// ('new')+ MemberExpression
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
if (peek() == Token::NEW) {
|
||||||
|
Consume(Token::NEW);
|
||||||
|
int new_pos = position();
|
||||||
|
ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
|
||||||
|
if (peek() == Token::LPAREN) {
|
||||||
|
// NewExpression with arguments.
|
||||||
|
typename Traits::Type::ExpressionList args =
|
||||||
|
this->ParseArguments(CHECK_OK);
|
||||||
|
result = factory()->NewCallNew(result, args, new_pos);
|
||||||
|
// The expression can still continue with . or [ after the arguments.
|
||||||
|
result = this->ParseMemberExpressionContinuation(result, CHECK_OK);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// NewExpression without arguments.
|
||||||
|
return factory()->NewCallNew(result, this->NewExpressionList(0, zone_),
|
||||||
|
new_pos);
|
||||||
|
}
|
||||||
|
// No 'new' keyword.
|
||||||
|
return this->ParseMemberExpression(ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class Traits>
|
||||||
|
typename ParserBase<Traits>::ExpressionT
|
||||||
|
ParserBase<Traits>::ParseMemberExpression(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.
|
||||||
|
ExpressionT result = this->EmptyExpression();
|
||||||
|
if (peek() == Token::FUNCTION) {
|
||||||
|
Consume(Token::FUNCTION);
|
||||||
|
int function_token_position = position();
|
||||||
|
bool is_generator = allow_generators() && Check(Token::MUL);
|
||||||
|
IdentifierT name;
|
||||||
|
bool is_strict_reserved_name = false;
|
||||||
|
Scanner::Location function_name_location = Scanner::Location::invalid();
|
||||||
|
FunctionLiteral::FunctionType function_type =
|
||||||
|
FunctionLiteral::ANONYMOUS_EXPRESSION;
|
||||||
|
if (peek_any_identifier()) {
|
||||||
|
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
|
||||||
|
CHECK_OK);
|
||||||
|
function_name_location = scanner()->location();
|
||||||
|
function_type = FunctionLiteral::NAMED_EXPRESSION;
|
||||||
|
}
|
||||||
|
result = this->ParseFunctionLiteral(name,
|
||||||
|
function_name_location,
|
||||||
|
is_strict_reserved_name,
|
||||||
|
is_generator,
|
||||||
|
function_token_position,
|
||||||
|
function_type,
|
||||||
|
CHECK_OK);
|
||||||
|
} else {
|
||||||
|
result = ParsePrimaryExpression(CHECK_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = ParseMemberExpressionContinuation(result, CHECK_OK);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class Traits>
|
||||||
|
typename ParserBase<Traits>::ExpressionT
|
||||||
|
ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression,
|
||||||
|
bool* ok) {
|
||||||
|
// Parses this part of MemberExpression:
|
||||||
|
// ('[' Expression ']' | '.' Identifier)*
|
||||||
|
while (true) {
|
||||||
|
switch (peek()) {
|
||||||
|
case Token::LBRACK: {
|
||||||
|
Consume(Token::LBRACK);
|
||||||
|
int pos = position();
|
||||||
|
ExpressionT index = this->ParseExpression(true, CHECK_OK);
|
||||||
|
expression = factory()->NewProperty(expression, index, pos);
|
||||||
|
if (fni_ != NULL) {
|
||||||
|
this->PushPropertyName(fni_, index);
|
||||||
|
}
|
||||||
|
Expect(Token::RBRACK, CHECK_OK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Token::PERIOD: {
|
||||||
|
Consume(Token::PERIOD);
|
||||||
|
int pos = position();
|
||||||
|
IdentifierT name = ParseIdentifierName(CHECK_OK);
|
||||||
|
expression = factory()->NewProperty(
|
||||||
|
expression, factory()->NewLiteral(name, pos), pos);
|
||||||
|
if (fni_ != NULL) {
|
||||||
|
this->PushLiteralName(fni_, name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT(false);
|
||||||
|
return this->EmptyExpression();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#undef CHECK_OK
|
#undef CHECK_OK
|
||||||
#undef CHECK_OK_CUSTOM
|
#undef CHECK_OK_CUSTOM
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user