1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "../include/v8stdint.h"
32 #include "allocation.h"
34 #include "conversions.h"
35 #include "conversions-inl.h"
39 #include "preparse-data-format.h"
40 #include "preparse-data.h"
41 #include "preparser.h"
45 #if V8_CC_MSVC && (_MSC_VER < 1800)
48 // Usually defined in math.h, but not in MSVC until VS2013+.
50 int isfinite(double value);
58 PreParser::PreParseResult PreParser::PreParseLazyFunction(
59 LanguageMode mode, bool is_generator, ParserRecorder* log) {
61 // Lazy functions always have trivial outer scopes (no with/catch scopes).
62 Scope top_scope(&scope_, kTopLevelScope);
63 set_language_mode(mode);
64 Scope function_scope(&scope_, kFunctionScope);
65 function_scope.set_is_generator(is_generator);
66 ASSERT_EQ(Token::LBRACE, scanner()->current_token());
68 int start_position = peek_position();
69 ParseLazyFunctionLiteralBody(&ok);
70 if (stack_overflow()) return kPreParseStackOverflow;
72 ReportUnexpectedToken(scanner()->current_token());
74 ASSERT_EQ(Token::RBRACE, scanner()->peek());
75 if (!is_classic_mode()) {
76 int end_pos = scanner()->location().end_pos;
77 CheckOctalLiteral(start_position, end_pos, &ok);
79 CheckDelayedStrictModeViolation(start_position, end_pos, &ok);
83 return kPreParseSuccess;
87 // Preparsing checks a JavaScript program and emits preparse-data that helps
88 // a later parsing to be faster.
89 // See preparser-data.h for the data.
91 // The PreParser checks that the syntax follows the grammar for JavaScript,
92 // and collects some information about the program along the way.
93 // The grammar check is only performed in order to understand the program
94 // sufficiently to deduce some information about it, that can be used
95 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
96 // rather it is to speed up properly written and correct programs.
97 // That means that contextual checks (like a label being declared where
98 // it is used) are generally omitted.
100 void PreParser::ReportUnexpectedToken(Token::Value token) {
101 // We don't report stack overflows here, to avoid increasing the
102 // stack depth even further. Instead we report it after parsing is
103 // over, in ParseProgram.
104 if (token == Token::ILLEGAL && stack_overflow()) {
107 Scanner::Location source_location = scanner()->location();
109 // Four of the tokens are treated specially
112 return ReportMessageAt(source_location, "unexpected_eos", NULL);
114 return ReportMessageAt(source_location, "unexpected_token_number", NULL);
116 return ReportMessageAt(source_location, "unexpected_token_string", NULL);
117 case Token::IDENTIFIER:
118 return ReportMessageAt(source_location,
119 "unexpected_token_identifier", NULL);
120 case Token::FUTURE_RESERVED_WORD:
121 return ReportMessageAt(source_location, "unexpected_reserved", NULL);
122 case Token::FUTURE_STRICT_RESERVED_WORD:
123 return ReportMessageAt(source_location,
124 "unexpected_strict_reserved", NULL);
126 const char* name = Token::String(token);
127 ReportMessageAt(source_location, "unexpected_token", name);
132 #define CHECK_OK ok); \
133 if (!*ok) return kUnknownSourceElements; \
135 #define DUMMY ) // to make indentation work
139 PreParser::Statement PreParser::ParseSourceElement(bool* ok) {
140 // (Ecma 262 5th Edition, clause 14):
143 // FunctionDeclaration
145 // In harmony mode we allow additionally the following productions
149 // GeneratorDeclaration
152 case Token::FUNCTION:
153 return ParseFunctionDeclaration(ok);
156 return ParseVariableStatement(kSourceElement, ok);
158 return ParseStatement(ok);
163 PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
166 // (Statement)* <end_token>
168 bool allow_directive_prologue = true;
169 while (peek() != end_token) {
170 Statement statement = ParseSourceElement(CHECK_OK);
171 if (allow_directive_prologue) {
172 if (statement.IsUseStrictLiteral()) {
173 set_language_mode(allow_harmony_scoping() ?
174 EXTENDED_MODE : STRICT_MODE);
175 } else if (!statement.IsStringLiteral()) {
176 allow_directive_prologue = false;
180 return kUnknownSourceElements;
185 #define CHECK_OK ok); \
186 if (!*ok) return Statement::Default(); \
188 #define DUMMY ) // to make indentation work
192 PreParser::Statement PreParser::ParseStatement(bool* ok) {
197 // ExpressionStatement
199 // IterationStatement
210 // Note: Since labels can only be used by 'break' and 'continue'
211 // statements, which themselves are only valid within blocks,
212 // iterations or 'switch' statements (i.e., BreakableStatements),
213 // labels can be simply ignored in all other cases; except for
214 // trivial labeled break statements 'label: break label' which is
215 // parsed into an empty statement.
217 // Keep the source position of the statement
220 return ParseBlock(ok);
225 return ParseVariableStatement(kStatement, ok);
227 case Token::SEMICOLON:
229 return Statement::Default();
232 return ParseIfStatement(ok);
235 return ParseDoWhileStatement(ok);
238 return ParseWhileStatement(ok);
241 return ParseForStatement(ok);
243 case Token::CONTINUE:
244 return ParseContinueStatement(ok);
247 return ParseBreakStatement(ok);
250 return ParseReturnStatement(ok);
253 return ParseWithStatement(ok);
256 return ParseSwitchStatement(ok);
259 return ParseThrowStatement(ok);
262 return ParseTryStatement(ok);
264 case Token::FUNCTION: {
265 Scanner::Location start_location = scanner()->peek_location();
266 Statement statement = ParseFunctionDeclaration(CHECK_OK);
267 Scanner::Location end_location = scanner()->location();
268 if (!is_classic_mode()) {
269 ReportMessageAt(start_location.beg_pos, end_location.end_pos,
270 "strict_function", NULL);
272 return Statement::Default();
278 case Token::DEBUGGER:
279 return ParseDebuggerStatement(ok);
282 return ParseExpressionOrLabelledStatement(ok);
287 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
288 // FunctionDeclaration ::
289 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
290 // GeneratorDeclaration ::
291 // 'function' '*' Identifier '(' FormalParameterListopt ')'
292 // '{' FunctionBody '}'
293 Expect(Token::FUNCTION, CHECK_OK);
295 bool is_generator = allow_generators() && Check(Token::MUL);
296 Identifier identifier = ParseIdentifier(CHECK_OK);
297 Scanner::Location location = scanner()->location();
299 Expression function_value = ParseFunctionLiteral(is_generator, CHECK_OK);
301 if (function_value.IsStrictFunction() &&
302 !identifier.IsValidStrictVariable()) {
303 // Strict mode violation, using either reserved word or eval/arguments
304 // as name of strict function.
305 const char* type = "strict_function_name";
306 if (identifier.IsFutureStrictReserved() || identifier.IsYield()) {
307 type = "strict_reserved_word";
309 ReportMessageAt(location, type, NULL);
312 return Statement::FunctionDeclaration();
316 PreParser::Statement PreParser::ParseBlock(bool* ok) {
318 // '{' Statement* '}'
320 // Note that a Block does not introduce a new execution scope!
321 // (ECMA-262, 3rd, 12.2)
323 Expect(Token::LBRACE, CHECK_OK);
324 while (peek() != Token::RBRACE) {
325 if (is_extended_mode()) {
326 ParseSourceElement(CHECK_OK);
328 ParseStatement(CHECK_OK);
331 Expect(Token::RBRACE, ok);
332 return Statement::Default();
336 PreParser::Statement PreParser::ParseVariableStatement(
337 VariableDeclarationContext var_context,
339 // VariableStatement ::
340 // VariableDeclarations ';'
342 Statement result = ParseVariableDeclarations(var_context,
346 ExpectSemicolon(CHECK_OK);
351 // If the variable declaration declares exactly one non-const
352 // variable, then *var is set to that variable. In all other cases,
353 // *var is untouched; in particular, it is the caller's responsibility
354 // to initialize it properly. This mechanism is also used for the parsing
355 // of 'for-in' loops.
356 PreParser::Statement PreParser::ParseVariableDeclarations(
357 VariableDeclarationContext var_context,
358 VariableDeclarationProperties* decl_props,
361 // VariableDeclarations ::
362 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
364 // The ES6 Draft Rev3 specifies the following grammar for const declarations
366 // ConstDeclaration ::
367 // const ConstBinding (',' ConstBinding)* ';'
369 // Identifier '=' AssignmentExpression
373 // BindingPattern '=' AssignmentExpression
374 bool require_initializer = false;
375 if (peek() == Token::VAR) {
377 } else if (peek() == Token::CONST) {
378 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
380 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
382 // * It is a Syntax Error if the code that matches this production is not
383 // contained in extended code.
385 // However disallowing const in classic mode will break compatibility with
386 // existing pages. Therefore we keep allowing const with the old
387 // non-harmony semantics in classic mode.
388 Consume(Token::CONST);
389 switch (language_mode()) {
393 Scanner::Location location = scanner()->peek_location();
394 ReportMessageAt(location, "strict_const", NULL);
396 return Statement::Default();
399 if (var_context != kSourceElement &&
400 var_context != kForStatement) {
401 Scanner::Location location = scanner()->peek_location();
402 ReportMessageAt(location.beg_pos, location.end_pos,
403 "unprotected_const", NULL);
405 return Statement::Default();
407 require_initializer = true;
410 } else if (peek() == Token::LET) {
411 // ES6 Draft Rev4 section 12.2.1:
413 // LetDeclaration : let LetBindingList ;
415 // * It is a Syntax Error if the code that matches this production is not
416 // contained in extended code.
417 if (!is_extended_mode()) {
418 Scanner::Location location = scanner()->peek_location();
419 ReportMessageAt(location.beg_pos, location.end_pos,
420 "illegal_let", NULL);
422 return Statement::Default();
425 if (var_context != kSourceElement &&
426 var_context != kForStatement) {
427 Scanner::Location location = scanner()->peek_location();
428 ReportMessageAt(location.beg_pos, location.end_pos,
429 "unprotected_let", NULL);
431 return Statement::Default();
435 return Statement::Default();
438 // The scope of a var/const declared variable anywhere inside a function
439 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
440 // of a let declared variable is the scope of the immediately enclosing
442 int nvars = 0; // the number of variables declared
444 // Parse variable name.
445 if (nvars > 0) Consume(Token::COMMA);
446 Identifier identifier = ParseIdentifier(CHECK_OK);
447 if (!is_classic_mode() && !identifier.IsValidStrictVariable()) {
448 StrictModeIdentifierViolation(scanner()->location(),
452 return Statement::Default();
455 if (peek() == Token::ASSIGN || require_initializer) {
456 Expect(Token::ASSIGN, CHECK_OK);
457 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
458 if (decl_props != NULL) *decl_props = kHasInitializers;
460 } while (peek() == Token::COMMA);
462 if (num_decl != NULL) *num_decl = nvars;
463 return Statement::Default();
467 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
468 // ExpressionStatement | LabelledStatement ::
470 // Identifier ':' Statement
472 Expression expr = ParseExpression(true, CHECK_OK);
473 if (expr.IsRawIdentifier()) {
474 ASSERT(!expr.AsIdentifier().IsFutureReserved());
475 ASSERT(is_classic_mode() ||
476 (!expr.AsIdentifier().IsFutureStrictReserved() &&
477 !expr.AsIdentifier().IsYield()));
478 if (peek() == Token::COLON) {
479 Consume(Token::COLON);
480 return ParseStatement(ok);
482 // Preparsing is disabled for extensions (because the extension details
483 // aren't passed to lazily compiled functions), so we don't
484 // accept "native function" in the preparser.
486 // Parsed expression statement.
487 ExpectSemicolon(CHECK_OK);
488 return Statement::ExpressionStatement(expr);
492 PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
494 // 'if' '(' Expression ')' Statement ('else' Statement)?
496 Expect(Token::IF, CHECK_OK);
497 Expect(Token::LPAREN, CHECK_OK);
498 ParseExpression(true, CHECK_OK);
499 Expect(Token::RPAREN, CHECK_OK);
500 ParseStatement(CHECK_OK);
501 if (peek() == Token::ELSE) {
503 ParseStatement(CHECK_OK);
505 return Statement::Default();
509 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
510 // ContinueStatement ::
511 // 'continue' [no line terminator] Identifier? ';'
513 Expect(Token::CONTINUE, CHECK_OK);
514 Token::Value tok = peek();
515 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
516 tok != Token::SEMICOLON &&
517 tok != Token::RBRACE &&
519 ParseIdentifier(CHECK_OK);
521 ExpectSemicolon(CHECK_OK);
522 return Statement::Default();
526 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
528 // 'break' [no line terminator] Identifier? ';'
530 Expect(Token::BREAK, CHECK_OK);
531 Token::Value tok = peek();
532 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
533 tok != Token::SEMICOLON &&
534 tok != Token::RBRACE &&
536 ParseIdentifier(CHECK_OK);
538 ExpectSemicolon(CHECK_OK);
539 return Statement::Default();
543 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
544 // ReturnStatement ::
545 // 'return' [no line terminator] Expression? ';'
547 // Consume the return token. It is necessary to do the before
548 // reporting any errors on it, because of the way errors are
549 // reported (underlining).
550 Expect(Token::RETURN, CHECK_OK);
552 // An ECMAScript program is considered syntactically incorrect if it
553 // contains a return statement that is not within the body of a
554 // function. See ECMA-262, section 12.9, page 67.
555 // This is not handled during preparsing.
557 Token::Value tok = peek();
558 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
559 tok != Token::SEMICOLON &&
560 tok != Token::RBRACE &&
562 ParseExpression(true, CHECK_OK);
564 ExpectSemicolon(CHECK_OK);
565 return Statement::Default();
569 PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
571 // 'with' '(' Expression ')' Statement
572 Expect(Token::WITH, CHECK_OK);
573 if (!is_classic_mode()) {
574 Scanner::Location location = scanner()->location();
575 ReportMessageAt(location, "strict_mode_with", NULL);
577 return Statement::Default();
579 Expect(Token::LPAREN, CHECK_OK);
580 ParseExpression(true, CHECK_OK);
581 Expect(Token::RPAREN, CHECK_OK);
583 Scope::InsideWith iw(scope_);
584 ParseStatement(CHECK_OK);
585 return Statement::Default();
589 PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
590 // SwitchStatement ::
591 // 'switch' '(' Expression ')' '{' CaseClause* '}'
593 Expect(Token::SWITCH, CHECK_OK);
594 Expect(Token::LPAREN, CHECK_OK);
595 ParseExpression(true, CHECK_OK);
596 Expect(Token::RPAREN, 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);
603 ParseExpression(true, CHECK_OK);
605 Expect(Token::DEFAULT, CHECK_OK);
607 Expect(Token::COLON, CHECK_OK);
609 while (token != Token::CASE &&
610 token != Token::DEFAULT &&
611 token != Token::RBRACE) {
612 ParseStatement(CHECK_OK);
616 Expect(Token::RBRACE, ok);
617 return Statement::Default();
621 PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
623 // 'do' Statement 'while' '(' Expression ')' ';'
625 Expect(Token::DO, CHECK_OK);
626 ParseStatement(CHECK_OK);
627 Expect(Token::WHILE, CHECK_OK);
628 Expect(Token::LPAREN, CHECK_OK);
629 ParseExpression(true, CHECK_OK);
630 Expect(Token::RPAREN, ok);
631 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
632 return Statement::Default();
636 PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
638 // 'while' '(' Expression ')' Statement
640 Expect(Token::WHILE, CHECK_OK);
641 Expect(Token::LPAREN, CHECK_OK);
642 ParseExpression(true, CHECK_OK);
643 Expect(Token::RPAREN, CHECK_OK);
645 return Statement::Default();
649 bool PreParser::CheckInOrOf(bool accept_OF) {
650 if (Check(Token::IN) ||
651 (allow_for_of() && accept_OF &&
652 CheckContextualKeyword(CStrVector("of")))) {
659 PreParser::Statement PreParser::ParseForStatement(bool* ok) {
661 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
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;
670 VariableDeclarationProperties decl_props = kHasNoInitializers;
671 ParseVariableDeclarations(
672 kForStatement, &decl_props, &decl_count, CHECK_OK);
673 bool has_initializers = decl_props == kHasInitializers;
674 bool accept_IN = decl_count == 1 && !(is_let && has_initializers);
675 bool accept_OF = !has_initializers;
676 if (accept_IN && CheckInOrOf(accept_OF)) {
677 ParseExpression(true, CHECK_OK);
678 Expect(Token::RPAREN, CHECK_OK);
680 ParseStatement(CHECK_OK);
681 return Statement::Default();
684 Expression lhs = ParseExpression(false, CHECK_OK);
685 if (CheckInOrOf(lhs.IsIdentifier())) {
686 ParseExpression(true, CHECK_OK);
687 Expect(Token::RPAREN, CHECK_OK);
689 ParseStatement(CHECK_OK);
690 return Statement::Default();
695 // Parsed initializer at this point.
696 Expect(Token::SEMICOLON, CHECK_OK);
698 if (peek() != Token::SEMICOLON) {
699 ParseExpression(true, CHECK_OK);
701 Expect(Token::SEMICOLON, CHECK_OK);
703 if (peek() != Token::RPAREN) {
704 ParseExpression(true, CHECK_OK);
706 Expect(Token::RPAREN, CHECK_OK);
709 return Statement::Default();
713 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
715 // 'throw' [no line terminator] Expression ';'
717 Expect(Token::THROW, CHECK_OK);
718 if (scanner()->HasAnyLineTerminatorBeforeNext()) {
719 Scanner::Location pos = scanner()->location();
720 ReportMessageAt(pos, "newline_after_throw", NULL);
722 return Statement::Default();
724 ParseExpression(true, CHECK_OK);
726 return Statement::Default();
730 PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
733 // 'try' Block Finally
734 // 'try' Block Catch Finally
737 // 'catch' '(' Identifier ')' Block
742 // In preparsing, allow any number of catch/finally blocks, including zero
745 Expect(Token::TRY, CHECK_OK);
747 ParseBlock(CHECK_OK);
749 bool catch_or_finally_seen = false;
750 if (peek() == Token::CATCH) {
751 Consume(Token::CATCH);
752 Expect(Token::LPAREN, CHECK_OK);
753 Identifier id = ParseIdentifier(CHECK_OK);
754 if (!is_classic_mode() && !id.IsValidStrictVariable()) {
755 StrictModeIdentifierViolation(scanner()->location(),
756 "strict_catch_variable",
759 return Statement::Default();
761 Expect(Token::RPAREN, CHECK_OK);
762 { Scope::InsideWith iw(scope_);
763 ParseBlock(CHECK_OK);
765 catch_or_finally_seen = true;
767 if (peek() == Token::FINALLY) {
768 Consume(Token::FINALLY);
769 ParseBlock(CHECK_OK);
770 catch_or_finally_seen = true;
772 if (!catch_or_finally_seen) {
775 return Statement::Default();
779 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
780 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
781 // contexts this is used as a statement which invokes the debugger as if a
782 // break point is present.
783 // DebuggerStatement ::
786 Expect(Token::DEBUGGER, CHECK_OK);
788 return Statement::Default();
793 #define CHECK_OK ok); \
794 if (!*ok) return Expression::Default(); \
796 #define DUMMY ) // to make indentation work
801 PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) {
803 // AssignmentExpression
804 // Expression ',' AssignmentExpression
806 Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
807 while (peek() == Token::COMMA) {
808 Expect(Token::COMMA, CHECK_OK);
809 ParseAssignmentExpression(accept_IN, CHECK_OK);
810 result = Expression::Default();
817 PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
819 // AssignmentExpression ::
820 // ConditionalExpression
822 // LeftHandSideExpression AssignmentOperator AssignmentExpression
824 if (scope_->is_generator() && peek() == Token::YIELD) {
825 return ParseYieldExpression(ok);
828 Scanner::Location before = scanner()->peek_location();
829 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
831 if (!Token::IsAssignmentOp(peek())) {
832 // Parsed conditional expression only (no assignment).
836 if (!is_classic_mode() &&
837 expression.IsIdentifier() &&
838 expression.AsIdentifier().IsEvalOrArguments()) {
839 Scanner::Location after = scanner()->location();
840 ReportMessageAt(before.beg_pos, after.end_pos,
841 "strict_lhs_assignment", NULL);
843 return Expression::Default();
846 Token::Value op = Next(); // Get assignment operator.
847 ParseAssignmentExpression(accept_IN, CHECK_OK);
849 if ((op == Token::ASSIGN) && expression.IsThisProperty()) {
850 scope_->AddProperty();
853 return Expression::Default();
858 PreParser::Expression PreParser::ParseYieldExpression(bool* ok) {
859 // YieldExpression ::
860 // 'yield' '*'? AssignmentExpression
861 Consume(Token::YIELD);
864 ParseAssignmentExpression(false, CHECK_OK);
866 return Expression::Default();
871 PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
873 // ConditionalExpression ::
874 // LogicalOrExpression
875 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
877 // We start using the binary expression parser for prec >= 4 only!
878 Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
879 if (peek() != Token::CONDITIONAL) return expression;
880 Consume(Token::CONDITIONAL);
881 // In parsing the first assignment expression in conditional
882 // expressions we always accept the 'in' keyword; see ECMA-262,
883 // section 11.12, page 58.
884 ParseAssignmentExpression(true, CHECK_OK);
885 Expect(Token::COLON, CHECK_OK);
886 ParseAssignmentExpression(accept_IN, CHECK_OK);
887 return Expression::Default();
892 PreParser::Expression PreParser::ParseBinaryExpression(int prec,
895 Expression result = ParseUnaryExpression(CHECK_OK);
896 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
898 while (Precedence(peek(), accept_IN) == prec1) {
900 ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
901 result = Expression::Default();
908 PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
909 // UnaryExpression ::
911 // 'delete' UnaryExpression
912 // 'void' UnaryExpression
913 // 'typeof' UnaryExpression
914 // '++' UnaryExpression
915 // '--' UnaryExpression
916 // '+' UnaryExpression
917 // '-' UnaryExpression
918 // '~' UnaryExpression
919 // '!' UnaryExpression
921 Token::Value op = peek();
922 if (Token::IsUnaryOp(op)) {
924 ParseUnaryExpression(ok);
925 return Expression::Default();
926 } else if (Token::IsCountOp(op)) {
928 Scanner::Location before = scanner()->peek_location();
929 Expression expression = ParseUnaryExpression(CHECK_OK);
930 if (!is_classic_mode() &&
931 expression.IsIdentifier() &&
932 expression.AsIdentifier().IsEvalOrArguments()) {
933 Scanner::Location after = scanner()->location();
934 ReportMessageAt(before.beg_pos, after.end_pos,
935 "strict_lhs_prefix", NULL);
938 return Expression::Default();
940 return ParsePostfixExpression(ok);
945 PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
946 // PostfixExpression ::
947 // LeftHandSideExpression ('++' | '--')?
949 Scanner::Location before = scanner()->peek_location();
950 Expression expression = ParseLeftHandSideExpression(CHECK_OK);
951 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
952 Token::IsCountOp(peek())) {
953 if (!is_classic_mode() &&
954 expression.IsIdentifier() &&
955 expression.AsIdentifier().IsEvalOrArguments()) {
956 Scanner::Location after = scanner()->location();
957 ReportMessageAt(before.beg_pos, after.end_pos,
958 "strict_lhs_postfix", NULL);
960 return Expression::Default();
963 return Expression::Default();
969 PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) {
970 // LeftHandSideExpression ::
971 // (NewExpression | MemberExpression) ...
973 Expression result = Expression::Default();
974 if (peek() == Token::NEW) {
975 result = ParseNewExpression(CHECK_OK);
977 result = ParseMemberExpression(CHECK_OK);
982 case Token::LBRACK: {
983 Consume(Token::LBRACK);
984 ParseExpression(true, CHECK_OK);
985 Expect(Token::RBRACK, CHECK_OK);
986 if (result.IsThis()) {
987 result = Expression::ThisProperty();
989 result = Expression::Default();
994 case Token::LPAREN: {
995 ParseArguments(CHECK_OK);
996 result = Expression::Default();
1000 case Token::PERIOD: {
1001 Consume(Token::PERIOD);
1002 ParseIdentifierName(CHECK_OK);
1003 if (result.IsThis()) {
1004 result = Expression::ThisProperty();
1006 result = Expression::Default();
1018 PreParser::Expression PreParser::ParseNewExpression(bool* ok) {
1020 // ('new')+ MemberExpression
1022 // The grammar for new expressions is pretty warped. The keyword
1023 // 'new' can either be a part of the new expression (where it isn't
1024 // followed by an argument list) or a part of the member expression,
1025 // where it must be followed by an argument list. To accommodate
1026 // this, we parse the 'new' keywords greedily and keep track of how
1027 // many we have parsed. This information is then passed on to the
1028 // member expression parser, which is only allowed to match argument
1029 // lists as long as it has 'new' prefixes left
1030 unsigned new_count = 0;
1032 Consume(Token::NEW);
1034 } while (peek() == Token::NEW);
1036 return ParseMemberWithNewPrefixesExpression(new_count, ok);
1040 PreParser::Expression PreParser::ParseMemberExpression(bool* ok) {
1041 return ParseMemberWithNewPrefixesExpression(0, ok);
1045 PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
1046 unsigned new_count, bool* ok) {
1047 // MemberExpression ::
1048 // (PrimaryExpression | FunctionLiteral)
1049 // ('[' Expression ']' | '.' Identifier | Arguments)*
1051 // Parse the initial primary or function expression.
1052 Expression result = Expression::Default();
1053 if (peek() == Token::FUNCTION) {
1054 Consume(Token::FUNCTION);
1056 bool is_generator = allow_generators() && Check(Token::MUL);
1057 Identifier identifier = Identifier::Default();
1058 if (peek_any_identifier()) {
1059 identifier = ParseIdentifier(CHECK_OK);
1061 result = ParseFunctionLiteral(is_generator, CHECK_OK);
1062 if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
1063 StrictModeIdentifierViolation(scanner()->location(),
1064 "strict_function_name",
1067 return Expression::Default();
1070 result = ParsePrimaryExpression(CHECK_OK);
1075 case Token::LBRACK: {
1076 Consume(Token::LBRACK);
1077 ParseExpression(true, CHECK_OK);
1078 Expect(Token::RBRACK, CHECK_OK);
1079 if (result.IsThis()) {
1080 result = Expression::ThisProperty();
1082 result = Expression::Default();
1086 case Token::PERIOD: {
1087 Consume(Token::PERIOD);
1088 ParseIdentifierName(CHECK_OK);
1089 if (result.IsThis()) {
1090 result = Expression::ThisProperty();
1092 result = Expression::Default();
1096 case Token::LPAREN: {
1097 if (new_count == 0) return result;
1098 // Consume one of the new prefixes (already parsed).
1099 ParseArguments(CHECK_OK);
1101 result = Expression::Default();
1111 PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
1112 // PrimaryExpression ::
1123 // '(' Expression ')'
1125 Expression result = Expression::Default();
1129 result = Expression::This();
1133 case Token::FUTURE_RESERVED_WORD:
1134 case Token::FUTURE_STRICT_RESERVED_WORD:
1136 case Token::IDENTIFIER: {
1137 Identifier id = ParseIdentifier(CHECK_OK);
1138 result = Expression::FromIdentifier(id);
1142 case Token::NULL_LITERAL:
1143 case Token::TRUE_LITERAL:
1144 case Token::FALSE_LITERAL:
1145 case Token::NUMBER: {
1149 case Token::STRING: {
1151 result = GetStringSymbol();
1155 case Token::ASSIGN_DIV:
1156 result = ParseRegExpLiteral(true, CHECK_OK);
1160 result = ParseRegExpLiteral(false, CHECK_OK);
1164 result = ParseArrayLiteral(CHECK_OK);
1168 result = ParseObjectLiteral(CHECK_OK);
1172 Consume(Token::LPAREN);
1173 parenthesized_function_ = (peek() == Token::FUNCTION);
1174 result = ParseExpression(true, CHECK_OK);
1175 Expect(Token::RPAREN, CHECK_OK);
1176 result = result.Parenthesize();
1180 result = ParseV8Intrinsic(CHECK_OK);
1186 return Expression::Default();
1194 PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
1196 // '[' Expression? (',' Expression?)* ']'
1197 Expect(Token::LBRACK, CHECK_OK);
1198 while (peek() != Token::RBRACK) {
1199 if (peek() != Token::COMMA) {
1200 ParseAssignmentExpression(true, CHECK_OK);
1202 if (peek() != Token::RBRACK) {
1203 Expect(Token::COMMA, CHECK_OK);
1206 Expect(Token::RBRACK, CHECK_OK);
1208 scope_->NextMaterializedLiteralIndex();
1209 return Expression::Default();
1213 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
1216 // ((IdentifierName | String | Number) ':' AssignmentExpression)
1217 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1220 ObjectLiteralChecker checker(this, language_mode());
1222 Expect(Token::LBRACE, CHECK_OK);
1223 while (peek() != Token::RBRACE) {
1224 Token::Value next = peek();
1226 case Token::IDENTIFIER:
1227 case Token::FUTURE_RESERVED_WORD:
1228 case Token::FUTURE_STRICT_RESERVED_WORD: {
1229 bool is_getter = false;
1230 bool is_setter = false;
1231 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
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 &&
1242 return Expression::Default();
1247 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
1248 checker.CheckProperty(name, type, CHECK_OK);
1249 ParseFunctionLiteral(false, CHECK_OK);
1250 if (peek() != Token::RBRACE) {
1251 Expect(Token::COMMA, CHECK_OK);
1253 continue; // restart the while
1255 checker.CheckProperty(next, kValueProperty, CHECK_OK);
1260 checker.CheckProperty(next, kValueProperty, CHECK_OK);
1265 checker.CheckProperty(next, kValueProperty, CHECK_OK);
1268 if (Token::IsKeyword(next)) {
1270 checker.CheckProperty(next, kValueProperty, CHECK_OK);
1272 // Unexpected token.
1274 return Expression::Default();
1278 Expect(Token::COLON, CHECK_OK);
1279 ParseAssignmentExpression(true, CHECK_OK);
1281 // TODO(1240767): Consider allowing trailing comma.
1282 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
1284 Expect(Token::RBRACE, CHECK_OK);
1286 scope_->NextMaterializedLiteralIndex();
1287 return Expression::Default();
1291 PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
1293 if (!scanner()->ScanRegExpPattern(seen_equal)) {
1295 ReportMessageAt(scanner()->location(), "unterminated_regexp", NULL);
1297 return Expression::Default();
1300 scope_->NextMaterializedLiteralIndex();
1302 if (!scanner()->ScanRegExpFlags()) {
1304 ReportMessageAt(scanner()->location(), "invalid_regexp_flags", NULL);
1306 return Expression::Default();
1309 return Expression::Default();
1313 PreParser::Arguments PreParser::ParseArguments(bool* ok) {
1315 // '(' (AssignmentExpression)*[','] ')'
1317 Expect(Token::LPAREN, ok);
1318 if (!*ok) return -1;
1319 bool done = (peek() == Token::RPAREN);
1322 ParseAssignmentExpression(true, ok);
1323 if (!*ok) return -1;
1325 done = (peek() == Token::RPAREN);
1327 Expect(Token::COMMA, ok);
1328 if (!*ok) return -1;
1331 Expect(Token::RPAREN, ok);
1336 PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator,
1339 // '(' FormalParameterList? ')' '{' FunctionBody '}'
1341 // Parse function body.
1342 ScopeType outer_scope_type = scope_->type();
1343 bool inside_with = scope_->IsInsideWith();
1344 Scope function_scope(&scope_, kFunctionScope);
1345 function_scope.set_is_generator(is_generator);
1346 // FormalParameterList ::
1347 // '(' (Identifier)*[','] ')'
1348 Expect(Token::LPAREN, CHECK_OK);
1349 int start_position = position();
1350 bool done = (peek() == Token::RPAREN);
1351 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
1353 Identifier id = ParseIdentifier(CHECK_OK);
1354 if (!id.IsValidStrictVariable()) {
1355 StrictModeIdentifierViolation(scanner()->location(),
1356 "strict_param_name",
1361 if (scanner()->is_literal_ascii()) {
1363 duplicate_finder.AddAsciiSymbol(scanner()->literal_ascii_string(), 1);
1366 duplicate_finder.AddUtf16Symbol(scanner()->literal_utf16_string(), 1);
1369 if (prev_value != 0) {
1370 SetStrictModeViolation(scanner()->location(),
1371 "strict_param_dupe",
1374 done = (peek() == Token::RPAREN);
1376 Expect(Token::COMMA, CHECK_OK);
1379 Expect(Token::RPAREN, CHECK_OK);
1381 // Determine if the function will be lazily compiled.
1382 // Currently only happens to top-level functions.
1383 // Optimistically assume that all top-level functions are lazily compiled.
1384 bool is_lazily_compiled = (outer_scope_type == kTopLevelScope &&
1385 !inside_with && allow_lazy() &&
1386 !parenthesized_function_);
1387 parenthesized_function_ = false;
1389 Expect(Token::LBRACE, CHECK_OK);
1390 if (is_lazily_compiled) {
1391 ParseLazyFunctionLiteralBody(CHECK_OK);
1393 ParseSourceElements(Token::RBRACE, ok);
1395 Expect(Token::RBRACE, CHECK_OK);
1397 if (!is_classic_mode()) {
1398 int end_position = scanner()->location().end_pos;
1399 CheckOctalLiteral(start_position, end_position, CHECK_OK);
1400 CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK);
1401 return Expression::StrictFunction();
1404 return Expression::Default();
1408 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
1409 int body_start = position();
1410 log_->PauseRecording();
1411 ParseSourceElements(Token::RBRACE, ok);
1412 log_->ResumeRecording();
1415 // Position right after terminal '}'.
1416 ASSERT_EQ(Token::RBRACE, scanner()->peek());
1417 int body_end = scanner()->peek_location().end_pos;
1418 log_->LogFunction(body_start, body_end,
1419 scope_->materialized_literal_count(),
1420 scope_->expected_properties(),
1425 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
1427 // '%' Identifier Arguments
1428 Expect(Token::MOD, CHECK_OK);
1429 if (!allow_natives_syntax()) {
1431 return Expression::Default();
1433 ParseIdentifier(CHECK_OK);
1436 return Expression::Default();
1442 void PreParser::LogSymbol() {
1443 int identifier_pos = position();
1444 if (scanner()->is_literal_ascii()) {
1445 log_->LogAsciiSymbol(identifier_pos, scanner()->literal_ascii_string());
1447 log_->LogUtf16Symbol(identifier_pos, scanner()->literal_utf16_string());
1452 PreParser::Expression PreParser::GetStringSymbol() {
1453 const int kUseStrictLength = 10;
1454 const char* kUseStrictChars = "use strict";
1456 if (scanner()->is_literal_ascii() &&
1457 scanner()->literal_length() == kUseStrictLength &&
1458 !scanner()->literal_contains_escapes() &&
1459 !strncmp(scanner()->literal_ascii_string().start(), kUseStrictChars,
1460 kUseStrictLength)) {
1461 return Expression::UseStrictStringLiteral();
1463 return Expression::StringLiteral();
1467 PreParser::Identifier PreParser::GetIdentifierSymbol() {
1469 if (scanner()->current_token() == Token::FUTURE_RESERVED_WORD) {
1470 return Identifier::FutureReserved();
1471 } else if (scanner()->current_token() ==
1472 Token::FUTURE_STRICT_RESERVED_WORD) {
1473 return Identifier::FutureStrictReserved();
1474 } else if (scanner()->current_token() == Token::YIELD) {
1475 return Identifier::Yield();
1477 if (scanner()->is_literal_ascii()) {
1478 // Detect strict-mode poison words.
1479 if (scanner()->literal_length() == 4 &&
1480 !strncmp(scanner()->literal_ascii_string().start(), "eval", 4)) {
1481 return Identifier::Eval();
1483 if (scanner()->literal_length() == 9 &&
1484 !strncmp(scanner()->literal_ascii_string().start(), "arguments", 9)) {
1485 return Identifier::Arguments();
1488 return Identifier::Default();
1492 PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
1493 Token::Value next = Next();
1495 case Token::FUTURE_RESERVED_WORD: {
1496 Scanner::Location location = scanner()->location();
1497 ReportMessageAt(location.beg_pos, location.end_pos,
1498 "reserved_word", NULL);
1500 return GetIdentifierSymbol();
1503 if (scope_->is_generator()) {
1504 // 'yield' in a generator is only valid as part of a YieldExpression.
1505 ReportMessageAt(scanner()->location(), "unexpected_token", "yield");
1507 return Identifier::Yield();
1510 case Token::FUTURE_STRICT_RESERVED_WORD:
1511 if (!is_classic_mode()) {
1512 Scanner::Location location = scanner()->location();
1513 ReportMessageAt(location.beg_pos, location.end_pos,
1514 "strict_reserved_word", NULL);
1518 case Token::IDENTIFIER:
1519 return GetIdentifierSymbol();
1522 return Identifier::Default();
1527 void PreParser::SetStrictModeViolation(Scanner::Location location,
1530 if (!is_classic_mode()) {
1531 ReportMessageAt(location, type, NULL);
1535 // Delay report in case this later turns out to be strict code
1536 // (i.e., for function names and parameters prior to a "use strict"
1538 // It's safe to overwrite an existing violation.
1539 // It's either from a function that turned out to be non-strict,
1540 // or it's in the current function (and we just need to report
1541 // one error), or it's in a unclosed nesting function that wasn't
1542 // strict (otherwise we would already be in strict mode).
1543 strict_mode_violation_location_ = location;
1544 strict_mode_violation_type_ = type;
1548 void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
1551 Scanner::Location location = strict_mode_violation_location_;
1552 if (location.IsValid() &&
1553 location.beg_pos > beg_pos && location.end_pos < end_pos) {
1554 ReportMessageAt(location, strict_mode_violation_type_, NULL);
1560 void PreParser::StrictModeIdentifierViolation(Scanner::Location location,
1561 const char* eval_args_type,
1562 Identifier identifier,
1564 const char* type = eval_args_type;
1565 if (identifier.IsFutureReserved()) {
1566 type = "reserved_word";
1567 } else if (identifier.IsFutureStrictReserved() || identifier.IsYield()) {
1568 type = "strict_reserved_word";
1570 if (!is_classic_mode()) {
1571 ReportMessageAt(location, type, NULL);
1575 strict_mode_violation_location_ = location;
1576 strict_mode_violation_type_ = type;
1580 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
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)));
1586 return Identifier::Default();
1588 if (next == Token::IDENTIFIER ||
1589 next == Token::FUTURE_RESERVED_WORD ||
1590 next == Token::FUTURE_STRICT_RESERVED_WORD) {
1591 return GetIdentifierSymbol();
1594 return Identifier::Default();
1600 // This function reads an identifier and determines whether or not it
1601 // is 'get' or 'set'.
1602 PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get,
1605 Identifier result = ParseIdentifierName(ok);
1606 if (!*ok) return Identifier::Default();
1607 if (scanner()->is_literal_ascii() &&
1608 scanner()->literal_length() == 3) {
1609 const char* token = scanner()->literal_ascii_string().start();
1610 *is_get = strncmp(token, "get", 3) == 0;
1611 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
1617 void PreParser::ObjectLiteralChecker::CheckProperty(Token::Value property,
1621 if (property == Token::NUMBER) {
1622 old = finder_.AddNumber(scanner()->literal_ascii_string(), type);
1623 } else if (scanner()->is_literal_ascii()) {
1624 old = finder_.AddAsciiSymbol(scanner()->literal_ascii_string(), type);
1626 old = finder_.AddUtf16Symbol(scanner()->literal_utf16_string(), type);
1628 PropertyKind old_type = static_cast<PropertyKind>(old);
1629 if (HasConflict(old_type, type)) {
1630 if (IsDataDataConflict(old_type, type)) {
1631 // Both are data properties.
1632 if (language_mode_ == CLASSIC_MODE) return;
1633 parser()->ReportMessageAt(scanner()->location(),
1634 "strict_duplicate_property");
1635 } else if (IsDataAccessorConflict(old_type, type)) {
1636 // Both a data and an accessor property with the same name.
1637 parser()->ReportMessageAt(scanner()->location(),
1638 "accessor_data_property");
1640 ASSERT(IsAccessorAccessorConflict(old_type, type));
1641 // Both accessors of the same type.
1642 parser()->ReportMessageAt(scanner()->location(),
1643 "accessor_get_set");