| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 13 matching lines...) Expand all Loading... |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_PREPARSER_H | 28 #ifndef V8_PREPARSER_H |
| 29 #define V8_PREPARSER_H | 29 #define V8_PREPARSER_H |
| 30 | 30 |
| 31 #include "unicode.h" | 31 #include "unicode.h" |
| 32 | 32 |
| 33 namespace v8 { | 33 namespace v8 { |
| 34 namespace internal { | |
| 35 namespace preparser { | 34 namespace preparser { |
| 36 | 35 |
| 37 // Preparsing checks a JavaScript program and emits preparse-data that helps | 36 // Preparsing checks a JavaScript program and emits preparse-data that helps |
| 38 // a later parsing to be faster. | 37 // a later parsing to be faster. |
| 39 // See preparser-data.h for the data. | 38 // See preparser-data.h for the data. |
| 40 | 39 |
| 41 // The PreParser checks that the syntax follows the grammar for JavaScript, | 40 // The PreParser checks that the syntax follows the grammar for JavaScript, |
| 42 // and collects some information about the program along the way. | 41 // and collects some information about the program along the way. |
| 43 // The grammar check is only performed in order to understand the program | 42 // The grammar check is only performed in order to understand the program |
| 44 // sufficiently to deduce some information about it, that can be used | 43 // sufficiently to deduce some information about it, that can be used |
| 45 // to speed up later parsing. Finding errors is not the goal of pre-parsing, | 44 // to speed up later parsing. Finding errors is not the goal of pre-parsing, |
| 46 // rather it is to speed up properly written and correct programs. | 45 // rather it is to speed up properly written and correct programs. |
| 47 // That means that contextual checks (like a label being declared where | 46 // That means that contextual checks (like a label being declared where |
| 48 // it is used) are generally omitted. | 47 // it is used) are generally omitted. |
| 49 | 48 |
| 49 namespace i = v8::internal; |
| 50 |
| 50 enum StatementType { | 51 enum StatementType { |
| 51 kUnknownStatement | 52 kUnknownStatement |
| 52 }; | 53 }; |
| 53 | 54 |
| 54 enum ExpressionType { | 55 enum ExpressionType { |
| 55 kUnknownExpression, | 56 kUnknownExpression, |
| 56 kIdentifierExpression, // Used to detect labels. | 57 kIdentifierExpression, // Used to detect labels. |
| 57 kThisExpression, | 58 kThisExpression, |
| 58 kThisPropertyExpression | 59 kThisPropertyExpression |
| 59 }; | 60 }; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 85 // captured the syntax error), and false if a stack-overflow happened | 86 // captured the syntax error), and false if a stack-overflow happened |
| 86 // during parsing. | 87 // during parsing. |
| 87 bool PreParseProgram(Scanner* scanner, | 88 bool PreParseProgram(Scanner* scanner, |
| 88 PreParserLog* log, | 89 PreParserLog* log, |
| 89 bool allow_lazy) { | 90 bool allow_lazy) { |
| 90 allow_lazy_ = allow_lazy; | 91 allow_lazy_ = allow_lazy; |
| 91 scanner_ = scanner; | 92 scanner_ = scanner; |
| 92 log_ = log; | 93 log_ = log; |
| 93 Scope top_scope(&scope_, kTopLevelScope); | 94 Scope top_scope(&scope_, kTopLevelScope); |
| 94 bool ok = true; | 95 bool ok = true; |
| 95 ParseSourceElements(Token::EOS, &ok); | 96 ParseSourceElements(i::Token::EOS, &ok); |
| 96 bool stack_overflow = scanner_->stack_overflow(); | 97 bool stack_overflow = scanner_->stack_overflow(); |
| 97 if (!ok && !stack_overflow) { | 98 if (!ok && !stack_overflow) { |
| 98 ReportUnexpectedToken(scanner_->current_token()); | 99 ReportUnexpectedToken(scanner_->current_token()); |
| 99 } | 100 } |
| 100 return !stack_overflow; | 101 return !stack_overflow; |
| 101 } | 102 } |
| 102 | 103 |
| 103 private: | 104 private: |
| 104 enum ScopeType { | 105 enum ScopeType { |
| 105 kTopLevelScope, | 106 kTopLevelScope, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 }; | 138 }; |
| 138 | 139 |
| 139 // Types that allow us to recognize simple this-property assignments. | 140 // Types that allow us to recognize simple this-property assignments. |
| 140 // A simple this-property assignment is a statement on the form | 141 // A simple this-property assignment is a statement on the form |
| 141 // "this.propertyName = {primitive constant or function parameter name);" | 142 // "this.propertyName = {primitive constant or function parameter name);" |
| 142 // where propertyName isn't "__proto__". | 143 // where propertyName isn't "__proto__". |
| 143 // The result is only relevant if the function body contains only | 144 // The result is only relevant if the function body contains only |
| 144 // simple this-property assignments. | 145 // simple this-property assignments. |
| 145 | 146 |
| 146 // Report syntax error | 147 // Report syntax error |
| 147 void ReportUnexpectedToken(Token::Value token); | 148 void ReportUnexpectedToken(i::Token::Value token); |
| 148 void ReportMessageAt(int start_pos, | 149 void ReportMessageAt(int start_pos, |
| 149 int end_pos, | 150 int end_pos, |
| 150 const char* type, | 151 const char* type, |
| 151 const char* name_opt) { | 152 const char* name_opt) { |
| 152 log_->LogMessage(start_pos, end_pos, type, name_opt); | 153 log_->LogMessage(start_pos, end_pos, type, name_opt); |
| 153 } | 154 } |
| 154 | 155 |
| 155 // All ParseXXX functions take as the last argument an *ok parameter | 156 // All ParseXXX functions take as the last argument an *ok parameter |
| 156 // which is set to false if parsing failed; it is unchanged otherwise. | 157 // which is set to false if parsing failed; it is unchanged otherwise. |
| 157 // By making the 'exception handling' explicit, we are forced to check | 158 // By making the 'exception handling' explicit, we are forced to check |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 | 199 |
| 199 Identifier ParseIdentifier(bool* ok); | 200 Identifier ParseIdentifier(bool* ok); |
| 200 Identifier ParseIdentifierName(bool* ok); | 201 Identifier ParseIdentifierName(bool* ok); |
| 201 Identifier ParseIdentifierOrGetOrSet(bool* is_get, bool* is_set, bool* ok); | 202 Identifier ParseIdentifierOrGetOrSet(bool* is_get, bool* is_set, bool* ok); |
| 202 | 203 |
| 203 Identifier GetIdentifierSymbol(); | 204 Identifier GetIdentifierSymbol(); |
| 204 unsigned int HexDigitValue(char digit); | 205 unsigned int HexDigitValue(char digit); |
| 205 Expression GetStringSymbol(); | 206 Expression GetStringSymbol(); |
| 206 | 207 |
| 207 | 208 |
| 208 Token::Value peek() { return scanner_->peek(); } | 209 i::Token::Value peek() { return scanner_->peek(); } |
| 209 Token::Value Next() { | 210 i::Token::Value Next() { |
| 210 Token::Value next = scanner_->Next(); | 211 i::Token::Value next = scanner_->Next(); |
| 211 return next; | 212 return next; |
| 212 } | 213 } |
| 213 | 214 |
| 214 void Consume(Token::Value token) { | 215 void Consume(i::Token::Value token) { |
| 215 Next(); | 216 Next(); |
| 216 } | 217 } |
| 217 | 218 |
| 218 void Expect(Token::Value token, bool* ok) { | 219 void Expect(i::Token::Value token, bool* ok) { |
| 219 if (Next() != token) { | 220 if (Next() != token) { |
| 220 *ok = false; | 221 *ok = false; |
| 221 } | 222 } |
| 222 } | 223 } |
| 223 | 224 |
| 224 bool Check(Token::Value token) { | 225 bool Check(i::Token::Value token) { |
| 225 Token::Value next = peek(); | 226 i::Token::Value next = peek(); |
| 226 if (next == token) { | 227 if (next == token) { |
| 227 Consume(next); | 228 Consume(next); |
| 228 return true; | 229 return true; |
| 229 } | 230 } |
| 230 return false; | 231 return false; |
| 231 } | 232 } |
| 232 void ExpectSemicolon(bool* ok); | 233 void ExpectSemicolon(bool* ok); |
| 233 | 234 |
| 234 static int Precedence(Token::Value tok, bool accept_IN); | 235 static int Precedence(i::Token::Value tok, bool accept_IN); |
| 235 | 236 |
| 236 Scanner* scanner_; | 237 Scanner* scanner_; |
| 237 PreParserLog* log_; | 238 PreParserLog* log_; |
| 238 Scope* scope_; | 239 Scope* scope_; |
| 239 bool allow_lazy_; | 240 bool allow_lazy_; |
| 240 }; | 241 }; |
| 241 | 242 |
| 242 | 243 |
| 243 #define CHECK_OK ok); \ | 244 #define CHECK_OK ok); \ |
| 244 if (!*ok) return -1; \ | 245 if (!*ok) return -1; \ |
| 245 ((void)0 | 246 ((void)0 |
| 246 #define DUMMY ) // to make indentation work | 247 #define DUMMY ) // to make indentation work |
| 247 #undef DUMMY | 248 #undef DUMMY |
| 248 | 249 |
| 249 | 250 |
| 250 template <typename Scanner, typename Log> | 251 template <typename Scanner, typename Log> |
| 251 void PreParser<Scanner, Log>::ReportUnexpectedToken(Token::Value token) { | 252 void PreParser<Scanner, Log>::ReportUnexpectedToken(i::Token::Value token) { |
| 252 // We don't report stack overflows here, to avoid increasing the | 253 // We don't report stack overflows here, to avoid increasing the |
| 253 // stack depth even further. Instead we report it after parsing is | 254 // stack depth even further. Instead we report it after parsing is |
| 254 // over, in ParseProgram. | 255 // over, in ParseProgram. |
| 255 if (token == Token::ILLEGAL && scanner_->stack_overflow()) { | 256 if (token == i::Token::ILLEGAL && scanner_->stack_overflow()) { |
| 256 return; | 257 return; |
| 257 } | 258 } |
| 258 typename Scanner::Location source_location = scanner_->location(); | 259 typename Scanner::Location source_location = scanner_->location(); |
| 259 | 260 |
| 260 // Four of the tokens are treated specially | 261 // Four of the tokens are treated specially |
| 261 switch (token) { | 262 switch (token) { |
| 262 case Token::EOS: | 263 case i::Token::EOS: |
| 263 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 264 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
| 264 "unexpected_eos", NULL); | 265 "unexpected_eos", NULL); |
| 265 case Token::NUMBER: | 266 case i::Token::NUMBER: |
| 266 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 267 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
| 267 "unexpected_token_number", NULL); | 268 "unexpected_token_number", NULL); |
| 268 case Token::STRING: | 269 case i::Token::STRING: |
| 269 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 270 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
| 270 "unexpected_token_string", NULL); | 271 "unexpected_token_string", NULL); |
| 271 case Token::IDENTIFIER: | 272 case i::Token::IDENTIFIER: |
| 272 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 273 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
| 273 "unexpected_token_identifier", NULL); | 274 "unexpected_token_identifier", NULL); |
| 274 default: | 275 default: |
| 275 const char* name = Token::String(token); | 276 const char* name = i::Token::String(token); |
| 276 ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 277 ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
| 277 "unexpected_token", name); | 278 "unexpected_token", name); |
| 278 } | 279 } |
| 279 } | 280 } |
| 280 | 281 |
| 281 | 282 |
| 282 template <typename Scanner, typename Log> | 283 template <typename Scanner, typename Log> |
| 283 SourceElements PreParser<Scanner, Log>::ParseSourceElements(int end_token, | 284 SourceElements PreParser<Scanner, Log>::ParseSourceElements(int end_token, |
| 284 bool* ok) { | 285 bool* ok) { |
| 285 // SourceElements :: | 286 // SourceElements :: |
| (...skipping 27 matching lines...) Expand all Loading... |
| 313 | 314 |
| 314 // Note: Since labels can only be used by 'break' and 'continue' | 315 // Note: Since labels can only be used by 'break' and 'continue' |
| 315 // statements, which themselves are only valid within blocks, | 316 // statements, which themselves are only valid within blocks, |
| 316 // iterations or 'switch' statements (i.e., BreakableStatements), | 317 // iterations or 'switch' statements (i.e., BreakableStatements), |
| 317 // labels can be simply ignored in all other cases; except for | 318 // labels can be simply ignored in all other cases; except for |
| 318 // trivial labeled break statements 'label: break label' which is | 319 // trivial labeled break statements 'label: break label' which is |
| 319 // parsed into an empty statement. | 320 // parsed into an empty statement. |
| 320 | 321 |
| 321 // Keep the source position of the statement | 322 // Keep the source position of the statement |
| 322 switch (peek()) { | 323 switch (peek()) { |
| 323 case Token::LBRACE: | 324 case i::Token::LBRACE: |
| 324 return ParseBlock(ok); | 325 return ParseBlock(ok); |
| 325 | 326 |
| 326 case Token::CONST: | 327 case i::Token::CONST: |
| 327 case Token::VAR: | 328 case i::Token::VAR: |
| 328 return ParseVariableStatement(ok); | 329 return ParseVariableStatement(ok); |
| 329 | 330 |
| 330 case Token::SEMICOLON: | 331 case i::Token::SEMICOLON: |
| 331 Next(); | 332 Next(); |
| 332 return kUnknownStatement; | 333 return kUnknownStatement; |
| 333 | 334 |
| 334 case Token::IF: | 335 case i::Token::IF: |
| 335 return ParseIfStatement(ok); | 336 return ParseIfStatement(ok); |
| 336 | 337 |
| 337 case Token::DO: | 338 case i::Token::DO: |
| 338 return ParseDoWhileStatement(ok); | 339 return ParseDoWhileStatement(ok); |
| 339 | 340 |
| 340 case Token::WHILE: | 341 case i::Token::WHILE: |
| 341 return ParseWhileStatement(ok); | 342 return ParseWhileStatement(ok); |
| 342 | 343 |
| 343 case Token::FOR: | 344 case i::Token::FOR: |
| 344 return ParseForStatement(ok); | 345 return ParseForStatement(ok); |
| 345 | 346 |
| 346 case Token::CONTINUE: | 347 case i::Token::CONTINUE: |
| 347 return ParseContinueStatement(ok); | 348 return ParseContinueStatement(ok); |
| 348 | 349 |
| 349 case Token::BREAK: | 350 case i::Token::BREAK: |
| 350 return ParseBreakStatement(ok); | 351 return ParseBreakStatement(ok); |
| 351 | 352 |
| 352 case Token::RETURN: | 353 case i::Token::RETURN: |
| 353 return ParseReturnStatement(ok); | 354 return ParseReturnStatement(ok); |
| 354 | 355 |
| 355 case Token::WITH: | 356 case i::Token::WITH: |
| 356 return ParseWithStatement(ok); | 357 return ParseWithStatement(ok); |
| 357 | 358 |
| 358 case Token::SWITCH: | 359 case i::Token::SWITCH: |
| 359 return ParseSwitchStatement(ok); | 360 return ParseSwitchStatement(ok); |
| 360 | 361 |
| 361 case Token::THROW: | 362 case i::Token::THROW: |
| 362 return ParseThrowStatement(ok); | 363 return ParseThrowStatement(ok); |
| 363 | 364 |
| 364 case Token::TRY: | 365 case i::Token::TRY: |
| 365 return ParseTryStatement(ok); | 366 return ParseTryStatement(ok); |
| 366 | 367 |
| 367 case Token::FUNCTION: | 368 case i::Token::FUNCTION: |
| 368 return ParseFunctionDeclaration(ok); | 369 return ParseFunctionDeclaration(ok); |
| 369 | 370 |
| 370 case Token::NATIVE: | 371 case i::Token::NATIVE: |
| 371 return ParseNativeDeclaration(ok); | 372 return ParseNativeDeclaration(ok); |
| 372 | 373 |
| 373 case Token::DEBUGGER: | 374 case i::Token::DEBUGGER: |
| 374 return ParseDebuggerStatement(ok); | 375 return ParseDebuggerStatement(ok); |
| 375 | 376 |
| 376 default: | 377 default: |
| 377 return ParseExpressionOrLabelledStatement(ok); | 378 return ParseExpressionOrLabelledStatement(ok); |
| 378 } | 379 } |
| 379 } | 380 } |
| 380 | 381 |
| 381 | 382 |
| 382 template <typename Scanner, typename Log> | 383 template <typename Scanner, typename Log> |
| 383 Statement PreParser<Scanner, Log>::ParseFunctionDeclaration(bool* ok) { | 384 Statement PreParser<Scanner, Log>::ParseFunctionDeclaration(bool* ok) { |
| 384 // FunctionDeclaration :: | 385 // FunctionDeclaration :: |
| 385 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 386 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
| 386 Expect(Token::FUNCTION, CHECK_OK); | 387 Expect(i::Token::FUNCTION, CHECK_OK); |
| 387 ParseIdentifier(CHECK_OK); | 388 ParseIdentifier(CHECK_OK); |
| 388 ParseFunctionLiteral(CHECK_OK); | 389 ParseFunctionLiteral(CHECK_OK); |
| 389 return kUnknownStatement; | 390 return kUnknownStatement; |
| 390 } | 391 } |
| 391 | 392 |
| 392 | 393 |
| 393 // Language extension which is only enabled for source files loaded | 394 // Language extension which is only enabled for source files loaded |
| 394 // through the API's extension mechanism. A native function | 395 // through the API's extension mechanism. A native function |
| 395 // declaration is resolved by looking up the function through a | 396 // declaration is resolved by looking up the function through a |
| 396 // callback provided by the extension. | 397 // callback provided by the extension. |
| 397 template <typename Scanner, typename Log> | 398 template <typename Scanner, typename Log> |
| 398 Statement PreParser<Scanner, Log>::ParseNativeDeclaration(bool* ok) { | 399 Statement PreParser<Scanner, Log>::ParseNativeDeclaration(bool* ok) { |
| 399 Expect(Token::NATIVE, CHECK_OK); | 400 Expect(i::Token::NATIVE, CHECK_OK); |
| 400 Expect(Token::FUNCTION, CHECK_OK); | 401 Expect(i::Token::FUNCTION, CHECK_OK); |
| 401 ParseIdentifier(CHECK_OK); | 402 ParseIdentifier(CHECK_OK); |
| 402 Expect(Token::LPAREN, CHECK_OK); | 403 Expect(i::Token::LPAREN, CHECK_OK); |
| 403 bool done = (peek() == Token::RPAREN); | 404 bool done = (peek() == i::Token::RPAREN); |
| 404 while (!done) { | 405 while (!done) { |
| 405 ParseIdentifier(CHECK_OK); | 406 ParseIdentifier(CHECK_OK); |
| 406 done = (peek() == Token::RPAREN); | 407 done = (peek() == i::Token::RPAREN); |
| 407 if (!done) { | 408 if (!done) { |
| 408 Expect(Token::COMMA, CHECK_OK); | 409 Expect(i::Token::COMMA, CHECK_OK); |
| 409 } | 410 } |
| 410 } | 411 } |
| 411 Expect(Token::RPAREN, CHECK_OK); | 412 Expect(i::Token::RPAREN, CHECK_OK); |
| 412 Expect(Token::SEMICOLON, CHECK_OK); | 413 Expect(i::Token::SEMICOLON, CHECK_OK); |
| 413 return kUnknownStatement; | 414 return kUnknownStatement; |
| 414 } | 415 } |
| 415 | 416 |
| 416 | 417 |
| 417 template <typename Scanner, typename Log> | 418 template <typename Scanner, typename Log> |
| 418 Statement PreParser<Scanner, Log>::ParseBlock(bool* ok) { | 419 Statement PreParser<Scanner, Log>::ParseBlock(bool* ok) { |
| 419 // Block :: | 420 // Block :: |
| 420 // '{' Statement* '}' | 421 // '{' Statement* '}' |
| 421 | 422 |
| 422 // Note that a Block does not introduce a new execution scope! | 423 // Note that a Block does not introduce a new execution scope! |
| 423 // (ECMA-262, 3rd, 12.2) | 424 // (ECMA-262, 3rd, 12.2) |
| 424 // | 425 // |
| 425 Expect(Token::LBRACE, CHECK_OK); | 426 Expect(i::Token::LBRACE, CHECK_OK); |
| 426 while (peek() != Token::RBRACE) { | 427 while (peek() != i::Token::RBRACE) { |
| 427 ParseStatement(CHECK_OK); | 428 ParseStatement(CHECK_OK); |
| 428 } | 429 } |
| 429 Expect(Token::RBRACE, CHECK_OK); | 430 Expect(i::Token::RBRACE, CHECK_OK); |
| 430 return kUnknownStatement; | 431 return kUnknownStatement; |
| 431 } | 432 } |
| 432 | 433 |
| 433 | 434 |
| 434 template <typename Scanner, typename Log> | 435 template <typename Scanner, typename Log> |
| 435 Statement PreParser<Scanner, Log>::ParseVariableStatement(bool* ok) { | 436 Statement PreParser<Scanner, Log>::ParseVariableStatement(bool* ok) { |
| 436 // VariableStatement :: | 437 // VariableStatement :: |
| 437 // VariableDeclarations ';' | 438 // VariableDeclarations ';' |
| 438 | 439 |
| 439 Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK); | 440 Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK); |
| 440 ExpectSemicolon(CHECK_OK); | 441 ExpectSemicolon(CHECK_OK); |
| 441 return result; | 442 return result; |
| 442 } | 443 } |
| 443 | 444 |
| 444 | 445 |
| 445 // If the variable declaration declares exactly one non-const | 446 // If the variable declaration declares exactly one non-const |
| 446 // variable, then *var is set to that variable. In all other cases, | 447 // variable, then *var is set to that variable. In all other cases, |
| 447 // *var is untouched; in particular, it is the caller's responsibility | 448 // *var is untouched; in particular, it is the caller's responsibility |
| 448 // to initialize it properly. This mechanism is also used for the parsing | 449 // to initialize it properly. This mechanism is also used for the parsing |
| 449 // of 'for-in' loops. | 450 // of 'for-in' loops. |
| 450 template <typename Scanner, typename Log> | 451 template <typename Scanner, typename Log> |
| 451 Statement PreParser<Scanner, Log>::ParseVariableDeclarations(bool accept_IN, | 452 Statement PreParser<Scanner, Log>::ParseVariableDeclarations(bool accept_IN, |
| 452 int* num_decl, | 453 int* num_decl, |
| 453 bool* ok) { | 454 bool* ok) { |
| 454 // VariableDeclarations :: | 455 // VariableDeclarations :: |
| 455 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] | 456 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
| 456 | 457 |
| 457 if (peek() == Token::VAR) { | 458 if (peek() == i::Token::VAR) { |
| 458 Consume(Token::VAR); | 459 Consume(i::Token::VAR); |
| 459 } else if (peek() == Token::CONST) { | 460 } else if (peek() == i::Token::CONST) { |
| 460 Consume(Token::CONST); | 461 Consume(i::Token::CONST); |
| 461 } else { | 462 } else { |
| 462 *ok = false; | 463 *ok = false; |
| 463 return 0; | 464 return 0; |
| 464 } | 465 } |
| 465 | 466 |
| 466 // The scope of a variable/const declared anywhere inside a function | 467 // The scope of a variable/const declared anywhere inside a function |
| 467 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). . | 468 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). . |
| 468 int nvars = 0; // the number of variables declared | 469 int nvars = 0; // the number of variables declared |
| 469 do { | 470 do { |
| 470 // Parse variable name. | 471 // Parse variable name. |
| 471 if (nvars > 0) Consume(Token::COMMA); | 472 if (nvars > 0) Consume(i::Token::COMMA); |
| 472 ParseIdentifier(CHECK_OK); | 473 ParseIdentifier(CHECK_OK); |
| 473 nvars++; | 474 nvars++; |
| 474 if (peek() == Token::ASSIGN) { | 475 if (peek() == i::Token::ASSIGN) { |
| 475 Expect(Token::ASSIGN, CHECK_OK); | 476 Expect(i::Token::ASSIGN, CHECK_OK); |
| 476 ParseAssignmentExpression(accept_IN, CHECK_OK); | 477 ParseAssignmentExpression(accept_IN, CHECK_OK); |
| 477 } | 478 } |
| 478 } while (peek() == Token::COMMA); | 479 } while (peek() == i::Token::COMMA); |
| 479 | 480 |
| 480 if (num_decl != NULL) *num_decl = nvars; | 481 if (num_decl != NULL) *num_decl = nvars; |
| 481 return kUnknownStatement; | 482 return kUnknownStatement; |
| 482 } | 483 } |
| 483 | 484 |
| 484 | 485 |
| 485 template <typename Scanner, typename Log> | 486 template <typename Scanner, typename Log> |
| 486 Statement PreParser<Scanner, Log>::ParseExpressionOrLabelledStatement( | 487 Statement PreParser<Scanner, Log>::ParseExpressionOrLabelledStatement( |
| 487 bool* ok) { | 488 bool* ok) { |
| 488 // ExpressionStatement | LabelledStatement :: | 489 // ExpressionStatement | LabelledStatement :: |
| 489 // Expression ';' | 490 // Expression ';' |
| 490 // Identifier ':' Statement | 491 // Identifier ':' Statement |
| 491 | 492 |
| 492 Expression expr = ParseExpression(true, CHECK_OK); | 493 Expression expr = ParseExpression(true, CHECK_OK); |
| 493 if (peek() == Token::COLON && expr == kIdentifierExpression) { | 494 if (peek() == i::Token::COLON && expr == kIdentifierExpression) { |
| 494 Consume(Token::COLON); | 495 Consume(i::Token::COLON); |
| 495 return ParseStatement(ok); | 496 return ParseStatement(ok); |
| 496 } | 497 } |
| 497 // Parsed expression statement. | 498 // Parsed expression statement. |
| 498 ExpectSemicolon(CHECK_OK); | 499 ExpectSemicolon(CHECK_OK); |
| 499 return kUnknownStatement; | 500 return kUnknownStatement; |
| 500 } | 501 } |
| 501 | 502 |
| 502 | 503 |
| 503 template <typename Scanner, typename Log> | 504 template <typename Scanner, typename Log> |
| 504 Statement PreParser<Scanner, Log>::ParseIfStatement(bool* ok) { | 505 Statement PreParser<Scanner, Log>::ParseIfStatement(bool* ok) { |
| 505 // IfStatement :: | 506 // IfStatement :: |
| 506 // 'if' '(' Expression ')' Statement ('else' Statement)? | 507 // 'if' '(' Expression ')' Statement ('else' Statement)? |
| 507 | 508 |
| 508 Expect(Token::IF, CHECK_OK); | 509 Expect(i::Token::IF, CHECK_OK); |
| 509 Expect(Token::LPAREN, CHECK_OK); | 510 Expect(i::Token::LPAREN, CHECK_OK); |
| 510 ParseExpression(true, CHECK_OK); | 511 ParseExpression(true, CHECK_OK); |
| 511 Expect(Token::RPAREN, CHECK_OK); | 512 Expect(i::Token::RPAREN, CHECK_OK); |
| 512 ParseStatement(CHECK_OK); | 513 ParseStatement(CHECK_OK); |
| 513 if (peek() == Token::ELSE) { | 514 if (peek() == i::Token::ELSE) { |
| 514 Next(); | 515 Next(); |
| 515 ParseStatement(CHECK_OK); | 516 ParseStatement(CHECK_OK); |
| 516 } | 517 } |
| 517 return kUnknownStatement; | 518 return kUnknownStatement; |
| 518 } | 519 } |
| 519 | 520 |
| 520 | 521 |
| 521 template <typename Scanner, typename Log> | 522 template <typename Scanner, typename Log> |
| 522 Statement PreParser<Scanner, Log>::ParseContinueStatement(bool* ok) { | 523 Statement PreParser<Scanner, Log>::ParseContinueStatement(bool* ok) { |
| 523 // ContinueStatement :: | 524 // ContinueStatement :: |
| 524 // 'continue' [no line terminator] Identifier? ';' | 525 // 'continue' [no line terminator] Identifier? ';' |
| 525 | 526 |
| 526 Expect(Token::CONTINUE, CHECK_OK); | 527 Expect(i::Token::CONTINUE, CHECK_OK); |
| 527 Token::Value tok = peek(); | 528 i::Token::Value tok = peek(); |
| 528 if (!scanner_->has_line_terminator_before_next() && | 529 if (!scanner_->has_line_terminator_before_next() && |
| 529 tok != Token::SEMICOLON && | 530 tok != i::Token::SEMICOLON && |
| 530 tok != Token::RBRACE && | 531 tok != i::Token::RBRACE && |
| 531 tok != Token::EOS) { | 532 tok != i::Token::EOS) { |
| 532 ParseIdentifier(CHECK_OK); | 533 ParseIdentifier(CHECK_OK); |
| 533 } | 534 } |
| 534 ExpectSemicolon(CHECK_OK); | 535 ExpectSemicolon(CHECK_OK); |
| 535 return kUnknownStatement; | 536 return kUnknownStatement; |
| 536 } | 537 } |
| 537 | 538 |
| 538 | 539 |
| 539 template <typename Scanner, typename Log> | 540 template <typename Scanner, typename Log> |
| 540 Statement PreParser<Scanner, Log>::ParseBreakStatement(bool* ok) { | 541 Statement PreParser<Scanner, Log>::ParseBreakStatement(bool* ok) { |
| 541 // BreakStatement :: | 542 // BreakStatement :: |
| 542 // 'break' [no line terminator] Identifier? ';' | 543 // 'break' [no line terminator] Identifier? ';' |
| 543 | 544 |
| 544 Expect(Token::BREAK, CHECK_OK); | 545 Expect(i::Token::BREAK, CHECK_OK); |
| 545 Token::Value tok = peek(); | 546 i::Token::Value tok = peek(); |
| 546 if (!scanner_->has_line_terminator_before_next() && | 547 if (!scanner_->has_line_terminator_before_next() && |
| 547 tok != Token::SEMICOLON && | 548 tok != i::Token::SEMICOLON && |
| 548 tok != Token::RBRACE && | 549 tok != i::Token::RBRACE && |
| 549 tok != Token::EOS) { | 550 tok != i::Token::EOS) { |
| 550 ParseIdentifier(CHECK_OK); | 551 ParseIdentifier(CHECK_OK); |
| 551 } | 552 } |
| 552 ExpectSemicolon(CHECK_OK); | 553 ExpectSemicolon(CHECK_OK); |
| 553 return kUnknownStatement; | 554 return kUnknownStatement; |
| 554 } | 555 } |
| 555 | 556 |
| 556 | 557 |
| 557 template <typename Scanner, typename Log> | 558 template <typename Scanner, typename Log> |
| 558 Statement PreParser<Scanner, Log>::ParseReturnStatement(bool* ok) { | 559 Statement PreParser<Scanner, Log>::ParseReturnStatement(bool* ok) { |
| 559 // ReturnStatement :: | 560 // ReturnStatement :: |
| 560 // 'return' [no line terminator] Expression? ';' | 561 // 'return' [no line terminator] Expression? ';' |
| 561 | 562 |
| 562 // Consume the return token. It is necessary to do the before | 563 // Consume the return token. It is necessary to do the before |
| 563 // reporting any errors on it, because of the way errors are | 564 // reporting any errors on it, because of the way errors are |
| 564 // reported (underlining). | 565 // reported (underlining). |
| 565 Expect(Token::RETURN, CHECK_OK); | 566 Expect(i::Token::RETURN, CHECK_OK); |
| 566 | 567 |
| 567 // An ECMAScript program is considered syntactically incorrect if it | 568 // An ECMAScript program is considered syntactically incorrect if it |
| 568 // contains a return statement that is not within the body of a | 569 // contains a return statement that is not within the body of a |
| 569 // function. See ECMA-262, section 12.9, page 67. | 570 // function. See ECMA-262, section 12.9, page 67. |
| 570 // This is not handled during preparsing. | 571 // This is not handled during preparsing. |
| 571 | 572 |
| 572 Token::Value tok = peek(); | 573 i::Token::Value tok = peek(); |
| 573 if (!scanner_->has_line_terminator_before_next() && | 574 if (!scanner_->has_line_terminator_before_next() && |
| 574 tok != Token::SEMICOLON && | 575 tok != i::Token::SEMICOLON && |
| 575 tok != Token::RBRACE && | 576 tok != i::Token::RBRACE && |
| 576 tok != Token::EOS) { | 577 tok != i::Token::EOS) { |
| 577 ParseExpression(true, CHECK_OK); | 578 ParseExpression(true, CHECK_OK); |
| 578 } | 579 } |
| 579 ExpectSemicolon(CHECK_OK); | 580 ExpectSemicolon(CHECK_OK); |
| 580 return kUnknownStatement; | 581 return kUnknownStatement; |
| 581 } | 582 } |
| 582 | 583 |
| 583 | 584 |
| 584 template <typename Scanner, typename Log> | 585 template <typename Scanner, typename Log> |
| 585 Statement PreParser<Scanner, Log>::ParseWithStatement(bool* ok) { | 586 Statement PreParser<Scanner, Log>::ParseWithStatement(bool* ok) { |
| 586 // WithStatement :: | 587 // WithStatement :: |
| 587 // 'with' '(' Expression ')' Statement | 588 // 'with' '(' Expression ')' Statement |
| 588 Expect(Token::WITH, CHECK_OK); | 589 Expect(i::Token::WITH, CHECK_OK); |
| 589 Expect(Token::LPAREN, CHECK_OK); | 590 Expect(i::Token::LPAREN, CHECK_OK); |
| 590 ParseExpression(true, CHECK_OK); | 591 ParseExpression(true, CHECK_OK); |
| 591 Expect(Token::RPAREN, CHECK_OK); | 592 Expect(i::Token::RPAREN, CHECK_OK); |
| 592 | 593 |
| 593 scope_->EnterWith(); | 594 scope_->EnterWith(); |
| 594 ParseStatement(CHECK_OK); | 595 ParseStatement(CHECK_OK); |
| 595 scope_->LeaveWith(); | 596 scope_->LeaveWith(); |
| 596 return kUnknownStatement; | 597 return kUnknownStatement; |
| 597 } | 598 } |
| 598 | 599 |
| 599 | 600 |
| 600 template <typename Scanner, typename Log> | 601 template <typename Scanner, typename Log> |
| 601 Statement PreParser<Scanner, Log>::ParseSwitchStatement(bool* ok) { | 602 Statement PreParser<Scanner, Log>::ParseSwitchStatement(bool* ok) { |
| 602 // SwitchStatement :: | 603 // SwitchStatement :: |
| 603 // 'switch' '(' Expression ')' '{' CaseClause* '}' | 604 // 'switch' '(' Expression ')' '{' CaseClause* '}' |
| 604 | 605 |
| 605 Expect(Token::SWITCH, CHECK_OK); | 606 Expect(i::Token::SWITCH, CHECK_OK); |
| 606 Expect(Token::LPAREN, CHECK_OK); | 607 Expect(i::Token::LPAREN, CHECK_OK); |
| 607 ParseExpression(true, CHECK_OK); | 608 ParseExpression(true, CHECK_OK); |
| 608 Expect(Token::RPAREN, CHECK_OK); | 609 Expect(i::Token::RPAREN, CHECK_OK); |
| 609 | 610 |
| 610 Expect(Token::LBRACE, CHECK_OK); | 611 Expect(i::Token::LBRACE, CHECK_OK); |
| 611 Token::Value token = peek(); | 612 i::Token::Value token = peek(); |
| 612 while (token != Token::RBRACE) { | 613 while (token != i::Token::RBRACE) { |
| 613 if (token == Token::CASE) { | 614 if (token == i::Token::CASE) { |
| 614 Expect(Token::CASE, CHECK_OK); | 615 Expect(i::Token::CASE, CHECK_OK); |
| 615 ParseExpression(true, CHECK_OK); | 616 ParseExpression(true, CHECK_OK); |
| 616 Expect(Token::COLON, CHECK_OK); | 617 Expect(i::Token::COLON, CHECK_OK); |
| 617 } else if (token == Token::DEFAULT) { | 618 } else if (token == i::Token::DEFAULT) { |
| 618 Expect(Token::DEFAULT, CHECK_OK); | 619 Expect(i::Token::DEFAULT, CHECK_OK); |
| 619 Expect(Token::COLON, CHECK_OK); | 620 Expect(i::Token::COLON, CHECK_OK); |
| 620 } else { | 621 } else { |
| 621 ParseStatement(CHECK_OK); | 622 ParseStatement(CHECK_OK); |
| 622 } | 623 } |
| 623 token = peek(); | 624 token = peek(); |
| 624 } | 625 } |
| 625 Expect(Token::RBRACE, CHECK_OK); | 626 Expect(i::Token::RBRACE, CHECK_OK); |
| 626 | 627 |
| 627 return kUnknownStatement; | 628 return kUnknownStatement; |
| 628 } | 629 } |
| 629 | 630 |
| 630 | 631 |
| 631 template <typename Scanner, typename Log> | 632 template <typename Scanner, typename Log> |
| 632 Statement PreParser<Scanner, Log>::ParseDoWhileStatement(bool* ok) { | 633 Statement PreParser<Scanner, Log>::ParseDoWhileStatement(bool* ok) { |
| 633 // DoStatement :: | 634 // DoStatement :: |
| 634 // 'do' Statement 'while' '(' Expression ')' ';' | 635 // 'do' Statement 'while' '(' Expression ')' ';' |
| 635 | 636 |
| 636 Expect(Token::DO, CHECK_OK); | 637 Expect(i::Token::DO, CHECK_OK); |
| 637 ParseStatement(CHECK_OK); | 638 ParseStatement(CHECK_OK); |
| 638 Expect(Token::WHILE, CHECK_OK); | 639 Expect(i::Token::WHILE, CHECK_OK); |
| 639 Expect(Token::LPAREN, CHECK_OK); | 640 Expect(i::Token::LPAREN, CHECK_OK); |
| 640 ParseExpression(true, CHECK_OK); | 641 ParseExpression(true, CHECK_OK); |
| 641 Expect(Token::RPAREN, CHECK_OK); | 642 Expect(i::Token::RPAREN, CHECK_OK); |
| 642 return kUnknownStatement; | 643 return kUnknownStatement; |
| 643 } | 644 } |
| 644 | 645 |
| 645 | 646 |
| 646 template <typename Scanner, typename Log> | 647 template <typename Scanner, typename Log> |
| 647 Statement PreParser<Scanner, Log>::ParseWhileStatement(bool* ok) { | 648 Statement PreParser<Scanner, Log>::ParseWhileStatement(bool* ok) { |
| 648 // WhileStatement :: | 649 // WhileStatement :: |
| 649 // 'while' '(' Expression ')' Statement | 650 // 'while' '(' Expression ')' Statement |
| 650 | 651 |
| 651 Expect(Token::WHILE, CHECK_OK); | 652 Expect(i::Token::WHILE, CHECK_OK); |
| 652 Expect(Token::LPAREN, CHECK_OK); | 653 Expect(i::Token::LPAREN, CHECK_OK); |
| 653 ParseExpression(true, CHECK_OK); | 654 ParseExpression(true, CHECK_OK); |
| 654 Expect(Token::RPAREN, CHECK_OK); | 655 Expect(i::Token::RPAREN, CHECK_OK); |
| 655 ParseStatement(CHECK_OK); | 656 ParseStatement(CHECK_OK); |
| 656 return kUnknownStatement; | 657 return kUnknownStatement; |
| 657 } | 658 } |
| 658 | 659 |
| 659 | 660 |
| 660 template <typename Scanner, typename Log> | 661 template <typename Scanner, typename Log> |
| 661 Statement PreParser<Scanner, Log>::ParseForStatement(bool* ok) { | 662 Statement PreParser<Scanner, Log>::ParseForStatement(bool* ok) { |
| 662 // ForStatement :: | 663 // ForStatement :: |
| 663 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 664 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
| 664 | 665 |
| 665 Expect(Token::FOR, CHECK_OK); | 666 Expect(i::Token::FOR, CHECK_OK); |
| 666 Expect(Token::LPAREN, CHECK_OK); | 667 Expect(i::Token::LPAREN, CHECK_OK); |
| 667 if (peek() != Token::SEMICOLON) { | 668 if (peek() != i::Token::SEMICOLON) { |
| 668 if (peek() == Token::VAR || peek() == Token::CONST) { | 669 if (peek() == i::Token::VAR || peek() == i::Token::CONST) { |
| 669 int decl_count; | 670 int decl_count; |
| 670 ParseVariableDeclarations(false, &decl_count, CHECK_OK); | 671 ParseVariableDeclarations(false, &decl_count, CHECK_OK); |
| 671 if (peek() == Token::IN && decl_count == 1) { | 672 if (peek() == i::Token::IN && decl_count == 1) { |
| 672 Expect(Token::IN, CHECK_OK); | 673 Expect(i::Token::IN, CHECK_OK); |
| 673 ParseExpression(true, CHECK_OK); | 674 ParseExpression(true, CHECK_OK); |
| 674 Expect(Token::RPAREN, CHECK_OK); | 675 Expect(i::Token::RPAREN, CHECK_OK); |
| 675 | 676 |
| 676 ParseStatement(CHECK_OK); | 677 ParseStatement(CHECK_OK); |
| 677 return kUnknownStatement; | 678 return kUnknownStatement; |
| 678 } | 679 } |
| 679 } else { | 680 } else { |
| 680 ParseExpression(false, CHECK_OK); | 681 ParseExpression(false, CHECK_OK); |
| 681 if (peek() == Token::IN) { | 682 if (peek() == i::Token::IN) { |
| 682 Expect(Token::IN, CHECK_OK); | 683 Expect(i::Token::IN, CHECK_OK); |
| 683 ParseExpression(true, CHECK_OK); | 684 ParseExpression(true, CHECK_OK); |
| 684 Expect(Token::RPAREN, CHECK_OK); | 685 Expect(i::Token::RPAREN, CHECK_OK); |
| 685 | 686 |
| 686 ParseStatement(CHECK_OK); | 687 ParseStatement(CHECK_OK); |
| 687 return kUnknownStatement; | 688 return kUnknownStatement; |
| 688 } | 689 } |
| 689 } | 690 } |
| 690 } | 691 } |
| 691 | 692 |
| 692 // Parsed initializer at this point. | 693 // Parsed initializer at this point. |
| 693 Expect(Token::SEMICOLON, CHECK_OK); | 694 Expect(i::Token::SEMICOLON, CHECK_OK); |
| 694 | 695 |
| 695 if (peek() != Token::SEMICOLON) { | 696 if (peek() != i::Token::SEMICOLON) { |
| 696 ParseExpression(true, CHECK_OK); | 697 ParseExpression(true, CHECK_OK); |
| 697 } | 698 } |
| 698 Expect(Token::SEMICOLON, CHECK_OK); | 699 Expect(i::Token::SEMICOLON, CHECK_OK); |
| 699 | 700 |
| 700 if (peek() != Token::RPAREN) { | 701 if (peek() != i::Token::RPAREN) { |
| 701 ParseExpression(true, CHECK_OK); | 702 ParseExpression(true, CHECK_OK); |
| 702 } | 703 } |
| 703 Expect(Token::RPAREN, CHECK_OK); | 704 Expect(i::Token::RPAREN, CHECK_OK); |
| 704 | 705 |
| 705 ParseStatement(CHECK_OK); | 706 ParseStatement(CHECK_OK); |
| 706 return kUnknownStatement; | 707 return kUnknownStatement; |
| 707 } | 708 } |
| 708 | 709 |
| 709 | 710 |
| 710 template <typename Scanner, typename Log> | 711 template <typename Scanner, typename Log> |
| 711 Statement PreParser<Scanner, Log>::ParseThrowStatement(bool* ok) { | 712 Statement PreParser<Scanner, Log>::ParseThrowStatement(bool* ok) { |
| 712 // ThrowStatement :: | 713 // ThrowStatement :: |
| 713 // 'throw' [no line terminator] Expression ';' | 714 // 'throw' [no line terminator] Expression ';' |
| 714 | 715 |
| 715 Expect(Token::THROW, CHECK_OK); | 716 Expect(i::Token::THROW, CHECK_OK); |
| 716 if (scanner_->has_line_terminator_before_next()) { | 717 if (scanner_->has_line_terminator_before_next()) { |
| 717 typename Scanner::Location pos = scanner_->location(); | 718 typename Scanner::Location pos = scanner_->location(); |
| 718 ReportMessageAt(pos.beg_pos, pos.end_pos, | 719 ReportMessageAt(pos.beg_pos, pos.end_pos, |
| 719 "newline_after_throw", NULL); | 720 "newline_after_throw", NULL); |
| 720 *ok = false; | 721 *ok = false; |
| 721 return NULL; | 722 return NULL; |
| 722 } | 723 } |
| 723 ParseExpression(true, CHECK_OK); | 724 ParseExpression(true, CHECK_OK); |
| 724 ExpectSemicolon(CHECK_OK); | 725 ExpectSemicolon(CHECK_OK); |
| 725 | 726 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 736 // | 737 // |
| 737 // Catch :: | 738 // Catch :: |
| 738 // 'catch' '(' Identifier ')' Block | 739 // 'catch' '(' Identifier ')' Block |
| 739 // | 740 // |
| 740 // Finally :: | 741 // Finally :: |
| 741 // 'finally' Block | 742 // 'finally' Block |
| 742 | 743 |
| 743 // In preparsing, allow any number of catch/finally blocks, including zero | 744 // In preparsing, allow any number of catch/finally blocks, including zero |
| 744 // of both. | 745 // of both. |
| 745 | 746 |
| 746 Expect(Token::TRY, CHECK_OK); | 747 Expect(i::Token::TRY, CHECK_OK); |
| 747 | 748 |
| 748 ParseBlock(CHECK_OK); | 749 ParseBlock(CHECK_OK); |
| 749 | 750 |
| 750 bool catch_or_finally_seen = false; | 751 bool catch_or_finally_seen = false; |
| 751 if (peek() == Token::CATCH) { | 752 if (peek() == i::Token::CATCH) { |
| 752 Expect(Token::CATCH, CHECK_OK); | 753 Expect(i::Token::CATCH, CHECK_OK); |
| 753 Expect(Token::LPAREN, CHECK_OK); | 754 Expect(i::Token::LPAREN, CHECK_OK); |
| 754 ParseIdentifier(CHECK_OK); | 755 ParseIdentifier(CHECK_OK); |
| 755 Expect(Token::RPAREN, CHECK_OK); | 756 Expect(i::Token::RPAREN, CHECK_OK); |
| 756 ParseBlock(CHECK_OK); | 757 ParseBlock(CHECK_OK); |
| 757 catch_or_finally_seen = true; | 758 catch_or_finally_seen = true; |
| 758 } | 759 } |
| 759 if (peek() == Token::FINALLY) { | 760 if (peek() == i::Token::FINALLY) { |
| 760 Expect(Token::FINALLY, CHECK_OK); | 761 Expect(i::Token::FINALLY, CHECK_OK); |
| 761 ParseBlock(CHECK_OK); | 762 ParseBlock(CHECK_OK); |
| 762 catch_or_finally_seen = true; | 763 catch_or_finally_seen = true; |
| 763 } | 764 } |
| 764 if (!catch_or_finally_seen) { | 765 if (!catch_or_finally_seen) { |
| 765 *ok = false; | 766 *ok = false; |
| 766 } | 767 } |
| 767 return kUnknownStatement; | 768 return kUnknownStatement; |
| 768 } | 769 } |
| 769 | 770 |
| 770 | 771 |
| 771 template <typename Scanner, typename Log> | 772 template <typename Scanner, typename Log> |
| 772 Statement PreParser<Scanner, Log>::ParseDebuggerStatement(bool* ok) { | 773 Statement PreParser<Scanner, Log>::ParseDebuggerStatement(bool* ok) { |
| 773 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser | 774 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser |
| 774 // contexts this is used as a statement which invokes the debugger as if a | 775 // contexts this is used as a statement which invokes the debugger as if a |
| 775 // break point is present. | 776 // break point is present. |
| 776 // DebuggerStatement :: | 777 // DebuggerStatement :: |
| 777 // 'debugger' ';' | 778 // 'debugger' ';' |
| 778 | 779 |
| 779 Expect(Token::DEBUGGER, CHECK_OK); | 780 Expect(i::Token::DEBUGGER, CHECK_OK); |
| 780 ExpectSemicolon(CHECK_OK); | 781 ExpectSemicolon(CHECK_OK); |
| 781 return kUnknownStatement; | 782 return kUnknownStatement; |
| 782 } | 783 } |
| 783 | 784 |
| 784 | 785 |
| 785 // Precedence = 1 | 786 // Precedence = 1 |
| 786 template <typename Scanner, typename Log> | 787 template <typename Scanner, typename Log> |
| 787 Expression PreParser<Scanner, Log>::ParseExpression(bool accept_IN, bool* ok) { | 788 Expression PreParser<Scanner, Log>::ParseExpression(bool accept_IN, bool* ok) { |
| 788 // Expression :: | 789 // Expression :: |
| 789 // AssignmentExpression | 790 // AssignmentExpression |
| 790 // Expression ',' AssignmentExpression | 791 // Expression ',' AssignmentExpression |
| 791 | 792 |
| 792 Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK); | 793 Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK); |
| 793 while (peek() == Token::COMMA) { | 794 while (peek() == i::Token::COMMA) { |
| 794 Expect(Token::COMMA, CHECK_OK); | 795 Expect(i::Token::COMMA, CHECK_OK); |
| 795 ParseAssignmentExpression(accept_IN, CHECK_OK); | 796 ParseAssignmentExpression(accept_IN, CHECK_OK); |
| 796 result = kUnknownExpression; | 797 result = kUnknownExpression; |
| 797 } | 798 } |
| 798 return result; | 799 return result; |
| 799 } | 800 } |
| 800 | 801 |
| 801 | 802 |
| 802 // Precedence = 2 | 803 // Precedence = 2 |
| 803 template <typename Scanner, typename Log> | 804 template <typename Scanner, typename Log> |
| 804 Expression PreParser<Scanner, Log>::ParseAssignmentExpression(bool accept_IN, | 805 Expression PreParser<Scanner, Log>::ParseAssignmentExpression(bool accept_IN, |
| 805 bool* ok) { | 806 bool* ok) { |
| 806 // AssignmentExpression :: | 807 // AssignmentExpression :: |
| 807 // ConditionalExpression | 808 // ConditionalExpression |
| 808 // LeftHandSideExpression AssignmentOperator AssignmentExpression | 809 // LeftHandSideExpression AssignmentOperator AssignmentExpression |
| 809 | 810 |
| 810 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK); | 811 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK); |
| 811 | 812 |
| 812 if (!Token::IsAssignmentOp(peek())) { | 813 if (!i::Token::IsAssignmentOp(peek())) { |
| 813 // Parsed conditional expression only (no assignment). | 814 // Parsed conditional expression only (no assignment). |
| 814 return expression; | 815 return expression; |
| 815 } | 816 } |
| 816 | 817 |
| 817 Token::Value op = Next(); // Get assignment operator. | 818 i::Token::Value op = Next(); // Get assignment operator. |
| 818 ParseAssignmentExpression(accept_IN, CHECK_OK); | 819 ParseAssignmentExpression(accept_IN, CHECK_OK); |
| 819 | 820 |
| 820 if ((op == Token::ASSIGN) && (expression == kThisPropertyExpression)) { | 821 if ((op == i::Token::ASSIGN) && (expression == kThisPropertyExpression)) { |
| 821 scope_->AddProperty(); | 822 scope_->AddProperty(); |
| 822 } | 823 } |
| 823 | 824 |
| 824 return kUnknownExpression; | 825 return kUnknownExpression; |
| 825 } | 826 } |
| 826 | 827 |
| 827 | 828 |
| 828 // Precedence = 3 | 829 // Precedence = 3 |
| 829 template <typename Scanner, typename Log> | 830 template <typename Scanner, typename Log> |
| 830 Expression PreParser<Scanner, Log>::ParseConditionalExpression(bool accept_IN, | 831 Expression PreParser<Scanner, Log>::ParseConditionalExpression(bool accept_IN, |
| 831 bool* ok) { | 832 bool* ok) { |
| 832 // ConditionalExpression :: | 833 // ConditionalExpression :: |
| 833 // LogicalOrExpression | 834 // LogicalOrExpression |
| 834 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression | 835 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression |
| 835 | 836 |
| 836 // We start using the binary expression parser for prec >= 4 only! | 837 // We start using the binary expression parser for prec >= 4 only! |
| 837 Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK); | 838 Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK); |
| 838 if (peek() != Token::CONDITIONAL) return expression; | 839 if (peek() != i::Token::CONDITIONAL) return expression; |
| 839 Consume(Token::CONDITIONAL); | 840 Consume(i::Token::CONDITIONAL); |
| 840 // In parsing the first assignment expression in conditional | 841 // In parsing the first assignment expression in conditional |
| 841 // expressions we always accept the 'in' keyword; see ECMA-262, | 842 // expressions we always accept the 'in' keyword; see ECMA-262, |
| 842 // section 11.12, page 58. | 843 // section 11.12, page 58. |
| 843 ParseAssignmentExpression(true, CHECK_OK); | 844 ParseAssignmentExpression(true, CHECK_OK); |
| 844 Expect(Token::COLON, CHECK_OK); | 845 Expect(i::Token::COLON, CHECK_OK); |
| 845 ParseAssignmentExpression(accept_IN, CHECK_OK); | 846 ParseAssignmentExpression(accept_IN, CHECK_OK); |
| 846 return kUnknownExpression; | 847 return kUnknownExpression; |
| 847 } | 848 } |
| 848 | 849 |
| 849 | 850 |
| 850 template <typename Scanner, typename Log> | 851 template <typename Scanner, typename Log> |
| 851 int PreParser<Scanner, Log>::Precedence(Token::Value tok, bool accept_IN) { | 852 int PreParser<Scanner, Log>::Precedence(i::Token::Value tok, bool accept_IN) { |
| 852 if (tok == Token::IN && !accept_IN) | 853 if (tok == i::Token::IN && !accept_IN) |
| 853 return 0; // 0 precedence will terminate binary expression parsing | 854 return 0; // 0 precedence will terminate binary expression parsing |
| 854 | 855 |
| 855 return Token::Precedence(tok); | 856 return i::Token::Precedence(tok); |
| 856 } | 857 } |
| 857 | 858 |
| 858 | 859 |
| 859 // Precedence >= 4 | 860 // Precedence >= 4 |
| 860 template <typename Scanner, typename Log> | 861 template <typename Scanner, typename Log> |
| 861 Expression PreParser<Scanner, Log>::ParseBinaryExpression(int prec, | 862 Expression PreParser<Scanner, Log>::ParseBinaryExpression(int prec, |
| 862 bool accept_IN, | 863 bool accept_IN, |
| 863 bool* ok) { | 864 bool* ok) { |
| 864 Expression result = ParseUnaryExpression(CHECK_OK); | 865 Expression result = ParseUnaryExpression(CHECK_OK); |
| 865 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { | 866 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 881 // 'delete' UnaryExpression | 882 // 'delete' UnaryExpression |
| 882 // 'void' UnaryExpression | 883 // 'void' UnaryExpression |
| 883 // 'typeof' UnaryExpression | 884 // 'typeof' UnaryExpression |
| 884 // '++' UnaryExpression | 885 // '++' UnaryExpression |
| 885 // '--' UnaryExpression | 886 // '--' UnaryExpression |
| 886 // '+' UnaryExpression | 887 // '+' UnaryExpression |
| 887 // '-' UnaryExpression | 888 // '-' UnaryExpression |
| 888 // '~' UnaryExpression | 889 // '~' UnaryExpression |
| 889 // '!' UnaryExpression | 890 // '!' UnaryExpression |
| 890 | 891 |
| 891 Token::Value op = peek(); | 892 i::Token::Value op = peek(); |
| 892 if (Token::IsUnaryOp(op) || Token::IsCountOp(op)) { | 893 if (i::Token::IsUnaryOp(op) || i::Token::IsCountOp(op)) { |
| 893 op = Next(); | 894 op = Next(); |
| 894 ParseUnaryExpression(ok); | 895 ParseUnaryExpression(ok); |
| 895 return kUnknownExpression; | 896 return kUnknownExpression; |
| 896 } else { | 897 } else { |
| 897 return ParsePostfixExpression(ok); | 898 return ParsePostfixExpression(ok); |
| 898 } | 899 } |
| 899 } | 900 } |
| 900 | 901 |
| 901 | 902 |
| 902 template <typename Scanner, typename Log> | 903 template <typename Scanner, typename Log> |
| 903 Expression PreParser<Scanner, Log>::ParsePostfixExpression(bool* ok) { | 904 Expression PreParser<Scanner, Log>::ParsePostfixExpression(bool* ok) { |
| 904 // PostfixExpression :: | 905 // PostfixExpression :: |
| 905 // LeftHandSideExpression ('++' | '--')? | 906 // LeftHandSideExpression ('++' | '--')? |
| 906 | 907 |
| 907 Expression expression = ParseLeftHandSideExpression(CHECK_OK); | 908 Expression expression = ParseLeftHandSideExpression(CHECK_OK); |
| 908 if (!scanner_->has_line_terminator_before_next() && | 909 if (!scanner_->has_line_terminator_before_next() && |
| 909 Token::IsCountOp(peek())) { | 910 i::Token::IsCountOp(peek())) { |
| 910 Next(); | 911 Next(); |
| 911 return kUnknownExpression; | 912 return kUnknownExpression; |
| 912 } | 913 } |
| 913 return expression; | 914 return expression; |
| 914 } | 915 } |
| 915 | 916 |
| 916 | 917 |
| 917 template <typename Scanner, typename Log> | 918 template <typename Scanner, typename Log> |
| 918 Expression PreParser<Scanner, Log>::ParseLeftHandSideExpression(bool* ok) { | 919 Expression PreParser<Scanner, Log>::ParseLeftHandSideExpression(bool* ok) { |
| 919 // LeftHandSideExpression :: | 920 // LeftHandSideExpression :: |
| 920 // (NewExpression | MemberExpression) ... | 921 // (NewExpression | MemberExpression) ... |
| 921 | 922 |
| 922 Expression result; | 923 Expression result; |
| 923 if (peek() == Token::NEW) { | 924 if (peek() == i::Token::NEW) { |
| 924 result = ParseNewExpression(CHECK_OK); | 925 result = ParseNewExpression(CHECK_OK); |
| 925 } else { | 926 } else { |
| 926 result = ParseMemberExpression(CHECK_OK); | 927 result = ParseMemberExpression(CHECK_OK); |
| 927 } | 928 } |
| 928 | 929 |
| 929 while (true) { | 930 while (true) { |
| 930 switch (peek()) { | 931 switch (peek()) { |
| 931 case Token::LBRACK: { | 932 case i::Token::LBRACK: { |
| 932 Consume(Token::LBRACK); | 933 Consume(i::Token::LBRACK); |
| 933 ParseExpression(true, CHECK_OK); | 934 ParseExpression(true, CHECK_OK); |
| 934 Expect(Token::RBRACK, CHECK_OK); | 935 Expect(i::Token::RBRACK, CHECK_OK); |
| 935 if (result == kThisExpression) { | 936 if (result == kThisExpression) { |
| 936 result = kThisPropertyExpression; | 937 result = kThisPropertyExpression; |
| 937 } else { | 938 } else { |
| 938 result = kUnknownExpression; | 939 result = kUnknownExpression; |
| 939 } | 940 } |
| 940 break; | 941 break; |
| 941 } | 942 } |
| 942 | 943 |
| 943 case Token::LPAREN: { | 944 case i::Token::LPAREN: { |
| 944 ParseArguments(CHECK_OK); | 945 ParseArguments(CHECK_OK); |
| 945 result = kUnknownExpression; | 946 result = kUnknownExpression; |
| 946 break; | 947 break; |
| 947 } | 948 } |
| 948 | 949 |
| 949 case Token::PERIOD: { | 950 case i::Token::PERIOD: { |
| 950 Consume(Token::PERIOD); | 951 Consume(i::Token::PERIOD); |
| 951 ParseIdentifierName(CHECK_OK); | 952 ParseIdentifierName(CHECK_OK); |
| 952 if (result == kThisExpression) { | 953 if (result == kThisExpression) { |
| 953 result = kThisPropertyExpression; | 954 result = kThisPropertyExpression; |
| 954 } else { | 955 } else { |
| 955 result = kUnknownExpression; | 956 result = kUnknownExpression; |
| 956 } | 957 } |
| 957 break; | 958 break; |
| 958 } | 959 } |
| 959 | 960 |
| 960 default: | 961 default: |
| (...skipping 11 matching lines...) Expand all Loading... |
| 972 // The grammar for new expressions is pretty warped. The keyword | 973 // The grammar for new expressions is pretty warped. The keyword |
| 973 // 'new' can either be a part of the new expression (where it isn't | 974 // 'new' can either be a part of the new expression (where it isn't |
| 974 // followed by an argument list) or a part of the member expression, | 975 // followed by an argument list) or a part of the member expression, |
| 975 // where it must be followed by an argument list. To accommodate | 976 // where it must be followed by an argument list. To accommodate |
| 976 // this, we parse the 'new' keywords greedily and keep track of how | 977 // this, we parse the 'new' keywords greedily and keep track of how |
| 977 // many we have parsed. This information is then passed on to the | 978 // many we have parsed. This information is then passed on to the |
| 978 // member expression parser, which is only allowed to match argument | 979 // member expression parser, which is only allowed to match argument |
| 979 // lists as long as it has 'new' prefixes left | 980 // lists as long as it has 'new' prefixes left |
| 980 unsigned new_count = 0; | 981 unsigned new_count = 0; |
| 981 do { | 982 do { |
| 982 Consume(Token::NEW); | 983 Consume(i::Token::NEW); |
| 983 new_count++; | 984 new_count++; |
| 984 } while (peek() == Token::NEW); | 985 } while (peek() == i::Token::NEW); |
| 985 | 986 |
| 986 return ParseMemberWithNewPrefixesExpression(new_count, ok); | 987 return ParseMemberWithNewPrefixesExpression(new_count, ok); |
| 987 } | 988 } |
| 988 | 989 |
| 989 | 990 |
| 990 template <typename Scanner, typename Log> | 991 template <typename Scanner, typename Log> |
| 991 Expression PreParser<Scanner, Log>::ParseMemberExpression(bool* ok) { | 992 Expression PreParser<Scanner, Log>::ParseMemberExpression(bool* ok) { |
| 992 return ParseMemberWithNewPrefixesExpression(0, ok); | 993 return ParseMemberWithNewPrefixesExpression(0, ok); |
| 993 } | 994 } |
| 994 | 995 |
| 995 | 996 |
| 996 template <typename Scanner, typename Log> | 997 template <typename Scanner, typename Log> |
| 997 Expression PreParser<Scanner, Log>::ParseMemberWithNewPrefixesExpression( | 998 Expression PreParser<Scanner, Log>::ParseMemberWithNewPrefixesExpression( |
| 998 unsigned new_count, bool* ok) { | 999 unsigned new_count, bool* ok) { |
| 999 // MemberExpression :: | 1000 // MemberExpression :: |
| 1000 // (PrimaryExpression | FunctionLiteral) | 1001 // (PrimaryExpression | FunctionLiteral) |
| 1001 // ('[' Expression ']' | '.' Identifier | Arguments)* | 1002 // ('[' Expression ']' | '.' Identifier | Arguments)* |
| 1002 | 1003 |
| 1003 // Parse the initial primary or function expression. | 1004 // Parse the initial primary or function expression. |
| 1004 Expression result = NULL; | 1005 Expression result = NULL; |
| 1005 if (peek() == Token::FUNCTION) { | 1006 if (peek() == i::Token::FUNCTION) { |
| 1006 Consume(Token::FUNCTION); | 1007 Consume(i::Token::FUNCTION); |
| 1007 if (peek() == Token::IDENTIFIER) { | 1008 if (peek() == i::Token::IDENTIFIER) { |
| 1008 ParseIdentifier(CHECK_OK); | 1009 ParseIdentifier(CHECK_OK); |
| 1009 } | 1010 } |
| 1010 result = ParseFunctionLiteral(CHECK_OK); | 1011 result = ParseFunctionLiteral(CHECK_OK); |
| 1011 } else { | 1012 } else { |
| 1012 result = ParsePrimaryExpression(CHECK_OK); | 1013 result = ParsePrimaryExpression(CHECK_OK); |
| 1013 } | 1014 } |
| 1014 | 1015 |
| 1015 while (true) { | 1016 while (true) { |
| 1016 switch (peek()) { | 1017 switch (peek()) { |
| 1017 case Token::LBRACK: { | 1018 case i::Token::LBRACK: { |
| 1018 Consume(Token::LBRACK); | 1019 Consume(i::Token::LBRACK); |
| 1019 ParseExpression(true, CHECK_OK); | 1020 ParseExpression(true, CHECK_OK); |
| 1020 Expect(Token::RBRACK, CHECK_OK); | 1021 Expect(i::Token::RBRACK, CHECK_OK); |
| 1021 if (result == kThisExpression) { | 1022 if (result == kThisExpression) { |
| 1022 result = kThisPropertyExpression; | 1023 result = kThisPropertyExpression; |
| 1023 } else { | 1024 } else { |
| 1024 result = kUnknownExpression; | 1025 result = kUnknownExpression; |
| 1025 } | 1026 } |
| 1026 break; | 1027 break; |
| 1027 } | 1028 } |
| 1028 case Token::PERIOD: { | 1029 case i::Token::PERIOD: { |
| 1029 Consume(Token::PERIOD); | 1030 Consume(i::Token::PERIOD); |
| 1030 ParseIdentifierName(CHECK_OK); | 1031 ParseIdentifierName(CHECK_OK); |
| 1031 if (result == kThisExpression) { | 1032 if (result == kThisExpression) { |
| 1032 result = kThisPropertyExpression; | 1033 result = kThisPropertyExpression; |
| 1033 } else { | 1034 } else { |
| 1034 result = kUnknownExpression; | 1035 result = kUnknownExpression; |
| 1035 } | 1036 } |
| 1036 break; | 1037 break; |
| 1037 } | 1038 } |
| 1038 case Token::LPAREN: { | 1039 case i::Token::LPAREN: { |
| 1039 if (new_count == 0) return result; | 1040 if (new_count == 0) return result; |
| 1040 // Consume one of the new prefixes (already parsed). | 1041 // Consume one of the new prefixes (already parsed). |
| 1041 ParseArguments(CHECK_OK); | 1042 ParseArguments(CHECK_OK); |
| 1042 new_count--; | 1043 new_count--; |
| 1043 result = kUnknownExpression; | 1044 result = kUnknownExpression; |
| 1044 break; | 1045 break; |
| 1045 } | 1046 } |
| 1046 default: | 1047 default: |
| 1047 return result; | 1048 return result; |
| 1048 } | 1049 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1060 // Identifier | 1061 // Identifier |
| 1061 // Number | 1062 // Number |
| 1062 // String | 1063 // String |
| 1063 // ArrayLiteral | 1064 // ArrayLiteral |
| 1064 // ObjectLiteral | 1065 // ObjectLiteral |
| 1065 // RegExpLiteral | 1066 // RegExpLiteral |
| 1066 // '(' Expression ')' | 1067 // '(' Expression ')' |
| 1067 | 1068 |
| 1068 Expression result = kUnknownExpression; | 1069 Expression result = kUnknownExpression; |
| 1069 switch (peek()) { | 1070 switch (peek()) { |
| 1070 case Token::THIS: { | 1071 case i::Token::THIS: { |
| 1071 Next(); | 1072 Next(); |
| 1072 result = kThisExpression; | 1073 result = kThisExpression; |
| 1073 break; | 1074 break; |
| 1074 } | 1075 } |
| 1075 | 1076 |
| 1076 case Token::IDENTIFIER: { | 1077 case i::Token::IDENTIFIER: { |
| 1077 ParseIdentifier(CHECK_OK); | 1078 ParseIdentifier(CHECK_OK); |
| 1078 result = kIdentifierExpression; | 1079 result = kIdentifierExpression; |
| 1079 break; | 1080 break; |
| 1080 } | 1081 } |
| 1081 | 1082 |
| 1082 case Token::NULL_LITERAL: | 1083 case i::Token::NULL_LITERAL: |
| 1083 case Token::TRUE_LITERAL: | 1084 case i::Token::TRUE_LITERAL: |
| 1084 case Token::FALSE_LITERAL: | 1085 case i::Token::FALSE_LITERAL: |
| 1085 case Token::NUMBER: { | 1086 case i::Token::NUMBER: { |
| 1086 Next(); | 1087 Next(); |
| 1087 break; | 1088 break; |
| 1088 } | 1089 } |
| 1089 case Token::STRING: { | 1090 case i::Token::STRING: { |
| 1090 Next(); | 1091 Next(); |
| 1091 result = GetStringSymbol(); | 1092 result = GetStringSymbol(); |
| 1092 break; | 1093 break; |
| 1093 } | 1094 } |
| 1094 | 1095 |
| 1095 case Token::ASSIGN_DIV: | 1096 case i::Token::ASSIGN_DIV: |
| 1096 result = ParseRegExpLiteral(true, CHECK_OK); | 1097 result = ParseRegExpLiteral(true, CHECK_OK); |
| 1097 break; | 1098 break; |
| 1098 | 1099 |
| 1099 case Token::DIV: | 1100 case i::Token::DIV: |
| 1100 result = ParseRegExpLiteral(false, CHECK_OK); | 1101 result = ParseRegExpLiteral(false, CHECK_OK); |
| 1101 break; | 1102 break; |
| 1102 | 1103 |
| 1103 case Token::LBRACK: | 1104 case i::Token::LBRACK: |
| 1104 result = ParseArrayLiteral(CHECK_OK); | 1105 result = ParseArrayLiteral(CHECK_OK); |
| 1105 break; | 1106 break; |
| 1106 | 1107 |
| 1107 case Token::LBRACE: | 1108 case i::Token::LBRACE: |
| 1108 result = ParseObjectLiteral(CHECK_OK); | 1109 result = ParseObjectLiteral(CHECK_OK); |
| 1109 break; | 1110 break; |
| 1110 | 1111 |
| 1111 case Token::LPAREN: | 1112 case i::Token::LPAREN: |
| 1112 Consume(Token::LPAREN); | 1113 Consume(i::Token::LPAREN); |
| 1113 result = ParseExpression(true, CHECK_OK); | 1114 result = ParseExpression(true, CHECK_OK); |
| 1114 Expect(Token::RPAREN, CHECK_OK); | 1115 Expect(i::Token::RPAREN, CHECK_OK); |
| 1115 if (result == kIdentifierExpression) result = kUnknownExpression; | 1116 if (result == kIdentifierExpression) result = kUnknownExpression; |
| 1116 break; | 1117 break; |
| 1117 | 1118 |
| 1118 case Token::MOD: | 1119 case i::Token::MOD: |
| 1119 result = ParseV8Intrinsic(CHECK_OK); | 1120 result = ParseV8Intrinsic(CHECK_OK); |
| 1120 break; | 1121 break; |
| 1121 | 1122 |
| 1122 default: { | 1123 default: { |
| 1123 Next(); | 1124 Next(); |
| 1124 *ok = false; | 1125 *ok = false; |
| 1125 return kUnknownExpression; | 1126 return kUnknownExpression; |
| 1126 } | 1127 } |
| 1127 } | 1128 } |
| 1128 | 1129 |
| 1129 return result; | 1130 return result; |
| 1130 } | 1131 } |
| 1131 | 1132 |
| 1132 | 1133 |
| 1133 template <typename Scanner, typename Log> | 1134 template <typename Scanner, typename Log> |
| 1134 Expression PreParser<Scanner, Log>::ParseArrayLiteral(bool* ok) { | 1135 Expression PreParser<Scanner, Log>::ParseArrayLiteral(bool* ok) { |
| 1135 // ArrayLiteral :: | 1136 // ArrayLiteral :: |
| 1136 // '[' Expression? (',' Expression?)* ']' | 1137 // '[' Expression? (',' Expression?)* ']' |
| 1137 Expect(Token::LBRACK, CHECK_OK); | 1138 Expect(i::Token::LBRACK, CHECK_OK); |
| 1138 while (peek() != Token::RBRACK) { | 1139 while (peek() != i::Token::RBRACK) { |
| 1139 if (peek() != Token::COMMA) { | 1140 if (peek() != i::Token::COMMA) { |
| 1140 ParseAssignmentExpression(true, CHECK_OK); | 1141 ParseAssignmentExpression(true, CHECK_OK); |
| 1141 } | 1142 } |
| 1142 if (peek() != Token::RBRACK) { | 1143 if (peek() != i::Token::RBRACK) { |
| 1143 Expect(Token::COMMA, CHECK_OK); | 1144 Expect(i::Token::COMMA, CHECK_OK); |
| 1144 } | 1145 } |
| 1145 } | 1146 } |
| 1146 Expect(Token::RBRACK, CHECK_OK); | 1147 Expect(i::Token::RBRACK, CHECK_OK); |
| 1147 | 1148 |
| 1148 scope_->NextMaterializedLiteralIndex(); | 1149 scope_->NextMaterializedLiteralIndex(); |
| 1149 return kUnknownExpression; | 1150 return kUnknownExpression; |
| 1150 } | 1151 } |
| 1151 | 1152 |
| 1152 | 1153 |
| 1153 template <typename Scanner, typename Log> | 1154 template <typename Scanner, typename Log> |
| 1154 Expression PreParser<Scanner, Log>::ParseObjectLiteral(bool* ok) { | 1155 Expression PreParser<Scanner, Log>::ParseObjectLiteral(bool* ok) { |
| 1155 // ObjectLiteral :: | 1156 // ObjectLiteral :: |
| 1156 // '{' ( | 1157 // '{' ( |
| 1157 // ((IdentifierName | String | Number) ':' AssignmentExpression) | 1158 // ((IdentifierName | String | Number) ':' AssignmentExpression) |
| 1158 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | 1159 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
| 1159 // )*[','] '}' | 1160 // )*[','] '}' |
| 1160 | 1161 |
| 1161 Expect(Token::LBRACE, CHECK_OK); | 1162 Expect(i::Token::LBRACE, CHECK_OK); |
| 1162 while (peek() != Token::RBRACE) { | 1163 while (peek() != i::Token::RBRACE) { |
| 1163 Token::Value next = peek(); | 1164 i::Token::Value next = peek(); |
| 1164 switch (next) { | 1165 switch (next) { |
| 1165 case Token::IDENTIFIER: { | 1166 case i::Token::IDENTIFIER: { |
| 1166 bool is_getter = false; | 1167 bool is_getter = false; |
| 1167 bool is_setter = false; | 1168 bool is_setter = false; |
| 1168 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | 1169 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
| 1169 if ((is_getter || is_setter) && peek() != Token::COLON) { | 1170 if ((is_getter || is_setter) && peek() != i::Token::COLON) { |
| 1170 Token::Value name = Next(); | 1171 i::Token::Value name = Next(); |
| 1171 if (name != Token::IDENTIFIER && | 1172 if (name != i::Token::IDENTIFIER && |
| 1172 name != Token::NUMBER && | 1173 name != i::Token::NUMBER && |
| 1173 name != Token::STRING && | 1174 name != i::Token::STRING && |
| 1174 !Token::IsKeyword(name)) { | 1175 !i::Token::IsKeyword(name)) { |
| 1175 *ok = false; | 1176 *ok = false; |
| 1176 return kUnknownExpression; | 1177 return kUnknownExpression; |
| 1177 } | 1178 } |
| 1178 ParseFunctionLiteral(CHECK_OK); | 1179 ParseFunctionLiteral(CHECK_OK); |
| 1179 if (peek() != Token::RBRACE) { | 1180 if (peek() != i::Token::RBRACE) { |
| 1180 Expect(Token::COMMA, CHECK_OK); | 1181 Expect(i::Token::COMMA, CHECK_OK); |
| 1181 } | 1182 } |
| 1182 continue; // restart the while | 1183 continue; // restart the while |
| 1183 } | 1184 } |
| 1184 break; | 1185 break; |
| 1185 } | 1186 } |
| 1186 case Token::STRING: | 1187 case i::Token::STRING: |
| 1187 Consume(next); | 1188 Consume(next); |
| 1188 GetStringSymbol(); | 1189 GetStringSymbol(); |
| 1189 break; | 1190 break; |
| 1190 case Token::NUMBER: | 1191 case i::Token::NUMBER: |
| 1191 Consume(next); | 1192 Consume(next); |
| 1192 break; | 1193 break; |
| 1193 default: | 1194 default: |
| 1194 if (Token::IsKeyword(next)) { | 1195 if (i::Token::IsKeyword(next)) { |
| 1195 Consume(next); | 1196 Consume(next); |
| 1196 } else { | 1197 } else { |
| 1197 // Unexpected token. | 1198 // Unexpected token. |
| 1198 *ok = false; | 1199 *ok = false; |
| 1199 return kUnknownExpression; | 1200 return kUnknownExpression; |
| 1200 } | 1201 } |
| 1201 } | 1202 } |
| 1202 | 1203 |
| 1203 Expect(Token::COLON, CHECK_OK); | 1204 Expect(i::Token::COLON, CHECK_OK); |
| 1204 ParseAssignmentExpression(true, CHECK_OK); | 1205 ParseAssignmentExpression(true, CHECK_OK); |
| 1205 | 1206 |
| 1206 // TODO(1240767): Consider allowing trailing comma. | 1207 // TODO(1240767): Consider allowing trailing comma. |
| 1207 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | 1208 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK); |
| 1208 } | 1209 } |
| 1209 Expect(Token::RBRACE, CHECK_OK); | 1210 Expect(i::Token::RBRACE, CHECK_OK); |
| 1210 | 1211 |
| 1211 scope_->NextMaterializedLiteralIndex(); | 1212 scope_->NextMaterializedLiteralIndex(); |
| 1212 return kUnknownExpression; | 1213 return kUnknownExpression; |
| 1213 } | 1214 } |
| 1214 | 1215 |
| 1215 | 1216 |
| 1216 template <typename Scanner, typename Log> | 1217 template <typename Scanner, typename Log> |
| 1217 Expression PreParser<Scanner, Log>::ParseRegExpLiteral(bool seen_equal, | 1218 Expression PreParser<Scanner, Log>::ParseRegExpLiteral(bool seen_equal, |
| 1218 bool* ok) { | 1219 bool* ok) { |
| 1219 if (!scanner_->ScanRegExpPattern(seen_equal)) { | 1220 if (!scanner_->ScanRegExpPattern(seen_equal)) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1238 Next(); | 1239 Next(); |
| 1239 return kUnknownExpression; | 1240 return kUnknownExpression; |
| 1240 } | 1241 } |
| 1241 | 1242 |
| 1242 | 1243 |
| 1243 template <typename Scanner, typename Log> | 1244 template <typename Scanner, typename Log> |
| 1244 Arguments PreParser<Scanner, Log>::ParseArguments(bool* ok) { | 1245 Arguments PreParser<Scanner, Log>::ParseArguments(bool* ok) { |
| 1245 // Arguments :: | 1246 // Arguments :: |
| 1246 // '(' (AssignmentExpression)*[','] ')' | 1247 // '(' (AssignmentExpression)*[','] ')' |
| 1247 | 1248 |
| 1248 Expect(Token::LPAREN, CHECK_OK); | 1249 Expect(i::Token::LPAREN, CHECK_OK); |
| 1249 bool done = (peek() == Token::RPAREN); | 1250 bool done = (peek() == i::Token::RPAREN); |
| 1250 int argc = 0; | 1251 int argc = 0; |
| 1251 while (!done) { | 1252 while (!done) { |
| 1252 ParseAssignmentExpression(true, CHECK_OK); | 1253 ParseAssignmentExpression(true, CHECK_OK); |
| 1253 argc++; | 1254 argc++; |
| 1254 done = (peek() == Token::RPAREN); | 1255 done = (peek() == i::Token::RPAREN); |
| 1255 if (!done) Expect(Token::COMMA, CHECK_OK); | 1256 if (!done) Expect(i::Token::COMMA, CHECK_OK); |
| 1256 } | 1257 } |
| 1257 Expect(Token::RPAREN, CHECK_OK); | 1258 Expect(i::Token::RPAREN, CHECK_OK); |
| 1258 return argc; | 1259 return argc; |
| 1259 } | 1260 } |
| 1260 | 1261 |
| 1261 | 1262 |
| 1262 template <typename Scanner, typename Log> | 1263 template <typename Scanner, typename Log> |
| 1263 Expression PreParser<Scanner, Log>::ParseFunctionLiteral(bool* ok) { | 1264 Expression PreParser<Scanner, Log>::ParseFunctionLiteral(bool* ok) { |
| 1264 // Function :: | 1265 // Function :: |
| 1265 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 1266 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
| 1266 | 1267 |
| 1267 // Parse function body. | 1268 // Parse function body. |
| 1268 ScopeType outer_scope_type = scope_->type(); | 1269 ScopeType outer_scope_type = scope_->type(); |
| 1269 bool inside_with = scope_->IsInsideWith(); | 1270 bool inside_with = scope_->IsInsideWith(); |
| 1270 Scope function_scope(&scope_, kFunctionScope); | 1271 Scope function_scope(&scope_, kFunctionScope); |
| 1271 | 1272 |
| 1272 // FormalParameterList :: | 1273 // FormalParameterList :: |
| 1273 // '(' (Identifier)*[','] ')' | 1274 // '(' (Identifier)*[','] ')' |
| 1274 Expect(Token::LPAREN, CHECK_OK); | 1275 Expect(i::Token::LPAREN, CHECK_OK); |
| 1275 bool done = (peek() == Token::RPAREN); | 1276 bool done = (peek() == i::Token::RPAREN); |
| 1276 while (!done) { | 1277 while (!done) { |
| 1277 ParseIdentifier(CHECK_OK); | 1278 ParseIdentifier(CHECK_OK); |
| 1278 done = (peek() == Token::RPAREN); | 1279 done = (peek() == i::Token::RPAREN); |
| 1279 if (!done) { | 1280 if (!done) { |
| 1280 Expect(Token::COMMA, CHECK_OK); | 1281 Expect(i::Token::COMMA, CHECK_OK); |
| 1281 } | 1282 } |
| 1282 } | 1283 } |
| 1283 Expect(Token::RPAREN, CHECK_OK); | 1284 Expect(i::Token::RPAREN, CHECK_OK); |
| 1284 | 1285 |
| 1285 Expect(Token::LBRACE, CHECK_OK); | 1286 Expect(i::Token::LBRACE, CHECK_OK); |
| 1286 int function_block_pos = scanner_->location().beg_pos; | 1287 int function_block_pos = scanner_->location().beg_pos; |
| 1287 | 1288 |
| 1288 // Determine if the function will be lazily compiled. | 1289 // Determine if the function will be lazily compiled. |
| 1289 // Currently only happens to top-level functions. | 1290 // Currently only happens to top-level functions. |
| 1290 // Optimistically assume that all top-level functions are lazily compiled. | 1291 // Optimistically assume that all top-level functions are lazily compiled. |
| 1291 bool is_lazily_compiled = | 1292 bool is_lazily_compiled = |
| 1292 (outer_scope_type == kTopLevelScope && !inside_with && allow_lazy_); | 1293 (outer_scope_type == kTopLevelScope && !inside_with && allow_lazy_); |
| 1293 | 1294 |
| 1294 if (is_lazily_compiled) { | 1295 if (is_lazily_compiled) { |
| 1295 log_->PauseRecording(); | 1296 log_->PauseRecording(); |
| 1296 ParseSourceElements(Token::RBRACE, ok); | 1297 ParseSourceElements(i::Token::RBRACE, ok); |
| 1297 log_->ResumeRecording(); | 1298 log_->ResumeRecording(); |
| 1298 if (!*ok) return kUnknownExpression; | 1299 if (!*ok) return kUnknownExpression; |
| 1299 | 1300 |
| 1300 Expect(Token::RBRACE, CHECK_OK); | 1301 Expect(i::Token::RBRACE, CHECK_OK); |
| 1301 | 1302 |
| 1302 int end_pos = scanner_->location().end_pos; | 1303 int end_pos = scanner_->location().end_pos; |
| 1303 log_->LogFunction(function_block_pos, end_pos, | 1304 log_->LogFunction(function_block_pos, end_pos, |
| 1304 function_scope.materialized_literal_count(), | 1305 function_scope.materialized_literal_count(), |
| 1305 function_scope.expected_properties()); | 1306 function_scope.expected_properties()); |
| 1306 } else { | 1307 } else { |
| 1307 ParseSourceElements(Token::RBRACE, CHECK_OK); | 1308 ParseSourceElements(i::Token::RBRACE, CHECK_OK); |
| 1308 Expect(Token::RBRACE, CHECK_OK); | 1309 Expect(i::Token::RBRACE, CHECK_OK); |
| 1309 } | 1310 } |
| 1310 return kUnknownExpression; | 1311 return kUnknownExpression; |
| 1311 } | 1312 } |
| 1312 | 1313 |
| 1313 | 1314 |
| 1314 template <typename Scanner, typename Log> | 1315 template <typename Scanner, typename Log> |
| 1315 Expression PreParser<Scanner, Log>::ParseV8Intrinsic(bool* ok) { | 1316 Expression PreParser<Scanner, Log>::ParseV8Intrinsic(bool* ok) { |
| 1316 // CallRuntime :: | 1317 // CallRuntime :: |
| 1317 // '%' Identifier Arguments | 1318 // '%' Identifier Arguments |
| 1318 | 1319 |
| 1319 Expect(Token::MOD, CHECK_OK); | 1320 Expect(i::Token::MOD, CHECK_OK); |
| 1320 ParseIdentifier(CHECK_OK); | 1321 ParseIdentifier(CHECK_OK); |
| 1321 ParseArguments(CHECK_OK); | 1322 ParseArguments(CHECK_OK); |
| 1322 | 1323 |
| 1323 return kUnknownExpression; | 1324 return kUnknownExpression; |
| 1324 } | 1325 } |
| 1325 | 1326 |
| 1326 | 1327 |
| 1327 template <typename Scanner, typename Log> | 1328 template <typename Scanner, typename Log> |
| 1328 void PreParser<Scanner, Log>::ExpectSemicolon(bool* ok) { | 1329 void PreParser<Scanner, Log>::ExpectSemicolon(bool* ok) { |
| 1329 // Check for automatic semicolon insertion according to | 1330 // Check for automatic semicolon insertion according to |
| 1330 // the rules given in ECMA-262, section 7.9, page 21. | 1331 // the rules given in ECMA-262, section 7.9, page 21. |
| 1331 Token::Value tok = peek(); | 1332 i::Token::Value tok = peek(); |
| 1332 if (tok == Token::SEMICOLON) { | 1333 if (tok == i::Token::SEMICOLON) { |
| 1333 Next(); | 1334 Next(); |
| 1334 return; | 1335 return; |
| 1335 } | 1336 } |
| 1336 if (scanner_->has_line_terminator_before_next() || | 1337 if (scanner_->has_line_terminator_before_next() || |
| 1337 tok == Token::RBRACE || | 1338 tok == i::Token::RBRACE || |
| 1338 tok == Token::EOS) { | 1339 tok == i::Token::EOS) { |
| 1339 return; | 1340 return; |
| 1340 } | 1341 } |
| 1341 Expect(Token::SEMICOLON, ok); | 1342 Expect(i::Token::SEMICOLON, ok); |
| 1342 } | 1343 } |
| 1343 | 1344 |
| 1344 | 1345 |
| 1345 template <typename Scanner, typename Log> | 1346 template <typename Scanner, typename Log> |
| 1346 Identifier PreParser<Scanner, Log>::GetIdentifierSymbol() { | 1347 Identifier PreParser<Scanner, Log>::GetIdentifierSymbol() { |
| 1347 const char* literal_chars = scanner_->literal_string(); | 1348 const char* literal_chars = scanner_->literal_string(); |
| 1348 int literal_length = scanner_->literal_length(); | 1349 int literal_length = scanner_->literal_length(); |
| 1349 int identifier_pos = scanner_->location().beg_pos; | 1350 int identifier_pos = scanner_->location().beg_pos; |
| 1350 | 1351 |
| 1351 log_->LogSymbol(identifier_pos, literal_chars, literal_length); | 1352 log_->LogSymbol(identifier_pos, literal_chars, literal_length); |
| 1352 | 1353 |
| 1353 return kUnknownExpression; | 1354 return kUnknownExpression; |
| 1354 } | 1355 } |
| 1355 | 1356 |
| 1356 | 1357 |
| 1357 template <typename Scanner, typename Log> | 1358 template <typename Scanner, typename Log> |
| 1358 Expression PreParser<Scanner, Log>::GetStringSymbol() { | 1359 Expression PreParser<Scanner, Log>::GetStringSymbol() { |
| 1359 const char* literal_chars = scanner_->literal_string(); | 1360 const char* literal_chars = scanner_->literal_string(); |
| 1360 int literal_length = scanner_->literal_length(); | 1361 int literal_length = scanner_->literal_length(); |
| 1361 | 1362 |
| 1362 int literal_position = scanner_->location().beg_pos; | 1363 int literal_position = scanner_->location().beg_pos; |
| 1363 log_->LogSymbol(literal_position, literal_chars, literal_length); | 1364 log_->LogSymbol(literal_position, literal_chars, literal_length); |
| 1364 | 1365 |
| 1365 return kUnknownExpression; | 1366 return kUnknownExpression; |
| 1366 } | 1367 } |
| 1367 | 1368 |
| 1368 | 1369 |
| 1369 template <typename Scanner, typename Log> | 1370 template <typename Scanner, typename Log> |
| 1370 Identifier PreParser<Scanner, Log>::ParseIdentifier(bool* ok) { | 1371 Identifier PreParser<Scanner, Log>::ParseIdentifier(bool* ok) { |
| 1371 Expect(Token::IDENTIFIER, ok); | 1372 Expect(i::Token::IDENTIFIER, ok); |
| 1372 return GetIdentifierSymbol(); | 1373 return GetIdentifierSymbol(); |
| 1373 } | 1374 } |
| 1374 | 1375 |
| 1375 | 1376 |
| 1376 template <typename Scanner, typename Log> | 1377 template <typename Scanner, typename Log> |
| 1377 Identifier PreParser<Scanner, Log>::ParseIdentifierName(bool* ok) { | 1378 Identifier PreParser<Scanner, Log>::ParseIdentifierName(bool* ok) { |
| 1378 Token::Value next = Next(); | 1379 i::Token::Value next = Next(); |
| 1379 if (Token::IsKeyword(next)) { | 1380 if (i::Token::IsKeyword(next)) { |
| 1380 int pos = scanner_->location().beg_pos; | 1381 int pos = scanner_->location().beg_pos; |
| 1381 const char* keyword = Token::String(next); | 1382 const char* keyword = i::Token::String(next); |
| 1382 log_->LogSymbol(pos, keyword, strlen(keyword)); | 1383 log_->LogSymbol(pos, keyword, strlen(keyword)); |
| 1383 return kUnknownExpression; | 1384 return kUnknownExpression; |
| 1384 } | 1385 } |
| 1385 if (next == Token::IDENTIFIER) { | 1386 if (next == i::Token::IDENTIFIER) { |
| 1386 return GetIdentifierSymbol(); | 1387 return GetIdentifierSymbol(); |
| 1387 } | 1388 } |
| 1388 *ok = false; | 1389 *ok = false; |
| 1389 return kUnknownIdentifier; | 1390 return kUnknownIdentifier; |
| 1390 } | 1391 } |
| 1391 | 1392 |
| 1392 | 1393 |
| 1393 // This function reads an identifier and determines whether or not it | 1394 // This function reads an identifier and determines whether or not it |
| 1394 // is 'get' or 'set'. The reason for not using ParseIdentifier and | 1395 // is 'get' or 'set'. The reason for not using ParseIdentifier and |
| 1395 // checking on the output is that this involves heap allocation which | 1396 // checking on the output is that this involves heap allocation which |
| 1396 // we can't do during preparsing. | 1397 // we can't do during preparsing. |
| 1397 template <typename Scanner, typename Log> | 1398 template <typename Scanner, typename Log> |
| 1398 Identifier PreParser<Scanner, Log>::ParseIdentifierOrGetOrSet(bool* is_get, | 1399 Identifier PreParser<Scanner, Log>::ParseIdentifierOrGetOrSet(bool* is_get, |
| 1399 bool* is_set, | 1400 bool* is_set, |
| 1400 bool* ok) { | 1401 bool* ok) { |
| 1401 Expect(Token::IDENTIFIER, CHECK_OK); | 1402 Expect(i::Token::IDENTIFIER, CHECK_OK); |
| 1402 if (scanner_->literal_length() == 3) { | 1403 if (scanner_->literal_length() == 3) { |
| 1403 const char* token = scanner_->literal_string(); | 1404 const char* token = scanner_->literal_string(); |
| 1404 *is_get = strncmp(token, "get", 3) == 0; | 1405 *is_get = strncmp(token, "get", 3) == 0; |
| 1405 *is_set = !*is_get && strncmp(token, "set", 3) == 0; | 1406 *is_set = !*is_get && strncmp(token, "set", 3) == 0; |
| 1406 } | 1407 } |
| 1407 return GetIdentifierSymbol(); | 1408 return GetIdentifierSymbol(); |
| 1408 } | 1409 } |
| 1409 | 1410 |
| 1410 #undef CHECK_OK | 1411 #undef CHECK_OK |
| 1411 } } } // v8::internal::preparser | 1412 } } // v8::preparser |
| 1412 | 1413 |
| 1413 #endif // V8_PREPARSER_H | 1414 #endif // V8_PREPARSER_H |
| OLD | NEW |