Revision f230a1cf deps/v8/src/preparser.cc
deps/v8/src/preparser.cc | ||
---|---|---|
42 | 42 |
#include "unicode.h" |
43 | 43 |
#include "utils.h" |
44 | 44 |
|
45 |
#ifdef _MSC_VER
|
|
45 |
#if V8_CC_MSVC && (_MSC_VER < 1800)
|
|
46 | 46 |
namespace std { |
47 | 47 |
|
48 |
// Usually defined in math.h, but not in MSVC. |
|
48 |
// Usually defined in math.h, but not in MSVC until VS2013+.
|
|
49 | 49 |
// Abstracted to work |
50 | 50 |
int isfinite(double value); |
51 | 51 |
|
... | ... | |
53 | 53 |
#endif |
54 | 54 |
|
55 | 55 |
namespace v8 { |
56 |
|
|
57 |
namespace preparser { |
|
56 |
namespace internal { |
|
58 | 57 |
|
59 | 58 |
PreParser::PreParseResult PreParser::PreParseLazyFunction( |
60 |
i::LanguageMode mode, bool is_generator, i::ParserRecorder* log) {
|
|
59 |
LanguageMode mode, bool is_generator, ParserRecorder* log) {
|
|
61 | 60 |
log_ = log; |
62 | 61 |
// Lazy functions always have trivial outer scopes (no with/catch scopes). |
63 | 62 |
Scope top_scope(&scope_, kTopLevelScope); |
64 | 63 |
set_language_mode(mode); |
65 | 64 |
Scope function_scope(&scope_, kFunctionScope); |
66 | 65 |
function_scope.set_is_generator(is_generator); |
67 |
ASSERT_EQ(i::Token::LBRACE, scanner_->current_token());
|
|
66 |
ASSERT_EQ(Token::LBRACE, scanner()->current_token());
|
|
68 | 67 |
bool ok = true; |
69 |
int start_position = scanner_->peek_location().beg_pos;
|
|
68 |
int start_position = peek_position();
|
|
70 | 69 |
ParseLazyFunctionLiteralBody(&ok); |
71 |
if (stack_overflow_) return kPreParseStackOverflow;
|
|
70 |
if (stack_overflow()) return kPreParseStackOverflow;
|
|
72 | 71 |
if (!ok) { |
73 |
ReportUnexpectedToken(scanner_->current_token());
|
|
72 |
ReportUnexpectedToken(scanner()->current_token());
|
|
74 | 73 |
} else { |
75 |
ASSERT_EQ(i::Token::RBRACE, scanner_->peek());
|
|
74 |
ASSERT_EQ(Token::RBRACE, scanner()->peek());
|
|
76 | 75 |
if (!is_classic_mode()) { |
77 |
int end_pos = scanner_->location().end_pos;
|
|
76 |
int end_pos = scanner()->location().end_pos;
|
|
78 | 77 |
CheckOctalLiteral(start_position, end_pos, &ok); |
79 | 78 |
if (ok) { |
80 | 79 |
CheckDelayedStrictModeViolation(start_position, end_pos, &ok); |
... | ... | |
98 | 97 |
// That means that contextual checks (like a label being declared where |
99 | 98 |
// it is used) are generally omitted. |
100 | 99 |
|
101 |
void PreParser::ReportUnexpectedToken(i::Token::Value token) {
|
|
100 |
void PreParser::ReportUnexpectedToken(Token::Value token) { |
|
102 | 101 |
// We don't report stack overflows here, to avoid increasing the |
103 | 102 |
// stack depth even further. Instead we report it after parsing is |
104 | 103 |
// over, in ParseProgram. |
105 |
if (token == i::Token::ILLEGAL && stack_overflow_) {
|
|
104 |
if (token == Token::ILLEGAL && stack_overflow()) {
|
|
106 | 105 |
return; |
107 | 106 |
} |
108 |
i::Scanner::Location source_location = scanner_->location();
|
|
107 |
Scanner::Location source_location = scanner()->location();
|
|
109 | 108 |
|
110 | 109 |
// Four of the tokens are treated specially |
111 | 110 |
switch (token) { |
112 |
case i::Token::EOS:
|
|
111 |
case Token::EOS: |
|
113 | 112 |
return ReportMessageAt(source_location, "unexpected_eos", NULL); |
114 |
case i::Token::NUMBER:
|
|
113 |
case Token::NUMBER: |
|
115 | 114 |
return ReportMessageAt(source_location, "unexpected_token_number", NULL); |
116 |
case i::Token::STRING:
|
|
115 |
case Token::STRING: |
|
117 | 116 |
return ReportMessageAt(source_location, "unexpected_token_string", NULL); |
118 |
case i::Token::IDENTIFIER:
|
|
117 |
case Token::IDENTIFIER: |
|
119 | 118 |
return ReportMessageAt(source_location, |
120 | 119 |
"unexpected_token_identifier", NULL); |
121 |
case i::Token::FUTURE_RESERVED_WORD:
|
|
120 |
case Token::FUTURE_RESERVED_WORD: |
|
122 | 121 |
return ReportMessageAt(source_location, "unexpected_reserved", NULL); |
123 |
case i::Token::FUTURE_STRICT_RESERVED_WORD:
|
|
122 |
case Token::FUTURE_STRICT_RESERVED_WORD: |
|
124 | 123 |
return ReportMessageAt(source_location, |
125 | 124 |
"unexpected_strict_reserved", NULL); |
126 | 125 |
default: |
127 |
const char* name = i::Token::String(token);
|
|
126 |
const char* name = Token::String(token); |
|
128 | 127 |
ReportMessageAt(source_location, "unexpected_token", name); |
129 | 128 |
} |
130 | 129 |
} |
131 | 130 |
|
132 | 131 |
|
133 |
// Checks whether octal literal last seen is between beg_pos and end_pos. |
|
134 |
// If so, reports an error. |
|
135 |
void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { |
|
136 |
i::Scanner::Location octal = scanner_->octal_position(); |
|
137 |
if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) { |
|
138 |
ReportMessageAt(octal, "strict_octal_literal", NULL); |
|
139 |
scanner_->clear_octal_position(); |
|
140 |
*ok = false; |
|
141 |
} |
|
142 |
} |
|
143 |
|
|
144 |
|
|
145 | 132 |
#define CHECK_OK ok); \ |
146 | 133 |
if (!*ok) return kUnknownSourceElements; \ |
147 | 134 |
((void)0 |
... | ... | |
162 | 149 |
// GeneratorDeclaration |
163 | 150 |
|
164 | 151 |
switch (peek()) { |
165 |
case i::Token::FUNCTION:
|
|
152 |
case Token::FUNCTION: |
|
166 | 153 |
return ParseFunctionDeclaration(ok); |
167 |
case i::Token::LET:
|
|
168 |
case i::Token::CONST:
|
|
154 |
case Token::LET: |
|
155 |
case Token::CONST: |
|
169 | 156 |
return ParseVariableStatement(kSourceElement, ok); |
170 | 157 |
default: |
171 | 158 |
return ParseStatement(ok); |
... | ... | |
184 | 171 |
if (allow_directive_prologue) { |
185 | 172 |
if (statement.IsUseStrictLiteral()) { |
186 | 173 |
set_language_mode(allow_harmony_scoping() ? |
187 |
i::EXTENDED_MODE : i::STRICT_MODE);
|
|
174 |
EXTENDED_MODE : STRICT_MODE);
|
|
188 | 175 |
} else if (!statement.IsStringLiteral()) { |
189 | 176 |
allow_directive_prologue = false; |
190 | 177 |
} |
... | ... | |
229 | 216 |
|
230 | 217 |
// Keep the source position of the statement |
231 | 218 |
switch (peek()) { |
232 |
case i::Token::LBRACE:
|
|
219 |
case Token::LBRACE: |
|
233 | 220 |
return ParseBlock(ok); |
234 | 221 |
|
235 |
case i::Token::CONST:
|
|
236 |
case i::Token::LET:
|
|
237 |
case i::Token::VAR:
|
|
222 |
case Token::CONST: |
|
223 |
case Token::LET: |
|
224 |
case Token::VAR: |
|
238 | 225 |
return ParseVariableStatement(kStatement, ok); |
239 | 226 |
|
240 |
case i::Token::SEMICOLON:
|
|
227 |
case Token::SEMICOLON: |
|
241 | 228 |
Next(); |
242 | 229 |
return Statement::Default(); |
243 | 230 |
|
244 |
case i::Token::IF:
|
|
231 |
case Token::IF: |
|
245 | 232 |
return ParseIfStatement(ok); |
246 | 233 |
|
247 |
case i::Token::DO:
|
|
234 |
case Token::DO: |
|
248 | 235 |
return ParseDoWhileStatement(ok); |
249 | 236 |
|
250 |
case i::Token::WHILE:
|
|
237 |
case Token::WHILE: |
|
251 | 238 |
return ParseWhileStatement(ok); |
252 | 239 |
|
253 |
case i::Token::FOR:
|
|
240 |
case Token::FOR: |
|
254 | 241 |
return ParseForStatement(ok); |
255 | 242 |
|
256 |
case i::Token::CONTINUE:
|
|
243 |
case Token::CONTINUE: |
|
257 | 244 |
return ParseContinueStatement(ok); |
258 | 245 |
|
259 |
case i::Token::BREAK:
|
|
246 |
case Token::BREAK: |
|
260 | 247 |
return ParseBreakStatement(ok); |
261 | 248 |
|
262 |
case i::Token::RETURN:
|
|
249 |
case Token::RETURN: |
|
263 | 250 |
return ParseReturnStatement(ok); |
264 | 251 |
|
265 |
case i::Token::WITH:
|
|
252 |
case Token::WITH: |
|
266 | 253 |
return ParseWithStatement(ok); |
267 | 254 |
|
268 |
case i::Token::SWITCH:
|
|
255 |
case Token::SWITCH: |
|
269 | 256 |
return ParseSwitchStatement(ok); |
270 | 257 |
|
271 |
case i::Token::THROW:
|
|
258 |
case Token::THROW: |
|
272 | 259 |
return ParseThrowStatement(ok); |
273 | 260 |
|
274 |
case i::Token::TRY:
|
|
261 |
case Token::TRY: |
|
275 | 262 |
return ParseTryStatement(ok); |
276 | 263 |
|
277 |
case i::Token::FUNCTION: {
|
|
278 |
i::Scanner::Location start_location = scanner_->peek_location();
|
|
264 |
case Token::FUNCTION: { |
|
265 |
Scanner::Location start_location = scanner()->peek_location();
|
|
279 | 266 |
Statement statement = ParseFunctionDeclaration(CHECK_OK); |
280 |
i::Scanner::Location end_location = scanner_->location();
|
|
267 |
Scanner::Location end_location = scanner()->location();
|
|
281 | 268 |
if (!is_classic_mode()) { |
282 | 269 |
ReportMessageAt(start_location.beg_pos, end_location.end_pos, |
283 | 270 |
"strict_function", NULL); |
... | ... | |
288 | 275 |
} |
289 | 276 |
} |
290 | 277 |
|
291 |
case i::Token::DEBUGGER:
|
|
278 |
case Token::DEBUGGER: |
|
292 | 279 |
return ParseDebuggerStatement(ok); |
293 | 280 |
|
294 | 281 |
default: |
... | ... | |
303 | 290 |
// GeneratorDeclaration :: |
304 | 291 |
// 'function' '*' Identifier '(' FormalParameterListopt ')' |
305 | 292 |
// '{' FunctionBody '}' |
306 |
Expect(i::Token::FUNCTION, CHECK_OK);
|
|
293 |
Expect(Token::FUNCTION, CHECK_OK); |
|
307 | 294 |
|
308 |
bool is_generator = allow_generators_ && Check(i::Token::MUL);
|
|
295 |
bool is_generator = allow_generators() && Check(Token::MUL);
|
|
309 | 296 |
Identifier identifier = ParseIdentifier(CHECK_OK); |
310 |
i::Scanner::Location location = scanner_->location();
|
|
297 |
Scanner::Location location = scanner()->location();
|
|
311 | 298 |
|
312 | 299 |
Expression function_value = ParseFunctionLiteral(is_generator, CHECK_OK); |
313 | 300 |
|
... | ... | |
333 | 320 |
// Note that a Block does not introduce a new execution scope! |
334 | 321 |
// (ECMA-262, 3rd, 12.2) |
335 | 322 |
// |
336 |
Expect(i::Token::LBRACE, CHECK_OK);
|
|
337 |
while (peek() != i::Token::RBRACE) {
|
|
323 |
Expect(Token::LBRACE, CHECK_OK); |
|
324 |
while (peek() != Token::RBRACE) { |
|
338 | 325 |
if (is_extended_mode()) { |
339 | 326 |
ParseSourceElement(CHECK_OK); |
340 | 327 |
} else { |
341 | 328 |
ParseStatement(CHECK_OK); |
342 | 329 |
} |
343 | 330 |
} |
344 |
Expect(i::Token::RBRACE, ok);
|
|
331 |
Expect(Token::RBRACE, ok); |
|
345 | 332 |
return Statement::Default(); |
346 | 333 |
} |
347 | 334 |
|
... | ... | |
385 | 372 |
// ConstBinding :: |
386 | 373 |
// BindingPattern '=' AssignmentExpression |
387 | 374 |
bool require_initializer = false; |
388 |
if (peek() == i::Token::VAR) {
|
|
389 |
Consume(i::Token::VAR);
|
|
390 |
} else if (peek() == i::Token::CONST) {
|
|
375 |
if (peek() == Token::VAR) { |
|
376 |
Consume(Token::VAR); |
|
377 |
} else if (peek() == Token::CONST) { |
|
391 | 378 |
// TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads: |
392 | 379 |
// |
393 | 380 |
// ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' |
... | ... | |
398 | 385 |
// However disallowing const in classic mode will break compatibility with |
399 | 386 |
// existing pages. Therefore we keep allowing const with the old |
400 | 387 |
// non-harmony semantics in classic mode. |
401 |
Consume(i::Token::CONST);
|
|
388 |
Consume(Token::CONST); |
|
402 | 389 |
switch (language_mode()) { |
403 |
case i::CLASSIC_MODE:
|
|
390 |
case CLASSIC_MODE: |
|
404 | 391 |
break; |
405 |
case i::STRICT_MODE: {
|
|
406 |
i::Scanner::Location location = scanner_->peek_location();
|
|
392 |
case STRICT_MODE: { |
|
393 |
Scanner::Location location = scanner()->peek_location();
|
|
407 | 394 |
ReportMessageAt(location, "strict_const", NULL); |
408 | 395 |
*ok = false; |
409 | 396 |
return Statement::Default(); |
410 | 397 |
} |
411 |
case i::EXTENDED_MODE:
|
|
398 |
case EXTENDED_MODE: |
|
412 | 399 |
if (var_context != kSourceElement && |
413 | 400 |
var_context != kForStatement) { |
414 |
i::Scanner::Location location = scanner_->peek_location();
|
|
401 |
Scanner::Location location = scanner()->peek_location();
|
|
415 | 402 |
ReportMessageAt(location.beg_pos, location.end_pos, |
416 | 403 |
"unprotected_const", NULL); |
417 | 404 |
*ok = false; |
... | ... | |
420 | 407 |
require_initializer = true; |
421 | 408 |
break; |
422 | 409 |
} |
423 |
} else if (peek() == i::Token::LET) {
|
|
410 |
} else if (peek() == Token::LET) { |
|
424 | 411 |
// ES6 Draft Rev4 section 12.2.1: |
425 | 412 |
// |
426 | 413 |
// LetDeclaration : let LetBindingList ; |
... | ... | |
428 | 415 |
// * It is a Syntax Error if the code that matches this production is not |
429 | 416 |
// contained in extended code. |
430 | 417 |
if (!is_extended_mode()) { |
431 |
i::Scanner::Location location = scanner_->peek_location();
|
|
418 |
Scanner::Location location = scanner()->peek_location();
|
|
432 | 419 |
ReportMessageAt(location.beg_pos, location.end_pos, |
433 | 420 |
"illegal_let", NULL); |
434 | 421 |
*ok = false; |
435 | 422 |
return Statement::Default(); |
436 | 423 |
} |
437 |
Consume(i::Token::LET);
|
|
424 |
Consume(Token::LET); |
|
438 | 425 |
if (var_context != kSourceElement && |
439 | 426 |
var_context != kForStatement) { |
440 |
i::Scanner::Location location = scanner_->peek_location();
|
|
427 |
Scanner::Location location = scanner()->peek_location();
|
|
441 | 428 |
ReportMessageAt(location.beg_pos, location.end_pos, |
442 | 429 |
"unprotected_let", NULL); |
443 | 430 |
*ok = false; |
... | ... | |
455 | 442 |
int nvars = 0; // the number of variables declared |
456 | 443 |
do { |
457 | 444 |
// Parse variable name. |
458 |
if (nvars > 0) Consume(i::Token::COMMA);
|
|
445 |
if (nvars > 0) Consume(Token::COMMA); |
|
459 | 446 |
Identifier identifier = ParseIdentifier(CHECK_OK); |
460 | 447 |
if (!is_classic_mode() && !identifier.IsValidStrictVariable()) { |
461 |
StrictModeIdentifierViolation(scanner_->location(),
|
|
448 |
StrictModeIdentifierViolation(scanner()->location(),
|
|
462 | 449 |
"strict_var_name", |
463 | 450 |
identifier, |
464 | 451 |
ok); |
465 | 452 |
return Statement::Default(); |
466 | 453 |
} |
467 | 454 |
nvars++; |
468 |
if (peek() == i::Token::ASSIGN || require_initializer) {
|
|
469 |
Expect(i::Token::ASSIGN, CHECK_OK);
|
|
455 |
if (peek() == Token::ASSIGN || require_initializer) { |
|
456 |
Expect(Token::ASSIGN, CHECK_OK); |
|
470 | 457 |
ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
471 | 458 |
if (decl_props != NULL) *decl_props = kHasInitializers; |
472 | 459 |
} |
473 |
} while (peek() == i::Token::COMMA);
|
|
460 |
} while (peek() == Token::COMMA); |
|
474 | 461 |
|
475 | 462 |
if (num_decl != NULL) *num_decl = nvars; |
476 | 463 |
return Statement::Default(); |
... | ... | |
488 | 475 |
ASSERT(is_classic_mode() || |
489 | 476 |
(!expr.AsIdentifier().IsFutureStrictReserved() && |
490 | 477 |
!expr.AsIdentifier().IsYield())); |
491 |
if (peek() == i::Token::COLON) {
|
|
492 |
Consume(i::Token::COLON);
|
|
478 |
if (peek() == Token::COLON) { |
|
479 |
Consume(Token::COLON); |
|
493 | 480 |
return ParseStatement(ok); |
494 | 481 |
} |
495 | 482 |
// Preparsing is disabled for extensions (because the extension details |
... | ... | |
506 | 493 |
// IfStatement :: |
507 | 494 |
// 'if' '(' Expression ')' Statement ('else' Statement)? |
508 | 495 |
|
509 |
Expect(i::Token::IF, CHECK_OK);
|
|
510 |
Expect(i::Token::LPAREN, CHECK_OK);
|
|
496 |
Expect(Token::IF, CHECK_OK); |
|
497 |
Expect(Token::LPAREN, CHECK_OK); |
|
511 | 498 |
ParseExpression(true, CHECK_OK); |
512 |
Expect(i::Token::RPAREN, CHECK_OK);
|
|
499 |
Expect(Token::RPAREN, CHECK_OK); |
|
513 | 500 |
ParseStatement(CHECK_OK); |
514 |
if (peek() == i::Token::ELSE) {
|
|
501 |
if (peek() == Token::ELSE) { |
|
515 | 502 |
Next(); |
516 | 503 |
ParseStatement(CHECK_OK); |
517 | 504 |
} |
... | ... | |
523 | 510 |
// ContinueStatement :: |
524 | 511 |
// 'continue' [no line terminator] Identifier? ';' |
525 | 512 |
|
526 |
Expect(i::Token::CONTINUE, CHECK_OK);
|
|
527 |
i::Token::Value tok = peek();
|
|
528 |
if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
|
|
529 |
tok != i::Token::SEMICOLON &&
|
|
530 |
tok != i::Token::RBRACE &&
|
|
531 |
tok != i::Token::EOS) {
|
|
513 |
Expect(Token::CONTINUE, CHECK_OK); |
|
514 |
Token::Value tok = peek(); |
|
515 |
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
|
|
516 |
tok != Token::SEMICOLON && |
|
517 |
tok != Token::RBRACE && |
|
518 |
tok != Token::EOS) { |
|
532 | 519 |
ParseIdentifier(CHECK_OK); |
533 | 520 |
} |
534 | 521 |
ExpectSemicolon(CHECK_OK); |
... | ... | |
540 | 527 |
// BreakStatement :: |
541 | 528 |
// 'break' [no line terminator] Identifier? ';' |
542 | 529 |
|
543 |
Expect(i::Token::BREAK, CHECK_OK);
|
|
544 |
i::Token::Value tok = peek();
|
|
545 |
if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
|
|
546 |
tok != i::Token::SEMICOLON &&
|
|
547 |
tok != i::Token::RBRACE &&
|
|
548 |
tok != i::Token::EOS) {
|
|
530 |
Expect(Token::BREAK, CHECK_OK); |
|
531 |
Token::Value tok = peek(); |
|
532 |
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
|
|
533 |
tok != Token::SEMICOLON && |
|
534 |
tok != Token::RBRACE && |
|
535 |
tok != Token::EOS) { |
|
549 | 536 |
ParseIdentifier(CHECK_OK); |
550 | 537 |
} |
551 | 538 |
ExpectSemicolon(CHECK_OK); |
... | ... | |
560 | 547 |
// Consume the return token. It is necessary to do the before |
561 | 548 |
// reporting any errors on it, because of the way errors are |
562 | 549 |
// reported (underlining). |
563 |
Expect(i::Token::RETURN, CHECK_OK);
|
|
550 |
Expect(Token::RETURN, CHECK_OK); |
|
564 | 551 |
|
565 | 552 |
// An ECMAScript program is considered syntactically incorrect if it |
566 | 553 |
// contains a return statement that is not within the body of a |
567 | 554 |
// function. See ECMA-262, section 12.9, page 67. |
568 | 555 |
// This is not handled during preparsing. |
569 | 556 |
|
570 |
i::Token::Value tok = peek();
|
|
571 |
if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
|
|
572 |
tok != i::Token::SEMICOLON &&
|
|
573 |
tok != i::Token::RBRACE &&
|
|
574 |
tok != i::Token::EOS) {
|
|
557 |
Token::Value tok = peek(); |
|
558 |
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
|
|
559 |
tok != Token::SEMICOLON && |
|
560 |
tok != Token::RBRACE && |
|
561 |
tok != Token::EOS) { |
|
575 | 562 |
ParseExpression(true, CHECK_OK); |
576 | 563 |
} |
577 | 564 |
ExpectSemicolon(CHECK_OK); |
... | ... | |
582 | 569 |
PreParser::Statement PreParser::ParseWithStatement(bool* ok) { |
583 | 570 |
// WithStatement :: |
584 | 571 |
// 'with' '(' Expression ')' Statement |
585 |
Expect(i::Token::WITH, CHECK_OK);
|
|
572 |
Expect(Token::WITH, CHECK_OK); |
|
586 | 573 |
if (!is_classic_mode()) { |
587 |
i::Scanner::Location location = scanner_->location();
|
|
574 |
Scanner::Location location = scanner()->location();
|
|
588 | 575 |
ReportMessageAt(location, "strict_mode_with", NULL); |
589 | 576 |
*ok = false; |
590 | 577 |
return Statement::Default(); |
591 | 578 |
} |
592 |
Expect(i::Token::LPAREN, CHECK_OK);
|
|
579 |
Expect(Token::LPAREN, CHECK_OK); |
|
593 | 580 |
ParseExpression(true, CHECK_OK); |
594 |
Expect(i::Token::RPAREN, CHECK_OK);
|
|
581 |
Expect(Token::RPAREN, CHECK_OK); |
|
595 | 582 |
|
596 | 583 |
Scope::InsideWith iw(scope_); |
597 | 584 |
ParseStatement(CHECK_OK); |
... | ... | |
603 | 590 |
// SwitchStatement :: |
604 | 591 |
// 'switch' '(' Expression ')' '{' CaseClause* '}' |
605 | 592 |
|
606 |
Expect(i::Token::SWITCH, CHECK_OK);
|
|
607 |
Expect(i::Token::LPAREN, CHECK_OK);
|
|
593 |
Expect(Token::SWITCH, CHECK_OK); |
|
594 |
Expect(Token::LPAREN, CHECK_OK); |
|
608 | 595 |
ParseExpression(true, CHECK_OK); |
609 |
Expect(i::Token::RPAREN, CHECK_OK);
|
|
596 |
Expect(Token::RPAREN, CHECK_OK); |
|
610 | 597 |
|
611 |
Expect(i::Token::LBRACE, CHECK_OK);
|
|
612 |
i::Token::Value token = peek();
|
|
613 |
while (token != i::Token::RBRACE) {
|
|
614 |
if (token == i::Token::CASE) {
|
|
615 |
Expect(i::Token::CASE, CHECK_OK);
|
|
598 |
Expect(Token::LBRACE, CHECK_OK); |
|
599 |
Token::Value token = peek(); |
|
600 |
while (token != Token::RBRACE) { |
|
601 |
if (token == Token::CASE) { |
|
602 |
Expect(Token::CASE, CHECK_OK); |
|
616 | 603 |
ParseExpression(true, CHECK_OK); |
617 | 604 |
} else { |
618 |
Expect(i::Token::DEFAULT, CHECK_OK);
|
|
605 |
Expect(Token::DEFAULT, CHECK_OK); |
|
619 | 606 |
} |
620 |
Expect(i::Token::COLON, CHECK_OK);
|
|
607 |
Expect(Token::COLON, CHECK_OK); |
|
621 | 608 |
token = peek(); |
622 |
while (token != i::Token::CASE &&
|
|
623 |
token != i::Token::DEFAULT &&
|
|
624 |
token != i::Token::RBRACE) {
|
|
609 |
while (token != Token::CASE && |
|
610 |
token != Token::DEFAULT && |
|
611 |
token != Token::RBRACE) { |
|
625 | 612 |
ParseStatement(CHECK_OK); |
626 | 613 |
token = peek(); |
627 | 614 |
} |
628 | 615 |
} |
629 |
Expect(i::Token::RBRACE, ok);
|
|
616 |
Expect(Token::RBRACE, ok); |
|
630 | 617 |
return Statement::Default(); |
631 | 618 |
} |
632 | 619 |
|
... | ... | |
635 | 622 |
// DoStatement :: |
636 | 623 |
// 'do' Statement 'while' '(' Expression ')' ';' |
637 | 624 |
|
638 |
Expect(i::Token::DO, CHECK_OK);
|
|
625 |
Expect(Token::DO, CHECK_OK); |
|
639 | 626 |
ParseStatement(CHECK_OK); |
640 |
Expect(i::Token::WHILE, CHECK_OK);
|
|
641 |
Expect(i::Token::LPAREN, CHECK_OK);
|
|
627 |
Expect(Token::WHILE, CHECK_OK); |
|
628 |
Expect(Token::LPAREN, CHECK_OK); |
|
642 | 629 |
ParseExpression(true, CHECK_OK); |
643 |
Expect(i::Token::RPAREN, ok);
|
|
644 |
if (peek() == i::Token::SEMICOLON) Consume(i::Token::SEMICOLON);
|
|
630 |
Expect(Token::RPAREN, ok); |
|
631 |
if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
|
|
645 | 632 |
return Statement::Default(); |
646 | 633 |
} |
647 | 634 |
|
... | ... | |
650 | 637 |
// WhileStatement :: |
651 | 638 |
// 'while' '(' Expression ')' Statement |
652 | 639 |
|
653 |
Expect(i::Token::WHILE, CHECK_OK);
|
|
654 |
Expect(i::Token::LPAREN, CHECK_OK);
|
|
640 |
Expect(Token::WHILE, CHECK_OK); |
|
641 |
Expect(Token::LPAREN, CHECK_OK); |
|
655 | 642 |
ParseExpression(true, CHECK_OK); |
656 |
Expect(i::Token::RPAREN, CHECK_OK);
|
|
643 |
Expect(Token::RPAREN, CHECK_OK); |
|
657 | 644 |
ParseStatement(ok); |
658 | 645 |
return Statement::Default(); |
659 | 646 |
} |
660 | 647 |
|
661 | 648 |
|
662 | 649 |
bool PreParser::CheckInOrOf(bool accept_OF) { |
663 |
if (peek() == i::Token::IN || |
|
664 |
(allow_for_of() && accept_OF && peek() == i::Token::IDENTIFIER && |
|
665 |
scanner_->is_next_contextual_keyword(v8::internal::CStrVector("of")))) { |
|
666 |
Next(); |
|
650 |
if (Check(Token::IN) || |
|
651 |
(allow_for_of() && accept_OF && |
|
652 |
CheckContextualKeyword(CStrVector("of")))) { |
|
667 | 653 |
return true; |
668 | 654 |
} |
669 | 655 |
return false; |
... | ... | |
674 | 660 |
// ForStatement :: |
675 | 661 |
// 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
676 | 662 |
|
677 |
Expect(i::Token::FOR, CHECK_OK);
|
|
678 |
Expect(i::Token::LPAREN, CHECK_OK);
|
|
679 |
if (peek() != i::Token::SEMICOLON) {
|
|
680 |
if (peek() == i::Token::VAR || peek() == i::Token::CONST ||
|
|
681 |
peek() == i::Token::LET) {
|
|
682 |
bool is_let = peek() == i::Token::LET;
|
|
663 |
Expect(Token::FOR, CHECK_OK); |
|
664 |
Expect(Token::LPAREN, CHECK_OK); |
|
665 |
if (peek() != Token::SEMICOLON) { |
|
666 |
if (peek() == Token::VAR || peek() == Token::CONST ||
|
|
667 |
peek() == Token::LET) { |
|
668 |
bool is_let = peek() == Token::LET; |
|
683 | 669 |
int decl_count; |
684 | 670 |
VariableDeclarationProperties decl_props = kHasNoInitializers; |
685 | 671 |
ParseVariableDeclarations( |
... | ... | |
689 | 675 |
bool accept_OF = !has_initializers; |
690 | 676 |
if (accept_IN && CheckInOrOf(accept_OF)) { |
691 | 677 |
ParseExpression(true, CHECK_OK); |
692 |
Expect(i::Token::RPAREN, CHECK_OK);
|
|
678 |
Expect(Token::RPAREN, CHECK_OK); |
|
693 | 679 |
|
694 | 680 |
ParseStatement(CHECK_OK); |
695 | 681 |
return Statement::Default(); |
... | ... | |
698 | 684 |
Expression lhs = ParseExpression(false, CHECK_OK); |
699 | 685 |
if (CheckInOrOf(lhs.IsIdentifier())) { |
700 | 686 |
ParseExpression(true, CHECK_OK); |
701 |
Expect(i::Token::RPAREN, CHECK_OK);
|
|
687 |
Expect(Token::RPAREN, CHECK_OK); |
|
702 | 688 |
|
703 | 689 |
ParseStatement(CHECK_OK); |
704 | 690 |
return Statement::Default(); |
... | ... | |
707 | 693 |
} |
708 | 694 |
|
709 | 695 |
// Parsed initializer at this point. |
710 |
Expect(i::Token::SEMICOLON, CHECK_OK);
|
|
696 |
Expect(Token::SEMICOLON, CHECK_OK); |
|
711 | 697 |
|
712 |
if (peek() != i::Token::SEMICOLON) {
|
|
698 |
if (peek() != Token::SEMICOLON) { |
|
713 | 699 |
ParseExpression(true, CHECK_OK); |
714 | 700 |
} |
715 |
Expect(i::Token::SEMICOLON, CHECK_OK);
|
|
701 |
Expect(Token::SEMICOLON, CHECK_OK); |
|
716 | 702 |
|
717 |
if (peek() != i::Token::RPAREN) {
|
|
703 |
if (peek() != Token::RPAREN) { |
|
718 | 704 |
ParseExpression(true, CHECK_OK); |
719 | 705 |
} |
720 |
Expect(i::Token::RPAREN, CHECK_OK);
|
|
706 |
Expect(Token::RPAREN, CHECK_OK); |
|
721 | 707 |
|
722 | 708 |
ParseStatement(ok); |
723 | 709 |
return Statement::Default(); |
... | ... | |
728 | 714 |
// ThrowStatement :: |
729 | 715 |
// 'throw' [no line terminator] Expression ';' |
730 | 716 |
|
731 |
Expect(i::Token::THROW, CHECK_OK);
|
|
732 |
if (scanner_->HasAnyLineTerminatorBeforeNext()) {
|
|
733 |
i::Scanner::Location pos = scanner_->location();
|
|
717 |
Expect(Token::THROW, CHECK_OK); |
|
718 |
if (scanner()->HasAnyLineTerminatorBeforeNext()) {
|
|
719 |
Scanner::Location pos = scanner()->location();
|
|
734 | 720 |
ReportMessageAt(pos, "newline_after_throw", NULL); |
735 | 721 |
*ok = false; |
736 | 722 |
return Statement::Default(); |
... | ... | |
756 | 742 |
// In preparsing, allow any number of catch/finally blocks, including zero |
757 | 743 |
// of both. |
758 | 744 |
|
759 |
Expect(i::Token::TRY, CHECK_OK);
|
|
745 |
Expect(Token::TRY, CHECK_OK); |
|
760 | 746 |
|
761 | 747 |
ParseBlock(CHECK_OK); |
762 | 748 |
|
763 | 749 |
bool catch_or_finally_seen = false; |
764 |
if (peek() == i::Token::CATCH) {
|
|
765 |
Consume(i::Token::CATCH);
|
|
766 |
Expect(i::Token::LPAREN, CHECK_OK);
|
|
750 |
if (peek() == Token::CATCH) { |
|
751 |
Consume(Token::CATCH); |
|
752 |
Expect(Token::LPAREN, CHECK_OK); |
|
767 | 753 |
Identifier id = ParseIdentifier(CHECK_OK); |
768 | 754 |
if (!is_classic_mode() && !id.IsValidStrictVariable()) { |
769 |
StrictModeIdentifierViolation(scanner_->location(),
|
|
755 |
StrictModeIdentifierViolation(scanner()->location(),
|
|
770 | 756 |
"strict_catch_variable", |
771 | 757 |
id, |
772 | 758 |
ok); |
773 | 759 |
return Statement::Default(); |
774 | 760 |
} |
775 |
Expect(i::Token::RPAREN, CHECK_OK);
|
|
761 |
Expect(Token::RPAREN, CHECK_OK); |
|
776 | 762 |
{ Scope::InsideWith iw(scope_); |
777 | 763 |
ParseBlock(CHECK_OK); |
778 | 764 |
} |
779 | 765 |
catch_or_finally_seen = true; |
780 | 766 |
} |
781 |
if (peek() == i::Token::FINALLY) {
|
|
782 |
Consume(i::Token::FINALLY);
|
|
767 |
if (peek() == Token::FINALLY) { |
|
768 |
Consume(Token::FINALLY); |
|
783 | 769 |
ParseBlock(CHECK_OK); |
784 | 770 |
catch_or_finally_seen = true; |
785 | 771 |
} |
... | ... | |
797 | 783 |
// DebuggerStatement :: |
798 | 784 |
// 'debugger' ';' |
799 | 785 |
|
800 |
Expect(i::Token::DEBUGGER, CHECK_OK);
|
|
786 |
Expect(Token::DEBUGGER, CHECK_OK); |
|
801 | 787 |
ExpectSemicolon(ok); |
802 | 788 |
return Statement::Default(); |
803 | 789 |
} |
... | ... | |
818 | 804 |
// Expression ',' AssignmentExpression |
819 | 805 |
|
820 | 806 |
Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK); |
821 |
while (peek() == i::Token::COMMA) {
|
|
822 |
Expect(i::Token::COMMA, CHECK_OK);
|
|
807 |
while (peek() == Token::COMMA) { |
|
808 |
Expect(Token::COMMA, CHECK_OK); |
|
823 | 809 |
ParseAssignmentExpression(accept_IN, CHECK_OK); |
824 | 810 |
result = Expression::Default(); |
825 | 811 |
} |
... | ... | |
835 | 821 |
// YieldExpression |
836 | 822 |
// LeftHandSideExpression AssignmentOperator AssignmentExpression |
837 | 823 |
|
838 |
if (scope_->is_generator() && peek() == i::Token::YIELD) {
|
|
824 |
if (scope_->is_generator() && peek() == Token::YIELD) { |
|
839 | 825 |
return ParseYieldExpression(ok); |
840 | 826 |
} |
841 | 827 |
|
842 |
i::Scanner::Location before = scanner_->peek_location();
|
|
828 |
Scanner::Location before = scanner()->peek_location();
|
|
843 | 829 |
Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK); |
844 | 830 |
|
845 |
if (!i::Token::IsAssignmentOp(peek())) {
|
|
831 |
if (!Token::IsAssignmentOp(peek())) { |
|
846 | 832 |
// Parsed conditional expression only (no assignment). |
847 | 833 |
return expression; |
848 | 834 |
} |
... | ... | |
850 | 836 |
if (!is_classic_mode() && |
851 | 837 |
expression.IsIdentifier() && |
852 | 838 |
expression.AsIdentifier().IsEvalOrArguments()) { |
853 |
i::Scanner::Location after = scanner_->location();
|
|
839 |
Scanner::Location after = scanner()->location();
|
|
854 | 840 |
ReportMessageAt(before.beg_pos, after.end_pos, |
855 | 841 |
"strict_lhs_assignment", NULL); |
856 | 842 |
*ok = false; |
857 | 843 |
return Expression::Default(); |
858 | 844 |
} |
859 | 845 |
|
860 |
i::Token::Value op = Next(); // Get assignment operator.
|
|
846 |
Token::Value op = Next(); // Get assignment operator. |
|
861 | 847 |
ParseAssignmentExpression(accept_IN, CHECK_OK); |
862 | 848 |
|
863 |
if ((op == i::Token::ASSIGN) && expression.IsThisProperty()) {
|
|
849 |
if ((op == Token::ASSIGN) && expression.IsThisProperty()) { |
|
864 | 850 |
scope_->AddProperty(); |
865 | 851 |
} |
866 | 852 |
|
... | ... | |
872 | 858 |
PreParser::Expression PreParser::ParseYieldExpression(bool* ok) { |
873 | 859 |
// YieldExpression :: |
874 | 860 |
// 'yield' '*'? AssignmentExpression |
875 |
Consume(i::Token::YIELD);
|
|
876 |
Check(i::Token::MUL);
|
|
861 |
Consume(Token::YIELD); |
|
862 |
Check(Token::MUL); |
|
877 | 863 |
|
878 | 864 |
ParseAssignmentExpression(false, CHECK_OK); |
879 | 865 |
|
... | ... | |
890 | 876 |
|
891 | 877 |
// We start using the binary expression parser for prec >= 4 only! |
892 | 878 |
Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK); |
893 |
if (peek() != i::Token::CONDITIONAL) return expression;
|
|
894 |
Consume(i::Token::CONDITIONAL);
|
|
879 |
if (peek() != Token::CONDITIONAL) return expression; |
|
880 |
Consume(Token::CONDITIONAL); |
|
895 | 881 |
// In parsing the first assignment expression in conditional |
896 | 882 |
// expressions we always accept the 'in' keyword; see ECMA-262, |
897 | 883 |
// section 11.12, page 58. |
898 | 884 |
ParseAssignmentExpression(true, CHECK_OK); |
899 |
Expect(i::Token::COLON, CHECK_OK);
|
|
885 |
Expect(Token::COLON, CHECK_OK); |
|
900 | 886 |
ParseAssignmentExpression(accept_IN, CHECK_OK); |
901 | 887 |
return Expression::Default(); |
902 | 888 |
} |
903 | 889 |
|
904 | 890 |
|
905 |
int PreParser::Precedence(i::Token::Value tok, bool accept_IN) { |
|
906 |
if (tok == i::Token::IN && !accept_IN) |
|
907 |
return 0; // 0 precedence will terminate binary expression parsing |
|
908 |
|
|
909 |
return i::Token::Precedence(tok); |
|
910 |
} |
|
911 |
|
|
912 |
|
|
913 | 891 |
// Precedence >= 4 |
914 | 892 |
PreParser::Expression PreParser::ParseBinaryExpression(int prec, |
915 | 893 |
bool accept_IN, |
... | ... | |
940 | 918 |
// '~' UnaryExpression |
941 | 919 |
// '!' UnaryExpression |
942 | 920 |
|
943 |
i::Token::Value op = peek();
|
|
944 |
if (i::Token::IsUnaryOp(op)) {
|
|
921 |
Token::Value op = peek(); |
|
922 |
if (Token::IsUnaryOp(op)) { |
|
945 | 923 |
op = Next(); |
946 | 924 |
ParseUnaryExpression(ok); |
947 | 925 |
return Expression::Default(); |
948 |
} else if (i::Token::IsCountOp(op)) {
|
|
926 |
} else if (Token::IsCountOp(op)) { |
|
949 | 927 |
op = Next(); |
950 |
i::Scanner::Location before = scanner_->peek_location();
|
|
928 |
Scanner::Location before = scanner()->peek_location();
|
|
951 | 929 |
Expression expression = ParseUnaryExpression(CHECK_OK); |
952 | 930 |
if (!is_classic_mode() && |
953 | 931 |
expression.IsIdentifier() && |
954 | 932 |
expression.AsIdentifier().IsEvalOrArguments()) { |
955 |
i::Scanner::Location after = scanner_->location();
|
|
933 |
Scanner::Location after = scanner()->location();
|
|
956 | 934 |
ReportMessageAt(before.beg_pos, after.end_pos, |
957 | 935 |
"strict_lhs_prefix", NULL); |
958 | 936 |
*ok = false; |
... | ... | |
968 | 946 |
// PostfixExpression :: |
969 | 947 |
// LeftHandSideExpression ('++' | '--')? |
970 | 948 |
|
971 |
i::Scanner::Location before = scanner_->peek_location();
|
|
949 |
Scanner::Location before = scanner()->peek_location();
|
|
972 | 950 |
Expression expression = ParseLeftHandSideExpression(CHECK_OK); |
973 |
if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
|
|
974 |
i::Token::IsCountOp(peek())) {
|
|
951 |
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
|
|
952 |
Token::IsCountOp(peek())) { |
|
975 | 953 |
if (!is_classic_mode() && |
976 | 954 |
expression.IsIdentifier() && |
977 | 955 |
expression.AsIdentifier().IsEvalOrArguments()) { |
978 |
i::Scanner::Location after = scanner_->location();
|
|
956 |
Scanner::Location after = scanner()->location();
|
|
979 | 957 |
ReportMessageAt(before.beg_pos, after.end_pos, |
980 | 958 |
"strict_lhs_postfix", NULL); |
981 | 959 |
*ok = false; |
... | ... | |
993 | 971 |
// (NewExpression | MemberExpression) ... |
994 | 972 |
|
995 | 973 |
Expression result = Expression::Default(); |
996 |
if (peek() == i::Token::NEW) {
|
|
974 |
if (peek() == Token::NEW) { |
|
997 | 975 |
result = ParseNewExpression(CHECK_OK); |
998 | 976 |
} else { |
999 | 977 |
result = ParseMemberExpression(CHECK_OK); |
... | ... | |
1001 | 979 |
|
1002 | 980 |
while (true) { |
1003 | 981 |
switch (peek()) { |
1004 |
case i::Token::LBRACK: {
|
|
1005 |
Consume(i::Token::LBRACK);
|
|
982 |
case Token::LBRACK: { |
|
983 |
Consume(Token::LBRACK); |
|
1006 | 984 |
ParseExpression(true, CHECK_OK); |
1007 |
Expect(i::Token::RBRACK, CHECK_OK);
|
|
985 |
Expect(Token::RBRACK, CHECK_OK); |
|
1008 | 986 |
if (result.IsThis()) { |
1009 | 987 |
result = Expression::ThisProperty(); |
1010 | 988 |
} else { |
... | ... | |
1013 | 991 |
break; |
1014 | 992 |
} |
1015 | 993 |
|
1016 |
case i::Token::LPAREN: {
|
|
994 |
case Token::LPAREN: { |
|
1017 | 995 |
ParseArguments(CHECK_OK); |
1018 | 996 |
result = Expression::Default(); |
1019 | 997 |
break; |
1020 | 998 |
} |
1021 | 999 |
|
1022 |
case i::Token::PERIOD: {
|
|
1023 |
Consume(i::Token::PERIOD);
|
|
1000 |
case Token::PERIOD: { |
|
1001 |
Consume(Token::PERIOD); |
|
1024 | 1002 |
ParseIdentifierName(CHECK_OK); |
1025 | 1003 |
if (result.IsThis()) { |
1026 | 1004 |
result = Expression::ThisProperty(); |
... | ... | |
1051 | 1029 |
// lists as long as it has 'new' prefixes left |
1052 | 1030 |
unsigned new_count = 0; |
1053 | 1031 |
do { |
1054 |
Consume(i::Token::NEW);
|
|
1032 |
Consume(Token::NEW); |
|
1055 | 1033 |
new_count++; |
1056 |
} while (peek() == i::Token::NEW);
|
|
1034 |
} while (peek() == Token::NEW); |
|
1057 | 1035 |
|
1058 | 1036 |
return ParseMemberWithNewPrefixesExpression(new_count, ok); |
1059 | 1037 |
} |
... | ... | |
1072 | 1050 |
|
1073 | 1051 |
// Parse the initial primary or function expression. |
1074 | 1052 |
Expression result = Expression::Default(); |
1075 |
if (peek() == i::Token::FUNCTION) {
|
|
1076 |
Consume(i::Token::FUNCTION);
|
|
1053 |
if (peek() == Token::FUNCTION) { |
|
1054 |
Consume(Token::FUNCTION); |
|
1077 | 1055 |
|
1078 |
bool is_generator = allow_generators_ && Check(i::Token::MUL);
|
|
1056 |
bool is_generator = allow_generators() && Check(Token::MUL);
|
|
1079 | 1057 |
Identifier identifier = Identifier::Default(); |
1080 | 1058 |
if (peek_any_identifier()) { |
1081 | 1059 |
identifier = ParseIdentifier(CHECK_OK); |
1082 | 1060 |
} |
1083 | 1061 |
result = ParseFunctionLiteral(is_generator, CHECK_OK); |
1084 | 1062 |
if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) { |
1085 |
StrictModeIdentifierViolation(scanner_->location(),
|
|
1063 |
StrictModeIdentifierViolation(scanner()->location(),
|
|
1086 | 1064 |
"strict_function_name", |
1087 | 1065 |
identifier, |
1088 | 1066 |
ok); |
... | ... | |
1094 | 1072 |
|
1095 | 1073 |
while (true) { |
1096 | 1074 |
switch (peek()) { |
1097 |
case i::Token::LBRACK: {
|
|
1098 |
Consume(i::Token::LBRACK);
|
|
1075 |
case Token::LBRACK: { |
|
1076 |
Consume(Token::LBRACK); |
|
1099 | 1077 |
ParseExpression(true, CHECK_OK); |
1100 |
Expect(i::Token::RBRACK, CHECK_OK);
|
|
1078 |
Expect(Token::RBRACK, CHECK_OK); |
|
1101 | 1079 |
if (result.IsThis()) { |
1102 | 1080 |
result = Expression::ThisProperty(); |
1103 | 1081 |
} else { |
... | ... | |
1105 | 1083 |
} |
1106 | 1084 |
break; |
1107 | 1085 |
} |
1108 |
case i::Token::PERIOD: {
|
|
1109 |
Consume(i::Token::PERIOD);
|
|
1086 |
case Token::PERIOD: { |
|
1087 |
Consume(Token::PERIOD); |
|
1110 | 1088 |
ParseIdentifierName(CHECK_OK); |
1111 | 1089 |
if (result.IsThis()) { |
1112 | 1090 |
result = Expression::ThisProperty(); |
... | ... | |
1115 | 1093 |
} |
1116 | 1094 |
break; |
1117 | 1095 |
} |
1118 |
case i::Token::LPAREN: {
|
|
1096 |
case Token::LPAREN: { |
|
1119 | 1097 |
if (new_count == 0) return result; |
1120 | 1098 |
// Consume one of the new prefixes (already parsed). |
1121 | 1099 |
ParseArguments(CHECK_OK); |
... | ... | |
1146 | 1124 |
|
1147 | 1125 |
Expression result = Expression::Default(); |
1148 | 1126 |
switch (peek()) { |
1149 |
case i::Token::THIS: {
|
|
1127 |
case Token::THIS: { |
|
1150 | 1128 |
Next(); |
1151 | 1129 |
result = Expression::This(); |
1152 | 1130 |
break; |
1153 | 1131 |
} |
1154 | 1132 |
|
1155 |
case i::Token::FUTURE_RESERVED_WORD:
|
|
1156 |
case i::Token::FUTURE_STRICT_RESERVED_WORD:
|
|
1157 |
case i::Token::YIELD:
|
|
1158 |
case i::Token::IDENTIFIER: {
|
|
1133 |
case Token::FUTURE_RESERVED_WORD: |
|
1134 |
case Token::FUTURE_STRICT_RESERVED_WORD: |
|
1135 |
case Token::YIELD: |
|
1136 |
case Token::IDENTIFIER: { |
|
1159 | 1137 |
Identifier id = ParseIdentifier(CHECK_OK); |
1160 | 1138 |
result = Expression::FromIdentifier(id); |
1161 | 1139 |
break; |
1162 | 1140 |
} |
1163 | 1141 |
|
1164 |
case i::Token::NULL_LITERAL:
|
|
1165 |
case i::Token::TRUE_LITERAL:
|
|
1166 |
case i::Token::FALSE_LITERAL:
|
|
1167 |
case i::Token::NUMBER: {
|
|
1142 |
case Token::NULL_LITERAL: |
|
1143 |
case Token::TRUE_LITERAL: |
|
1144 |
case Token::FALSE_LITERAL: |
|
1145 |
case Token::NUMBER: { |
|
1168 | 1146 |
Next(); |
1169 | 1147 |
break; |
1170 | 1148 |
} |
1171 |
case i::Token::STRING: {
|
|
1149 |
case Token::STRING: { |
|
1172 | 1150 |
Next(); |
1173 | 1151 |
result = GetStringSymbol(); |
1174 | 1152 |
break; |
1175 | 1153 |
} |
1176 | 1154 |
|
1177 |
case i::Token::ASSIGN_DIV:
|
|
1155 |
case Token::ASSIGN_DIV: |
|
1178 | 1156 |
result = ParseRegExpLiteral(true, CHECK_OK); |
1179 | 1157 |
break; |
1180 | 1158 |
|
1181 |
case i::Token::DIV:
|
|
1159 |
case Token::DIV: |
|
1182 | 1160 |
result = ParseRegExpLiteral(false, CHECK_OK); |
1183 | 1161 |
break; |
1184 | 1162 |
|
1185 |
case i::Token::LBRACK:
|
|
1163 |
case Token::LBRACK: |
|
1186 | 1164 |
result = ParseArrayLiteral(CHECK_OK); |
1187 | 1165 |
break; |
1188 | 1166 |
|
1189 |
case i::Token::LBRACE:
|
|
1167 |
case Token::LBRACE: |
|
1190 | 1168 |
result = ParseObjectLiteral(CHECK_OK); |
1191 | 1169 |
break; |
1192 | 1170 |
|
1193 |
case i::Token::LPAREN:
|
|
1194 |
Consume(i::Token::LPAREN);
|
|
1195 |
parenthesized_function_ = (peek() == i::Token::FUNCTION);
|
|
1171 |
case Token::LPAREN: |
|
1172 |
Consume(Token::LPAREN); |
|
1173 |
parenthesized_function_ = (peek() == Token::FUNCTION); |
|
1196 | 1174 |
result = ParseExpression(true, CHECK_OK); |
1197 |
Expect(i::Token::RPAREN, CHECK_OK);
|
|
1175 |
Expect(Token::RPAREN, CHECK_OK); |
|
1198 | 1176 |
result = result.Parenthesize(); |
1199 | 1177 |
break; |
1200 | 1178 |
|
1201 |
case i::Token::MOD:
|
|
1179 |
case Token::MOD: |
|
1202 | 1180 |
result = ParseV8Intrinsic(CHECK_OK); |
1203 | 1181 |
break; |
1204 | 1182 |
|
... | ... | |
1216 | 1194 |
PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) { |
1217 | 1195 |
// ArrayLiteral :: |
1218 | 1196 |
// '[' Expression? (',' Expression?)* ']' |
1219 |
Expect(i::Token::LBRACK, CHECK_OK);
|
|
1220 |
while (peek() != i::Token::RBRACK) {
|
|
1221 |
if (peek() != i::Token::COMMA) {
|
|
1197 |
Expect(Token::LBRACK, CHECK_OK); |
|
1198 |
while (peek() != Token::RBRACK) { |
|
1199 |
if (peek() != Token::COMMA) { |
|
1222 | 1200 |
ParseAssignmentExpression(true, CHECK_OK); |
1223 | 1201 |
} |
1224 |
if (peek() != i::Token::RBRACK) {
|
|
1225 |
Expect(i::Token::COMMA, CHECK_OK);
|
|
1202 |
if (peek() != Token::RBRACK) { |
|
1203 |
Expect(Token::COMMA, CHECK_OK); |
|
1226 | 1204 |
} |
1227 | 1205 |
} |
1228 |
Expect(i::Token::RBRACK, CHECK_OK);
|
|
1206 |
Expect(Token::RBRACK, CHECK_OK); |
|
1229 | 1207 |
|
1230 | 1208 |
scope_->NextMaterializedLiteralIndex(); |
1231 | 1209 |
return Expression::Default(); |
1232 | 1210 |
} |
1233 | 1211 |
|
1234 |
void PreParser::CheckDuplicate(DuplicateFinder* finder, |
|
1235 |
i::Token::Value property, |
|
1236 |
int type, |
|
1237 |
bool* ok) { |
|
1238 |
int old_type; |
|
1239 |
if (property == i::Token::NUMBER) { |
|
1240 |
old_type = finder->AddNumber(scanner_->literal_ascii_string(), type); |
|
1241 |
} else if (scanner_->is_literal_ascii()) { |
|
1242 |
old_type = finder->AddAsciiSymbol(scanner_->literal_ascii_string(), |
|
1243 |
type); |
|
1244 |
} else { |
|
1245 |
old_type = finder->AddUtf16Symbol(scanner_->literal_utf16_string(), type); |
|
1246 |
} |
|
1247 |
if (HasConflict(old_type, type)) { |
|
1248 |
if (IsDataDataConflict(old_type, type)) { |
|
1249 |
// Both are data properties. |
|
1250 |
if (is_classic_mode()) return; |
|
1251 |
ReportMessageAt(scanner_->location(), |
|
1252 |
"strict_duplicate_property", NULL); |
|
1253 |
} else if (IsDataAccessorConflict(old_type, type)) { |
|
1254 |
// Both a data and an accessor property with the same name. |
|
1255 |
ReportMessageAt(scanner_->location(), |
|
1256 |
"accessor_data_property", NULL); |
|
1257 |
} else { |
|
1258 |
ASSERT(IsAccessorAccessorConflict(old_type, type)); |
|
1259 |
// Both accessors of the same type. |
|
1260 |
ReportMessageAt(scanner_->location(), |
|
1261 |
"accessor_get_set", NULL); |
|
1262 |
} |
|
1263 |
*ok = false; |
|
1264 |
} |
|
1265 |
} |
|
1266 |
|
|
1267 | 1212 |
|
1268 | 1213 |
PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { |
1269 | 1214 |
// ObjectLiteral :: |
... | ... | |
1272 | 1217 |
// | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
1273 | 1218 |
// )*[','] '}' |
1274 | 1219 |
|
1275 |
Expect(i::Token::LBRACE, CHECK_OK); |
|
1276 |
DuplicateFinder duplicate_finder(scanner_->unicode_cache()); |
|
1277 |
while (peek() != i::Token::RBRACE) { |
|
1278 |
i::Token::Value next = peek(); |
|
1220 |
ObjectLiteralChecker checker(this, language_mode()); |
|
1221 |
|
|
1222 |
Expect(Token::LBRACE, CHECK_OK); |
|
1223 |
while (peek() != Token::RBRACE) { |
|
1224 |
Token::Value next = peek(); |
|
1279 | 1225 |
switch (next) { |
1280 |
case i::Token::IDENTIFIER:
|
|
1281 |
case i::Token::FUTURE_RESERVED_WORD:
|
|
1282 |
case i::Token::FUTURE_STRICT_RESERVED_WORD: {
|
|
1226 |
case Token::IDENTIFIER: |
|
1227 |
case Token::FUTURE_RESERVED_WORD: |
|
1228 |
case Token::FUTURE_STRICT_RESERVED_WORD: { |
|
1283 | 1229 |
bool is_getter = false; |
1284 | 1230 |
bool is_setter = false; |
1285 | 1231 |
ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
1286 |
if ((is_getter || is_setter) && peek() != i::Token::COLON) {
|
|
1287 |
i::Token::Value name = Next();
|
|
1288 |
bool is_keyword = i::Token::IsKeyword(name);
|
|
1289 |
if (name != i::Token::IDENTIFIER &&
|
|
1290 |
name != i::Token::FUTURE_RESERVED_WORD &&
|
|
1291 |
name != i::Token::FUTURE_STRICT_RESERVED_WORD &&
|
|
1292 |
name != i::Token::NUMBER &&
|
|
1293 |
name != i::Token::STRING &&
|
|
1232 |
if ((is_getter || is_setter) && peek() != Token::COLON) { |
|
1233 |
Token::Value name = Next(); |
|
1234 |
bool is_keyword = Token::IsKeyword(name); |
|
1235 |
if (name != Token::IDENTIFIER && |
|
1236 |
name != Token::FUTURE_RESERVED_WORD && |
|
1237 |
name != Token::FUTURE_STRICT_RESERVED_WORD && |
|
1238 |
name != Token::NUMBER && |
|
1239 |
name != Token::STRING && |
|
1294 | 1240 |
!is_keyword) { |
1295 | 1241 |
*ok = false; |
1296 | 1242 |
return Expression::Default(); |
... | ... | |
1298 | 1244 |
if (!is_keyword) { |
1299 | 1245 |
LogSymbol(); |
1300 | 1246 |
} |
1301 |
PropertyType type = is_getter ? kGetterProperty : kSetterProperty;
|
|
1302 |
CheckDuplicate(&duplicate_finder, name, type, CHECK_OK);
|
|
1247 |
PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
|
|
1248 |
checker.CheckProperty(name, type, CHECK_OK);
|
|
1303 | 1249 |
ParseFunctionLiteral(false, CHECK_OK); |
1304 |
if (peek() != i::Token::RBRACE) {
|
|
1305 |
Expect(i::Token::COMMA, CHECK_OK);
|
|
1250 |
if (peek() != Token::RBRACE) { |
|
1251 |
Expect(Token::COMMA, CHECK_OK); |
|
1306 | 1252 |
} |
1307 | 1253 |
continue; // restart the while |
1308 | 1254 |
} |
1309 |
CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
|
|
1255 |
checker.CheckProperty(next, kValueProperty, CHECK_OK);
|
|
1310 | 1256 |
break; |
1311 | 1257 |
} |
1312 |
case i::Token::STRING:
|
|
1258 |
case Token::STRING: |
|
1313 | 1259 |
Consume(next); |
1314 |
CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
|
|
1260 |
checker.CheckProperty(next, kValueProperty, CHECK_OK);
|
|
1315 | 1261 |
GetStringSymbol(); |
1316 | 1262 |
break; |
1317 |
case i::Token::NUMBER:
|
|
1263 |
case Token::NUMBER: |
|
1318 | 1264 |
Consume(next); |
1319 |
CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
|
|
1265 |
checker.CheckProperty(next, kValueProperty, CHECK_OK);
|
|
1320 | 1266 |
break; |
1321 | 1267 |
default: |
1322 |
if (i::Token::IsKeyword(next)) {
|
|
1268 |
if (Token::IsKeyword(next)) { |
|
1323 | 1269 |
Consume(next); |
1324 |
CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
|
|
1270 |
checker.CheckProperty(next, kValueProperty, CHECK_OK);
|
|
1325 | 1271 |
} else { |
1326 | 1272 |
// Unexpected token. |
1327 | 1273 |
*ok = false; |
... | ... | |
1329 | 1275 |
} |
1330 | 1276 |
} |
1331 | 1277 |
|
1332 |
Expect(i::Token::COLON, CHECK_OK);
|
|
1278 |
Expect(Token::COLON, CHECK_OK); |
|
1333 | 1279 |
ParseAssignmentExpression(true, CHECK_OK); |
1334 | 1280 |
|
1335 | 1281 |
// TODO(1240767): Consider allowing trailing comma. |
1336 |
if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
|
|
1282 |
if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
|
|
1337 | 1283 |
} |
1338 |
Expect(i::Token::RBRACE, CHECK_OK);
|
|
1284 |
Expect(Token::RBRACE, CHECK_OK); |
|
1339 | 1285 |
|
1340 | 1286 |
scope_->NextMaterializedLiteralIndex(); |
1341 | 1287 |
return Expression::Default(); |
... | ... | |
1344 | 1290 |
|
1345 | 1291 |
PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal, |
1346 | 1292 |
bool* ok) { |
1347 |
if (!scanner_->ScanRegExpPattern(seen_equal)) {
|
|
1293 |
if (!scanner()->ScanRegExpPattern(seen_equal)) {
|
|
1348 | 1294 |
Next(); |
1349 |
ReportMessageAt(scanner_->location(), "unterminated_regexp", NULL);
|
|
1295 |
ReportMessageAt(scanner()->location(), "unterminated_regexp", NULL);
|
|
1350 | 1296 |
*ok = false; |
1351 | 1297 |
return Expression::Default(); |
1352 | 1298 |
} |
1353 | 1299 |
|
1354 | 1300 |
scope_->NextMaterializedLiteralIndex(); |
1355 | 1301 |
|
1356 |
if (!scanner_->ScanRegExpFlags()) {
|
|
1302 |
if (!scanner()->ScanRegExpFlags()) {
|
|
1357 | 1303 |
Next(); |
1358 |
ReportMessageAt(scanner_->location(), "invalid_regexp_flags", NULL);
|
|
1304 |
ReportMessageAt(scanner()->location(), "invalid_regexp_flags", NULL);
|
|
1359 | 1305 |
*ok = false; |
1360 | 1306 |
return Expression::Default(); |
1361 | 1307 |
} |
... | ... | |
1368 | 1314 |
// Arguments :: |
1369 | 1315 |
// '(' (AssignmentExpression)*[','] ')' |
1370 | 1316 |
|
1371 |
Expect(i::Token::LPAREN, ok);
|
|
1317 |
Expect(Token::LPAREN, ok); |
|
1372 | 1318 |
if (!*ok) return -1; |
1373 |
bool done = (peek() == i::Token::RPAREN);
|
|
1319 |
bool done = (peek() == Token::RPAREN); |
|
1374 | 1320 |
int argc = 0; |
1375 | 1321 |
while (!done) { |
1376 | 1322 |
ParseAssignmentExpression(true, ok); |
1377 | 1323 |
if (!*ok) return -1; |
1378 | 1324 |
argc++; |
1379 |
done = (peek() == i::Token::RPAREN);
|
|
1325 |
done = (peek() == Token::RPAREN); |
|
1380 | 1326 |
if (!done) { |
1381 |
Expect(i::Token::COMMA, ok);
|
|
1327 |
Expect(Token::COMMA, ok); |
|
1382 | 1328 |
if (!*ok) return -1; |
1383 | 1329 |
} |
1384 | 1330 |
} |
1385 |
Expect(i::Token::RPAREN, ok);
|
|
1331 |
Expect(Token::RPAREN, ok); |
|
1386 | 1332 |
return argc; |
1387 | 1333 |
} |
1388 | 1334 |
|
... | ... | |
1399 | 1345 |
function_scope.set_is_generator(is_generator); |
1400 | 1346 |
// FormalParameterList :: |
1401 | 1347 |
// '(' (Identifier)*[','] ')' |
1402 |
Expect(i::Token::LPAREN, CHECK_OK);
|
|
1403 |
int start_position = scanner_->location().beg_pos;
|
|
1404 |
bool done = (peek() == i::Token::RPAREN);
|
|
1405 |
DuplicateFinder duplicate_finder(scanner_->unicode_cache());
|
|
1348 |
Expect(Token::LPAREN, CHECK_OK); |
|
1349 |
int start_position = position();
|
|
1350 |
bool done = (peek() == Token::RPAREN); |
|
1351 |
DuplicateFinder duplicate_finder(scanner()->unicode_cache());
|
|
1406 | 1352 |
while (!done) { |
1407 | 1353 |
Identifier id = ParseIdentifier(CHECK_OK); |
1408 | 1354 |
if (!id.IsValidStrictVariable()) { |
1409 |
StrictModeIdentifierViolation(scanner_->location(),
|
|
1355 |
StrictModeIdentifierViolation(scanner()->location(),
|
|
1410 | 1356 |
"strict_param_name", |
1411 | 1357 |
id, |
1412 | 1358 |
CHECK_OK); |
1413 | 1359 |
} |
1414 | 1360 |
int prev_value; |
1415 |
if (scanner_->is_literal_ascii()) {
|
|
1361 |
if (scanner()->is_literal_ascii()) {
|
|
1416 | 1362 |
prev_value = |
1417 |
duplicate_finder.AddAsciiSymbol(scanner_->literal_ascii_string(), 1);
|
|
1363 |
duplicate_finder.AddAsciiSymbol(scanner()->literal_ascii_string(), 1);
|
|
1418 | 1364 |
} else { |
1419 | 1365 |
prev_value = |
1420 |
duplicate_finder.AddUtf16Symbol(scanner_->literal_utf16_string(), 1);
|
|
1366 |
duplicate_finder.AddUtf16Symbol(scanner()->literal_utf16_string(), 1);
|
|
1421 | 1367 |
} |
1422 | 1368 |
|
1423 | 1369 |
if (prev_value != 0) { |
1424 |
SetStrictModeViolation(scanner_->location(),
|
|
1370 |
SetStrictModeViolation(scanner()->location(),
|
|
1425 | 1371 |
"strict_param_dupe", |
1426 | 1372 |
CHECK_OK); |
1427 | 1373 |
} |
1428 |
done = (peek() == i::Token::RPAREN);
|
|
1374 |
done = (peek() == Token::RPAREN); |
|
1429 | 1375 |
if (!done) { |
1430 |
Expect(i::Token::COMMA, CHECK_OK);
|
|
1376 |
Expect(Token::COMMA, CHECK_OK); |
|
1431 | 1377 |
} |
1432 | 1378 |
} |
1433 |
Expect(i::Token::RPAREN, CHECK_OK);
|
|
1379 |
Expect(Token::RPAREN, CHECK_OK); |
|
1434 | 1380 |
|
1435 | 1381 |
// Determine if the function will be lazily compiled. |
1436 | 1382 |
// Currently only happens to top-level functions. |
1437 | 1383 |
// Optimistically assume that all top-level functions are lazily compiled. |
1438 | 1384 |
bool is_lazily_compiled = (outer_scope_type == kTopLevelScope && |
1439 |
!inside_with && allow_lazy_ &&
|
|
1385 |
!inside_with && allow_lazy() &&
|
|
1440 | 1386 |
!parenthesized_function_); |
1441 | 1387 |
parenthesized_function_ = false; |
1442 | 1388 |
|
1443 |
Expect(i::Token::LBRACE, CHECK_OK);
|
|
1389 |
Expect(Token::LBRACE, CHECK_OK); |
|
1444 | 1390 |
if (is_lazily_compiled) { |
1445 | 1391 |
ParseLazyFunctionLiteralBody(CHECK_OK); |
1446 | 1392 |
} else { |
1447 |
ParseSourceElements(i::Token::RBRACE, ok);
|
|
1393 |
ParseSourceElements(Token::RBRACE, ok); |
|
1448 | 1394 |
} |
1449 |
Expect(i::Token::RBRACE, CHECK_OK);
|
|
1395 |
Expect(Token::RBRACE, CHECK_OK); |
|
1450 | 1396 |
|
1451 | 1397 |
if (!is_classic_mode()) { |
1452 |
int end_position = scanner_->location().end_pos;
|
|
1398 |
int end_position = scanner()->location().end_pos;
|
|
1453 | 1399 |
CheckOctalLiteral(start_position, end_position, CHECK_OK); |
1454 | 1400 |
CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK); |
1455 | 1401 |
return Expression::StrictFunction(); |
... | ... | |
1460 | 1406 |
|
1461 | 1407 |
|
1462 | 1408 |
void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { |
1463 |
int body_start = scanner_->location().beg_pos;
|
|
1409 |
int body_start = position();
|
|
1464 | 1410 |
log_->PauseRecording(); |
1465 |
ParseSourceElements(i::Token::RBRACE, ok);
|
|
1411 |
ParseSourceElements(Token::RBRACE, ok); |
|
1466 | 1412 |
log_->ResumeRecording(); |
1467 | 1413 |
if (!*ok) return; |
1468 | 1414 |
|
1469 | 1415 |
// Position right after terminal '}'. |
1470 |
ASSERT_EQ(i::Token::RBRACE, scanner_->peek());
|
|
1471 |
int body_end = scanner_->peek_location().end_pos;
|
|
1416 |
ASSERT_EQ(Token::RBRACE, scanner()->peek());
|
|
1417 |
int body_end = scanner()->peek_location().end_pos;
|
|
1472 | 1418 |
log_->LogFunction(body_start, body_end, |
1473 | 1419 |
scope_->materialized_literal_count(), |
1474 | 1420 |
scope_->expected_properties(), |
... | ... | |
1479 | 1425 |
PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { |
1480 | 1426 |
// CallRuntime :: |
1481 | 1427 |
// '%' Identifier Arguments |
1482 |
Expect(i::Token::MOD, CHECK_OK);
|
|
1483 |
if (!allow_natives_syntax_) {
|
|
1428 |
Expect(Token::MOD, CHECK_OK); |
|
1429 |
if (!allow_natives_syntax()) {
|
|
1484 | 1430 |
*ok = false; |
1485 | 1431 |
return Expression::Default(); |
1486 | 1432 |
} |
... | ... | |
1493 | 1439 |
#undef CHECK_OK |
1494 | 1440 |
|
1495 | 1441 |
|
1496 |
void PreParser::ExpectSemicolon(bool* ok) { |
|
1497 |
// Check for automatic semicolon insertion according to |
|
1498 |
// the rules given in ECMA-262, section 7.9, page 21. |
|
1499 |
i::Token::Value tok = peek(); |
|
1500 |
if (tok == i::Token::SEMICOLON) { |
|
1501 |
Next(); |
|
1502 |
return; |
|
1503 |
} |
|
1504 |
if (scanner_->HasAnyLineTerminatorBeforeNext() || |
|
1505 |
tok == i::Token::RBRACE || |
|
1506 |
tok == i::Token::EOS) { |
|
1507 |
return; |
|
1508 |
} |
|
1509 |
Expect(i::Token::SEMICOLON, ok); |
|
1510 |
} |
|
1511 |
|
|
1512 |
|
|
1513 | 1442 |
void PreParser::LogSymbol() { |
1514 |
int identifier_pos = scanner_->location().beg_pos;
|
|
1515 |
if (scanner_->is_literal_ascii()) {
|
|
1516 |
log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
|
|
1443 |
int identifier_pos = position();
|
|
1444 |
if (scanner()->is_literal_ascii()) {
|
|
1445 |
log_->LogAsciiSymbol(identifier_pos, scanner()->literal_ascii_string());
|
|
1517 | 1446 |
} else { |
1518 |
log_->LogUtf16Symbol(identifier_pos, scanner_->literal_utf16_string());
|
|
1447 |
log_->LogUtf16Symbol(identifier_pos, scanner()->literal_utf16_string());
|
|
1519 | 1448 |
} |
1520 | 1449 |
} |
1521 | 1450 |
|
... | ... | |
1524 | 1453 |
const int kUseStrictLength = 10; |
1525 | 1454 |
const char* kUseStrictChars = "use strict"; |
1526 | 1455 |
LogSymbol(); |
1527 |
if (scanner_->is_literal_ascii() &&
|
|
1528 |
scanner_->literal_length() == kUseStrictLength &&
|
|
1529 |
!scanner_->literal_contains_escapes() &&
|
|
1530 |
!strncmp(scanner_->literal_ascii_string().start(), kUseStrictChars,
|
|
1456 |
if (scanner()->is_literal_ascii() &&
|
|
1457 |
scanner()->literal_length() == kUseStrictLength &&
|
|
1458 |
!scanner()->literal_contains_escapes() &&
|
|
1459 |
!strncmp(scanner()->literal_ascii_string().start(), kUseStrictChars,
|
|
1531 | 1460 |
kUseStrictLength)) { |
1532 | 1461 |
return Expression::UseStrictStringLiteral(); |
1533 | 1462 |
} |
... | ... | |
1537 | 1466 |
|
1538 | 1467 |
PreParser::Identifier PreParser::GetIdentifierSymbol() { |
1539 | 1468 |
LogSymbol(); |
1540 |
if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) {
|
|
1469 |
if (scanner()->current_token() == Token::FUTURE_RESERVED_WORD) {
|
|
1541 | 1470 |
return Identifier::FutureReserved(); |
1542 |
} else if (scanner_->current_token() ==
|
|
1543 |
i::Token::FUTURE_STRICT_RESERVED_WORD) {
|
|
1471 |
} else if (scanner()->current_token() ==
|
|
1472 |
Token::FUTURE_STRICT_RESERVED_WORD) { |
|
1544 | 1473 |
return Identifier::FutureStrictReserved(); |
1545 |
} else if (scanner_->current_token() == i::Token::YIELD) {
|
|
1474 |
} else if (scanner()->current_token() == Token::YIELD) {
|
|
1546 | 1475 |
return Identifier::Yield(); |
1547 | 1476 |
} |
1548 |
if (scanner_->is_literal_ascii()) {
|
|
1477 |
if (scanner()->is_literal_ascii()) {
|
|
1549 | 1478 |
// Detect strict-mode poison words. |
1550 |
if (scanner_->literal_length() == 4 &&
|
|
1551 |
!strncmp(scanner_->literal_ascii_string().start(), "eval", 4)) {
|
|
1479 |
if (scanner()->literal_length() == 4 &&
|
|
1480 |
!strncmp(scanner()->literal_ascii_string().start(), "eval", 4)) {
|
|
1552 | 1481 |
return Identifier::Eval(); |
1553 | 1482 |
} |
1554 |
if (scanner_->literal_length() == 9 &&
|
|
1555 |
!strncmp(scanner_->literal_ascii_string().start(), "arguments", 9)) {
|
|
1483 |
if (scanner()->literal_length() == 9 &&
|
|
1484 |
!strncmp(scanner()->literal_ascii_string().start(), "arguments", 9)) {
|
|
1556 | 1485 |
return Identifier::Arguments(); |
1557 | 1486 |
} |
1558 | 1487 |
} |
... | ... | |
1561 | 1490 |
|
1562 | 1491 |
|
1563 | 1492 |
PreParser::Identifier PreParser::ParseIdentifier(bool* ok) { |
1564 |
i::Token::Value next = Next();
|
|
1493 |
Token::Value next = Next(); |
|
1565 | 1494 |
switch (next) { |
1566 |
case i::Token::FUTURE_RESERVED_WORD: {
|
|
1567 |
i::Scanner::Location location = scanner_->location();
|
|
1495 |
case Token::FUTURE_RESERVED_WORD: { |
|
1496 |
Scanner::Location location = scanner()->location();
|
|
1568 | 1497 |
ReportMessageAt(location.beg_pos, location.end_pos, |
1569 | 1498 |
"reserved_word", NULL); |
1570 | 1499 |
*ok = false; |
1571 | 1500 |
return GetIdentifierSymbol(); |
1572 | 1501 |
} |
1573 |
case i::Token::YIELD:
|
|
1502 |
case Token::YIELD: |
|
1574 | 1503 |
if (scope_->is_generator()) { |
1575 | 1504 |
// 'yield' in a generator is only valid as part of a YieldExpression. |
1576 |
ReportMessageAt(scanner_->location(), "unexpected_token", "yield");
|
|
1505 |
ReportMessageAt(scanner()->location(), "unexpected_token", "yield");
|
|
1577 | 1506 |
*ok = false; |
1578 | 1507 |
return Identifier::Yield(); |
1579 | 1508 |
} |
1580 | 1509 |
// FALLTHROUGH |
1581 |
case i::Token::FUTURE_STRICT_RESERVED_WORD:
|
|
1510 |
case Token::FUTURE_STRICT_RESERVED_WORD: |
|
1582 | 1511 |
if (!is_classic_mode()) { |
1583 |
i::Scanner::Location location = scanner_->location();
|
|
1512 |
Scanner::Location location = scanner()->location();
|
|
1584 | 1513 |
ReportMessageAt(location.beg_pos, location.end_pos, |
1585 | 1514 |
"strict_reserved_word", NULL); |
1586 | 1515 |
*ok = false; |
1587 | 1516 |
} |
1588 | 1517 |
// FALLTHROUGH |
1589 |
case i::Token::IDENTIFIER:
|
|
1518 |
case Token::IDENTIFIER: |
|
1590 | 1519 |
return GetIdentifierSymbol(); |
1591 | 1520 |
default: |
1592 | 1521 |
*ok = false; |
... | ... | |
1595 | 1524 |
} |
1596 | 1525 |
|
1597 | 1526 |
|
1598 |
void PreParser::SetStrictModeViolation(i::Scanner::Location location,
|
|
1527 |
void PreParser::SetStrictModeViolation(Scanner::Location location, |
|
1599 | 1528 |
const char* type, |
1600 | 1529 |
bool* ok) { |
1601 | 1530 |
if (!is_classic_mode()) { |
... | ... | |
1619 | 1548 |
void PreParser::CheckDelayedStrictModeViolation(int beg_pos, |
1620 | 1549 |
int end_pos, |
1621 | 1550 |
bool* ok) { |
1622 |
i::Scanner::Location location = strict_mode_violation_location_;
|
|
1551 |
Scanner::Location location = strict_mode_violation_location_; |
|
1623 | 1552 |
if (location.IsValid() && |
1624 | 1553 |
location.beg_pos > beg_pos && location.end_pos < end_pos) { |
1625 | 1554 |
ReportMessageAt(location, strict_mode_violation_type_, NULL); |
... | ... | |
1628 | 1557 |
} |
1629 | 1558 |
|
1630 | 1559 |
|
1631 |
void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
|
|
1560 |
void PreParser::StrictModeIdentifierViolation(Scanner::Location location, |
|
1632 | 1561 |
const char* eval_args_type, |
1633 | 1562 |
Identifier identifier, |
1634 | 1563 |
bool* ok) { |
... | ... | |
1649 | 1578 |
|
1650 | 1579 |
|
1651 | 1580 |
PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { |
1652 |
i::Token::Value next = Next(); |
|
1653 |
if (i::Token::IsKeyword(next)) { |
|
1654 |
int pos = scanner_->location().beg_pos; |
|
1655 |
const char* keyword = i::Token::String(next); |
|
1656 |
log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword, |
|
1657 |
i::StrLength(keyword))); |
|
1581 |
Token::Value next = Next(); |
|
1582 |
if (Token::IsKeyword(next)) { |
|
1583 |
int pos = position(); |
|
1584 |
const char* keyword = Token::String(next); |
|
1585 |
log_->LogAsciiSymbol(pos, Vector<const char>(keyword, StrLength(keyword))); |
|
1658 | 1586 |
return Identifier::Default(); |
1659 | 1587 |
} |
1660 |
if (next == i::Token::IDENTIFIER || |
|
1661 |
next == i::Token::FUTURE_RESERVED_WORD || |
|
1662 |
next == i::Token::FUTURE_STRICT_RESERVED_WORD) { |
|
1588 |
if (next == Token::IDENTIFIER || |
Also available in: Unified diff