| 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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 } | 105 } |
| 106 | 106 |
| 107 | 107 |
| 108 #define CHECK_OK ok); \ | 108 #define CHECK_OK ok); \ |
| 109 if (!*ok) return kUnknownSourceElements; \ | 109 if (!*ok) return kUnknownSourceElements; \ |
| 110 ((void)0 | 110 ((void)0 |
| 111 #define DUMMY ) // to make indentation work | 111 #define DUMMY ) // to make indentation work |
| 112 #undef DUMMY | 112 #undef DUMMY |
| 113 | 113 |
| 114 | 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 |
| 115 PreParser::SourceElements PreParser::ParseSourceElements(int end_token, | 125 PreParser::SourceElements PreParser::ParseSourceElements(int end_token, |
| 116 bool* ok) { | 126 bool* ok) { |
| 117 // SourceElements :: | 127 // SourceElements :: |
| 118 // (Statement)* <end_token> | 128 // (Statement)* <end_token> |
| 119 | 129 |
| 120 bool allow_directive_prologue = true; | 130 bool allow_directive_prologue = true; |
| 121 while (peek() != end_token) { | 131 while (peek() != end_token) { |
| 122 Statement statement = ParseStatement(CHECK_OK); | 132 Statement statement = ParseSourceElement(CHECK_OK); |
| 123 if (allow_directive_prologue) { | 133 if (allow_directive_prologue) { |
| 124 if (statement.IsUseStrictLiteral()) { | 134 if (statement.IsUseStrictLiteral()) { |
| 125 set_strict_mode(); | 135 set_strict_mode(); |
| 126 } else if (!statement.IsStringLiteral()) { | 136 } else if (!statement.IsStringLiteral()) { |
| 127 allow_directive_prologue = false; | 137 allow_directive_prologue = false; |
| 128 } | 138 } |
| 129 } | 139 } |
| 130 } | 140 } |
| 131 return kUnknownSourceElements; | 141 return kUnknownSourceElements; |
| 132 } | 142 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 // trivial labeled break statements 'label: break label' which is | 175 // trivial labeled break statements 'label: break label' which is |
| 166 // parsed into an empty statement. | 176 // parsed into an empty statement. |
| 167 | 177 |
| 168 // Keep the source position of the statement | 178 // Keep the source position of the statement |
| 169 switch (peek()) { | 179 switch (peek()) { |
| 170 case i::Token::LBRACE: | 180 case i::Token::LBRACE: |
| 171 return ParseBlock(ok); | 181 return ParseBlock(ok); |
| 172 | 182 |
| 173 case i::Token::CONST: | 183 case i::Token::CONST: |
| 174 case i::Token::VAR: | 184 case i::Token::VAR: |
| 175 return ParseVariableStatement(ok); | 185 return ParseVariableStatement(kStatement, ok); |
| 176 | 186 |
| 177 case i::Token::SEMICOLON: | 187 case i::Token::SEMICOLON: |
| 178 Next(); | 188 Next(); |
| 179 return Statement::Default(); | 189 return Statement::Default(); |
| 180 | 190 |
| 181 case i::Token::IF: | 191 case i::Token::IF: |
| 182 return ParseIfStatement(ok); | 192 return ParseIfStatement(ok); |
| 183 | 193 |
| 184 case i::Token::DO: | 194 case i::Token::DO: |
| 185 return ParseDoWhileStatement(ok); | 195 return ParseDoWhileStatement(ok); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 PreParser::Statement PreParser::ParseBlock(bool* ok) { | 261 PreParser::Statement PreParser::ParseBlock(bool* ok) { |
| 252 // Block :: | 262 // Block :: |
| 253 // '{' Statement* '}' | 263 // '{' Statement* '}' |
| 254 | 264 |
| 255 // Note that a Block does not introduce a new execution scope! | 265 // Note that a Block does not introduce a new execution scope! |
| 256 // (ECMA-262, 3rd, 12.2) | 266 // (ECMA-262, 3rd, 12.2) |
| 257 // | 267 // |
| 258 Expect(i::Token::LBRACE, CHECK_OK); | 268 Expect(i::Token::LBRACE, CHECK_OK); |
| 259 while (peek() != i::Token::RBRACE) { | 269 while (peek() != i::Token::RBRACE) { |
| 260 i::Scanner::Location start_location = scanner_->peek_location(); | 270 i::Scanner::Location start_location = scanner_->peek_location(); |
| 261 Statement statement = ParseStatement(CHECK_OK); | 271 Statement statement = ParseSourceElement(CHECK_OK); |
| 262 i::Scanner::Location end_location = scanner_->location(); | 272 i::Scanner::Location end_location = scanner_->location(); |
| 263 if (strict_mode() && statement.IsFunctionDeclaration()) { | 273 if (strict_mode() && statement.IsFunctionDeclaration()) { |
| 264 ReportMessageAt(start_location.beg_pos, end_location.end_pos, | 274 ReportMessageAt(start_location.beg_pos, end_location.end_pos, |
| 265 "strict_function", NULL); | 275 "strict_function", NULL); |
| 266 *ok = false; | 276 *ok = false; |
| 267 return Statement::Default(); | 277 return Statement::Default(); |
| 268 } | 278 } |
| 269 } | 279 } |
| 270 Expect(i::Token::RBRACE, ok); | 280 Expect(i::Token::RBRACE, ok); |
| 271 return Statement::Default(); | 281 return Statement::Default(); |
| 272 } | 282 } |
| 273 | 283 |
| 274 | 284 |
| 275 PreParser::Statement PreParser::ParseVariableStatement(bool* ok) { | 285 PreParser::Statement PreParser::ParseVariableStatement( |
| 286 VariableDeclarationContext var_context, |
| 287 bool* ok) { |
| 276 // VariableStatement :: | 288 // VariableStatement :: |
| 277 // VariableDeclarations ';' | 289 // VariableDeclarations ';' |
| 278 | 290 |
| 279 Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK); | 291 Statement result = ParseVariableDeclarations(var_context, |
| 292 NULL, |
| 293 CHECK_OK); |
| 280 ExpectSemicolon(CHECK_OK); | 294 ExpectSemicolon(CHECK_OK); |
| 281 return result; | 295 return result; |
| 282 } | 296 } |
| 283 | 297 |
| 284 | 298 |
| 285 // If the variable declaration declares exactly one non-const | 299 // If the variable declaration declares exactly one non-const |
| 286 // 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, |
| 287 // *var is untouched; in particular, it is the caller's responsibility | 301 // *var is untouched; in particular, it is the caller's responsibility |
| 288 // 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 |
| 289 // of 'for-in' loops. | 303 // of 'for-in' loops. |
| 290 PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN, | 304 PreParser::Statement PreParser::ParseVariableDeclarations( |
| 291 int* num_decl, | 305 VariableDeclarationContext var_context, |
| 292 bool* ok) { | 306 int* num_decl, |
| 307 bool* ok) { |
| 293 // VariableDeclarations :: | 308 // VariableDeclarations :: |
| 294 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] | 309 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
| 295 | 310 |
| 296 if (peek() == i::Token::VAR) { | 311 if (peek() == i::Token::VAR) { |
| 297 Consume(i::Token::VAR); | 312 Consume(i::Token::VAR); |
| 298 } else if (peek() == i::Token::CONST) { | 313 } else if (peek() == i::Token::CONST) { |
| 299 if (strict_mode()) { | 314 if (strict_mode()) { |
| 300 i::Scanner::Location location = scanner_->peek_location(); | 315 i::Scanner::Location location = scanner_->peek_location(); |
| 301 ReportMessageAt(location.beg_pos, location.end_pos, | 316 ReportMessageAt(location.beg_pos, location.end_pos, |
| 302 "strict_const", NULL); | 317 "strict_const", NULL); |
| 303 *ok = false; | 318 *ok = false; |
| 304 return Statement::Default(); | 319 return Statement::Default(); |
| 305 } | 320 } |
| 306 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); |
| 307 } else { | 332 } else { |
| 308 *ok = false; | 333 *ok = false; |
| 309 return Statement::Default(); | 334 return Statement::Default(); |
| 310 } | 335 } |
| 311 | 336 |
| 312 // The scope of a variable/const declared anywhere inside a function | 337 // The scope of a var/const declared variable anywhere inside a function |
| 313 // 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. |
| 314 int nvars = 0; // the number of variables declared | 341 int nvars = 0; // the number of variables declared |
| 315 do { | 342 do { |
| 316 // Parse variable name. | 343 // Parse variable name. |
| 317 if (nvars > 0) Consume(i::Token::COMMA); | 344 if (nvars > 0) Consume(i::Token::COMMA); |
| 318 Identifier identifier = ParseIdentifier(CHECK_OK); | 345 Identifier identifier = ParseIdentifier(CHECK_OK); |
| 319 if (strict_mode() && !identifier.IsValidStrictVariable()) { | 346 if (strict_mode() && !identifier.IsValidStrictVariable()) { |
| 320 StrictModeIdentifierViolation(scanner_->location(), | 347 StrictModeIdentifierViolation(scanner_->location(), |
| 321 "strict_var_name", | 348 "strict_var_name", |
| 322 identifier, | 349 identifier, |
| 323 ok); | 350 ok); |
| 324 return Statement::Default(); | 351 return Statement::Default(); |
| 325 } | 352 } |
| 326 nvars++; | 353 nvars++; |
| 327 if (peek() == i::Token::ASSIGN) { | 354 if (peek() == i::Token::ASSIGN) { |
| 328 Expect(i::Token::ASSIGN, CHECK_OK); | 355 Expect(i::Token::ASSIGN, CHECK_OK); |
| 329 ParseAssignmentExpression(accept_IN, CHECK_OK); | 356 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
| 330 } | 357 } |
| 331 } while (peek() == i::Token::COMMA); | 358 } while (peek() == i::Token::COMMA); |
| 332 | 359 |
| 333 if (num_decl != NULL) *num_decl = nvars; | 360 if (num_decl != NULL) *num_decl = nvars; |
| 334 return Statement::Default(); | 361 return Statement::Default(); |
| 335 } | 362 } |
| 336 | 363 |
| 337 | 364 |
| 338 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { | 365 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { |
| 339 // ExpressionStatement | LabelledStatement :: | 366 // ExpressionStatement | LabelledStatement :: |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 } | 555 } |
| 529 | 556 |
| 530 | 557 |
| 531 PreParser::Statement PreParser::ParseForStatement(bool* ok) { | 558 PreParser::Statement PreParser::ParseForStatement(bool* ok) { |
| 532 // ForStatement :: | 559 // ForStatement :: |
| 533 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 560 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
| 534 | 561 |
| 535 Expect(i::Token::FOR, CHECK_OK); | 562 Expect(i::Token::FOR, CHECK_OK); |
| 536 Expect(i::Token::LPAREN, CHECK_OK); | 563 Expect(i::Token::LPAREN, CHECK_OK); |
| 537 if (peek() != i::Token::SEMICOLON) { | 564 if (peek() != i::Token::SEMICOLON) { |
| 538 if (peek() == i::Token::VAR || peek() == i::Token::CONST) { | 565 if (peek() == i::Token::VAR || peek() == i::Token::CONST || |
| 566 peek() == i::Token::LET) { |
| 539 int decl_count; | 567 int decl_count; |
| 540 ParseVariableDeclarations(false, &decl_count, CHECK_OK); | 568 ParseVariableDeclarations(kForStatement, &decl_count, CHECK_OK); |
| 541 if (peek() == i::Token::IN && decl_count == 1) { | 569 if (peek() == i::Token::IN && decl_count == 1) { |
| 542 Expect(i::Token::IN, CHECK_OK); | 570 Expect(i::Token::IN, CHECK_OK); |
| 543 ParseExpression(true, CHECK_OK); | 571 ParseExpression(true, CHECK_OK); |
| 544 Expect(i::Token::RPAREN, CHECK_OK); | 572 Expect(i::Token::RPAREN, CHECK_OK); |
| 545 | 573 |
| 546 ParseStatement(CHECK_OK); | 574 ParseStatement(CHECK_OK); |
| 547 return Statement::Default(); | 575 return Statement::Default(); |
| 548 } | 576 } |
| 549 } else { | 577 } else { |
| 550 ParseExpression(false, CHECK_OK); | 578 ParseExpression(false, CHECK_OK); |
| (...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1454 return result; | 1482 return result; |
| 1455 } | 1483 } |
| 1456 | 1484 |
| 1457 bool PreParser::peek_any_identifier() { | 1485 bool PreParser::peek_any_identifier() { |
| 1458 i::Token::Value next = peek(); | 1486 i::Token::Value next = peek(); |
| 1459 return next == i::Token::IDENTIFIER || | 1487 return next == i::Token::IDENTIFIER || |
| 1460 next == i::Token::FUTURE_RESERVED_WORD || | 1488 next == i::Token::FUTURE_RESERVED_WORD || |
| 1461 next == i::Token::FUTURE_STRICT_RESERVED_WORD; | 1489 next == i::Token::FUTURE_STRICT_RESERVED_WORD; |
| 1462 } | 1490 } |
| 1463 } } // v8::preparser | 1491 } } // v8::preparser |
| OLD | NEW |