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 |