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"
48 // Usually defined in math.h, but not in MSVC.
50 int isfinite(double value);
55 PreParser::PreParseResult PreParser::PreParseLazyFunction(
56 i::LanguageMode mode, i::ParserRecorder* log) {
58 // Lazy functions always have trivial outer scopes (no with/catch scopes).
59 Scope top_scope(&scope_, kTopLevelScope);
60 set_language_mode(mode);
61 Scope function_scope(&scope_, kFunctionScope);
62 ASSERT_EQ(i::Token::LBRACE, scanner_->current_token());
64 int start_position = scanner_->peek_location().beg_pos;
65 ParseLazyFunctionLiteralBody(&ok);
66 if (stack_overflow_) return kPreParseStackOverflow;
68 ReportUnexpectedToken(scanner_->current_token());
70 ASSERT_EQ(i::Token::RBRACE, scanner_->peek());
71 if (!is_classic_mode()) {
72 int end_pos = scanner_->location().end_pos;
73 CheckOctalLiteral(start_position, end_pos, &ok);
75 CheckDelayedStrictModeViolation(start_position, end_pos, &ok);
79 return kPreParseSuccess;
83 // Preparsing checks a JavaScript program and emits preparse-data that helps
84 // a later parsing to be faster.
85 // See preparser-data.h for the data.
87 // The PreParser checks that the syntax follows the grammar for JavaScript,
88 // and collects some information about the program along the way.
89 // The grammar check is only performed in order to understand the program
90 // sufficiently to deduce some information about it, that can be used
91 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
92 // rather it is to speed up properly written and correct programs.
93 // That means that contextual checks (like a label being declared where
94 // it is used) are generally omitted.
96 void PreParser::ReportUnexpectedToken(i::Token::Value token) {
97 // We don't report stack overflows here, to avoid increasing the
98 // stack depth even further. Instead we report it after parsing is
99 // over, in ParseProgram.
100 if (token == i::Token::ILLEGAL && stack_overflow_) {
103 i::Scanner::Location source_location = scanner_->location();
105 // Four of the tokens are treated specially
108 return ReportMessageAt(source_location, "unexpected_eos", NULL);
109 case i::Token::NUMBER:
110 return ReportMessageAt(source_location, "unexpected_token_number", NULL);
111 case i::Token::STRING:
112 return ReportMessageAt(source_location, "unexpected_token_string", NULL);
113 case i::Token::IDENTIFIER:
114 return ReportMessageAt(source_location,
115 "unexpected_token_identifier", NULL);
116 case i::Token::FUTURE_RESERVED_WORD:
117 return ReportMessageAt(source_location, "unexpected_reserved", NULL);
118 case i::Token::FUTURE_STRICT_RESERVED_WORD:
119 return ReportMessageAt(source_location,
120 "unexpected_strict_reserved", NULL);
122 const char* name = i::Token::String(token);
123 ReportMessageAt(source_location, "unexpected_token", name);
128 // Checks whether octal literal last seen is between beg_pos and end_pos.
129 // If so, reports an error.
130 void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
131 i::Scanner::Location octal = scanner_->octal_position();
132 if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
133 ReportMessageAt(octal, "strict_octal_literal", NULL);
134 scanner_->clear_octal_position();
140 #define CHECK_OK ok); \
141 if (!*ok) return kUnknownSourceElements; \
143 #define DUMMY ) // to make indentation work
147 PreParser::Statement PreParser::ParseSourceElement(bool* ok) {
148 // (Ecma 262 5th Edition, clause 14):
151 // FunctionDeclaration
153 // In harmony mode we allow additionally the following productions
159 case i::Token::FUNCTION:
160 return ParseFunctionDeclaration(ok);
162 case i::Token::CONST:
163 return ParseVariableStatement(kSourceElement, ok);
165 return ParseStatement(ok);
170 PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
173 // (Statement)* <end_token>
175 bool allow_directive_prologue = true;
176 while (peek() != end_token) {
177 Statement statement = ParseSourceElement(CHECK_OK);
178 if (allow_directive_prologue) {
179 if (statement.IsUseStrictLiteral()) {
180 set_language_mode(harmony_scoping_ ?
181 i::EXTENDED_MODE : i::STRICT_MODE);
182 } else if (!statement.IsStringLiteral()) {
183 allow_directive_prologue = false;
187 return kUnknownSourceElements;
192 #define CHECK_OK ok); \
193 if (!*ok) return Statement::Default(); \
195 #define DUMMY ) // to make indentation work
199 PreParser::Statement PreParser::ParseStatement(bool* ok) {
204 // ExpressionStatement
206 // IterationStatement
217 // Note: Since labels can only be used by 'break' and 'continue'
218 // statements, which themselves are only valid within blocks,
219 // iterations or 'switch' statements (i.e., BreakableStatements),
220 // labels can be simply ignored in all other cases; except for
221 // trivial labeled break statements 'label: break label' which is
222 // parsed into an empty statement.
224 // Keep the source position of the statement
226 case i::Token::LBRACE:
227 return ParseBlock(ok);
229 case i::Token::CONST:
232 return ParseVariableStatement(kStatement, ok);
234 case i::Token::SEMICOLON:
236 return Statement::Default();
239 return ParseIfStatement(ok);
242 return ParseDoWhileStatement(ok);
244 case i::Token::WHILE:
245 return ParseWhileStatement(ok);
248 return ParseForStatement(ok);
250 case i::Token::CONTINUE:
251 return ParseContinueStatement(ok);
253 case i::Token::BREAK:
254 return ParseBreakStatement(ok);
256 case i::Token::RETURN:
257 return ParseReturnStatement(ok);
260 return ParseWithStatement(ok);
262 case i::Token::SWITCH:
263 return ParseSwitchStatement(ok);
265 case i::Token::THROW:
266 return ParseThrowStatement(ok);
269 return ParseTryStatement(ok);
271 case i::Token::FUNCTION: {
272 i::Scanner::Location start_location = scanner_->peek_location();
273 Statement statement = ParseFunctionDeclaration(CHECK_OK);
274 i::Scanner::Location end_location = scanner_->location();
275 if (!is_classic_mode()) {
276 ReportMessageAt(start_location.beg_pos, end_location.end_pos,
277 "strict_function", NULL);
279 return Statement::Default();
285 case i::Token::DEBUGGER:
286 return ParseDebuggerStatement(ok);
289 return ParseExpressionOrLabelledStatement(ok);
294 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
295 // FunctionDeclaration ::
296 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
297 Expect(i::Token::FUNCTION, CHECK_OK);
299 Identifier identifier = ParseIdentifier(CHECK_OK);
300 i::Scanner::Location location = scanner_->location();
302 Expression function_value = ParseFunctionLiteral(CHECK_OK);
304 if (function_value.IsStrictFunction() &&
305 !identifier.IsValidStrictVariable()) {
306 // Strict mode violation, using either reserved word or eval/arguments
307 // as name of strict function.
308 const char* type = "strict_function_name";
309 if (identifier.IsFutureStrictReserved()) {
310 type = "strict_reserved_word";
312 ReportMessageAt(location, type, NULL);
315 return Statement::FunctionDeclaration();
319 PreParser::Statement PreParser::ParseBlock(bool* ok) {
321 // '{' Statement* '}'
323 // Note that a Block does not introduce a new execution scope!
324 // (ECMA-262, 3rd, 12.2)
326 Expect(i::Token::LBRACE, CHECK_OK);
327 while (peek() != i::Token::RBRACE) {
328 if (is_extended_mode()) {
329 ParseSourceElement(CHECK_OK);
331 ParseStatement(CHECK_OK);
334 Expect(i::Token::RBRACE, ok);
335 return Statement::Default();
339 PreParser::Statement PreParser::ParseVariableStatement(
340 VariableDeclarationContext var_context,
342 // VariableStatement ::
343 // VariableDeclarations ';'
345 Statement result = ParseVariableDeclarations(var_context,
349 ExpectSemicolon(CHECK_OK);
354 // If the variable declaration declares exactly one non-const
355 // variable, then *var is set to that variable. In all other cases,
356 // *var is untouched; in particular, it is the caller's responsibility
357 // to initialize it properly. This mechanism is also used for the parsing
358 // of 'for-in' loops.
359 PreParser::Statement PreParser::ParseVariableDeclarations(
360 VariableDeclarationContext var_context,
361 VariableDeclarationProperties* decl_props,
364 // VariableDeclarations ::
365 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
367 // The ES6 Draft Rev3 specifies the following grammar for const declarations
369 // ConstDeclaration ::
370 // const ConstBinding (',' ConstBinding)* ';'
372 // Identifier '=' AssignmentExpression
376 // BindingPattern '=' AssignmentExpression
377 bool require_initializer = false;
378 if (peek() == i::Token::VAR) {
379 Consume(i::Token::VAR);
380 } else if (peek() == i::Token::CONST) {
381 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
383 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
385 // * It is a Syntax Error if the code that matches this production is not
386 // contained in extended code.
388 // However disallowing const in classic mode will break compatibility with
389 // existing pages. Therefore we keep allowing const with the old
390 // non-harmony semantics in classic mode.
391 Consume(i::Token::CONST);
392 switch (language_mode()) {
393 case i::CLASSIC_MODE:
395 case i::STRICT_MODE: {
396 i::Scanner::Location location = scanner_->peek_location();
397 ReportMessageAt(location, "strict_const", NULL);
399 return Statement::Default();
401 case i::EXTENDED_MODE:
402 if (var_context != kSourceElement &&
403 var_context != kForStatement) {
404 i::Scanner::Location location = scanner_->peek_location();
405 ReportMessageAt(location.beg_pos, location.end_pos,
406 "unprotected_const", NULL);
408 return Statement::Default();
410 require_initializer = true;
413 } else if (peek() == i::Token::LET) {
414 // ES6 Draft Rev4 section 12.2.1:
416 // LetDeclaration : let LetBindingList ;
418 // * It is a Syntax Error if the code that matches this production is not
419 // contained in extended code.
420 if (!is_extended_mode()) {
421 i::Scanner::Location location = scanner_->peek_location();
422 ReportMessageAt(location.beg_pos, location.end_pos,
423 "illegal_let", NULL);
425 return Statement::Default();
427 Consume(i::Token::LET);
428 if (var_context != kSourceElement &&
429 var_context != kForStatement) {
430 i::Scanner::Location location = scanner_->peek_location();
431 ReportMessageAt(location.beg_pos, location.end_pos,
432 "unprotected_let", NULL);
434 return Statement::Default();
438 return Statement::Default();
441 // The scope of a var/const declared variable anywhere inside a function
442 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
443 // of a let declared variable is the scope of the immediately enclosing
445 int nvars = 0; // the number of variables declared
447 // Parse variable name.
448 if (nvars > 0) Consume(i::Token::COMMA);
449 Identifier identifier = ParseIdentifier(CHECK_OK);
450 if (!is_classic_mode() && !identifier.IsValidStrictVariable()) {
451 StrictModeIdentifierViolation(scanner_->location(),
455 return Statement::Default();
458 if (peek() == i::Token::ASSIGN || require_initializer) {
459 Expect(i::Token::ASSIGN, CHECK_OK);
460 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
461 if (decl_props != NULL) *decl_props = kHasInitializers;
463 } while (peek() == i::Token::COMMA);
465 if (num_decl != NULL) *num_decl = nvars;
466 return Statement::Default();
470 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
471 // ExpressionStatement | LabelledStatement ::
473 // Identifier ':' Statement
475 Expression expr = ParseExpression(true, CHECK_OK);
476 if (expr.IsRawIdentifier()) {
477 ASSERT(!expr.AsIdentifier().IsFutureReserved());
478 ASSERT(is_classic_mode() || !expr.AsIdentifier().IsFutureStrictReserved());
479 if (peek() == i::Token::COLON) {
480 Consume(i::Token::COLON);
481 return ParseStatement(ok);
483 // Preparsing is disabled for extensions (because the extension details
484 // aren't passed to lazily compiled functions), so we don't
485 // accept "native function" in the preparser.
487 // Parsed expression statement.
488 ExpectSemicolon(CHECK_OK);
489 return Statement::ExpressionStatement(expr);
493 PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
495 // 'if' '(' Expression ')' Statement ('else' Statement)?
497 Expect(i::Token::IF, CHECK_OK);
498 Expect(i::Token::LPAREN, CHECK_OK);
499 ParseExpression(true, CHECK_OK);
500 Expect(i::Token::RPAREN, CHECK_OK);
501 ParseStatement(CHECK_OK);
502 if (peek() == i::Token::ELSE) {
504 ParseStatement(CHECK_OK);
506 return Statement::Default();
510 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
511 // ContinueStatement ::
512 // 'continue' [no line terminator] Identifier? ';'
514 Expect(i::Token::CONTINUE, CHECK_OK);
515 i::Token::Value tok = peek();
516 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
517 tok != i::Token::SEMICOLON &&
518 tok != i::Token::RBRACE &&
519 tok != i::Token::EOS) {
520 ParseIdentifier(CHECK_OK);
522 ExpectSemicolon(CHECK_OK);
523 return Statement::Default();
527 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
529 // 'break' [no line terminator] Identifier? ';'
531 Expect(i::Token::BREAK, CHECK_OK);
532 i::Token::Value tok = peek();
533 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
534 tok != i::Token::SEMICOLON &&
535 tok != i::Token::RBRACE &&
536 tok != i::Token::EOS) {
537 ParseIdentifier(CHECK_OK);
539 ExpectSemicolon(CHECK_OK);
540 return Statement::Default();
544 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
545 // ReturnStatement ::
546 // 'return' [no line terminator] Expression? ';'
548 // Consume the return token. It is necessary to do the before
549 // reporting any errors on it, because of the way errors are
550 // reported (underlining).
551 Expect(i::Token::RETURN, CHECK_OK);
553 // An ECMAScript program is considered syntactically incorrect if it
554 // contains a return statement that is not within the body of a
555 // function. See ECMA-262, section 12.9, page 67.
556 // This is not handled during preparsing.
558 i::Token::Value tok = peek();
559 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
560 tok != i::Token::SEMICOLON &&
561 tok != i::Token::RBRACE &&
562 tok != i::Token::EOS) {
563 ParseExpression(true, CHECK_OK);
565 ExpectSemicolon(CHECK_OK);
566 return Statement::Default();
570 PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
572 // 'with' '(' Expression ')' Statement
573 Expect(i::Token::WITH, CHECK_OK);
574 if (!is_classic_mode()) {
575 i::Scanner::Location location = scanner_->location();
576 ReportMessageAt(location, "strict_mode_with", NULL);
578 return Statement::Default();
580 Expect(i::Token::LPAREN, CHECK_OK);
581 ParseExpression(true, CHECK_OK);
582 Expect(i::Token::RPAREN, CHECK_OK);
584 Scope::InsideWith iw(scope_);
585 ParseStatement(CHECK_OK);
586 return Statement::Default();
590 PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
591 // SwitchStatement ::
592 // 'switch' '(' Expression ')' '{' CaseClause* '}'
594 Expect(i::Token::SWITCH, CHECK_OK);
595 Expect(i::Token::LPAREN, CHECK_OK);
596 ParseExpression(true, CHECK_OK);
597 Expect(i::Token::RPAREN, CHECK_OK);
599 Expect(i::Token::LBRACE, CHECK_OK);
600 i::Token::Value token = peek();
601 while (token != i::Token::RBRACE) {
602 if (token == i::Token::CASE) {
603 Expect(i::Token::CASE, CHECK_OK);
604 ParseExpression(true, CHECK_OK);
605 Expect(i::Token::COLON, CHECK_OK);
606 } else if (token == i::Token::DEFAULT) {
607 Expect(i::Token::DEFAULT, CHECK_OK);
608 Expect(i::Token::COLON, CHECK_OK);
610 ParseStatement(CHECK_OK);
614 Expect(i::Token::RBRACE, ok);
615 return Statement::Default();
619 PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
621 // 'do' Statement 'while' '(' Expression ')' ';'
623 Expect(i::Token::DO, CHECK_OK);
624 ParseStatement(CHECK_OK);
625 Expect(i::Token::WHILE, CHECK_OK);
626 Expect(i::Token::LPAREN, CHECK_OK);
627 ParseExpression(true, CHECK_OK);
628 Expect(i::Token::RPAREN, ok);
629 if (peek() == i::Token::SEMICOLON) Consume(i::Token::SEMICOLON);
630 return Statement::Default();
634 PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
636 // 'while' '(' Expression ')' Statement
638 Expect(i::Token::WHILE, CHECK_OK);
639 Expect(i::Token::LPAREN, CHECK_OK);
640 ParseExpression(true, CHECK_OK);
641 Expect(i::Token::RPAREN, CHECK_OK);
643 return Statement::Default();
647 PreParser::Statement PreParser::ParseForStatement(bool* ok) {
649 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
651 Expect(i::Token::FOR, CHECK_OK);
652 Expect(i::Token::LPAREN, CHECK_OK);
653 if (peek() != i::Token::SEMICOLON) {
654 if (peek() == i::Token::VAR || peek() == i::Token::CONST ||
655 peek() == i::Token::LET) {
656 bool is_let = peek() == i::Token::LET;
658 VariableDeclarationProperties decl_props = kHasNoInitializers;
659 ParseVariableDeclarations(
660 kForStatement, &decl_props, &decl_count, CHECK_OK);
661 bool accept_IN = decl_count == 1 &&
662 !(is_let && decl_props == kHasInitializers);
663 if (peek() == i::Token::IN && accept_IN) {
664 Expect(i::Token::IN, CHECK_OK);
665 ParseExpression(true, CHECK_OK);
666 Expect(i::Token::RPAREN, CHECK_OK);
668 ParseStatement(CHECK_OK);
669 return Statement::Default();
672 ParseExpression(false, CHECK_OK);
673 if (peek() == i::Token::IN) {
674 Expect(i::Token::IN, CHECK_OK);
675 ParseExpression(true, CHECK_OK);
676 Expect(i::Token::RPAREN, CHECK_OK);
678 ParseStatement(CHECK_OK);
679 return Statement::Default();
684 // Parsed initializer at this point.
685 Expect(i::Token::SEMICOLON, CHECK_OK);
687 if (peek() != i::Token::SEMICOLON) {
688 ParseExpression(true, CHECK_OK);
690 Expect(i::Token::SEMICOLON, CHECK_OK);
692 if (peek() != i::Token::RPAREN) {
693 ParseExpression(true, CHECK_OK);
695 Expect(i::Token::RPAREN, CHECK_OK);
698 return Statement::Default();
702 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
704 // 'throw' [no line terminator] Expression ';'
706 Expect(i::Token::THROW, CHECK_OK);
707 if (scanner_->HasAnyLineTerminatorBeforeNext()) {
708 i::Scanner::Location pos = scanner_->location();
709 ReportMessageAt(pos, "newline_after_throw", NULL);
711 return Statement::Default();
713 ParseExpression(true, CHECK_OK);
715 return Statement::Default();
719 PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
722 // 'try' Block Finally
723 // 'try' Block Catch Finally
726 // 'catch' '(' Identifier ')' Block
731 // In preparsing, allow any number of catch/finally blocks, including zero
734 Expect(i::Token::TRY, CHECK_OK);
736 ParseBlock(CHECK_OK);
738 bool catch_or_finally_seen = false;
739 if (peek() == i::Token::CATCH) {
740 Consume(i::Token::CATCH);
741 Expect(i::Token::LPAREN, CHECK_OK);
742 Identifier id = ParseIdentifier(CHECK_OK);
743 if (!is_classic_mode() && !id.IsValidStrictVariable()) {
744 StrictModeIdentifierViolation(scanner_->location(),
745 "strict_catch_variable",
748 return Statement::Default();
750 Expect(i::Token::RPAREN, CHECK_OK);
751 { Scope::InsideWith iw(scope_);
752 ParseBlock(CHECK_OK);
754 catch_or_finally_seen = true;
756 if (peek() == i::Token::FINALLY) {
757 Consume(i::Token::FINALLY);
758 ParseBlock(CHECK_OK);
759 catch_or_finally_seen = true;
761 if (!catch_or_finally_seen) {
764 return Statement::Default();
768 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
769 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
770 // contexts this is used as a statement which invokes the debugger as if a
771 // break point is present.
772 // DebuggerStatement ::
775 Expect(i::Token::DEBUGGER, CHECK_OK);
777 return Statement::Default();
782 #define CHECK_OK ok); \
783 if (!*ok) return Expression::Default(); \
785 #define DUMMY ) // to make indentation work
790 PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) {
792 // AssignmentExpression
793 // Expression ',' AssignmentExpression
795 Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
796 while (peek() == i::Token::COMMA) {
797 Expect(i::Token::COMMA, CHECK_OK);
798 ParseAssignmentExpression(accept_IN, CHECK_OK);
799 result = Expression::Default();
806 PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
808 // AssignmentExpression ::
809 // ConditionalExpression
810 // LeftHandSideExpression AssignmentOperator AssignmentExpression
812 i::Scanner::Location before = scanner_->peek_location();
813 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
815 if (!i::Token::IsAssignmentOp(peek())) {
816 // Parsed conditional expression only (no assignment).
820 if (!is_classic_mode() &&
821 expression.IsIdentifier() &&
822 expression.AsIdentifier().IsEvalOrArguments()) {
823 i::Scanner::Location after = scanner_->location();
824 ReportMessageAt(before.beg_pos, after.end_pos,
825 "strict_lhs_assignment", NULL);
827 return Expression::Default();
830 i::Token::Value op = Next(); // Get assignment operator.
831 ParseAssignmentExpression(accept_IN, CHECK_OK);
833 if ((op == i::Token::ASSIGN) && expression.IsThisProperty()) {
834 scope_->AddProperty();
837 return Expression::Default();
842 PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
844 // ConditionalExpression ::
845 // LogicalOrExpression
846 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
848 // We start using the binary expression parser for prec >= 4 only!
849 Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
850 if (peek() != i::Token::CONDITIONAL) return expression;
851 Consume(i::Token::CONDITIONAL);
852 // In parsing the first assignment expression in conditional
853 // expressions we always accept the 'in' keyword; see ECMA-262,
854 // section 11.12, page 58.
855 ParseAssignmentExpression(true, CHECK_OK);
856 Expect(i::Token::COLON, CHECK_OK);
857 ParseAssignmentExpression(accept_IN, CHECK_OK);
858 return Expression::Default();
862 int PreParser::Precedence(i::Token::Value tok, bool accept_IN) {
863 if (tok == i::Token::IN && !accept_IN)
864 return 0; // 0 precedence will terminate binary expression parsing
866 return i::Token::Precedence(tok);
871 PreParser::Expression PreParser::ParseBinaryExpression(int prec,
874 Expression result = ParseUnaryExpression(CHECK_OK);
875 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
877 while (Precedence(peek(), accept_IN) == prec1) {
879 ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
880 result = Expression::Default();
887 PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
888 // UnaryExpression ::
890 // 'delete' UnaryExpression
891 // 'void' UnaryExpression
892 // 'typeof' UnaryExpression
893 // '++' UnaryExpression
894 // '--' UnaryExpression
895 // '+' UnaryExpression
896 // '-' UnaryExpression
897 // '~' UnaryExpression
898 // '!' UnaryExpression
900 i::Token::Value op = peek();
901 if (i::Token::IsUnaryOp(op)) {
903 ParseUnaryExpression(ok);
904 return Expression::Default();
905 } else if (i::Token::IsCountOp(op)) {
907 i::Scanner::Location before = scanner_->peek_location();
908 Expression expression = ParseUnaryExpression(CHECK_OK);
909 if (!is_classic_mode() &&
910 expression.IsIdentifier() &&
911 expression.AsIdentifier().IsEvalOrArguments()) {
912 i::Scanner::Location after = scanner_->location();
913 ReportMessageAt(before.beg_pos, after.end_pos,
914 "strict_lhs_prefix", NULL);
917 return Expression::Default();
919 return ParsePostfixExpression(ok);
924 PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
925 // PostfixExpression ::
926 // LeftHandSideExpression ('++' | '--')?
928 i::Scanner::Location before = scanner_->peek_location();
929 Expression expression = ParseLeftHandSideExpression(CHECK_OK);
930 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
931 i::Token::IsCountOp(peek())) {
932 if (!is_classic_mode() &&
933 expression.IsIdentifier() &&
934 expression.AsIdentifier().IsEvalOrArguments()) {
935 i::Scanner::Location after = scanner_->location();
936 ReportMessageAt(before.beg_pos, after.end_pos,
937 "strict_lhs_postfix", NULL);
939 return Expression::Default();
942 return Expression::Default();
948 PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) {
949 // LeftHandSideExpression ::
950 // (NewExpression | MemberExpression) ...
952 Expression result = Expression::Default();
953 if (peek() == i::Token::NEW) {
954 result = ParseNewExpression(CHECK_OK);
956 result = ParseMemberExpression(CHECK_OK);
961 case i::Token::LBRACK: {
962 Consume(i::Token::LBRACK);
963 ParseExpression(true, CHECK_OK);
964 Expect(i::Token::RBRACK, CHECK_OK);
965 if (result.IsThis()) {
966 result = Expression::ThisProperty();
968 result = Expression::Default();
973 case i::Token::LPAREN: {
974 ParseArguments(CHECK_OK);
975 result = Expression::Default();
979 case i::Token::PERIOD: {
980 Consume(i::Token::PERIOD);
981 ParseIdentifierName(CHECK_OK);
982 if (result.IsThis()) {
983 result = Expression::ThisProperty();
985 result = Expression::Default();
997 PreParser::Expression PreParser::ParseNewExpression(bool* ok) {
999 // ('new')+ MemberExpression
1001 // The grammar for new expressions is pretty warped. The keyword
1002 // 'new' can either be a part of the new expression (where it isn't
1003 // followed by an argument list) or a part of the member expression,
1004 // where it must be followed by an argument list. To accommodate
1005 // this, we parse the 'new' keywords greedily and keep track of how
1006 // many we have parsed. This information is then passed on to the
1007 // member expression parser, which is only allowed to match argument
1008 // lists as long as it has 'new' prefixes left
1009 unsigned new_count = 0;
1011 Consume(i::Token::NEW);
1013 } while (peek() == i::Token::NEW);
1015 return ParseMemberWithNewPrefixesExpression(new_count, ok);
1019 PreParser::Expression PreParser::ParseMemberExpression(bool* ok) {
1020 return ParseMemberWithNewPrefixesExpression(0, ok);
1024 PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
1025 unsigned new_count, bool* ok) {
1026 // MemberExpression ::
1027 // (PrimaryExpression | FunctionLiteral)
1028 // ('[' Expression ']' | '.' Identifier | Arguments)*
1030 // Parse the initial primary or function expression.
1031 Expression result = Expression::Default();
1032 if (peek() == i::Token::FUNCTION) {
1033 Consume(i::Token::FUNCTION);
1034 Identifier identifier = Identifier::Default();
1035 if (peek_any_identifier()) {
1036 identifier = ParseIdentifier(CHECK_OK);
1038 result = ParseFunctionLiteral(CHECK_OK);
1039 if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
1040 StrictModeIdentifierViolation(scanner_->location(),
1041 "strict_function_name",
1044 return Expression::Default();
1047 result = ParsePrimaryExpression(CHECK_OK);
1052 case i::Token::LBRACK: {
1053 Consume(i::Token::LBRACK);
1054 ParseExpression(true, CHECK_OK);
1055 Expect(i::Token::RBRACK, CHECK_OK);
1056 if (result.IsThis()) {
1057 result = Expression::ThisProperty();
1059 result = Expression::Default();
1063 case i::Token::PERIOD: {
1064 Consume(i::Token::PERIOD);
1065 ParseIdentifierName(CHECK_OK);
1066 if (result.IsThis()) {
1067 result = Expression::ThisProperty();
1069 result = Expression::Default();
1073 case i::Token::LPAREN: {
1074 if (new_count == 0) return result;
1075 // Consume one of the new prefixes (already parsed).
1076 ParseArguments(CHECK_OK);
1078 result = Expression::Default();
1088 PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
1089 // PrimaryExpression ::
1100 // '(' Expression ')'
1102 Expression result = Expression::Default();
1104 case i::Token::THIS: {
1106 result = Expression::This();
1110 case i::Token::FUTURE_RESERVED_WORD: {
1112 i::Scanner::Location location = scanner_->location();
1113 ReportMessageAt(location.beg_pos, location.end_pos,
1114 "reserved_word", NULL);
1116 return Expression::Default();
1119 case i::Token::FUTURE_STRICT_RESERVED_WORD:
1120 if (!is_classic_mode()) {
1122 i::Scanner::Location location = scanner_->location();
1123 ReportMessageAt(location, "strict_reserved_word", NULL);
1125 return Expression::Default();
1128 case i::Token::IDENTIFIER: {
1129 Identifier id = ParseIdentifier(CHECK_OK);
1130 result = Expression::FromIdentifier(id);
1134 case i::Token::NULL_LITERAL:
1135 case i::Token::TRUE_LITERAL:
1136 case i::Token::FALSE_LITERAL:
1137 case i::Token::NUMBER: {
1141 case i::Token::STRING: {
1143 result = GetStringSymbol();
1147 case i::Token::ASSIGN_DIV:
1148 result = ParseRegExpLiteral(true, CHECK_OK);
1152 result = ParseRegExpLiteral(false, CHECK_OK);
1155 case i::Token::LBRACK:
1156 result = ParseArrayLiteral(CHECK_OK);
1159 case i::Token::LBRACE:
1160 result = ParseObjectLiteral(CHECK_OK);
1163 case i::Token::LPAREN:
1164 Consume(i::Token::LPAREN);
1165 parenthesized_function_ = (peek() == i::Token::FUNCTION);
1166 result = ParseExpression(true, CHECK_OK);
1167 Expect(i::Token::RPAREN, CHECK_OK);
1168 result = result.Parenthesize();
1172 result = ParseV8Intrinsic(CHECK_OK);
1178 return Expression::Default();
1186 PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
1188 // '[' Expression? (',' Expression?)* ']'
1189 Expect(i::Token::LBRACK, CHECK_OK);
1190 while (peek() != i::Token::RBRACK) {
1191 if (peek() != i::Token::COMMA) {
1192 ParseAssignmentExpression(true, CHECK_OK);
1194 if (peek() != i::Token::RBRACK) {
1195 Expect(i::Token::COMMA, CHECK_OK);
1198 Expect(i::Token::RBRACK, CHECK_OK);
1200 scope_->NextMaterializedLiteralIndex();
1201 return Expression::Default();
1204 void PreParser::CheckDuplicate(DuplicateFinder* finder,
1205 i::Token::Value property,
1209 if (property == i::Token::NUMBER) {
1210 old_type = finder->AddNumber(scanner_->literal_ascii_string(), type);
1211 } else if (scanner_->is_literal_ascii()) {
1212 old_type = finder->AddAsciiSymbol(scanner_->literal_ascii_string(),
1215 old_type = finder->AddUtf16Symbol(scanner_->literal_utf16_string(), type);
1217 if (HasConflict(old_type, type)) {
1218 if (IsDataDataConflict(old_type, type)) {
1219 // Both are data properties.
1220 if (is_classic_mode()) return;
1221 ReportMessageAt(scanner_->location(),
1222 "strict_duplicate_property", NULL);
1223 } else if (IsDataAccessorConflict(old_type, type)) {
1224 // Both a data and an accessor property with the same name.
1225 ReportMessageAt(scanner_->location(),
1226 "accessor_data_property", NULL);
1228 ASSERT(IsAccessorAccessorConflict(old_type, type));
1229 // Both accessors of the same type.
1230 ReportMessageAt(scanner_->location(),
1231 "accessor_get_set", NULL);
1238 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
1241 // ((IdentifierName | String | Number) ':' AssignmentExpression)
1242 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1245 Expect(i::Token::LBRACE, CHECK_OK);
1246 DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1247 while (peek() != i::Token::RBRACE) {
1248 i::Token::Value next = peek();
1250 case i::Token::IDENTIFIER:
1251 case i::Token::FUTURE_RESERVED_WORD:
1252 case i::Token::FUTURE_STRICT_RESERVED_WORD: {
1253 bool is_getter = false;
1254 bool is_setter = false;
1255 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
1256 if ((is_getter || is_setter) && peek() != i::Token::COLON) {
1257 i::Token::Value name = Next();
1258 bool is_keyword = i::Token::IsKeyword(name);
1259 if (name != i::Token::IDENTIFIER &&
1260 name != i::Token::FUTURE_RESERVED_WORD &&
1261 name != i::Token::FUTURE_STRICT_RESERVED_WORD &&
1262 name != i::Token::NUMBER &&
1263 name != i::Token::STRING &&
1266 return Expression::Default();
1271 PropertyType type = is_getter ? kGetterProperty : kSetterProperty;
1272 CheckDuplicate(&duplicate_finder, name, type, CHECK_OK);
1273 ParseFunctionLiteral(CHECK_OK);
1274 if (peek() != i::Token::RBRACE) {
1275 Expect(i::Token::COMMA, CHECK_OK);
1277 continue; // restart the while
1279 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1282 case i::Token::STRING:
1284 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1287 case i::Token::NUMBER:
1289 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1292 if (i::Token::IsKeyword(next)) {
1294 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1296 // Unexpected token.
1298 return Expression::Default();
1302 Expect(i::Token::COLON, CHECK_OK);
1303 ParseAssignmentExpression(true, CHECK_OK);
1305 // TODO(1240767): Consider allowing trailing comma.
1306 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
1308 Expect(i::Token::RBRACE, CHECK_OK);
1310 scope_->NextMaterializedLiteralIndex();
1311 return Expression::Default();
1315 PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
1317 if (!scanner_->ScanRegExpPattern(seen_equal)) {
1319 ReportMessageAt(scanner_->location(), "unterminated_regexp", NULL);
1321 return Expression::Default();
1324 scope_->NextMaterializedLiteralIndex();
1326 if (!scanner_->ScanRegExpFlags()) {
1328 ReportMessageAt(scanner_->location(), "invalid_regexp_flags", NULL);
1330 return Expression::Default();
1333 return Expression::Default();
1337 PreParser::Arguments PreParser::ParseArguments(bool* ok) {
1339 // '(' (AssignmentExpression)*[','] ')'
1341 Expect(i::Token::LPAREN, ok);
1342 if (!*ok) return -1;
1343 bool done = (peek() == i::Token::RPAREN);
1346 ParseAssignmentExpression(true, ok);
1347 if (!*ok) return -1;
1349 done = (peek() == i::Token::RPAREN);
1351 Expect(i::Token::COMMA, ok);
1352 if (!*ok) return -1;
1355 Expect(i::Token::RPAREN, ok);
1360 PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
1362 // '(' FormalParameterList? ')' '{' FunctionBody '}'
1364 // Parse function body.
1365 ScopeType outer_scope_type = scope_->type();
1366 bool inside_with = scope_->IsInsideWith();
1367 Scope function_scope(&scope_, kFunctionScope);
1368 // FormalParameterList ::
1369 // '(' (Identifier)*[','] ')'
1370 Expect(i::Token::LPAREN, CHECK_OK);
1371 int start_position = scanner_->location().beg_pos;
1372 bool done = (peek() == i::Token::RPAREN);
1373 DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1375 Identifier id = ParseIdentifier(CHECK_OK);
1376 if (!id.IsValidStrictVariable()) {
1377 StrictModeIdentifierViolation(scanner_->location(),
1378 "strict_param_name",
1383 if (scanner_->is_literal_ascii()) {
1385 duplicate_finder.AddAsciiSymbol(scanner_->literal_ascii_string(), 1);
1388 duplicate_finder.AddUtf16Symbol(scanner_->literal_utf16_string(), 1);
1391 if (prev_value != 0) {
1392 SetStrictModeViolation(scanner_->location(),
1393 "strict_param_dupe",
1396 done = (peek() == i::Token::RPAREN);
1398 Expect(i::Token::COMMA, CHECK_OK);
1401 Expect(i::Token::RPAREN, CHECK_OK);
1403 // Determine if the function will be lazily compiled.
1404 // Currently only happens to top-level functions.
1405 // Optimistically assume that all top-level functions are lazily compiled.
1406 bool is_lazily_compiled = (outer_scope_type == kTopLevelScope &&
1407 !inside_with && allow_lazy_ &&
1408 !parenthesized_function_);
1409 parenthesized_function_ = false;
1411 Expect(i::Token::LBRACE, CHECK_OK);
1412 if (is_lazily_compiled) {
1413 ParseLazyFunctionLiteralBody(CHECK_OK);
1415 ParseSourceElements(i::Token::RBRACE, ok);
1417 Expect(i::Token::RBRACE, CHECK_OK);
1419 if (!is_classic_mode()) {
1420 int end_position = scanner_->location().end_pos;
1421 CheckOctalLiteral(start_position, end_position, CHECK_OK);
1422 CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK);
1423 return Expression::StrictFunction();
1426 return Expression::Default();
1430 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
1431 int body_start = scanner_->location().beg_pos;
1432 log_->PauseRecording();
1433 ParseSourceElements(i::Token::RBRACE, ok);
1434 log_->ResumeRecording();
1437 // Position right after terminal '}'.
1438 ASSERT_EQ(i::Token::RBRACE, scanner_->peek());
1439 int body_end = scanner_->peek_location().end_pos;
1440 log_->LogFunction(body_start, body_end,
1441 scope_->materialized_literal_count(),
1442 scope_->expected_properties(),
1447 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
1449 // '%' Identifier Arguments
1450 Expect(i::Token::MOD, CHECK_OK);
1451 if (!allow_natives_syntax_) {
1453 return Expression::Default();
1455 ParseIdentifier(CHECK_OK);
1458 return Expression::Default();
1464 void PreParser::ExpectSemicolon(bool* ok) {
1465 // Check for automatic semicolon insertion according to
1466 // the rules given in ECMA-262, section 7.9, page 21.
1467 i::Token::Value tok = peek();
1468 if (tok == i::Token::SEMICOLON) {
1472 if (scanner_->HasAnyLineTerminatorBeforeNext() ||
1473 tok == i::Token::RBRACE ||
1474 tok == i::Token::EOS) {
1477 Expect(i::Token::SEMICOLON, ok);
1481 void PreParser::LogSymbol() {
1482 int identifier_pos = scanner_->location().beg_pos;
1483 if (scanner_->is_literal_ascii()) {
1484 log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
1486 log_->LogUtf16Symbol(identifier_pos, scanner_->literal_utf16_string());
1491 PreParser::Expression PreParser::GetStringSymbol() {
1492 const int kUseStrictLength = 10;
1493 const char* kUseStrictChars = "use strict";
1495 if (scanner_->is_literal_ascii() &&
1496 scanner_->literal_length() == kUseStrictLength &&
1497 !scanner_->literal_contains_escapes() &&
1498 !strncmp(scanner_->literal_ascii_string().start(), kUseStrictChars,
1499 kUseStrictLength)) {
1500 return Expression::UseStrictStringLiteral();
1502 return Expression::StringLiteral();
1506 PreParser::Identifier PreParser::GetIdentifierSymbol() {
1508 if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) {
1509 return Identifier::FutureReserved();
1510 } else if (scanner_->current_token() ==
1511 i::Token::FUTURE_STRICT_RESERVED_WORD) {
1512 return Identifier::FutureStrictReserved();
1514 if (scanner_->is_literal_ascii()) {
1515 // Detect strict-mode poison words.
1516 if (scanner_->literal_length() == 4 &&
1517 !strncmp(scanner_->literal_ascii_string().start(), "eval", 4)) {
1518 return Identifier::Eval();
1520 if (scanner_->literal_length() == 9 &&
1521 !strncmp(scanner_->literal_ascii_string().start(), "arguments", 9)) {
1522 return Identifier::Arguments();
1525 return Identifier::Default();
1529 PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
1530 i::Token::Value next = Next();
1532 case i::Token::FUTURE_RESERVED_WORD: {
1533 i::Scanner::Location location = scanner_->location();
1534 ReportMessageAt(location.beg_pos, location.end_pos,
1535 "reserved_word", NULL);
1537 return GetIdentifierSymbol();
1539 case i::Token::FUTURE_STRICT_RESERVED_WORD:
1540 if (!is_classic_mode()) {
1541 i::Scanner::Location location = scanner_->location();
1542 ReportMessageAt(location.beg_pos, location.end_pos,
1543 "strict_reserved_word", NULL);
1547 case i::Token::IDENTIFIER:
1548 return GetIdentifierSymbol();
1551 return Identifier::Default();
1556 void PreParser::SetStrictModeViolation(i::Scanner::Location location,
1559 if (!is_classic_mode()) {
1560 ReportMessageAt(location, type, NULL);
1564 // Delay report in case this later turns out to be strict code
1565 // (i.e., for function names and parameters prior to a "use strict"
1567 // It's safe to overwrite an existing violation.
1568 // It's either from a function that turned out to be non-strict,
1569 // or it's in the current function (and we just need to report
1570 // one error), or it's in a unclosed nesting function that wasn't
1571 // strict (otherwise we would already be in strict mode).
1572 strict_mode_violation_location_ = location;
1573 strict_mode_violation_type_ = type;
1577 void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
1580 i::Scanner::Location location = strict_mode_violation_location_;
1581 if (location.IsValid() &&
1582 location.beg_pos > beg_pos && location.end_pos < end_pos) {
1583 ReportMessageAt(location, strict_mode_violation_type_, NULL);
1589 void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
1590 const char* eval_args_type,
1591 Identifier identifier,
1593 const char* type = eval_args_type;
1594 if (identifier.IsFutureReserved()) {
1595 type = "reserved_word";
1596 } else if (identifier.IsFutureStrictReserved()) {
1597 type = "strict_reserved_word";
1599 if (!is_classic_mode()) {
1600 ReportMessageAt(location, type, NULL);
1604 strict_mode_violation_location_ = location;
1605 strict_mode_violation_type_ = type;
1609 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
1610 i::Token::Value next = Next();
1611 if (i::Token::IsKeyword(next)) {
1612 int pos = scanner_->location().beg_pos;
1613 const char* keyword = i::Token::String(next);
1614 log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword,
1615 i::StrLength(keyword)));
1616 return Identifier::Default();
1618 if (next == i::Token::IDENTIFIER ||
1619 next == i::Token::FUTURE_RESERVED_WORD ||
1620 next == i::Token::FUTURE_STRICT_RESERVED_WORD) {
1621 return GetIdentifierSymbol();
1624 return Identifier::Default();
1630 // This function reads an identifier and determines whether or not it
1631 // is 'get' or 'set'.
1632 PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get,
1635 Identifier result = ParseIdentifierName(ok);
1636 if (!*ok) return Identifier::Default();
1637 if (scanner_->is_literal_ascii() &&
1638 scanner_->literal_length() == 3) {
1639 const char* token = scanner_->literal_ascii_string().start();
1640 *is_get = strncmp(token, "get", 3) == 0;
1641 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
1646 bool PreParser::peek_any_identifier() {
1647 i::Token::Value next = peek();
1648 return next == i::Token::IDENTIFIER ||
1649 next == i::Token::FUTURE_RESERVED_WORD ||
1650 next == i::Token::FUTURE_STRICT_RESERVED_WORD;
1654 int DuplicateFinder::AddAsciiSymbol(i::Vector<const char> key, int value) {
1655 return AddSymbol(i::Vector<const byte>::cast(key), true, value);
1658 int DuplicateFinder::AddUtf16Symbol(i::Vector<const uint16_t> key, int value) {
1659 return AddSymbol(i::Vector<const byte>::cast(key), false, value);
1662 int DuplicateFinder::AddSymbol(i::Vector<const byte> key,
1665 uint32_t hash = Hash(key, is_ascii);
1666 byte* encoding = BackupKey(key, is_ascii);
1667 i::HashMap::Entry* entry = map_.Lookup(encoding, hash, true);
1668 int old_value = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1670 reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value));
1675 int DuplicateFinder::AddNumber(i::Vector<const char> key, int value) {
1676 ASSERT(key.length() > 0);
1677 // Quick check for already being in canonical form.
1678 if (IsNumberCanonical(key)) {
1679 return AddAsciiSymbol(key, value);
1682 int flags = i::ALLOW_HEX | i::ALLOW_OCTALS;
1683 double double_value = StringToDouble(unicode_constants_, key, flags, 0.0);
1686 if (!isfinite(double_value)) {
1687 string = "Infinity";
1688 length = 8; // strlen("Infinity");
1690 string = DoubleToCString(double_value,
1691 i::Vector<char>(number_buffer_, kBufferSize));
1692 length = i::StrLength(string);
1694 return AddSymbol(i::Vector<const byte>(reinterpret_cast<const byte*>(string),
1695 length), true, value);
1699 bool DuplicateFinder::IsNumberCanonical(i::Vector<const char> number) {
1700 // Test for a safe approximation of number literals that are already
1701 // in canonical form: max 15 digits, no leading zeroes, except an
1702 // integer part that is a single zero, and no trailing zeros below
1703 // the decimal point.
1705 int length = number.length();
1706 if (number.length() > 15) return false;
1707 if (number[pos] == '0') {
1710 while (pos < length &&
1711 static_cast<unsigned>(number[pos] - '0') <= ('9' - '0')) pos++;
1713 if (length == pos) return true;
1714 if (number[pos] != '.') return false;
1716 bool invalid_last_digit = true;
1717 while (pos < length) {
1718 byte digit = number[pos] - '0';
1719 if (digit > '9' - '0') return false;
1720 invalid_last_digit = (digit == 0);
1723 return !invalid_last_digit;
1727 uint32_t DuplicateFinder::Hash(i::Vector<const byte> key, bool is_ascii) {
1728 // Primitive hash function, almost identical to the one used
1729 // for strings (except that it's seeded by the length and ASCII-ness).
1730 int length = key.length();
1731 uint32_t hash = (length << 1) | (is_ascii ? 1 : 0) ;
1732 for (int i = 0; i < length; i++) {
1733 uint32_t c = key[i];
1734 hash = (hash + c) * 1025;
1735 hash ^= (hash >> 6);
1741 bool DuplicateFinder::Match(void* first, void* second) {
1743 // Length + ASCII-bit is encoded as base 128, most significant heptet first,
1744 // with a 8th bit being non-zero while there are more heptets.
1745 // The value encodes the number of bytes following, and whether the original
1747 byte* s1 = reinterpret_cast<byte*>(first);
1748 byte* s2 = reinterpret_cast<byte*>(second);
1749 uint32_t length_ascii_field = 0;
1753 if (c1 != *s2) return false;
1754 length_ascii_field = (length_ascii_field << 7) | (c1 & 0x7f);
1757 } while ((c1 & 0x80) != 0);
1758 int length = static_cast<int>(length_ascii_field >> 1);
1759 return memcmp(s1, s2, length) == 0;
1763 byte* DuplicateFinder::BackupKey(i::Vector<const byte> bytes,
1765 uint32_t ascii_length = (bytes.length() << 1) | (is_ascii ? 1 : 0);
1766 backing_store_.StartSequence();
1767 // Emit ascii_length as base-128 encoded number, with the 7th bit set
1768 // on the byte of every heptet except the last, least significant, one.
1769 if (ascii_length >= (1 << 7)) {
1770 if (ascii_length >= (1 << 14)) {
1771 if (ascii_length >= (1 << 21)) {
1772 if (ascii_length >= (1 << 28)) {
1773 backing_store_.Add(static_cast<byte>((ascii_length >> 28) | 0x80));
1775 backing_store_.Add(static_cast<byte>((ascii_length >> 21) | 0x80u));
1777 backing_store_.Add(static_cast<byte>((ascii_length >> 14) | 0x80u));
1779 backing_store_.Add(static_cast<byte>((ascii_length >> 7) | 0x80u));
1781 backing_store_.Add(static_cast<byte>(ascii_length & 0x7f));
1783 backing_store_.AddBlock(bytes);
1784 return backing_store_.EndSequence().start();
1786 } } // v8::preparser