preparser.cc revision 44f0eee88ff00398ff7f715fab053374d808c90d
1// Copyright 2010 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#include "../include/v8stdint.h" 29#include "unicode.h" 30#include "globals.h" 31#include "checks.h" 32#include "allocation.h" 33#include "utils.h" 34#include "list.h" 35 36#include "scanner-base.h" 37#include "preparse-data.h" 38#include "preparser.h" 39 40namespace v8 { 41namespace preparser { 42 43// Preparsing checks a JavaScript program and emits preparse-data that helps 44// a later parsing to be faster. 45// See preparser-data.h for the data. 46 47// The PreParser checks that the syntax follows the grammar for JavaScript, 48// and collects some information about the program along the way. 49// The grammar check is only performed in order to understand the program 50// sufficiently to deduce some information about it, that can be used 51// to speed up later parsing. Finding errors is not the goal of pre-parsing, 52// rather it is to speed up properly written and correct programs. 53// That means that contextual checks (like a label being declared where 54// it is used) are generally omitted. 55 56namespace i = ::v8::internal; 57 58#define CHECK_OK ok); \ 59 if (!*ok) return -1; \ 60 ((void)0 61#define DUMMY ) // to make indentation work 62#undef DUMMY 63 64 65void PreParser::ReportUnexpectedToken(i::Token::Value token) { 66 // We don't report stack overflows here, to avoid increasing the 67 // stack depth even further. Instead we report it after parsing is 68 // over, in ParseProgram. 69 if (token == i::Token::ILLEGAL && stack_overflow_) { 70 return; 71 } 72 i::JavaScriptScanner::Location source_location = scanner_->location(); 73 74 // Four of the tokens are treated specially 75 switch (token) { 76 case i::Token::EOS: 77 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 78 "unexpected_eos", NULL); 79 case i::Token::NUMBER: 80 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 81 "unexpected_token_number", NULL); 82 case i::Token::STRING: 83 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 84 "unexpected_token_string", NULL); 85 case i::Token::IDENTIFIER: 86 case i::Token::FUTURE_RESERVED_WORD: 87 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 88 "unexpected_token_identifier", NULL); 89 default: 90 const char* name = i::Token::String(token); 91 ReportMessageAt(source_location.beg_pos, source_location.end_pos, 92 "unexpected_token", name); 93 } 94} 95 96 97PreParser::SourceElements PreParser::ParseSourceElements(int end_token, 98 bool* ok) { 99 // SourceElements :: 100 // (Statement)* <end_token> 101 102 while (peek() != end_token) { 103 ParseStatement(CHECK_OK); 104 } 105 return kUnknownSourceElements; 106} 107 108 109PreParser::Statement PreParser::ParseStatement(bool* ok) { 110 // Statement :: 111 // Block 112 // VariableStatement 113 // EmptyStatement 114 // ExpressionStatement 115 // IfStatement 116 // IterationStatement 117 // ContinueStatement 118 // BreakStatement 119 // ReturnStatement 120 // WithStatement 121 // LabelledStatement 122 // SwitchStatement 123 // ThrowStatement 124 // TryStatement 125 // DebuggerStatement 126 127 // Note: Since labels can only be used by 'break' and 'continue' 128 // statements, which themselves are only valid within blocks, 129 // iterations or 'switch' statements (i.e., BreakableStatements), 130 // labels can be simply ignored in all other cases; except for 131 // trivial labeled break statements 'label: break label' which is 132 // parsed into an empty statement. 133 134 // Keep the source position of the statement 135 switch (peek()) { 136 case i::Token::LBRACE: 137 return ParseBlock(ok); 138 139 case i::Token::CONST: 140 case i::Token::VAR: 141 return ParseVariableStatement(ok); 142 143 case i::Token::SEMICOLON: 144 Next(); 145 return kUnknownStatement; 146 147 case i::Token::IF: 148 return ParseIfStatement(ok); 149 150 case i::Token::DO: 151 return ParseDoWhileStatement(ok); 152 153 case i::Token::WHILE: 154 return ParseWhileStatement(ok); 155 156 case i::Token::FOR: 157 return ParseForStatement(ok); 158 159 case i::Token::CONTINUE: 160 return ParseContinueStatement(ok); 161 162 case i::Token::BREAK: 163 return ParseBreakStatement(ok); 164 165 case i::Token::RETURN: 166 return ParseReturnStatement(ok); 167 168 case i::Token::WITH: 169 return ParseWithStatement(ok); 170 171 case i::Token::SWITCH: 172 return ParseSwitchStatement(ok); 173 174 case i::Token::THROW: 175 return ParseThrowStatement(ok); 176 177 case i::Token::TRY: 178 return ParseTryStatement(ok); 179 180 case i::Token::FUNCTION: 181 return ParseFunctionDeclaration(ok); 182 183 case i::Token::NATIVE: 184 return ParseNativeDeclaration(ok); 185 186 case i::Token::DEBUGGER: 187 return ParseDebuggerStatement(ok); 188 189 default: 190 return ParseExpressionOrLabelledStatement(ok); 191 } 192} 193 194 195PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { 196 // FunctionDeclaration :: 197 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' 198 Expect(i::Token::FUNCTION, CHECK_OK); 199 ParseIdentifier(CHECK_OK); 200 ParseFunctionLiteral(CHECK_OK); 201 return kUnknownStatement; 202} 203 204 205// Language extension which is only enabled for source files loaded 206// through the API's extension mechanism. A native function 207// declaration is resolved by looking up the function through a 208// callback provided by the extension. 209PreParser::Statement PreParser::ParseNativeDeclaration(bool* ok) { 210 Expect(i::Token::NATIVE, CHECK_OK); 211 Expect(i::Token::FUNCTION, CHECK_OK); 212 ParseIdentifier(CHECK_OK); 213 Expect(i::Token::LPAREN, CHECK_OK); 214 bool done = (peek() == i::Token::RPAREN); 215 while (!done) { 216 ParseIdentifier(CHECK_OK); 217 done = (peek() == i::Token::RPAREN); 218 if (!done) { 219 Expect(i::Token::COMMA, CHECK_OK); 220 } 221 } 222 Expect(i::Token::RPAREN, CHECK_OK); 223 Expect(i::Token::SEMICOLON, CHECK_OK); 224 return kUnknownStatement; 225} 226 227 228PreParser::Statement PreParser::ParseBlock(bool* ok) { 229 // Block :: 230 // '{' Statement* '}' 231 232 // Note that a Block does not introduce a new execution scope! 233 // (ECMA-262, 3rd, 12.2) 234 // 235 Expect(i::Token::LBRACE, CHECK_OK); 236 while (peek() != i::Token::RBRACE) { 237 ParseStatement(CHECK_OK); 238 } 239 Expect(i::Token::RBRACE, CHECK_OK); 240 return kUnknownStatement; 241} 242 243 244PreParser::Statement PreParser::ParseVariableStatement(bool* ok) { 245 // VariableStatement :: 246 // VariableDeclarations ';' 247 248 Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK); 249 ExpectSemicolon(CHECK_OK); 250 return result; 251} 252 253 254// If the variable declaration declares exactly one non-const 255// variable, then *var is set to that variable. In all other cases, 256// *var is untouched; in particular, it is the caller's responsibility 257// to initialize it properly. This mechanism is also used for the parsing 258// of 'for-in' loops. 259PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN, 260 int* num_decl, 261 bool* ok) { 262 // VariableDeclarations :: 263 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] 264 265 if (peek() == i::Token::VAR) { 266 Consume(i::Token::VAR); 267 } else if (peek() == i::Token::CONST) { 268 Consume(i::Token::CONST); 269 } else { 270 *ok = false; 271 return 0; 272 } 273 274 // The scope of a variable/const declared anywhere inside a function 275 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). . 276 int nvars = 0; // the number of variables declared 277 do { 278 // Parse variable name. 279 if (nvars > 0) Consume(i::Token::COMMA); 280 ParseIdentifier(CHECK_OK); 281 nvars++; 282 if (peek() == i::Token::ASSIGN) { 283 Expect(i::Token::ASSIGN, CHECK_OK); 284 ParseAssignmentExpression(accept_IN, CHECK_OK); 285 } 286 } while (peek() == i::Token::COMMA); 287 288 if (num_decl != NULL) *num_decl = nvars; 289 return kUnknownStatement; 290} 291 292 293PreParser::Statement PreParser::ParseExpressionOrLabelledStatement( 294 bool* ok) { 295 // ExpressionStatement | LabelledStatement :: 296 // Expression ';' 297 // Identifier ':' Statement 298 299 Expression expr = ParseExpression(true, CHECK_OK); 300 if (peek() == i::Token::COLON && expr == kIdentifierExpression) { 301 Consume(i::Token::COLON); 302 return ParseStatement(ok); 303 } 304 // Parsed expression statement. 305 ExpectSemicolon(CHECK_OK); 306 return kUnknownStatement; 307} 308 309 310PreParser::Statement PreParser::ParseIfStatement(bool* ok) { 311 // IfStatement :: 312 // 'if' '(' Expression ')' Statement ('else' Statement)? 313 314 Expect(i::Token::IF, CHECK_OK); 315 Expect(i::Token::LPAREN, CHECK_OK); 316 ParseExpression(true, CHECK_OK); 317 Expect(i::Token::RPAREN, CHECK_OK); 318 ParseStatement(CHECK_OK); 319 if (peek() == i::Token::ELSE) { 320 Next(); 321 ParseStatement(CHECK_OK); 322 } 323 return kUnknownStatement; 324} 325 326 327PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { 328 // ContinueStatement :: 329 // 'continue' [no line terminator] Identifier? ';' 330 331 Expect(i::Token::CONTINUE, CHECK_OK); 332 i::Token::Value tok = peek(); 333 if (!scanner_->has_line_terminator_before_next() && 334 tok != i::Token::SEMICOLON && 335 tok != i::Token::RBRACE && 336 tok != i::Token::EOS) { 337 ParseIdentifier(CHECK_OK); 338 } 339 ExpectSemicolon(CHECK_OK); 340 return kUnknownStatement; 341} 342 343 344PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { 345 // BreakStatement :: 346 // 'break' [no line terminator] Identifier? ';' 347 348 Expect(i::Token::BREAK, CHECK_OK); 349 i::Token::Value tok = peek(); 350 if (!scanner_->has_line_terminator_before_next() && 351 tok != i::Token::SEMICOLON && 352 tok != i::Token::RBRACE && 353 tok != i::Token::EOS) { 354 ParseIdentifier(CHECK_OK); 355 } 356 ExpectSemicolon(CHECK_OK); 357 return kUnknownStatement; 358} 359 360 361PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { 362 // ReturnStatement :: 363 // 'return' [no line terminator] Expression? ';' 364 365 // Consume the return token. It is necessary to do the before 366 // reporting any errors on it, because of the way errors are 367 // reported (underlining). 368 Expect(i::Token::RETURN, CHECK_OK); 369 370 // An ECMAScript program is considered syntactically incorrect if it 371 // contains a return statement that is not within the body of a 372 // function. See ECMA-262, section 12.9, page 67. 373 // This is not handled during preparsing. 374 375 i::Token::Value tok = peek(); 376 if (!scanner_->has_line_terminator_before_next() && 377 tok != i::Token::SEMICOLON && 378 tok != i::Token::RBRACE && 379 tok != i::Token::EOS) { 380 ParseExpression(true, CHECK_OK); 381 } 382 ExpectSemicolon(CHECK_OK); 383 return kUnknownStatement; 384} 385 386 387PreParser::Statement PreParser::ParseWithStatement(bool* ok) { 388 // WithStatement :: 389 // 'with' '(' Expression ')' Statement 390 Expect(i::Token::WITH, CHECK_OK); 391 Expect(i::Token::LPAREN, CHECK_OK); 392 ParseExpression(true, CHECK_OK); 393 Expect(i::Token::RPAREN, CHECK_OK); 394 395 scope_->EnterWith(); 396 ParseStatement(CHECK_OK); 397 scope_->LeaveWith(); 398 return kUnknownStatement; 399} 400 401 402PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) { 403 // SwitchStatement :: 404 // 'switch' '(' Expression ')' '{' CaseClause* '}' 405 406 Expect(i::Token::SWITCH, CHECK_OK); 407 Expect(i::Token::LPAREN, CHECK_OK); 408 ParseExpression(true, CHECK_OK); 409 Expect(i::Token::RPAREN, CHECK_OK); 410 411 Expect(i::Token::LBRACE, CHECK_OK); 412 i::Token::Value token = peek(); 413 while (token != i::Token::RBRACE) { 414 if (token == i::Token::CASE) { 415 Expect(i::Token::CASE, CHECK_OK); 416 ParseExpression(true, CHECK_OK); 417 Expect(i::Token::COLON, CHECK_OK); 418 } else if (token == i::Token::DEFAULT) { 419 Expect(i::Token::DEFAULT, CHECK_OK); 420 Expect(i::Token::COLON, CHECK_OK); 421 } else { 422 ParseStatement(CHECK_OK); 423 } 424 token = peek(); 425 } 426 Expect(i::Token::RBRACE, CHECK_OK); 427 428 return kUnknownStatement; 429} 430 431 432PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) { 433 // DoStatement :: 434 // 'do' Statement 'while' '(' Expression ')' ';' 435 436 Expect(i::Token::DO, CHECK_OK); 437 ParseStatement(CHECK_OK); 438 Expect(i::Token::WHILE, CHECK_OK); 439 Expect(i::Token::LPAREN, CHECK_OK); 440 ParseExpression(true, CHECK_OK); 441 Expect(i::Token::RPAREN, CHECK_OK); 442 return kUnknownStatement; 443} 444 445 446PreParser::Statement PreParser::ParseWhileStatement(bool* ok) { 447 // WhileStatement :: 448 // 'while' '(' Expression ')' Statement 449 450 Expect(i::Token::WHILE, CHECK_OK); 451 Expect(i::Token::LPAREN, CHECK_OK); 452 ParseExpression(true, CHECK_OK); 453 Expect(i::Token::RPAREN, CHECK_OK); 454 ParseStatement(CHECK_OK); 455 return kUnknownStatement; 456} 457 458 459PreParser::Statement PreParser::ParseForStatement(bool* ok) { 460 // ForStatement :: 461 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement 462 463 Expect(i::Token::FOR, CHECK_OK); 464 Expect(i::Token::LPAREN, CHECK_OK); 465 if (peek() != i::Token::SEMICOLON) { 466 if (peek() == i::Token::VAR || peek() == i::Token::CONST) { 467 int decl_count; 468 ParseVariableDeclarations(false, &decl_count, CHECK_OK); 469 if (peek() == i::Token::IN && decl_count == 1) { 470 Expect(i::Token::IN, CHECK_OK); 471 ParseExpression(true, CHECK_OK); 472 Expect(i::Token::RPAREN, CHECK_OK); 473 474 ParseStatement(CHECK_OK); 475 return kUnknownStatement; 476 } 477 } else { 478 ParseExpression(false, CHECK_OK); 479 if (peek() == i::Token::IN) { 480 Expect(i::Token::IN, CHECK_OK); 481 ParseExpression(true, CHECK_OK); 482 Expect(i::Token::RPAREN, CHECK_OK); 483 484 ParseStatement(CHECK_OK); 485 return kUnknownStatement; 486 } 487 } 488 } 489 490 // Parsed initializer at this point. 491 Expect(i::Token::SEMICOLON, CHECK_OK); 492 493 if (peek() != i::Token::SEMICOLON) { 494 ParseExpression(true, CHECK_OK); 495 } 496 Expect(i::Token::SEMICOLON, CHECK_OK); 497 498 if (peek() != i::Token::RPAREN) { 499 ParseExpression(true, CHECK_OK); 500 } 501 Expect(i::Token::RPAREN, CHECK_OK); 502 503 ParseStatement(CHECK_OK); 504 return kUnknownStatement; 505} 506 507 508PreParser::Statement PreParser::ParseThrowStatement(bool* ok) { 509 // ThrowStatement :: 510 // 'throw' [no line terminator] Expression ';' 511 512 Expect(i::Token::THROW, CHECK_OK); 513 if (scanner_->has_line_terminator_before_next()) { 514 i::JavaScriptScanner::Location pos = scanner_->location(); 515 ReportMessageAt(pos.beg_pos, pos.end_pos, 516 "newline_after_throw", NULL); 517 *ok = false; 518 return kUnknownStatement; 519 } 520 ParseExpression(true, CHECK_OK); 521 ExpectSemicolon(CHECK_OK); 522 523 return kUnknownStatement; 524} 525 526 527PreParser::Statement PreParser::ParseTryStatement(bool* ok) { 528 // TryStatement :: 529 // 'try' Block Catch 530 // 'try' Block Finally 531 // 'try' Block Catch Finally 532 // 533 // Catch :: 534 // 'catch' '(' Identifier ')' Block 535 // 536 // Finally :: 537 // 'finally' Block 538 539 // In preparsing, allow any number of catch/finally blocks, including zero 540 // of both. 541 542 Expect(i::Token::TRY, CHECK_OK); 543 544 ParseBlock(CHECK_OK); 545 546 bool catch_or_finally_seen = false; 547 if (peek() == i::Token::CATCH) { 548 Consume(i::Token::CATCH); 549 Expect(i::Token::LPAREN, CHECK_OK); 550 ParseIdentifier(CHECK_OK); 551 Expect(i::Token::RPAREN, CHECK_OK); 552 scope_->EnterWith(); 553 ParseBlock(ok); 554 scope_->LeaveWith(); 555 if (!*ok) return kUnknownStatement; 556 catch_or_finally_seen = true; 557 } 558 if (peek() == i::Token::FINALLY) { 559 Consume(i::Token::FINALLY); 560 ParseBlock(CHECK_OK); 561 catch_or_finally_seen = true; 562 } 563 if (!catch_or_finally_seen) { 564 *ok = false; 565 } 566 return kUnknownStatement; 567} 568 569 570PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { 571 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser 572 // contexts this is used as a statement which invokes the debugger as if a 573 // break point is present. 574 // DebuggerStatement :: 575 // 'debugger' ';' 576 577 Expect(i::Token::DEBUGGER, CHECK_OK); 578 ExpectSemicolon(CHECK_OK); 579 return kUnknownStatement; 580} 581 582 583// Precedence = 1 584PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) { 585 // Expression :: 586 // AssignmentExpression 587 // Expression ',' AssignmentExpression 588 589 Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK); 590 while (peek() == i::Token::COMMA) { 591 Expect(i::Token::COMMA, CHECK_OK); 592 ParseAssignmentExpression(accept_IN, CHECK_OK); 593 result = kUnknownExpression; 594 } 595 return result; 596} 597 598 599// Precedence = 2 600PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN, 601 bool* ok) { 602 // AssignmentExpression :: 603 // ConditionalExpression 604 // LeftHandSideExpression AssignmentOperator AssignmentExpression 605 606 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK); 607 608 if (!i::Token::IsAssignmentOp(peek())) { 609 // Parsed conditional expression only (no assignment). 610 return expression; 611 } 612 613 i::Token::Value op = Next(); // Get assignment operator. 614 ParseAssignmentExpression(accept_IN, CHECK_OK); 615 616 if ((op == i::Token::ASSIGN) && (expression == kThisPropertyExpression)) { 617 scope_->AddProperty(); 618 } 619 620 return kUnknownExpression; 621} 622 623 624// Precedence = 3 625PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN, 626 bool* ok) { 627 // ConditionalExpression :: 628 // LogicalOrExpression 629 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression 630 631 // We start using the binary expression parser for prec >= 4 only! 632 Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK); 633 if (peek() != i::Token::CONDITIONAL) return expression; 634 Consume(i::Token::CONDITIONAL); 635 // In parsing the first assignment expression in conditional 636 // expressions we always accept the 'in' keyword; see ECMA-262, 637 // section 11.12, page 58. 638 ParseAssignmentExpression(true, CHECK_OK); 639 Expect(i::Token::COLON, CHECK_OK); 640 ParseAssignmentExpression(accept_IN, CHECK_OK); 641 return kUnknownExpression; 642} 643 644 645int PreParser::Precedence(i::Token::Value tok, bool accept_IN) { 646 if (tok == i::Token::IN && !accept_IN) 647 return 0; // 0 precedence will terminate binary expression parsing 648 649 return i::Token::Precedence(tok); 650} 651 652 653// Precedence >= 4 654PreParser::Expression PreParser::ParseBinaryExpression(int prec, 655 bool accept_IN, 656 bool* ok) { 657 Expression result = ParseUnaryExpression(CHECK_OK); 658 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { 659 // prec1 >= 4 660 while (Precedence(peek(), accept_IN) == prec1) { 661 Next(); 662 ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK); 663 result = kUnknownExpression; 664 } 665 } 666 return result; 667} 668 669 670PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) { 671 // UnaryExpression :: 672 // PostfixExpression 673 // 'delete' UnaryExpression 674 // 'void' UnaryExpression 675 // 'typeof' UnaryExpression 676 // '++' UnaryExpression 677 // '--' UnaryExpression 678 // '+' UnaryExpression 679 // '-' UnaryExpression 680 // '~' UnaryExpression 681 // '!' UnaryExpression 682 683 i::Token::Value op = peek(); 684 if (i::Token::IsUnaryOp(op) || i::Token::IsCountOp(op)) { 685 op = Next(); 686 ParseUnaryExpression(ok); 687 return kUnknownExpression; 688 } else { 689 return ParsePostfixExpression(ok); 690 } 691} 692 693 694PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) { 695 // PostfixExpression :: 696 // LeftHandSideExpression ('++' | '--')? 697 698 Expression expression = ParseLeftHandSideExpression(CHECK_OK); 699 if (!scanner_->has_line_terminator_before_next() && 700 i::Token::IsCountOp(peek())) { 701 Next(); 702 return kUnknownExpression; 703 } 704 return expression; 705} 706 707 708PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) { 709 // LeftHandSideExpression :: 710 // (NewExpression | MemberExpression) ... 711 712 Expression result; 713 if (peek() == i::Token::NEW) { 714 result = ParseNewExpression(CHECK_OK); 715 } else { 716 result = ParseMemberExpression(CHECK_OK); 717 } 718 719 while (true) { 720 switch (peek()) { 721 case i::Token::LBRACK: { 722 Consume(i::Token::LBRACK); 723 ParseExpression(true, CHECK_OK); 724 Expect(i::Token::RBRACK, CHECK_OK); 725 if (result == kThisExpression) { 726 result = kThisPropertyExpression; 727 } else { 728 result = kUnknownExpression; 729 } 730 break; 731 } 732 733 case i::Token::LPAREN: { 734 ParseArguments(CHECK_OK); 735 result = kUnknownExpression; 736 break; 737 } 738 739 case i::Token::PERIOD: { 740 Consume(i::Token::PERIOD); 741 ParseIdentifierName(CHECK_OK); 742 if (result == kThisExpression) { 743 result = kThisPropertyExpression; 744 } else { 745 result = kUnknownExpression; 746 } 747 break; 748 } 749 750 default: 751 return result; 752 } 753 } 754} 755 756 757PreParser::Expression PreParser::ParseNewExpression(bool* ok) { 758 // NewExpression :: 759 // ('new')+ MemberExpression 760 761 // The grammar for new expressions is pretty warped. The keyword 762 // 'new' can either be a part of the new expression (where it isn't 763 // followed by an argument list) or a part of the member expression, 764 // where it must be followed by an argument list. To accommodate 765 // this, we parse the 'new' keywords greedily and keep track of how 766 // many we have parsed. This information is then passed on to the 767 // member expression parser, which is only allowed to match argument 768 // lists as long as it has 'new' prefixes left 769 unsigned new_count = 0; 770 do { 771 Consume(i::Token::NEW); 772 new_count++; 773 } while (peek() == i::Token::NEW); 774 775 return ParseMemberWithNewPrefixesExpression(new_count, ok); 776} 777 778 779PreParser::Expression PreParser::ParseMemberExpression(bool* ok) { 780 return ParseMemberWithNewPrefixesExpression(0, ok); 781} 782 783 784PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( 785 unsigned new_count, bool* ok) { 786 // MemberExpression :: 787 // (PrimaryExpression | FunctionLiteral) 788 // ('[' Expression ']' | '.' Identifier | Arguments)* 789 790 // Parse the initial primary or function expression. 791 Expression result = kUnknownExpression; 792 if (peek() == i::Token::FUNCTION) { 793 Consume(i::Token::FUNCTION); 794 if (peek_any_identifier()) { 795 ParseIdentifier(CHECK_OK); 796 } 797 result = ParseFunctionLiteral(CHECK_OK); 798 } else { 799 result = ParsePrimaryExpression(CHECK_OK); 800 } 801 802 while (true) { 803 switch (peek()) { 804 case i::Token::LBRACK: { 805 Consume(i::Token::LBRACK); 806 ParseExpression(true, CHECK_OK); 807 Expect(i::Token::RBRACK, CHECK_OK); 808 if (result == kThisExpression) { 809 result = kThisPropertyExpression; 810 } else { 811 result = kUnknownExpression; 812 } 813 break; 814 } 815 case i::Token::PERIOD: { 816 Consume(i::Token::PERIOD); 817 ParseIdentifierName(CHECK_OK); 818 if (result == kThisExpression) { 819 result = kThisPropertyExpression; 820 } else { 821 result = kUnknownExpression; 822 } 823 break; 824 } 825 case i::Token::LPAREN: { 826 if (new_count == 0) return result; 827 // Consume one of the new prefixes (already parsed). 828 ParseArguments(CHECK_OK); 829 new_count--; 830 result = kUnknownExpression; 831 break; 832 } 833 default: 834 return result; 835 } 836 } 837} 838 839 840PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) { 841 // PrimaryExpression :: 842 // 'this' 843 // 'null' 844 // 'true' 845 // 'false' 846 // Identifier 847 // Number 848 // String 849 // ArrayLiteral 850 // ObjectLiteral 851 // RegExpLiteral 852 // '(' Expression ')' 853 854 Expression result = kUnknownExpression; 855 switch (peek()) { 856 case i::Token::THIS: { 857 Next(); 858 result = kThisExpression; 859 break; 860 } 861 862 case i::Token::IDENTIFIER: 863 case i::Token::FUTURE_RESERVED_WORD: { 864 ParseIdentifier(CHECK_OK); 865 result = kIdentifierExpression; 866 break; 867 } 868 869 case i::Token::NULL_LITERAL: 870 case i::Token::TRUE_LITERAL: 871 case i::Token::FALSE_LITERAL: 872 case i::Token::NUMBER: { 873 Next(); 874 break; 875 } 876 case i::Token::STRING: { 877 Next(); 878 result = GetStringSymbol(); 879 break; 880 } 881 882 case i::Token::ASSIGN_DIV: 883 result = ParseRegExpLiteral(true, CHECK_OK); 884 break; 885 886 case i::Token::DIV: 887 result = ParseRegExpLiteral(false, CHECK_OK); 888 break; 889 890 case i::Token::LBRACK: 891 result = ParseArrayLiteral(CHECK_OK); 892 break; 893 894 case i::Token::LBRACE: 895 result = ParseObjectLiteral(CHECK_OK); 896 break; 897 898 case i::Token::LPAREN: 899 Consume(i::Token::LPAREN); 900 parenthesized_function_ = (peek() == i::Token::FUNCTION); 901 result = ParseExpression(true, CHECK_OK); 902 Expect(i::Token::RPAREN, CHECK_OK); 903 if (result == kIdentifierExpression) result = kUnknownExpression; 904 break; 905 906 case i::Token::MOD: 907 result = ParseV8Intrinsic(CHECK_OK); 908 break; 909 910 default: { 911 Next(); 912 *ok = false; 913 return kUnknownExpression; 914 } 915 } 916 917 return result; 918} 919 920 921PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) { 922 // ArrayLiteral :: 923 // '[' Expression? (',' Expression?)* ']' 924 Expect(i::Token::LBRACK, CHECK_OK); 925 while (peek() != i::Token::RBRACK) { 926 if (peek() != i::Token::COMMA) { 927 ParseAssignmentExpression(true, CHECK_OK); 928 } 929 if (peek() != i::Token::RBRACK) { 930 Expect(i::Token::COMMA, CHECK_OK); 931 } 932 } 933 Expect(i::Token::RBRACK, CHECK_OK); 934 935 scope_->NextMaterializedLiteralIndex(); 936 return kUnknownExpression; 937} 938 939 940PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { 941 // ObjectLiteral :: 942 // '{' ( 943 // ((IdentifierName | String | Number) ':' AssignmentExpression) 944 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) 945 // )*[','] '}' 946 947 Expect(i::Token::LBRACE, CHECK_OK); 948 while (peek() != i::Token::RBRACE) { 949 i::Token::Value next = peek(); 950 switch (next) { 951 case i::Token::IDENTIFIER: 952 case i::Token::FUTURE_RESERVED_WORD: { 953 bool is_getter = false; 954 bool is_setter = false; 955 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); 956 if ((is_getter || is_setter) && peek() != i::Token::COLON) { 957 i::Token::Value name = Next(); 958 bool is_keyword = i::Token::IsKeyword(name); 959 if (name != i::Token::IDENTIFIER && 960 name != i::Token::FUTURE_RESERVED_WORD && 961 name != i::Token::NUMBER && 962 name != i::Token::STRING && 963 !is_keyword) { 964 *ok = false; 965 return kUnknownExpression; 966 } 967 if (!is_keyword) { 968 LogSymbol(); 969 } 970 ParseFunctionLiteral(CHECK_OK); 971 if (peek() != i::Token::RBRACE) { 972 Expect(i::Token::COMMA, CHECK_OK); 973 } 974 continue; // restart the while 975 } 976 break; 977 } 978 case i::Token::STRING: 979 Consume(next); 980 GetStringSymbol(); 981 break; 982 case i::Token::NUMBER: 983 Consume(next); 984 break; 985 default: 986 if (i::Token::IsKeyword(next)) { 987 Consume(next); 988 } else { 989 // Unexpected token. 990 *ok = false; 991 return kUnknownExpression; 992 } 993 } 994 995 Expect(i::Token::COLON, CHECK_OK); 996 ParseAssignmentExpression(true, CHECK_OK); 997 998 // TODO(1240767): Consider allowing trailing comma. 999 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK); 1000 } 1001 Expect(i::Token::RBRACE, CHECK_OK); 1002 1003 scope_->NextMaterializedLiteralIndex(); 1004 return kUnknownExpression; 1005} 1006 1007 1008PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal, 1009 bool* ok) { 1010 if (!scanner_->ScanRegExpPattern(seen_equal)) { 1011 Next(); 1012 i::JavaScriptScanner::Location location = scanner_->location(); 1013 ReportMessageAt(location.beg_pos, location.end_pos, 1014 "unterminated_regexp", NULL); 1015 *ok = false; 1016 return kUnknownExpression; 1017 } 1018 1019 scope_->NextMaterializedLiteralIndex(); 1020 1021 if (!scanner_->ScanRegExpFlags()) { 1022 Next(); 1023 i::JavaScriptScanner::Location location = scanner_->location(); 1024 ReportMessageAt(location.beg_pos, location.end_pos, 1025 "invalid_regexp_flags", NULL); 1026 *ok = false; 1027 return kUnknownExpression; 1028 } 1029 Next(); 1030 return kUnknownExpression; 1031} 1032 1033 1034PreParser::Arguments PreParser::ParseArguments(bool* ok) { 1035 // Arguments :: 1036 // '(' (AssignmentExpression)*[','] ')' 1037 1038 Expect(i::Token::LPAREN, CHECK_OK); 1039 bool done = (peek() == i::Token::RPAREN); 1040 int argc = 0; 1041 while (!done) { 1042 ParseAssignmentExpression(true, CHECK_OK); 1043 argc++; 1044 done = (peek() == i::Token::RPAREN); 1045 if (!done) Expect(i::Token::COMMA, CHECK_OK); 1046 } 1047 Expect(i::Token::RPAREN, CHECK_OK); 1048 return argc; 1049} 1050 1051 1052PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) { 1053 // Function :: 1054 // '(' FormalParameterList? ')' '{' FunctionBody '}' 1055 1056 // Parse function body. 1057 ScopeType outer_scope_type = scope_->type(); 1058 bool inside_with = scope_->IsInsideWith(); 1059 Scope function_scope(&scope_, kFunctionScope); 1060 1061 // FormalParameterList :: 1062 // '(' (Identifier)*[','] ')' 1063 Expect(i::Token::LPAREN, CHECK_OK); 1064 bool done = (peek() == i::Token::RPAREN); 1065 while (!done) { 1066 ParseIdentifier(CHECK_OK); 1067 done = (peek() == i::Token::RPAREN); 1068 if (!done) { 1069 Expect(i::Token::COMMA, CHECK_OK); 1070 } 1071 } 1072 Expect(i::Token::RPAREN, CHECK_OK); 1073 1074 Expect(i::Token::LBRACE, CHECK_OK); 1075 int function_block_pos = scanner_->location().beg_pos; 1076 1077 // Determine if the function will be lazily compiled. 1078 // Currently only happens to top-level functions. 1079 // Optimistically assume that all top-level functions are lazily compiled. 1080 bool is_lazily_compiled = (outer_scope_type == kTopLevelScope && 1081 !inside_with && allow_lazy_ && 1082 !parenthesized_function_); 1083 parenthesized_function_ = false; 1084 1085 if (is_lazily_compiled) { 1086 log_->PauseRecording(); 1087 ParseSourceElements(i::Token::RBRACE, ok); 1088 log_->ResumeRecording(); 1089 if (!*ok) return kUnknownExpression; 1090 1091 Expect(i::Token::RBRACE, CHECK_OK); 1092 1093 // Position right after terminal '}'. 1094 int end_pos = scanner_->location().end_pos; 1095 log_->LogFunction(function_block_pos, end_pos, 1096 function_scope.materialized_literal_count(), 1097 function_scope.expected_properties()); 1098 } else { 1099 ParseSourceElements(i::Token::RBRACE, CHECK_OK); 1100 Expect(i::Token::RBRACE, CHECK_OK); 1101 } 1102 return kUnknownExpression; 1103} 1104 1105 1106PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { 1107 // CallRuntime :: 1108 // '%' Identifier Arguments 1109 1110 Expect(i::Token::MOD, CHECK_OK); 1111 ParseIdentifier(CHECK_OK); 1112 ParseArguments(CHECK_OK); 1113 1114 return kUnknownExpression; 1115} 1116 1117 1118void PreParser::ExpectSemicolon(bool* ok) { 1119 // Check for automatic semicolon insertion according to 1120 // the rules given in ECMA-262, section 7.9, page 21. 1121 i::Token::Value tok = peek(); 1122 if (tok == i::Token::SEMICOLON) { 1123 Next(); 1124 return; 1125 } 1126 if (scanner_->has_line_terminator_before_next() || 1127 tok == i::Token::RBRACE || 1128 tok == i::Token::EOS) { 1129 return; 1130 } 1131 Expect(i::Token::SEMICOLON, ok); 1132} 1133 1134 1135void PreParser::LogSymbol() { 1136 int identifier_pos = scanner_->location().beg_pos; 1137 if (scanner_->is_literal_ascii()) { 1138 log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string()); 1139 } else { 1140 log_->LogUC16Symbol(identifier_pos, scanner_->literal_uc16_string()); 1141 } 1142} 1143 1144 1145PreParser::Identifier PreParser::GetIdentifierSymbol() { 1146 LogSymbol(); 1147 return kUnknownIdentifier; 1148} 1149 1150 1151PreParser::Expression PreParser::GetStringSymbol() { 1152 LogSymbol(); 1153 return kUnknownExpression; 1154} 1155 1156 1157PreParser::Identifier PreParser::ParseIdentifier(bool* ok) { 1158 if (!Check(i::Token::FUTURE_RESERVED_WORD)) { 1159 Expect(i::Token::IDENTIFIER, ok); 1160 } 1161 if (!*ok) return kUnknownIdentifier; 1162 return GetIdentifierSymbol(); 1163} 1164 1165 1166PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { 1167 i::Token::Value next = Next(); 1168 if (i::Token::IsKeyword(next)) { 1169 int pos = scanner_->location().beg_pos; 1170 const char* keyword = i::Token::String(next); 1171 log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword, 1172 i::StrLength(keyword))); 1173 return kUnknownExpression; 1174 } 1175 if (next == i::Token::IDENTIFIER || 1176 next == i::Token::FUTURE_RESERVED_WORD) { 1177 return GetIdentifierSymbol(); 1178 } 1179 *ok = false; 1180 return kUnknownIdentifier; 1181} 1182 1183 1184// This function reads an identifier and determines whether or not it 1185// is 'get' or 'set'. 1186PreParser::Identifier PreParser::ParseIdentifierOrGetOrSet(bool* is_get, 1187 bool* is_set, 1188 bool* ok) { 1189 PreParser::Identifier result = ParseIdentifier(CHECK_OK); 1190 if (scanner_->is_literal_ascii() && scanner_->literal_length() == 3) { 1191 const char* token = scanner_->literal_ascii_string().start(); 1192 *is_get = strncmp(token, "get", 3) == 0; 1193 *is_set = !*is_get && strncmp(token, "set", 3) == 0; 1194 } 1195 return result; 1196} 1197 1198bool PreParser::peek_any_identifier() { 1199 i::Token::Value next = peek(); 1200 return next == i::Token::IDENTIFIER || 1201 next == i::Token::FUTURE_RESERVED_WORD; 1202} 1203 1204#undef CHECK_OK 1205} } // v8::preparser 1206