Chromium Code Reviews| Index: src/parser.cc |
| diff --git a/src/parser.cc b/src/parser.cc |
| index 3ef220478d10dcbb47f1f0d6f9124079ba6cc4b2..afeb013b06ce5b423596521ea9f4c71fc0d1f353 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), |
| @@ -3292,12 +3249,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()) { |
| @@ -3366,50 +3318,42 @@ 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()) |
| -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); |
| + return factory()->NewCallNew(result, args, new_pos); |
| + } |
| + // 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)* |
| @@ -3469,14 +3413,6 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack, |
| 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); |
|
marja
2014/02/17 15:11:42
The problem is:
In the original code, we can have
|
| - break; |
| - } |
| default: |
| return result; |
| } |