blob: da1c35bcc0660e2bd7e52870f7cebd94bfbdec73 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2011 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <cmath>
6
7#include "src/allocation.h"
8#include "src/base/logging.h"
9#include "src/conversions-inl.h"
10#include "src/conversions.h"
11#include "src/globals.h"
12#include "src/hashmap.h"
13#include "src/list.h"
14#include "src/parsing/parser-base.h"
15#include "src/parsing/preparse-data.h"
16#include "src/parsing/preparse-data-format.h"
17#include "src/parsing/preparser.h"
18#include "src/unicode.h"
19#include "src/utils.h"
20
21namespace v8 {
22namespace internal {
23
24void PreParserTraits::ReportMessageAt(Scanner::Location location,
25 MessageTemplate::Template message,
26 const char* arg,
27 ParseErrorType error_type) {
28 ReportMessageAt(location.beg_pos, location.end_pos, message, arg, error_type);
29}
30
31
32void PreParserTraits::ReportMessageAt(int start_pos, int end_pos,
33 MessageTemplate::Template message,
34 const char* arg,
35 ParseErrorType error_type) {
36 pre_parser_->log_->LogMessage(start_pos, end_pos, message, arg, error_type);
37}
38
39
40PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
41 if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) {
42 return PreParserIdentifier::FutureReserved();
43 } else if (scanner->current_token() ==
44 Token::FUTURE_STRICT_RESERVED_WORD) {
45 return PreParserIdentifier::FutureStrictReserved();
46 } else if (scanner->current_token() == Token::LET) {
47 return PreParserIdentifier::Let();
48 } else if (scanner->current_token() == Token::STATIC) {
49 return PreParserIdentifier::Static();
50 } else if (scanner->current_token() == Token::YIELD) {
51 return PreParserIdentifier::Yield();
52 }
53 if (scanner->UnescapedLiteralMatches("eval", 4)) {
54 return PreParserIdentifier::Eval();
55 }
56 if (scanner->UnescapedLiteralMatches("arguments", 9)) {
57 return PreParserIdentifier::Arguments();
58 }
59 if (scanner->UnescapedLiteralMatches("undefined", 9)) {
60 return PreParserIdentifier::Undefined();
61 }
62 if (scanner->LiteralMatches("prototype", 9)) {
63 return PreParserIdentifier::Prototype();
64 }
65 if (scanner->LiteralMatches("constructor", 11)) {
66 return PreParserIdentifier::Constructor();
67 }
68 return PreParserIdentifier::Default();
69}
70
71
72PreParserIdentifier PreParserTraits::GetNumberAsSymbol(Scanner* scanner) {
73 return PreParserIdentifier::Default();
74}
75
76
77PreParserExpression PreParserTraits::ExpressionFromString(
78 int pos, Scanner* scanner, PreParserFactory* factory) {
79 if (scanner->UnescapedLiteralMatches("use strict", 10)) {
80 return PreParserExpression::UseStrictStringLiteral();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 }
82 return PreParserExpression::StringLiteral();
83}
84
85
86PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
87 return pre_parser_->ParseV8Intrinsic(ok);
88}
89
90
91PreParserExpression PreParserTraits::ParseFunctionLiteral(
92 PreParserIdentifier name, Scanner::Location function_name_location,
93 FunctionNameValidity function_name_validity, FunctionKind kind,
94 int function_token_position, FunctionLiteral::FunctionType type,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000095 LanguageMode language_mode, bool* ok) {
96 return pre_parser_->ParseFunctionLiteral(
97 name, function_name_location, function_name_validity, kind,
Ben Murdoch097c5b22016-05-18 11:27:45 +010098 function_token_position, type, language_mode, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099}
100
101
102PreParser::PreParseResult PreParser::PreParseLazyFunction(
103 LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters,
104 ParserRecorder* log, Scanner::BookmarkScope* bookmark) {
105 log_ = log;
106 // Lazy functions always have trivial outer scopes (no with/catch scopes).
107 Scope* top_scope = NewScope(scope_, SCRIPT_SCOPE);
108 PreParserFactory top_factory(NULL);
109 FunctionState top_state(&function_state_, &scope_, top_scope, kNormalFunction,
110 &top_factory);
111 scope_->SetLanguageMode(language_mode);
112 Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind);
113 if (!has_simple_parameters) function_scope->SetHasNonSimpleParameters();
114 PreParserFactory function_factory(NULL);
115 FunctionState function_state(&function_state_, &scope_, function_scope, kind,
116 &function_factory);
117 DCHECK_EQ(Token::LBRACE, scanner()->current_token());
118 bool ok = true;
119 int start_position = peek_position();
120 ParseLazyFunctionLiteralBody(&ok, bookmark);
121 if (bookmark && bookmark->HasBeenReset()) {
122 // Do nothing, as we've just aborted scanning this function.
123 } else if (stack_overflow()) {
124 return kPreParseStackOverflow;
125 } else if (!ok) {
126 ReportUnexpectedToken(scanner()->current_token());
127 } else {
128 DCHECK_EQ(Token::RBRACE, scanner()->peek());
129 if (is_strict(scope_->language_mode())) {
130 int end_pos = scanner()->location().end_pos;
131 CheckStrictOctalLiteral(start_position, end_pos, &ok);
132 if (!ok) return kPreParseSuccess;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133 }
134 }
135 return kPreParseSuccess;
136}
137
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138PreParserExpression PreParserTraits::ParseClassLiteral(
Ben Murdochda12d292016-06-02 14:46:10 +0100139 Type::ExpressionClassifier* classifier, PreParserIdentifier name,
140 Scanner::Location class_name_location, bool name_is_strict_reserved,
141 int pos, bool* ok) {
142 return pre_parser_->ParseClassLiteral(classifier, name, class_name_location,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143 name_is_strict_reserved, pos, ok);
144}
145
146
147// Preparsing checks a JavaScript program and emits preparse-data that helps
148// a later parsing to be faster.
149// See preparser-data.h for the data.
150
151// The PreParser checks that the syntax follows the grammar for JavaScript,
152// and collects some information about the program along the way.
153// The grammar check is only performed in order to understand the program
154// sufficiently to deduce some information about it, that can be used
155// to speed up later parsing. Finding errors is not the goal of pre-parsing,
156// rather it is to speed up properly written and correct programs.
157// That means that contextual checks (like a label being declared where
158// it is used) are generally omitted.
159
160
161PreParser::Statement PreParser::ParseStatementListItem(bool* ok) {
162 // ECMA 262 6th Edition
163 // StatementListItem[Yield, Return] :
164 // Statement[?Yield, ?Return]
165 // Declaration[?Yield]
166 //
167 // Declaration[Yield] :
168 // HoistableDeclaration[?Yield]
169 // ClassDeclaration[?Yield]
170 // LexicalDeclaration[In, ?Yield]
171 //
172 // HoistableDeclaration[Yield, Default] :
173 // FunctionDeclaration[?Yield, ?Default]
174 // GeneratorDeclaration[?Yield, ?Default]
175 //
176 // LexicalDeclaration[In, Yield] :
177 // LetOrConst BindingList[?In, ?Yield] ;
178
179 switch (peek()) {
180 case Token::FUNCTION:
181 return ParseFunctionDeclaration(ok);
182 case Token::CLASS:
183 return ParseClassDeclaration(ok);
184 case Token::CONST:
185 if (allow_const()) {
186 return ParseVariableStatement(kStatementListItem, ok);
187 }
188 break;
189 case Token::LET:
190 if (IsNextLetKeyword()) {
191 return ParseVariableStatement(kStatementListItem, ok);
192 }
193 break;
194 default:
195 break;
196 }
Ben Murdochda12d292016-06-02 14:46:10 +0100197 return ParseStatement(kAllowLabelledFunctionStatement, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198}
199
200
201void PreParser::ParseStatementList(int end_token, bool* ok,
202 Scanner::BookmarkScope* bookmark) {
203 // SourceElements ::
204 // (Statement)* <end_token>
205
206 // Bookkeeping for trial parse if bookmark is set:
207 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet());
208 bool maybe_reset = bookmark != nullptr;
209 int count_statements = 0;
210
211 bool directive_prologue = true;
212 while (peek() != end_token) {
213 if (directive_prologue && peek() != Token::STRING) {
214 directive_prologue = false;
215 }
216 bool starts_with_identifier = peek() == Token::IDENTIFIER;
217 Scanner::Location token_loc = scanner()->peek_location();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 Statement statement = ParseStatementListItem(ok);
219 if (!*ok) return;
220
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000221 if (directive_prologue) {
222 bool use_strict_found = statement.IsUseStrictLiteral();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223
224 if (use_strict_found) {
225 scope_->SetLanguageMode(
226 static_cast<LanguageMode>(scope_->language_mode() | STRICT));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 } else if (!statement.IsStringLiteral()) {
228 directive_prologue = false;
229 }
230
Ben Murdochda12d292016-06-02 14:46:10 +0100231 if (use_strict_found && !scope_->HasSimpleParameters()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 // TC39 deemed "use strict" directives to be an error when occurring
233 // in the body of a function with non-simple parameter list, on
234 // 29/7/2015. https://goo.gl/ueA7Ln
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000235 PreParserTraits::ReportMessageAt(
236 token_loc, MessageTemplate::kIllegalLanguageModeDirective,
Ben Murdochda12d292016-06-02 14:46:10 +0100237 "use strict");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 *ok = false;
239 return;
240 }
241 }
242
243 // If we're allowed to reset to a bookmark, we will do so when we see a long
244 // and trivial function.
245 // Our current definition of 'long and trivial' is:
246 // - over 200 statements
247 // - all starting with an identifier (i.e., no if, for, while, etc.)
248 if (maybe_reset && (!starts_with_identifier ||
249 ++count_statements > kLazyParseTrialLimit)) {
250 if (count_statements > kLazyParseTrialLimit) {
251 bookmark->Reset();
252 return;
253 }
254 maybe_reset = false;
255 }
256 }
257}
258
259
260#define CHECK_OK ok); \
261 if (!*ok) return Statement::Default(); \
262 ((void)0
263#define DUMMY ) // to make indentation work
264#undef DUMMY
265
Ben Murdochda12d292016-06-02 14:46:10 +0100266PreParser::Statement PreParser::ParseStatement(
267 AllowLabelledFunctionStatement allow_function, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268 // Statement ::
269 // EmptyStatement
270 // ...
271
272 if (peek() == Token::SEMICOLON) {
273 Next();
274 return Statement::Default();
275 }
Ben Murdochda12d292016-06-02 14:46:10 +0100276 return ParseSubStatement(allow_function, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277}
278
Ben Murdochda12d292016-06-02 14:46:10 +0100279PreParser::Statement PreParser::ParseScopedStatement(bool legacy, bool* ok) {
280 if (is_strict(language_mode()) || peek() != Token::FUNCTION ||
281 (legacy && allow_harmony_restrictive_declarations())) {
282 return ParseSubStatement(kDisallowLabelledFunctionStatement, ok);
283 } else {
284 return ParseFunctionDeclaration(CHECK_OK);
285 }
286}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287
Ben Murdochda12d292016-06-02 14:46:10 +0100288PreParser::Statement PreParser::ParseSubStatement(
289 AllowLabelledFunctionStatement allow_function, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290 // Statement ::
291 // Block
292 // VariableStatement
293 // EmptyStatement
294 // ExpressionStatement
295 // IfStatement
296 // IterationStatement
297 // ContinueStatement
298 // BreakStatement
299 // ReturnStatement
300 // WithStatement
301 // LabelledStatement
302 // SwitchStatement
303 // ThrowStatement
304 // TryStatement
305 // DebuggerStatement
306
307 // Note: Since labels can only be used by 'break' and 'continue'
308 // statements, which themselves are only valid within blocks,
309 // iterations or 'switch' statements (i.e., BreakableStatements),
310 // labels can be simply ignored in all other cases; except for
311 // trivial labeled break statements 'label: break label' which is
312 // parsed into an empty statement.
313
314 // Keep the source position of the statement
315 switch (peek()) {
316 case Token::LBRACE:
317 return ParseBlock(ok);
318
319 case Token::SEMICOLON:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320 Next();
321 return Statement::Default();
322
323 case Token::IF:
324 return ParseIfStatement(ok);
325
326 case Token::DO:
327 return ParseDoWhileStatement(ok);
328
329 case Token::WHILE:
330 return ParseWhileStatement(ok);
331
332 case Token::FOR:
333 return ParseForStatement(ok);
334
335 case Token::CONTINUE:
336 return ParseContinueStatement(ok);
337
338 case Token::BREAK:
339 return ParseBreakStatement(ok);
340
341 case Token::RETURN:
342 return ParseReturnStatement(ok);
343
344 case Token::WITH:
345 return ParseWithStatement(ok);
346
347 case Token::SWITCH:
348 return ParseSwitchStatement(ok);
349
350 case Token::THROW:
351 return ParseThrowStatement(ok);
352
353 case Token::TRY:
354 return ParseTryStatement(ok);
355
Ben Murdochda12d292016-06-02 14:46:10 +0100356 case Token::FUNCTION:
357 // FunctionDeclaration only allowed as a StatementListItem, not in
358 // an arbitrary Statement position. Exceptions such as
359 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
360 // are handled by calling ParseScopedStatement rather than
361 // ParseSubStatement directly.
362 ReportMessageAt(scanner()->peek_location(),
363 is_strict(language_mode())
364 ? MessageTemplate::kStrictFunction
365 : MessageTemplate::kSloppyFunction);
366 *ok = false;
367 return Statement::Default();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000368
369 case Token::DEBUGGER:
370 return ParseDebuggerStatement(ok);
371
372 case Token::VAR:
373 return ParseVariableStatement(kStatement, ok);
374
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000375 default:
Ben Murdochda12d292016-06-02 14:46:10 +0100376 return ParseExpressionOrLabelledStatement(allow_function, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000377 }
378}
379
380
381PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
382 // FunctionDeclaration ::
383 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
384 // GeneratorDeclaration ::
385 // 'function' '*' Identifier '(' FormalParameterListopt ')'
386 // '{' FunctionBody '}'
387 Expect(Token::FUNCTION, CHECK_OK);
388 int pos = position();
389 bool is_generator = Check(Token::MUL);
390 bool is_strict_reserved = false;
391 Identifier name = ParseIdentifierOrStrictReservedWord(
392 &is_strict_reserved, CHECK_OK);
393 ParseFunctionLiteral(name, scanner()->location(),
394 is_strict_reserved ? kFunctionNameIsStrictReserved
395 : kFunctionNameValidityUnknown,
396 is_generator ? FunctionKind::kGeneratorFunction
397 : FunctionKind::kNormalFunction,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100398 pos, FunctionLiteral::kDeclaration, language_mode(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 CHECK_OK);
400 return Statement::FunctionDeclaration();
401}
402
403
404PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
405 Expect(Token::CLASS, CHECK_OK);
406 if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
407 ReportMessage(MessageTemplate::kSloppyLexical);
408 *ok = false;
409 return Statement::Default();
410 }
411
412 int pos = position();
413 bool is_strict_reserved = false;
414 Identifier name =
415 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +0100416 ParseClassLiteral(nullptr, name, scanner()->location(), is_strict_reserved,
417 pos, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000418 return Statement::Default();
419}
420
421
422PreParser::Statement PreParser::ParseBlock(bool* ok) {
423 // Block ::
424 // '{' StatementList '}'
425
426 Expect(Token::LBRACE, CHECK_OK);
427 Statement final = Statement::Default();
428 while (peek() != Token::RBRACE) {
429 final = ParseStatementListItem(CHECK_OK);
430 }
431 Expect(Token::RBRACE, ok);
432 return final;
433}
434
435
436PreParser::Statement PreParser::ParseVariableStatement(
437 VariableDeclarationContext var_context,
438 bool* ok) {
439 // VariableStatement ::
440 // VariableDeclarations ';'
441
442 Statement result = ParseVariableDeclarations(
443 var_context, nullptr, nullptr, nullptr, nullptr, nullptr, CHECK_OK);
444 ExpectSemicolon(CHECK_OK);
445 return result;
446}
447
448
449// If the variable declaration declares exactly one non-const
450// variable, then *var is set to that variable. In all other cases,
451// *var is untouched; in particular, it is the caller's responsibility
452// to initialize it properly. This mechanism is also used for the parsing
453// of 'for-in' loops.
454PreParser::Statement PreParser::ParseVariableDeclarations(
455 VariableDeclarationContext var_context, int* num_decl, bool* is_lexical,
456 bool* is_binding_pattern, Scanner::Location* first_initializer_loc,
457 Scanner::Location* bindings_loc, bool* ok) {
458 // VariableDeclarations ::
459 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
460 //
461 // The ES6 Draft Rev3 specifies the following grammar for const declarations
462 //
463 // ConstDeclaration ::
464 // const ConstBinding (',' ConstBinding)* ';'
465 // ConstBinding ::
466 // Identifier '=' AssignmentExpression
467 //
468 // TODO(ES6):
469 // ConstBinding ::
470 // BindingPattern '=' AssignmentExpression
471 bool require_initializer = false;
472 bool lexical = false;
473 bool is_pattern = false;
474 if (peek() == Token::VAR) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475 Consume(Token::VAR);
476 } else if (peek() == Token::CONST && allow_const()) {
477 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
478 //
479 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
480 //
481 // * It is a Syntax Error if the code that matches this production is not
482 // contained in extended code.
483 //
484 // However disallowing const in sloppy mode will break compatibility with
485 // existing pages. Therefore we keep allowing const with the old
486 // non-harmony semantics in sloppy mode.
487 Consume(Token::CONST);
Ben Murdochda12d292016-06-02 14:46:10 +0100488 if (is_strict(language_mode()) || allow_harmony_sloppy()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000489 DCHECK(var_context != kStatement);
490 require_initializer = true;
491 lexical = true;
492 }
493 } else if (peek() == Token::LET && allow_let()) {
494 Consume(Token::LET);
495 DCHECK(var_context != kStatement);
496 lexical = true;
497 } else {
498 *ok = false;
499 return Statement::Default();
500 }
501
502 // The scope of a var/const declared variable anywhere inside a function
503 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
504 // of a let declared variable is the scope of the immediately enclosing
505 // block.
506 int nvars = 0; // the number of variables declared
507 int bindings_start = peek_position();
508 do {
509 // Parse binding pattern.
510 if (nvars > 0) Consume(Token::COMMA);
511 int decl_pos = peek_position();
512 PreParserExpression pattern = PreParserExpression::Default();
513 {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100514 ExpressionClassifier pattern_classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000515 pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
516
517 ValidateBindingPattern(&pattern_classifier, CHECK_OK);
518 if (lexical) {
519 ValidateLetPattern(&pattern_classifier, CHECK_OK);
520 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000521 }
522
Ben Murdoch097c5b22016-05-18 11:27:45 +0100523 is_pattern = pattern.IsObjectLiteral() || pattern.IsArrayLiteral();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000524
525 Scanner::Location variable_loc = scanner()->location();
526 nvars++;
527 if (Check(Token::ASSIGN)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100528 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529 ParseAssignmentExpression(var_context != kForStatement, &classifier,
530 CHECK_OK);
531 ValidateExpression(&classifier, CHECK_OK);
532
533 variable_loc.end_pos = scanner()->location().end_pos;
534 if (first_initializer_loc && !first_initializer_loc->IsValid()) {
535 *first_initializer_loc = variable_loc;
536 }
537 } else if ((require_initializer || is_pattern) &&
Ben Murdoch097c5b22016-05-18 11:27:45 +0100538 (var_context != kForStatement || !PeekInOrOf())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000539 PreParserTraits::ReportMessageAt(
540 Scanner::Location(decl_pos, scanner()->location().end_pos),
541 MessageTemplate::kDeclarationMissingInitializer,
542 is_pattern ? "destructuring" : "const");
543 *ok = false;
544 return Statement::Default();
545 }
546 } while (peek() == Token::COMMA);
547
548 if (bindings_loc) {
549 *bindings_loc =
550 Scanner::Location(bindings_start, scanner()->location().end_pos);
551 }
552
553 if (num_decl != nullptr) *num_decl = nvars;
554 if (is_lexical != nullptr) *is_lexical = lexical;
555 if (is_binding_pattern != nullptr) *is_binding_pattern = is_pattern;
556 return Statement::Default();
557}
558
Ben Murdochda12d292016-06-02 14:46:10 +0100559PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(
560 AllowLabelledFunctionStatement allow_function, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000561 // ExpressionStatement | LabelledStatement ::
562 // Expression ';'
563 // Identifier ':' Statement
564
565 switch (peek()) {
566 case Token::FUNCTION:
567 case Token::LBRACE:
568 UNREACHABLE(); // Always handled by the callers.
569 case Token::CLASS:
570 ReportUnexpectedToken(Next());
571 *ok = false;
572 return Statement::Default();
573
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000574 default:
575 break;
576 }
577
578 bool starts_with_identifier = peek_any_identifier();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100579 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000580 Expression expr = ParseExpression(true, &classifier, CHECK_OK);
581 ValidateExpression(&classifier, CHECK_OK);
582
583 // Even if the expression starts with an identifier, it is not necessarily an
584 // identifier. For example, "foo + bar" starts with an identifier but is not
585 // an identifier.
586 if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) {
587 // Expression is a single identifier, and not, e.g., a parenthesized
588 // identifier.
589 DCHECK(!expr.AsIdentifier().IsFutureReserved());
590 DCHECK(is_sloppy(language_mode()) ||
591 !IsFutureStrictReserved(expr.AsIdentifier()));
592 Consume(Token::COLON);
Ben Murdochda12d292016-06-02 14:46:10 +0100593 // ES#sec-labelled-function-declarations Labelled Function Declarations
594 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) {
595 if (allow_function == kAllowLabelledFunctionStatement) {
596 return ParseFunctionDeclaration(ok);
597 } else {
598 return ParseScopedStatement(true, ok);
599 }
600 }
601 Statement statement =
602 ParseStatement(kDisallowLabelledFunctionStatement, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000603 return statement.IsJumpStatement() ? Statement::Default() : statement;
604 // Preparsing is disabled for extensions (because the extension details
605 // aren't passed to lazily compiled functions), so we don't
606 // accept "native function" in the preparser.
607 }
608 // Parsed expression statement.
609 // Detect attempts at 'let' declarations in sloppy mode.
610 if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
611 is_sloppy(language_mode()) && expr.IsIdentifier() &&
612 expr.AsIdentifier().IsLet()) {
613 ReportMessage(MessageTemplate::kSloppyLexical, NULL);
614 *ok = false;
615 return Statement::Default();
616 }
617 ExpectSemicolon(CHECK_OK);
618 return Statement::ExpressionStatement(expr);
619}
620
621
622PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
623 // IfStatement ::
624 // 'if' '(' Expression ')' Statement ('else' Statement)?
625
626 Expect(Token::IF, CHECK_OK);
627 Expect(Token::LPAREN, CHECK_OK);
628 ParseExpression(true, CHECK_OK);
629 Expect(Token::RPAREN, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +0100630 Statement stat = ParseScopedStatement(false, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000631 if (peek() == Token::ELSE) {
632 Next();
Ben Murdochda12d292016-06-02 14:46:10 +0100633 Statement else_stat = ParseScopedStatement(false, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000634 stat = (stat.IsJumpStatement() && else_stat.IsJumpStatement()) ?
635 Statement::Jump() : Statement::Default();
636 } else {
637 stat = Statement::Default();
638 }
639 return stat;
640}
641
642
643PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
644 // ContinueStatement ::
645 // 'continue' [no line terminator] Identifier? ';'
646
647 Expect(Token::CONTINUE, CHECK_OK);
648 Token::Value tok = peek();
649 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
650 tok != Token::SEMICOLON &&
651 tok != Token::RBRACE &&
652 tok != Token::EOS) {
653 // ECMA allows "eval" or "arguments" as labels even in strict mode.
654 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
655 }
656 ExpectSemicolon(CHECK_OK);
657 return Statement::Jump();
658}
659
660
661PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
662 // BreakStatement ::
663 // 'break' [no line terminator] Identifier? ';'
664
665 Expect(Token::BREAK, CHECK_OK);
666 Token::Value tok = peek();
667 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
668 tok != Token::SEMICOLON &&
669 tok != Token::RBRACE &&
670 tok != Token::EOS) {
671 // ECMA allows "eval" or "arguments" as labels even in strict mode.
672 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
673 }
674 ExpectSemicolon(CHECK_OK);
675 return Statement::Jump();
676}
677
678
679PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
680 // ReturnStatement ::
681 // 'return' [no line terminator] Expression? ';'
682
683 // Consume the return token. It is necessary to do before
684 // reporting any errors on it, because of the way errors are
685 // reported (underlining).
686 Expect(Token::RETURN, CHECK_OK);
687 function_state_->set_return_location(scanner()->location());
688
689 // An ECMAScript program is considered syntactically incorrect if it
690 // contains a return statement that is not within the body of a
691 // function. See ECMA-262, section 12.9, page 67.
692 // This is not handled during preparsing.
693
694 Token::Value tok = peek();
695 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
696 tok != Token::SEMICOLON &&
697 tok != Token::RBRACE &&
698 tok != Token::EOS) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000699 ParseExpression(true, CHECK_OK);
700 }
701 ExpectSemicolon(CHECK_OK);
702 return Statement::Jump();
703}
704
705
706PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
707 // WithStatement ::
708 // 'with' '(' Expression ')' Statement
709 Expect(Token::WITH, CHECK_OK);
710 if (is_strict(language_mode())) {
711 ReportMessageAt(scanner()->location(), MessageTemplate::kStrictWith);
712 *ok = false;
713 return Statement::Default();
714 }
715 Expect(Token::LPAREN, CHECK_OK);
716 ParseExpression(true, CHECK_OK);
717 Expect(Token::RPAREN, CHECK_OK);
718
719 Scope* with_scope = NewScope(scope_, WITH_SCOPE);
720 BlockState block_state(&scope_, with_scope);
Ben Murdochda12d292016-06-02 14:46:10 +0100721 ParseScopedStatement(true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000722 return Statement::Default();
723}
724
725
726PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
727 // SwitchStatement ::
728 // 'switch' '(' Expression ')' '{' CaseClause* '}'
729
730 Expect(Token::SWITCH, CHECK_OK);
731 Expect(Token::LPAREN, CHECK_OK);
732 ParseExpression(true, CHECK_OK);
733 Expect(Token::RPAREN, CHECK_OK);
734
735 Expect(Token::LBRACE, CHECK_OK);
736 Token::Value token = peek();
737 while (token != Token::RBRACE) {
738 if (token == Token::CASE) {
739 Expect(Token::CASE, CHECK_OK);
740 ParseExpression(true, CHECK_OK);
741 } else {
742 Expect(Token::DEFAULT, CHECK_OK);
743 }
744 Expect(Token::COLON, CHECK_OK);
745 token = peek();
746 Statement statement = Statement::Jump();
747 while (token != Token::CASE &&
748 token != Token::DEFAULT &&
749 token != Token::RBRACE) {
750 statement = ParseStatementListItem(CHECK_OK);
751 token = peek();
752 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000753 }
754 Expect(Token::RBRACE, ok);
755 return Statement::Default();
756}
757
758
759PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
760 // DoStatement ::
761 // 'do' Statement 'while' '(' Expression ')' ';'
762
763 Expect(Token::DO, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +0100764 ParseScopedStatement(true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000765 Expect(Token::WHILE, CHECK_OK);
766 Expect(Token::LPAREN, CHECK_OK);
767 ParseExpression(true, CHECK_OK);
768 Expect(Token::RPAREN, ok);
769 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
770 return Statement::Default();
771}
772
773
774PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
775 // WhileStatement ::
776 // 'while' '(' Expression ')' Statement
777
778 Expect(Token::WHILE, CHECK_OK);
779 Expect(Token::LPAREN, CHECK_OK);
780 ParseExpression(true, CHECK_OK);
781 Expect(Token::RPAREN, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +0100782 ParseScopedStatement(true, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000783 return Statement::Default();
784}
785
786
787PreParser::Statement PreParser::ParseForStatement(bool* ok) {
788 // ForStatement ::
789 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
790
791 Expect(Token::FOR, CHECK_OK);
792 Expect(Token::LPAREN, CHECK_OK);
793 bool is_let_identifier_expression = false;
794 if (peek() != Token::SEMICOLON) {
795 ForEachStatement::VisitMode mode;
796 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) ||
797 (peek() == Token::LET && IsNextLetKeyword())) {
798 int decl_count;
799 bool is_lexical;
800 bool is_binding_pattern;
801 Scanner::Location first_initializer_loc = Scanner::Location::invalid();
802 Scanner::Location bindings_loc = Scanner::Location::invalid();
803 ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical,
804 &is_binding_pattern, &first_initializer_loc,
805 &bindings_loc, CHECK_OK);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100806 if (CheckInOrOf(&mode, ok)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000807 if (!*ok) return Statement::Default();
808 if (decl_count != 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000809 PreParserTraits::ReportMessageAt(
810 bindings_loc, MessageTemplate::kForInOfLoopMultiBindings,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100811 ForEachStatement::VisitModeString(mode));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000812 *ok = false;
813 return Statement::Default();
814 }
815 if (first_initializer_loc.IsValid() &&
816 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE ||
817 is_lexical || is_binding_pattern)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100818 PreParserTraits::ReportMessageAt(
819 first_initializer_loc, MessageTemplate::kForInOfLoopInitializer,
820 ForEachStatement::VisitModeString(mode));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000821 *ok = false;
822 return Statement::Default();
823 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100824
825 if (mode == ForEachStatement::ITERATE) {
826 ExpressionClassifier classifier(this);
827 ParseAssignmentExpression(true, &classifier, CHECK_OK);
828 RewriteNonPattern(&classifier, CHECK_OK);
829 } else {
830 ParseExpression(true, CHECK_OK);
831 }
832
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000833 Expect(Token::RPAREN, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +0100834 ParseScopedStatement(true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000835 return Statement::Default();
836 }
837 } else {
838 int lhs_beg_pos = peek_position();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100839 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000840 Expression lhs = ParseExpression(false, &classifier, CHECK_OK);
841 int lhs_end_pos = scanner()->location().end_pos;
842 is_let_identifier_expression =
843 lhs.IsIdentifier() && lhs.AsIdentifier().IsLet();
844 bool is_for_each = CheckInOrOf(&mode, ok);
845 if (!*ok) return Statement::Default();
846 bool is_destructuring = is_for_each &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000847 (lhs->IsArrayLiteral() || lhs->IsObjectLiteral());
848
849 if (is_destructuring) {
850 ValidateAssignmentPattern(&classifier, CHECK_OK);
851 } else {
852 ValidateExpression(&classifier, CHECK_OK);
853 }
854
855 if (is_for_each) {
856 if (!is_destructuring) {
857 lhs = CheckAndRewriteReferenceExpression(
858 lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
859 kSyntaxError, CHECK_OK);
860 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100861
862 if (mode == ForEachStatement::ITERATE) {
863 ExpressionClassifier classifier(this);
864 ParseAssignmentExpression(true, &classifier, CHECK_OK);
865 RewriteNonPattern(&classifier, CHECK_OK);
866 } else {
867 ParseExpression(true, CHECK_OK);
868 }
869
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000870 Expect(Token::RPAREN, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +0100871 ParseScopedStatement(true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000872 return Statement::Default();
873 }
874 }
875 }
876
877 // Parsed initializer at this point.
878 // Detect attempts at 'let' declarations in sloppy mode.
879 if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
880 is_sloppy(language_mode()) && is_let_identifier_expression) {
881 ReportMessage(MessageTemplate::kSloppyLexical, NULL);
882 *ok = false;
883 return Statement::Default();
884 }
885 Expect(Token::SEMICOLON, CHECK_OK);
886
887 if (peek() != Token::SEMICOLON) {
888 ParseExpression(true, CHECK_OK);
889 }
890 Expect(Token::SEMICOLON, CHECK_OK);
891
892 if (peek() != Token::RPAREN) {
893 ParseExpression(true, CHECK_OK);
894 }
895 Expect(Token::RPAREN, CHECK_OK);
896
Ben Murdochda12d292016-06-02 14:46:10 +0100897 ParseScopedStatement(true, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000898 return Statement::Default();
899}
900
901
902PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
903 // ThrowStatement ::
904 // 'throw' [no line terminator] Expression ';'
905
906 Expect(Token::THROW, CHECK_OK);
907 if (scanner()->HasAnyLineTerminatorBeforeNext()) {
908 ReportMessageAt(scanner()->location(), MessageTemplate::kNewlineAfterThrow);
909 *ok = false;
910 return Statement::Default();
911 }
912 ParseExpression(true, CHECK_OK);
913 ExpectSemicolon(ok);
914 return Statement::Jump();
915}
916
917
918PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
919 // TryStatement ::
920 // 'try' Block Catch
921 // 'try' Block Finally
922 // 'try' Block Catch Finally
923 //
924 // Catch ::
925 // 'catch' '(' Identifier ')' Block
926 //
927 // Finally ::
928 // 'finally' Block
929
930 Expect(Token::TRY, CHECK_OK);
931
932 ParseBlock(CHECK_OK);
933
934 Token::Value tok = peek();
935 if (tok != Token::CATCH && tok != Token::FINALLY) {
936 ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally);
937 *ok = false;
938 return Statement::Default();
939 }
940 if (tok == Token::CATCH) {
941 Consume(Token::CATCH);
942 Expect(Token::LPAREN, CHECK_OK);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100943 ExpressionClassifier pattern_classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000944 ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
945 ValidateBindingPattern(&pattern_classifier, CHECK_OK);
946 Expect(Token::RPAREN, CHECK_OK);
947 {
948 // TODO(adamk): Make this CATCH_SCOPE
949 Scope* with_scope = NewScope(scope_, WITH_SCOPE);
950 BlockState block_state(&scope_, with_scope);
951 ParseBlock(CHECK_OK);
952 }
953 tok = peek();
954 }
955 if (tok == Token::FINALLY) {
956 Consume(Token::FINALLY);
957 ParseBlock(CHECK_OK);
958 }
959 return Statement::Default();
960}
961
962
963PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
964 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
965 // contexts this is used as a statement which invokes the debugger as if a
966 // break point is present.
967 // DebuggerStatement ::
968 // 'debugger' ';'
969
970 Expect(Token::DEBUGGER, CHECK_OK);
971 ExpectSemicolon(ok);
972 return Statement::Default();
973}
974
975
976#undef CHECK_OK
977#define CHECK_OK ok); \
978 if (!*ok) return Expression::Default(); \
979 ((void)0
980#define DUMMY ) // to make indentation work
981#undef DUMMY
982
983
984PreParser::Expression PreParser::ParseFunctionLiteral(
985 Identifier function_name, Scanner::Location function_name_location,
986 FunctionNameValidity function_name_validity, FunctionKind kind,
987 int function_token_pos, FunctionLiteral::FunctionType function_type,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000988 LanguageMode language_mode, bool* ok) {
989 // Function ::
990 // '(' FormalParameterList? ')' '{' FunctionBody '}'
991
992 // Parse function body.
993 bool outer_is_script_scope = scope_->is_script_scope();
994 Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind);
995 function_scope->SetLanguageMode(language_mode);
996 PreParserFactory factory(NULL);
997 FunctionState function_state(&function_state_, &scope_, function_scope, kind,
998 &factory);
999 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001000 ExpressionClassifier formals_classifier(this, &duplicate_finder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001
1002 Expect(Token::LPAREN, CHECK_OK);
1003 int start_position = scanner()->location().beg_pos;
1004 function_scope->set_start_position(start_position);
1005 PreParserFormalParameters formals(function_scope);
1006 ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK);
1007 Expect(Token::RPAREN, CHECK_OK);
1008 int formals_end_position = scanner()->location().end_pos;
1009
Ben Murdoch097c5b22016-05-18 11:27:45 +01001010 CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011 formals_end_position, CHECK_OK);
1012
1013 // See Parser::ParseFunctionLiteral for more information about lazy parsing
1014 // and lazy compilation.
1015 bool is_lazily_parsed =
1016 (outer_is_script_scope && allow_lazy() && !parenthesized_function_);
1017 parenthesized_function_ = false;
1018
1019 Expect(Token::LBRACE, CHECK_OK);
1020 if (is_lazily_parsed) {
1021 ParseLazyFunctionLiteralBody(CHECK_OK);
1022 } else {
1023 ParseStatementList(Token::RBRACE, CHECK_OK);
1024 }
1025 Expect(Token::RBRACE, CHECK_OK);
1026
1027 // Parsing the body may change the language mode in our scope.
1028 language_mode = function_scope->language_mode();
1029
1030 // Validate name and parameter names. We can do this only after parsing the
1031 // function, since the function can declare itself strict.
1032 CheckFunctionName(language_mode, function_name, function_name_validity,
1033 function_name_location, CHECK_OK);
1034 const bool allow_duplicate_parameters =
1035 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
1036 ValidateFormalParameters(&formals_classifier, language_mode,
1037 allow_duplicate_parameters, CHECK_OK);
1038
1039 if (is_strict(language_mode)) {
1040 int end_position = scanner()->location().end_pos;
1041 CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
1042 }
1043
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001044 return Expression::Default();
1045}
1046
1047
1048void PreParser::ParseLazyFunctionLiteralBody(bool* ok,
1049 Scanner::BookmarkScope* bookmark) {
1050 int body_start = position();
1051 ParseStatementList(Token::RBRACE, ok, bookmark);
1052 if (!*ok) return;
1053 if (bookmark && bookmark->HasBeenReset()) return;
1054
1055 // Position right after terminal '}'.
1056 DCHECK_EQ(Token::RBRACE, scanner()->peek());
1057 int body_end = scanner()->peek_location().end_pos;
1058 log_->LogFunction(body_start, body_end,
1059 function_state_->materialized_literal_count(),
1060 function_state_->expected_property_count(), language_mode(),
1061 scope_->uses_super_property(), scope_->calls_eval());
1062}
1063
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001064PreParserExpression PreParser::ParseClassLiteral(
Ben Murdochda12d292016-06-02 14:46:10 +01001065 ExpressionClassifier* classifier, PreParserIdentifier name,
1066 Scanner::Location class_name_location, bool name_is_strict_reserved,
1067 int pos, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001068 // All parts of a ClassDeclaration and ClassExpression are strict code.
1069 if (name_is_strict_reserved) {
1070 ReportMessageAt(class_name_location,
1071 MessageTemplate::kUnexpectedStrictReserved);
1072 *ok = false;
1073 return EmptyExpression();
1074 }
1075 if (IsEvalOrArguments(name)) {
1076 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments);
1077 *ok = false;
1078 return EmptyExpression();
1079 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001080
Ben Murdochda12d292016-06-02 14:46:10 +01001081 LanguageMode class_language_mode = language_mode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001082 Scope* scope = NewScope(scope_, BLOCK_SCOPE);
1083 BlockState block_state(&scope_, scope);
1084 scope_->SetLanguageMode(
1085 static_cast<LanguageMode>(class_language_mode | STRICT));
1086 // TODO(marja): Make PreParser use scope names too.
1087 // scope_->SetScopeName(name);
1088
1089 bool has_extends = Check(Token::EXTENDS);
1090 if (has_extends) {
Ben Murdochda12d292016-06-02 14:46:10 +01001091 ExpressionClassifier extends_classifier(this);
1092 ParseLeftHandSideExpression(&extends_classifier, CHECK_OK);
1093 ValidateExpression(&extends_classifier, CHECK_OK);
1094 if (classifier != nullptr) {
1095 classifier->Accumulate(&extends_classifier,
1096 ExpressionClassifier::ExpressionProductions);
1097 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001098 }
1099
1100 ClassLiteralChecker checker(this);
1101 bool has_seen_constructor = false;
1102
1103 Expect(Token::LBRACE, CHECK_OK);
1104 while (peek() != Token::RBRACE) {
1105 if (Check(Token::SEMICOLON)) continue;
1106 const bool in_class = true;
1107 const bool is_static = false;
1108 bool is_computed_name = false; // Classes do not care about computed
1109 // property names here.
1110 Identifier name;
Ben Murdochda12d292016-06-02 14:46:10 +01001111 ExpressionClassifier property_classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001112 ParsePropertyDefinition(&checker, in_class, has_extends, is_static,
1113 &is_computed_name, &has_seen_constructor,
Ben Murdochda12d292016-06-02 14:46:10 +01001114 &property_classifier, &name, CHECK_OK);
1115 ValidateExpression(&property_classifier, CHECK_OK);
1116 if (classifier != nullptr) {
1117 classifier->Accumulate(&property_classifier,
1118 ExpressionClassifier::ExpressionProductions);
1119 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001120 }
1121
1122 Expect(Token::RBRACE, CHECK_OK);
1123
1124 return Expression::Default();
1125}
1126
1127
1128PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
1129 // CallRuntime ::
1130 // '%' Identifier Arguments
1131 Expect(Token::MOD, CHECK_OK);
1132 if (!allow_natives()) {
1133 *ok = false;
1134 return Expression::Default();
1135 }
1136 // Allow "eval" or "arguments" for backward compatibility.
1137 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
1138 Scanner::Location spread_pos;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001139 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001140 ParseArguments(&spread_pos, &classifier, ok);
1141 ValidateExpression(&classifier, CHECK_OK);
1142
1143 DCHECK(!spread_pos.IsValid());
1144
1145 return Expression::Default();
1146}
1147
1148
1149PreParserExpression PreParser::ParseDoExpression(bool* ok) {
1150 // AssignmentExpression ::
1151 // do '{' StatementList '}'
1152 Expect(Token::DO, CHECK_OK);
1153 Expect(Token::LBRACE, CHECK_OK);
1154 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
1155 {
1156 BlockState block_state(&scope_, block_scope);
1157 while (peek() != Token::RBRACE) {
1158 ParseStatementListItem(CHECK_OK);
1159 }
1160 Expect(Token::RBRACE, CHECK_OK);
1161 return PreParserExpression::Default();
1162 }
1163}
1164
1165#undef CHECK_OK
1166
1167
1168} // namespace internal
1169} // namespace v8