| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 | 49 |
| 50 // The PreParser checks that the syntax follows the grammar for JavaScript, | 50 // The PreParser checks that the syntax follows the grammar for JavaScript, |
| 51 // and collects some information about the program along the way. | 51 // and collects some information about the program along the way. |
| 52 // The grammar check is only performed in order to understand the program | 52 // The grammar check is only performed in order to understand the program |
| 53 // sufficiently to deduce some information about it, that can be used | 53 // sufficiently to deduce some information about it, that can be used |
| 54 // to speed up later parsing. Finding errors is not the goal of pre-parsing, | 54 // to speed up later parsing. Finding errors is not the goal of pre-parsing, |
| 55 // rather it is to speed up properly written and correct programs. | 55 // rather it is to speed up properly written and correct programs. |
| 56 // That means that contextual checks (like a label being declared where | 56 // That means that contextual checks (like a label being declared where |
| 57 // it is used) are generally omitted. | 57 // it is used) are generally omitted. |
| 58 | 58 |
| 59 namespace i = ::v8::internal; | |
| 60 | |
| 61 void PreParser::ReportUnexpectedToken(i::Token::Value token) { | 59 void PreParser::ReportUnexpectedToken(i::Token::Value token) { |
| 62 // We don't report stack overflows here, to avoid increasing the | 60 // We don't report stack overflows here, to avoid increasing the |
| 63 // stack depth even further. Instead we report it after parsing is | 61 // stack depth even further. Instead we report it after parsing is |
| 64 // over, in ParseProgram. | 62 // over, in ParseProgram. |
| 65 if (token == i::Token::ILLEGAL && stack_overflow_) { | 63 if (token == i::Token::ILLEGAL && stack_overflow_) { |
| 66 return; | 64 return; |
| 67 } | 65 } |
| 68 i::JavaScriptScanner::Location source_location = scanner_->location(); | 66 i::JavaScriptScanner::Location source_location = scanner_->location(); |
| 69 | 67 |
| 70 // Four of the tokens are treated specially | 68 // Four of the tokens are treated specially |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 } | 105 } |
| 108 | 106 |
| 109 | 107 |
| 110 #define CHECK_OK ok); \ | 108 #define CHECK_OK ok); \ |
| 111 if (!*ok) return kUnknownSourceElements; \ | 109 if (!*ok) return kUnknownSourceElements; \ |
| 112 ((void)0 | 110 ((void)0 |
| 113 #define DUMMY ) // to make indentation work | 111 #define DUMMY ) // to make indentation work |
| 114 #undef DUMMY | 112 #undef DUMMY |
| 115 | 113 |
| 116 | 114 |
| 115 PreParser::Statement PreParser::ParseSourceElement(bool* ok) { |
| 116 switch (peek()) { |
| 117 case i::Token::LET: |
| 118 return ParseVariableStatement(kSourceElement, ok); |
| 119 default: |
| 120 return ParseStatement(ok); |
| 121 } |
| 122 } |
| 123 |
| 124 |
| 117 PreParser::SourceElements PreParser::ParseSourceElements(int end_token, | 125 PreParser::SourceElements PreParser::ParseSourceElements(int end_token, |
| 118 bool* ok) { | 126 bool* ok) { |
| 119 // SourceElements :: | 127 // SourceElements :: |
| 120 // (Statement)* <end_token> | 128 // (Statement)* <end_token> |
| 121 | 129 |
| 122 bool allow_directive_prologue = true; | 130 bool allow_directive_prologue = true; |
| 123 while (peek() != end_token) { | 131 while (peek() != end_token) { |
| 124 Statement statement = ParseStatement(CHECK_OK); | 132 Statement statement = ParseSourceElement(CHECK_OK); |
| 125 if (allow_directive_prologue) { | 133 if (allow_directive_prologue) { |
| 126 if (statement.IsUseStrictLiteral()) { | 134 if (statement.IsUseStrictLiteral()) { |
| 127 set_strict_mode(); | 135 set_strict_mode(); |
| 128 } else if (!statement.IsStringLiteral()) { | 136 } else if (!statement.IsStringLiteral()) { |
| 129 allow_directive_prologue = false; | 137 allow_directive_prologue = false; |
| 130 } | 138 } |
| 131 } | 139 } |
| 132 } | 140 } |
| 133 return kUnknownSourceElements; | 141 return kUnknownSourceElements; |
| 134 } | 142 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 // trivial labeled break statements 'label: break label' which is | 175 // trivial labeled break statements 'label: break label' which is |
| 168 // parsed into an empty statement. | 176 // parsed into an empty statement. |
| 169 | 177 |
| 170 // Keep the source position of the statement | 178 // Keep the source position of the statement |
| 171 switch (peek()) { | 179 switch (peek()) { |
| 172 case i::Token::LBRACE: | 180 case i::Token::LBRACE: |
| 173 return ParseBlock(ok); | 181 return ParseBlock(ok); |
| 174 | 182 |
| 175 case i::Token::CONST: | 183 case i::Token::CONST: |
| 176 case i::Token::VAR: | 184 case i::Token::VAR: |
| 177 return ParseVariableStatement(ok); | 185 return ParseVariableStatement(kStatement, ok); |
| 178 | 186 |
| 179 case i::Token::SEMICOLON: | 187 case i::Token::SEMICOLON: |
| 180 Next(); | 188 Next(); |
| 181 return Statement::Default(); | 189 return Statement::Default(); |
| 182 | 190 |
| 183 case i::Token::IF: | 191 case i::Token::IF: |
| 184 return ParseIfStatement(ok); | 192 return ParseIfStatement(ok); |
| 185 | 193 |
| 186 case i::Token::DO: | 194 case i::Token::DO: |
| 187 return ParseDoWhileStatement(ok); | 195 return ParseDoWhileStatement(ok); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 PreParser::Statement PreParser::ParseBlock(bool* ok) { | 261 PreParser::Statement PreParser::ParseBlock(bool* ok) { |
| 254 // Block :: | 262 // Block :: |
| 255 // '{' Statement* '}' | 263 // '{' Statement* '}' |
| 256 | 264 |
| 257 // Note that a Block does not introduce a new execution scope! | 265 // Note that a Block does not introduce a new execution scope! |
| 258 // (ECMA-262, 3rd, 12.2) | 266 // (ECMA-262, 3rd, 12.2) |
| 259 // | 267 // |
| 260 Expect(i::Token::LBRACE, CHECK_OK); | 268 Expect(i::Token::LBRACE, CHECK_OK); |
| 261 while (peek() != i::Token::RBRACE) { | 269 while (peek() != i::Token::RBRACE) { |
| 262 i::Scanner::Location start_location = scanner_->peek_location(); | 270 i::Scanner::Location start_location = scanner_->peek_location(); |
| 263 Statement statement = ParseStatement(CHECK_OK); | 271 Statement statement = ParseSourceElement(CHECK_OK); |
| 264 i::Scanner::Location end_location = scanner_->location(); | 272 i::Scanner::Location end_location = scanner_->location(); |
| 265 if (strict_mode() && statement.IsFunctionDeclaration()) { | 273 if (strict_mode() && statement.IsFunctionDeclaration()) { |
| 266 ReportMessageAt(start_location.beg_pos, end_location.end_pos, | 274 ReportMessageAt(start_location.beg_pos, end_location.end_pos, |
| 267 "strict_function", NULL); | 275 "strict_function", NULL); |
| 268 *ok = false; | 276 *ok = false; |
| 269 return Statement::Default(); | 277 return Statement::Default(); |
| 270 } | 278 } |
| 271 } | 279 } |
| 272 Expect(i::Token::RBRACE, ok); | 280 Expect(i::Token::RBRACE, ok); |
| 273 return Statement::Default(); | 281 return Statement::Default(); |
| 274 } | 282 } |
| 275 | 283 |
| 276 | 284 |
| 277 PreParser::Statement PreParser::ParseVariableStatement(bool* ok) { | 285 PreParser::Statement PreParser::ParseVariableStatement( |
| 286 VariableDeclarationContext var_context, |
| 287 bool* ok) { |
| 278 // VariableStatement :: | 288 // VariableStatement :: |
| 279 // VariableDeclarations ';' | 289 // VariableDeclarations ';' |
| 280 | 290 |
| 281 Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK); | 291 Statement result = ParseVariableDeclarations(var_context, |
| 292 NULL, |
| 293 CHECK_OK); |
| 282 ExpectSemicolon(CHECK_OK); | 294 ExpectSemicolon(CHECK_OK); |
| 283 return result; | 295 return result; |
| 284 } | 296 } |
| 285 | 297 |
| 286 | 298 |
| 287 // If the variable declaration declares exactly one non-const | 299 // If the variable declaration declares exactly one non-const |
| 288 // variable, then *var is set to that variable. In all other cases, | 300 // variable, then *var is set to that variable. In all other cases, |
| 289 // *var is untouched; in particular, it is the caller's responsibility | 301 // *var is untouched; in particular, it is the caller's responsibility |
| 290 // to initialize it properly. This mechanism is also used for the parsing | 302 // to initialize it properly. This mechanism is also used for the parsing |
| 291 // of 'for-in' loops. | 303 // of 'for-in' loops. |
| 292 PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN, | 304 PreParser::Statement PreParser::ParseVariableDeclarations( |
| 293 int* num_decl, | 305 VariableDeclarationContext var_context, |
| 294 bool* ok) { | 306 int* num_decl, |
| 307 bool* ok) { |
| 295 // VariableDeclarations :: | 308 // VariableDeclarations :: |
| 296 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] | 309 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
| 297 | 310 |
| 298 if (peek() == i::Token::VAR) { | 311 if (peek() == i::Token::VAR) { |
| 299 Consume(i::Token::VAR); | 312 Consume(i::Token::VAR); |
| 300 } else if (peek() == i::Token::CONST) { | 313 } else if (peek() == i::Token::CONST) { |
| 301 if (strict_mode()) { | 314 if (strict_mode()) { |
| 302 i::Scanner::Location location = scanner_->peek_location(); | 315 i::Scanner::Location location = scanner_->peek_location(); |
| 303 ReportMessageAt(location.beg_pos, location.end_pos, | 316 ReportMessageAt(location.beg_pos, location.end_pos, |
| 304 "strict_const", NULL); | 317 "strict_const", NULL); |
| 305 *ok = false; | 318 *ok = false; |
| 306 return Statement::Default(); | 319 return Statement::Default(); |
| 307 } | 320 } |
| 308 Consume(i::Token::CONST); | 321 Consume(i::Token::CONST); |
| 322 } else if (peek() == i::Token::LET) { |
| 323 if (var_context != kSourceElement && |
| 324 var_context != kForStatement) { |
| 325 i::Scanner::Location location = scanner_->peek_location(); |
| 326 ReportMessageAt(location.beg_pos, location.end_pos, |
| 327 "unprotected_let", NULL); |
| 328 *ok = false; |
| 329 return Statement::Default(); |
| 330 } |
| 331 Consume(i::Token::LET); |
| 309 } else { | 332 } else { |
| 310 *ok = false; | 333 *ok = false; |
| 311 return Statement::Default(); | 334 return Statement::Default(); |
| 312 } | 335 } |
| 313 | 336 |
| 314 // The scope of a variable/const declared anywhere inside a function | 337 // The scope of a var/const declared variable anywhere inside a function |
| 315 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). . | 338 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope |
| 339 // of a let declared variable is the scope of the immediately enclosing |
| 340 // block. |
| 316 int nvars = 0; // the number of variables declared | 341 int nvars = 0; // the number of variables declared |
| 317 do { | 342 do { |
| 318 // Parse variable name. | 343 // Parse variable name. |
| 319 if (nvars > 0) Consume(i::Token::COMMA); | 344 if (nvars > 0) Consume(i::Token::COMMA); |
| 320 Identifier identifier = ParseIdentifier(CHECK_OK); | 345 Identifier identifier = ParseIdentifier(CHECK_OK); |
| 321 if (strict_mode() && !identifier.IsValidStrictVariable()) { | 346 if (strict_mode() && !identifier.IsValidStrictVariable()) { |
| 322 StrictModeIdentifierViolation(scanner_->location(), | 347 StrictModeIdentifierViolation(scanner_->location(), |
| 323 "strict_var_name", | 348 "strict_var_name", |
| 324 identifier, | 349 identifier, |
| 325 ok); | 350 ok); |
| 326 return Statement::Default(); | 351 return Statement::Default(); |
| 327 } | 352 } |
| 328 nvars++; | 353 nvars++; |
| 329 if (peek() == i::Token::ASSIGN) { | 354 if (peek() == i::Token::ASSIGN) { |
| 330 Expect(i::Token::ASSIGN, CHECK_OK); | 355 Expect(i::Token::ASSIGN, CHECK_OK); |
| 331 ParseAssignmentExpression(accept_IN, CHECK_OK); | 356 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
| 332 } | 357 } |
| 333 } while (peek() == i::Token::COMMA); | 358 } while (peek() == i::Token::COMMA); |
| 334 | 359 |
| 335 if (num_decl != NULL) *num_decl = nvars; | 360 if (num_decl != NULL) *num_decl = nvars; |
| 336 return Statement::Default(); | 361 return Statement::Default(); |
| 337 } | 362 } |
| 338 | 363 |
| 339 | 364 |
| 340 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { | 365 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { |
| 341 // ExpressionStatement | LabelledStatement :: | 366 // ExpressionStatement | LabelledStatement :: |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 } | 555 } |
| 531 | 556 |
| 532 | 557 |
| 533 PreParser::Statement PreParser::ParseForStatement(bool* ok) { | 558 PreParser::Statement PreParser::ParseForStatement(bool* ok) { |
| 534 // ForStatement :: | 559 // ForStatement :: |
| 535 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 560 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
| 536 | 561 |
| 537 Expect(i::Token::FOR, CHECK_OK); | 562 Expect(i::Token::FOR, CHECK_OK); |
| 538 Expect(i::Token::LPAREN, CHECK_OK); | 563 Expect(i::Token::LPAREN, CHECK_OK); |
| 539 if (peek() != i::Token::SEMICOLON) { | 564 if (peek() != i::Token::SEMICOLON) { |
| 540 if (peek() == i::Token::VAR || peek() == i::Token::CONST) { | 565 if (peek() == i::Token::VAR || peek() == i::Token::CONST || |
| 566 peek() == i::Token::LET) { |
| 541 int decl_count; | 567 int decl_count; |
| 542 ParseVariableDeclarations(false, &decl_count, CHECK_OK); | 568 ParseVariableDeclarations(kForStatement, &decl_count, CHECK_OK); |
| 543 if (peek() == i::Token::IN && decl_count == 1) { | 569 if (peek() == i::Token::IN && decl_count == 1) { |
| 544 Expect(i::Token::IN, CHECK_OK); | 570 Expect(i::Token::IN, CHECK_OK); |
| 545 ParseExpression(true, CHECK_OK); | 571 ParseExpression(true, CHECK_OK); |
| 546 Expect(i::Token::RPAREN, CHECK_OK); | 572 Expect(i::Token::RPAREN, CHECK_OK); |
| 547 | 573 |
| 548 ParseStatement(CHECK_OK); | 574 ParseStatement(CHECK_OK); |
| 549 return Statement::Default(); | 575 return Statement::Default(); |
| 550 } | 576 } |
| 551 } else { | 577 } else { |
| 552 ParseExpression(false, CHECK_OK); | 578 ParseExpression(false, CHECK_OK); |
| (...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1456 return result; | 1482 return result; |
| 1457 } | 1483 } |
| 1458 | 1484 |
| 1459 bool PreParser::peek_any_identifier() { | 1485 bool PreParser::peek_any_identifier() { |
| 1460 i::Token::Value next = peek(); | 1486 i::Token::Value next = peek(); |
| 1461 return next == i::Token::IDENTIFIER || | 1487 return next == i::Token::IDENTIFIER || |
| 1462 next == i::Token::FUTURE_RESERVED_WORD || | 1488 next == i::Token::FUTURE_RESERVED_WORD || |
| 1463 next == i::Token::FUTURE_STRICT_RESERVED_WORD; | 1489 next == i::Token::FUTURE_STRICT_RESERVED_WORD; |
| 1464 } | 1490 } |
| 1465 } } // v8::preparser | 1491 } } // v8::preparser |
| OLD | NEW |