Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index 3ef220478d10dcbb47f1f0d6f9124079ba6cc4b2..409059778a6a5f44606f6d0bed20af710cb797ec 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,54 +3318,54 @@ 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) { |
@@ -3442,13 +3394,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()); |
@@ -3464,23 +3425,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; |
} |