Chromium Code Reviews| Index: src/parser.cc |
| =================================================================== |
| --- src/parser.cc (revision 1968) |
| +++ src/parser.cc (working copy) |
| @@ -42,9 +42,50 @@ |
| class ParserFactory; |
| class ParserLog; |
| class TemporaryScope; |
| +class Target; |
| + |
| template <typename T> class ZoneListWrapper; |
| +// PositionStack is used for on-stack allocation of token positions for |
| +// new expressions. Please look at ParseNewExpression. |
| + |
| +class PositionStack { |
| + public: |
| + PositionStack() : top_(NULL) {} |
| + ~PositionStack() { } |
| + |
| + class Element { |
|
Kasper Lund
2009/05/15 13:37:11
Couldn't the entire Element class be private?
|
| + public: |
| + Element(PositionStack* stack, int value) { |
| + previous_ = stack->top(); |
| + value_ = value; |
| + stack->set_top(this); |
| + } |
| + protected: |
|
Kasper Lund
2009/05/15 13:37:11
How about a newline before protected: and private:
Kasper Lund
2009/05/15 13:37:11
Why do you have both private and protected? Do you
|
| + Element* previous() { return previous_; } |
| + int value() { return value_; } |
| + friend class PositionStack; |
| + private: |
| + Element* previous_; |
| + int value_; |
| + }; |
| + |
| + bool is_empty() { return top_ == NULL; } |
| + int pop() { |
| + ASSERT(!is_empty()); |
| + int result = top_->value(); |
| + top_ = top_->previous(); |
| + return result; |
| + } |
| + protected: |
| + Element* top() { return top_; } |
| + void set_top(Element* value) { top_ = value; } |
| + private: |
| + Element* top_; |
| +}; |
| + |
| + |
| class Parser { |
| public: |
| Parser(Handle<Script> script, bool allow_natives_syntax, |
| @@ -93,7 +134,8 @@ |
| TemporaryScope* temp_scope_; |
| Mode mode_; |
| - List<Node*>* target_stack_; // for break, continue statements |
| + |
| + Target* target_stack_; // for break, continue statements |
| bool allow_natives_syntax_; |
| v8::Extension* extension_; |
| ParserFactory* factory_; |
| @@ -150,7 +192,8 @@ |
| Expression* ParseLeftHandSideExpression(bool* ok); |
| Expression* ParseNewExpression(bool* ok); |
| Expression* ParseMemberExpression(bool* ok); |
| - Expression* ParseMemberWithNewPrefixesExpression(List<int>* new_prefixes, |
| + Expression* ParseNewPrefix(PositionStack* stack, bool* ok); |
| + Expression* ParseMemberWithNewPrefixesExpression(PositionStack* stack, |
| bool* ok); |
| Expression* ParsePrimaryExpression(bool* ok); |
| Expression* ParseArrayLiteral(bool* ok); |
| @@ -208,7 +251,7 @@ |
| BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok); |
| IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok); |
| - void RegisterTargetUse(BreakTarget* target, int index); |
| + void RegisterTargetUse(BreakTarget* target, Target* stop); |
| // Create a number literal. |
| Literal* NewNumberLiteral(double value); |
| @@ -971,35 +1014,39 @@ |
| class Target BASE_EMBEDDED { |
| public: |
| - Target(Parser* parser, Node* node) : parser_(parser) { |
| - parser_->target_stack_->Add(node); |
| + Target(Parser* parser, Node* node) |
| + : parser_(parser), node_(node), previous_(parser_->target_stack_) { |
| + parser_->target_stack_ = this; |
| } |
| ~Target() { |
| - parser_->target_stack_->RemoveLast(); |
| + parser_->target_stack_ = previous_; |
| } |
| + Target* previous() { return previous_; } |
| + Node* node() { return node_; } |
| + |
| private: |
| Parser* parser_; |
| + Node* node_; |
| + Target* previous_; |
| }; |
| class TargetScope BASE_EMBEDDED { |
| public: |
| explicit TargetScope(Parser* parser) |
| - : parser_(parser), previous_(parser->target_stack_), stack_(0) { |
| - parser_->target_stack_ = &stack_; |
| + : parser_(parser), previous_(parser->target_stack_) { |
| + parser->target_stack_ = NULL; |
| } |
| ~TargetScope() { |
| - ASSERT(stack_.is_empty()); |
| parser_->target_stack_ = previous_; |
| } |
| private: |
| Parser* parser_; |
| - List<Node*>* previous_; |
| - List<Node*> stack_; |
| + Target* previous_; |
| }; |
| @@ -2792,7 +2839,8 @@ |
| } |
| -Expression* Parser::ParseNewExpression(bool* ok) { |
| + |
| +Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) { |
| // NewExpression :: |
| // ('new')+ MemberExpression |
| @@ -2804,32 +2852,36 @@ |
| // 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 |
| - List<int> new_positions(4); |
| - while (peek() == Token::NEW) { |
| - Consume(Token::NEW); |
| - new_positions.Add(scanner().location().beg_pos); |
| + Expect(Token::NEW, CHECK_OK); |
| + PositionStack::Element pos(stack, scanner().location().beg_pos); |
| + |
| + Expression* result; |
| + if (peek() == Token::NEW) { |
| + result = ParseNewPrefix(stack, CHECK_OK); |
| + } else { |
| + result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK); |
| } |
| - ASSERT(new_positions.length() > 0); |
| - Expression* result = |
| - ParseMemberWithNewPrefixesExpression(&new_positions, CHECK_OK); |
| - while (!new_positions.is_empty()) { |
| - int last = new_positions.RemoveLast(); |
| - result = NEW(CallNew(result, new ZoneList<Expression*>(0), last)); |
| + if (!stack->is_empty()) { |
| + result = NEW(CallNew(result, new ZoneList<Expression*>(0), stack->pop())); |
| } |
| return result; |
| } |
| +Expression* Parser::ParseNewExpression(bool* ok) { |
| + PositionStack stack; |
| + return ParseNewPrefix(&stack, ok); |
| +} |
| + |
| + |
| Expression* Parser::ParseMemberExpression(bool* ok) { |
| - static List<int> new_positions(0); |
| - return ParseMemberWithNewPrefixesExpression(&new_positions, ok); |
| + return ParseMemberWithNewPrefixesExpression(NULL, ok); |
| } |
| -Expression* Parser::ParseMemberWithNewPrefixesExpression( |
| - List<int>* new_positions, |
| - bool* ok) { |
| +Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack, |
| + bool* ok) { |
| // MemberExpression :: |
| // (PrimaryExpression | FunctionLiteral) |
| // ('[' Expression ']' | '.' Identifier | Arguments)* |
| @@ -2865,11 +2917,10 @@ |
| break; |
| } |
| case Token::LPAREN: { |
| - if (new_positions->is_empty()) return result; |
| + if ((stack == NULL) || stack->is_empty()) return result; |
| // Consume one of the new prefixes (already parsed). |
| ZoneList<Expression*>* args = ParseArguments(CHECK_OK); |
| - int last = new_positions->RemoveLast(); |
| - result = NEW(CallNew(result, args, last)); |
| + result = NEW(CallNew(result, args, stack->pop())); |
| break; |
| } |
| default: |
| @@ -3548,8 +3599,8 @@ |
| bool Parser::TargetStackContainsLabel(Handle<String> label) { |
| - for (int i = target_stack_->length(); i-- > 0;) { |
| - BreakableStatement* stat = target_stack_->at(i)->AsBreakableStatement(); |
| + for (Target* t = target_stack_; t != NULL; t = t->previous()) { |
| + BreakableStatement* stat = t->node()->AsBreakableStatement(); |
| if (stat != NULL && ContainsLabel(stat->labels(), label)) |
| return true; |
| } |
| @@ -3559,13 +3610,12 @@ |
| BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) { |
| bool anonymous = label.is_null(); |
| - for (int i = target_stack_->length(); i-- > 0;) { |
| - BreakableStatement* stat = target_stack_->at(i)->AsBreakableStatement(); |
| + for (Target* t = target_stack_; t != NULL; t = t->previous()) { |
| + BreakableStatement* stat = t->node()->AsBreakableStatement(); |
| if (stat == NULL) continue; |
| - |
| if ((anonymous && stat->is_target_for_anonymous()) || |
| (!anonymous && ContainsLabel(stat->labels(), label))) { |
| - RegisterTargetUse(stat->break_target(), i); |
| + RegisterTargetUse(stat->break_target(), t->previous()); |
| return stat; |
| } |
| } |
| @@ -3576,13 +3626,13 @@ |
| IterationStatement* Parser::LookupContinueTarget(Handle<String> label, |
| bool* ok) { |
| bool anonymous = label.is_null(); |
| - for (int i = target_stack_->length(); i-- > 0;) { |
| - IterationStatement* stat = target_stack_->at(i)->AsIterationStatement(); |
| + for (Target* t = target_stack_; t != NULL; t = t->previous()) { |
| + IterationStatement* stat = t->node()->AsIterationStatement(); |
| if (stat == NULL) continue; |
| ASSERT(stat->is_target_for_anonymous()); |
| if (anonymous || ContainsLabel(stat->labels(), label)) { |
| - RegisterTargetUse(stat->continue_target(), i); |
| + RegisterTargetUse(stat->continue_target(), t->previous()); |
| return stat; |
| } |
| } |
| @@ -3590,12 +3640,12 @@ |
| } |
| -void Parser::RegisterTargetUse(BreakTarget* target, int index) { |
| - // Register that a break target found at the given index in the |
| +void Parser::RegisterTargetUse(BreakTarget* target, Target* stop) { |
| + // Register that a break target found at the given stop in the |
| // target stack has been used from the top of the target stack. Add |
| // the break target to any TargetCollectors passed on the stack. |
| - for (int i = target_stack_->length(); i-- > index;) { |
| - TargetCollector* collector = target_stack_->at(i)->AsTargetCollector(); |
| + for (Target* t = target_stack_; t != stop; t = t->previous()) { |
| + TargetCollector* collector = t->node()->AsTargetCollector(); |
| if (collector != NULL) collector->AddTarget(target); |
| } |
| } |