Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: src/preparser.cc

Issue 7616009: Parse harmony let declarations. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Updated tests. Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698