Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(320)

Unified Diff: src/parser.cc

Issue 164183006: Revert "(Pre)Parser: Simplify NewExpression handling." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index afeb013b06ce5b423596521ea9f4c71fc0d1f353..3ef220478d10dcbb47f1f0d6f9124079ba6cc4b2 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -46,6 +46,49 @@
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),
@@ -3249,7 +3292,12 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
// LeftHandSideExpression ::
// (NewExpression | MemberExpression) ...
- Expression* result = ParseMemberWithNewPrefixesExpression(CHECK_OK);
+ Expression* result;
+ if (peek() == Token::NEW) {
+ result = ParseNewExpression(CHECK_OK);
+ } else {
+ result = ParseMemberExpression(CHECK_OK);
+ }
while (true) {
switch (peek()) {
@@ -3318,42 +3366,50 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
}
-Expression* Parser::ParseMemberWithNewPrefixesExpression(bool* ok) {
+Expression* Parser::ParseNewPrefix(PositionStack* stack, 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())
-
+ // 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) {
- 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);
+ 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);
}
- // No 'new' keyword.
- return ParseMemberExpression(ok);
+ return result;
+}
+
+
+Expression* Parser::ParseNewExpression(bool* ok) {
+ PositionStack stack(ok);
+ return ParseNewPrefix(&stack, ok);
}
Expression* Parser::ParseMemberExpression(bool* ok) {
+ return ParseMemberWithNewPrefixesExpression(NULL, ok);
+}
+
+
+Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
+ bool* ok) {
// MemberExpression ::
// (PrimaryExpression | FunctionLiteral)
// ('[' Expression ']' | '.' Identifier | Arguments)*
@@ -3413,6 +3469,14 @@ Expression* Parser::ParseMemberExpression(bool* ok) {
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;
}
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698