| Index: src/preparser.h
|
| diff --git a/src/preparser.h b/src/preparser.h
|
| index 7977fe2fd5362df0639cf01f9d9fd8a95064fe19..ee8e46b96e6e00bb41ca3d926918206a40606e5e 100644
|
| --- a/src/preparser.h
|
| +++ b/src/preparser.h
|
| @@ -420,6 +420,10 @@ class ParserBase : public Traits {
|
| ExpressionT ParseUnaryExpression(bool* ok);
|
| ExpressionT ParsePostfixExpression(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
|
| // kGetterProperty, kSetterProperty and kValueProperty represents
|
| @@ -504,6 +508,7 @@ class ParserBase : public Traits {
|
|
|
| class PreParserIdentifier {
|
| public:
|
| + PreParserIdentifier() : type_(kUnknownIdentifier) {}
|
| static PreParserIdentifier Default() {
|
| return PreParserIdentifier(kUnknownIdentifier);
|
| }
|
| @@ -791,6 +796,11 @@ class PreParserFactory {
|
| int pos) {
|
| 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.
|
| static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) {
|
| // PreParser should not use FuncNameInferrer.
|
| - ASSERT(false);
|
| + UNREACHABLE();
|
| + }
|
| + static void PushPropertyName(FuncNameInferrer* fni,
|
| + PreParserExpression expression) {
|
| + // PreParser should not use FuncNameInferrer.
|
| + UNREACHABLE();
|
| }
|
|
|
| static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
|
| @@ -979,7 +994,6 @@ class PreParserTraits {
|
| int function_token_position,
|
| FunctionLiteral::FunctionType type,
|
| bool* ok);
|
| - PreParserExpression ParseMemberWithNewPrefixesExpression(bool* ok);
|
|
|
| private:
|
| PreParser* pre_parser_;
|
| @@ -1143,10 +1157,6 @@ class PreParser : public ParserBase<PreParserTraits> {
|
| Statement ParseTryStatement(bool* ok);
|
| Statement ParseDebuggerStatement(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 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_CUSTOM
|
|
|
|
|