| 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;
|
| }
|
|
|
|
|
|
|