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

Side by Side Diff: src/parser.cc

Issue 166943002: (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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 28 matching lines...) Expand all
39 #include "platform.h" 39 #include "platform.h"
40 #include "preparser.h" 40 #include "preparser.h"
41 #include "runtime.h" 41 #include "runtime.h"
42 #include "scanner-character-streams.h" 42 #include "scanner-character-streams.h"
43 #include "scopeinfo.h" 43 #include "scopeinfo.h"
44 #include "string-stream.h" 44 #include "string-stream.h"
45 45
46 namespace v8 { 46 namespace v8 {
47 namespace internal { 47 namespace internal {
48 48
49 // PositionStack is used for on-stack allocation of token positions for
50 // new expressions. Please look at ParseNewExpression.
51
52 class PositionStack {
53 public:
54 explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
55 ~PositionStack() {
56 ASSERT(!*ok_ || is_empty());
57 USE(ok_);
58 }
59
60 class Element {
61 public:
62 Element(PositionStack* stack, int value) {
63 previous_ = stack->top();
64 value_ = value;
65 stack->set_top(this);
66 }
67
68 private:
69 Element* previous() { return previous_; }
70 int value() { return value_; }
71 friend class PositionStack;
72 Element* previous_;
73 int value_;
74 };
75
76 bool is_empty() { return top_ == NULL; }
77 int pop() {
78 ASSERT(!is_empty());
79 int result = top_->value();
80 top_ = top_->previous();
81 return result;
82 }
83
84 private:
85 Element* top() { return top_; }
86 void set_top(Element* value) { top_ = value; }
87 Element* top_;
88 bool* ok_;
89 };
90
91
92 RegExpBuilder::RegExpBuilder(Zone* zone) 49 RegExpBuilder::RegExpBuilder(Zone* zone)
93 : zone_(zone), 50 : zone_(zone),
94 pending_empty_(false), 51 pending_empty_(false),
95 characters_(NULL), 52 characters_(NULL),
96 terms_(), 53 terms_(),
97 alternatives_() 54 alternatives_()
98 #ifdef DEBUG 55 #ifdef DEBUG
99 , last_added_(ADD_NONE) 56 , last_added_(ADD_NONE)
100 #endif 57 #endif
101 {} 58 {}
(...skipping 3183 matching lines...) Expand 10 before | Expand all | Expand 10 after
3285 position()); 3242 position());
3286 } 3243 }
3287 return expression; 3244 return expression;
3288 } 3245 }
3289 3246
3290 3247
3291 Expression* Parser::ParseLeftHandSideExpression(bool* ok) { 3248 Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
3292 // LeftHandSideExpression :: 3249 // LeftHandSideExpression ::
3293 // (NewExpression | MemberExpression) ... 3250 // (NewExpression | MemberExpression) ...
3294 3251
3295 Expression* result; 3252 Expression* result = ParseMemberWithNewPrefixesExpression(CHECK_OK);
3296 if (peek() == Token::NEW) {
3297 result = ParseNewExpression(CHECK_OK);
3298 } else {
3299 result = ParseMemberExpression(CHECK_OK);
3300 }
3301 3253
3302 while (true) { 3254 while (true) {
3303 switch (peek()) { 3255 switch (peek()) {
3304 case Token::LBRACK: { 3256 case Token::LBRACK: {
3305 Consume(Token::LBRACK); 3257 Consume(Token::LBRACK);
3306 int pos = position(); 3258 int pos = position();
3307 Expression* index = ParseExpression(true, CHECK_OK); 3259 Expression* index = ParseExpression(true, CHECK_OK);
3308 result = factory()->NewProperty(result, index, pos); 3260 result = factory()->NewProperty(result, index, pos);
3309 Expect(Token::RBRACK, CHECK_OK); 3261 Expect(Token::RBRACK, CHECK_OK);
3310 break; 3262 break;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
3359 break; 3311 break;
3360 } 3312 }
3361 3313
3362 default: 3314 default:
3363 return result; 3315 return result;
3364 } 3316 }
3365 } 3317 }
3366 } 3318 }
3367 3319
3368 3320
3369 Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) { 3321 Expression* Parser::ParseMemberWithNewPrefixesExpression(bool* ok) {
3370 // NewExpression :: 3322 // NewExpression ::
3371 // ('new')+ MemberExpression 3323 // ('new')+ MemberExpression
3372 3324
3373 // The grammar for new expressions is pretty warped. The keyword 3325 // The grammar for new expressions is pretty warped. We can have several 'new'
3374 // 'new' can either be a part of the new expression (where it isn't 3326 // keywords following each other, and then a MemberExpression. When we see '('
3375 // followed by an argument list) or a part of the member expression, 3327 // after the MemberExpression, it's associated with the rightmost unassociated
3376 // where it must be followed by an argument list. To accommodate 3328 // 'new' to create a NewExpression with arguments. However, a NewExpression
3377 // this, we parse the 'new' keywords greedily and keep track of how 3329 // can also occur without arguments.
3378 // many we have parsed. This information is then passed on to the
3379 // member expression parser, which is only allowed to match argument
3380 // lists as long as it has 'new' prefixes left
3381 Expect(Token::NEW, CHECK_OK);
3382 PositionStack::Element pos(stack, position());
3383 3330
3384 Expression* result; 3331 // Examples of new expression:
3332 // new foo.bar().baz means (new (foo.bar)()).baz
3333 // new foo()() means (new foo())()
3334 // new new foo()() means (new (new foo())())
3335 // new new foo means new (new foo)
3336 // new new foo() means new (new foo())
3337
3385 if (peek() == Token::NEW) { 3338 if (peek() == Token::NEW) {
3386 result = ParseNewPrefix(stack, CHECK_OK); 3339 Consume(Token::NEW);
3387 } else { 3340 int new_pos = position();
3388 result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK); 3341 Expression* result = ParseMemberWithNewPrefixesExpression(CHECK_OK);
3342 if (peek() == Token::LPAREN) {
3343 // NewExpression with arguments.
3344 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
3345 return factory()->NewCallNew(result, args, new_pos);
3346 }
3347 // NewExpression without arguments.
3348 return factory()->NewCallNew(
3349 result, new(zone()) ZoneList<Expression*>(0, zone()), new_pos);
3389 } 3350 }
3390 3351 // No 'new' keyword.
3391 if (!stack->is_empty()) { 3352 return ParseMemberExpression(ok);
3392 int last = stack->pop();
3393 result = factory()->NewCallNew(
3394 result, new(zone()) ZoneList<Expression*>(0, zone()), last);
3395 }
3396 return result;
3397 }
3398
3399
3400 Expression* Parser::ParseNewExpression(bool* ok) {
3401 PositionStack stack(ok);
3402 return ParseNewPrefix(&stack, ok);
3403 } 3353 }
3404 3354
3405 3355
3406 Expression* Parser::ParseMemberExpression(bool* ok) { 3356 Expression* Parser::ParseMemberExpression(bool* ok) {
3407 return ParseMemberWithNewPrefixesExpression(NULL, ok);
3408 }
3409
3410
3411 Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
3412 bool* ok) {
3413 // MemberExpression :: 3357 // MemberExpression ::
3414 // (PrimaryExpression | FunctionLiteral) 3358 // (PrimaryExpression | FunctionLiteral)
3415 // ('[' Expression ']' | '.' Identifier | Arguments)* 3359 // ('[' Expression ']' | '.' Identifier | Arguments)*
3416 3360
3417 // Parse the initial primary or function expression. 3361 // Parse the initial primary or function expression.
3418 Expression* result = NULL; 3362 Expression* result = NULL;
3419 if (peek() == Token::FUNCTION) { 3363 if (peek() == Token::FUNCTION) {
3420 Consume(Token::FUNCTION); 3364 Consume(Token::FUNCTION);
3421 int function_token_position = position(); 3365 int function_token_position = position();
3422 bool is_generator = allow_generators() && Check(Token::MUL); 3366 bool is_generator = allow_generators() && Check(Token::MUL);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
3462 } 3406 }
3463 case Token::PERIOD: { 3407 case Token::PERIOD: {
3464 Consume(Token::PERIOD); 3408 Consume(Token::PERIOD);
3465 int pos = position(); 3409 int pos = position();
3466 Handle<String> name = ParseIdentifierName(CHECK_OK); 3410 Handle<String> name = ParseIdentifierName(CHECK_OK);
3467 result = factory()->NewProperty( 3411 result = factory()->NewProperty(
3468 result, factory()->NewLiteral(name, pos), pos); 3412 result, factory()->NewLiteral(name, pos), pos);
3469 if (fni_ != NULL) fni_->PushLiteralName(name); 3413 if (fni_ != NULL) fni_->PushLiteralName(name);
3470 break; 3414 break;
3471 } 3415 }
3472 case Token::LPAREN: {
3473 if ((stack == NULL) || stack->is_empty()) return result;
3474 // Consume one of the new prefixes (already parsed).
3475 ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
3476 int pos = stack->pop();
3477 result = factory()->NewCallNew(result, args, pos);
marja 2014/02/17 15:11:42 The problem is: In the original code, we can have
3478 break;
3479 }
3480 default: 3416 default:
3481 return result; 3417 return result;
3482 } 3418 }
3483 } 3419 }
3484 } 3420 }
3485 3421
3486 3422
3487 DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) { 3423 DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
3488 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser 3424 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
3489 // contexts this is used as a statement which invokes the debugger as i a 3425 // contexts this is used as a statement which invokes the debugger as i a
(...skipping 1920 matching lines...) Expand 10 before | Expand all | Expand 10 after
5410 ASSERT(info()->isolate()->has_pending_exception()); 5346 ASSERT(info()->isolate()->has_pending_exception());
5411 } else { 5347 } else {
5412 result = ParseProgram(); 5348 result = ParseProgram();
5413 } 5349 }
5414 } 5350 }
5415 info()->SetFunction(result); 5351 info()->SetFunction(result);
5416 return (result != NULL); 5352 return (result != NULL);
5417 } 5353 }
5418 5354
5419 } } // namespace v8::internal 5355 } } // namespace v8::internal
OLDNEW
« 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