Home | History | Annotate | Download | only in src
      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 
     40 namespace v8 {
     41 namespace 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 
     56 namespace 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 
     65 void 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 
     97 PreParser::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 
    109 PreParser::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 
    195 PreParser::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.
    209 PreParser::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 
    228 PreParser::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 
    244 PreParser::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.
    259 PreParser::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 
    293 PreParser::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 
    310 PreParser::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 
    327 PreParser::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 
    344 PreParser::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 
    361 PreParser::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 
    387 PreParser::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 
    402 PreParser::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 
    432 PreParser::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 
    446 PreParser::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 
    459 PreParser::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 
    508 PreParser::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 
    527 PreParser::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 
    570 PreParser::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
    584 PreParser::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
    600 PreParser::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
    625 PreParser::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 
    645 int 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
    654 PreParser::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 
    670 PreParser::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 
    694 PreParser::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 
    708 PreParser::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 
    757 PreParser::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 
    779 PreParser::Expression PreParser::ParseMemberExpression(bool* ok) {
    780   return ParseMemberWithNewPrefixesExpression(0, ok);
    781 }
    782 
    783 
    784 PreParser::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 
    840 PreParser::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 
    921 PreParser::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 
    940 PreParser::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 
   1008 PreParser::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 
   1034 PreParser::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 
   1052 PreParser::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 
   1106 PreParser::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 
   1118 void 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 
   1135 void 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 
   1145 PreParser::Identifier PreParser::GetIdentifierSymbol() {
   1146   LogSymbol();
   1147   return kUnknownIdentifier;
   1148 }
   1149 
   1150 
   1151 PreParser::Expression PreParser::GetStringSymbol() {
   1152   LogSymbol();
   1153   return kUnknownExpression;
   1154 }
   1155 
   1156 
   1157 PreParser::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 
   1166 PreParser::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'.
   1186 PreParser::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 
   1198 bool 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