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);
585 ParseStatement(CHECK_OK);
587 return Statement::Default();
591 PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
592 // SwitchStatement ::
593 // 'switch' '(' Expression ')' '{' CaseClause* '}'
595 Expect(i::Token::SWITCH, CHECK_OK);
596 Expect(i::Token::LPAREN, CHECK_OK);
597 ParseExpression(true, CHECK_OK);
598 Expect(i::Token::RPAREN, CHECK_OK);
600 Expect(i::Token::LBRACE, CHECK_OK);
601 i::Token::Value token = peek();
602 while (token != i::Token::RBRACE) {
603 if (token == i::Token::CASE) {
604 Expect(i::Token::CASE, CHECK_OK);
605 ParseExpression(true, CHECK_OK);
606 Expect(i::Token::COLON, CHECK_OK);
607 } else if (token == i::Token::DEFAULT) {
608 Expect(i::Token::DEFAULT, CHECK_OK);
609 Expect(i::Token::COLON, CHECK_OK);
611 ParseStatement(CHECK_OK);
615 Expect(i::Token::RBRACE, ok);
616 return Statement::Default();
620 PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
622 // 'do' Statement 'while' '(' Expression ')' ';'
624 Expect(i::Token::DO, CHECK_OK);
625 ParseStatement(CHECK_OK);
626 Expect(i::Token::WHILE, CHECK_OK);
627 Expect(i::Token::LPAREN, CHECK_OK);
628 ParseExpression(true, CHECK_OK);
629 Expect(i::Token::RPAREN, ok);
630 if (peek() == i::Token::SEMICOLON) Consume(i::Token::SEMICOLON);
631 return Statement::Default();
635 PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
637 // 'while' '(' Expression ')' Statement
639 Expect(i::Token::WHILE, CHECK_OK);
640 Expect(i::Token::LPAREN, CHECK_OK);
641 ParseExpression(true, CHECK_OK);
642 Expect(i::Token::RPAREN, CHECK_OK);
644 return Statement::Default();
648 PreParser::Statement PreParser::ParseForStatement(bool* ok) {
650 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
652 Expect(i::Token::FOR, CHECK_OK);
653 Expect(i::Token::LPAREN, CHECK_OK);
654 if (peek() != i::Token::SEMICOLON) {
655 if (peek() == i::Token::VAR || peek() == i::Token::CONST ||
656 peek() == i::Token::LET) {
657 bool is_let = peek() == i::Token::LET;
659 VariableDeclarationProperties decl_props = kHasNoInitializers;
660 ParseVariableDeclarations(
661 kForStatement, &decl_props, &decl_count, CHECK_OK);
662 bool accept_IN = decl_count == 1 &&
663 !(is_let && decl_props == kHasInitializers);
664 if (peek() == i::Token::IN && accept_IN) {
665 Expect(i::Token::IN, CHECK_OK);
666 ParseExpression(true, CHECK_OK);
667 Expect(i::Token::RPAREN, CHECK_OK);
669 ParseStatement(CHECK_OK);
670 return Statement::Default();
673 ParseExpression(false, CHECK_OK);
674 if (peek() == i::Token::IN) {
675 Expect(i::Token::IN, CHECK_OK);
676 ParseExpression(true, CHECK_OK);
677 Expect(i::Token::RPAREN, CHECK_OK);
679 ParseStatement(CHECK_OK);
680 return Statement::Default();
685 // Parsed initializer at this point.
686 Expect(i::Token::SEMICOLON, CHECK_OK);
688 if (peek() != i::Token::SEMICOLON) {
689 ParseExpression(true, CHECK_OK);
691 Expect(i::Token::SEMICOLON, CHECK_OK);
693 if (peek() != i::Token::RPAREN) {
694 ParseExpression(true, CHECK_OK);
696 Expect(i::Token::RPAREN, CHECK_OK);
699 return Statement::Default();
703 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
705 // 'throw' [no line terminator] Expression ';'
707 Expect(i::Token::THROW, CHECK_OK);
708 if (scanner_->HasAnyLineTerminatorBeforeNext()) {
709 i::Scanner::Location pos = scanner_->location();
710 ReportMessageAt(pos, "newline_after_throw", NULL);
712 return Statement::Default();
714 ParseExpression(true, CHECK_OK);
716 return Statement::Default();
720 PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
723 // 'try' Block Finally
724 // 'try' Block Catch Finally
727 // 'catch' '(' Identifier ')' Block
732 // In preparsing, allow any number of catch/finally blocks, including zero
735 Expect(i::Token::TRY, CHECK_OK);
737 ParseBlock(CHECK_OK);
739 bool catch_or_finally_seen = false;
740 if (peek() == i::Token::CATCH) {
741 Consume(i::Token::CATCH);
742 Expect(i::Token::LPAREN, CHECK_OK);
743 Identifier id = ParseIdentifier(CHECK_OK);
744 if (!is_classic_mode() && !id.IsValidStrictVariable()) {
745 StrictModeIdentifierViolation(scanner_->location(),
746 "strict_catch_variable",
749 return Statement::Default();
751 Expect(i::Token::RPAREN, CHECK_OK);
755 if (!*ok) Statement::Default();
756 catch_or_finally_seen = true;
758 if (peek() == i::Token::FINALLY) {
759 Consume(i::Token::FINALLY);
760 ParseBlock(CHECK_OK);
761 catch_or_finally_seen = true;
763 if (!catch_or_finally_seen) {
766 return Statement::Default();
770 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
771 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
772 // contexts this is used as a statement which invokes the debugger as if a
773 // break point is present.
774 // DebuggerStatement ::
777 Expect(i::Token::DEBUGGER, CHECK_OK);
779 return Statement::Default();
784 #define CHECK_OK ok); \
785 if (!*ok) return Expression::Default(); \
787 #define DUMMY ) // to make indentation work
792 PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) {
794 // AssignmentExpression
795 // Expression ',' AssignmentExpression
797 Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
798 while (peek() == i::Token::COMMA) {
799 Expect(i::Token::COMMA, CHECK_OK);
800 ParseAssignmentExpression(accept_IN, CHECK_OK);
801 result = Expression::Default();
808 PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
810 // AssignmentExpression ::
811 // ConditionalExpression
812 // LeftHandSideExpression AssignmentOperator AssignmentExpression
814 i::Scanner::Location before = scanner_->peek_location();
815 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
817 if (!i::Token::IsAssignmentOp(peek())) {
818 // Parsed conditional expression only (no assignment).
822 if (!is_classic_mode() &&
823 expression.IsIdentifier() &&
824 expression.AsIdentifier().IsEvalOrArguments()) {
825 i::Scanner::Location after = scanner_->location();
826 ReportMessageAt(before.beg_pos, after.end_pos,
827 "strict_lhs_assignment", NULL);
829 return Expression::Default();
832 i::Token::Value op = Next(); // Get assignment operator.
833 ParseAssignmentExpression(accept_IN, CHECK_OK);
835 if ((op == i::Token::ASSIGN) && expression.IsThisProperty()) {
836 scope_->AddProperty();
839 return Expression::Default();
844 PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
846 // ConditionalExpression ::
847 // LogicalOrExpression
848 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
850 // We start using the binary expression parser for prec >= 4 only!
851 Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
852 if (peek() != i::Token::CONDITIONAL) return expression;
853 Consume(i::Token::CONDITIONAL);
854 // In parsing the first assignment expression in conditional
855 // expressions we always accept the 'in' keyword; see ECMA-262,
856 // section 11.12, page 58.
857 ParseAssignmentExpression(true, CHECK_OK);
858 Expect(i::Token::COLON, CHECK_OK);
859 ParseAssignmentExpression(accept_IN, CHECK_OK);
860 return Expression::Default();
864 int PreParser::Precedence(i::Token::Value tok, bool accept_IN) {
865 if (tok == i::Token::IN && !accept_IN)
866 return 0; // 0 precedence will terminate binary expression parsing
868 return i::Token::Precedence(tok);
873 PreParser::Expression PreParser::ParseBinaryExpression(int prec,
876 Expression result = ParseUnaryExpression(CHECK_OK);
877 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
879 while (Precedence(peek(), accept_IN) == prec1) {
881 ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
882 result = Expression::Default();
889 PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
890 // UnaryExpression ::
892 // 'delete' UnaryExpression
893 // 'void' UnaryExpression
894 // 'typeof' UnaryExpression
895 // '++' UnaryExpression
896 // '--' UnaryExpression
897 // '+' UnaryExpression
898 // '-' UnaryExpression
899 // '~' UnaryExpression
900 // '!' UnaryExpression
902 i::Token::Value op = peek();
903 if (i::Token::IsUnaryOp(op)) {
905 ParseUnaryExpression(ok);
906 return Expression::Default();
907 } else if (i::Token::IsCountOp(op)) {
909 i::Scanner::Location before = scanner_->peek_location();
910 Expression expression = ParseUnaryExpression(CHECK_OK);
911 if (!is_classic_mode() &&
912 expression.IsIdentifier() &&
913 expression.AsIdentifier().IsEvalOrArguments()) {
914 i::Scanner::Location after = scanner_->location();
915 ReportMessageAt(before.beg_pos, after.end_pos,
916 "strict_lhs_prefix", NULL);
919 return Expression::Default();
921 return ParsePostfixExpression(ok);
926 PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
927 // PostfixExpression ::
928 // LeftHandSideExpression ('++' | '--')?
930 i::Scanner::Location before = scanner_->peek_location();
931 Expression expression = ParseLeftHandSideExpression(CHECK_OK);
932 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
933 i::Token::IsCountOp(peek())) {
934 if (!is_classic_mode() &&
935 expression.IsIdentifier() &&
936 expression.AsIdentifier().IsEvalOrArguments()) {
937 i::Scanner::Location after = scanner_->location();
938 ReportMessageAt(before.beg_pos, after.end_pos,
939 "strict_lhs_postfix", NULL);
941 return Expression::Default();
944 return Expression::Default();
950 PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) {
951 // LeftHandSideExpression ::
952 // (NewExpression | MemberExpression) ...
954 Expression result = Expression::Default();
955 if (peek() == i::Token::NEW) {
956 result = ParseNewExpression(CHECK_OK);
958 result = ParseMemberExpression(CHECK_OK);
963 case i::Token::LBRACK: {
964 Consume(i::Token::LBRACK);
965 ParseExpression(true, CHECK_OK);
966 Expect(i::Token::RBRACK, CHECK_OK);
967 if (result.IsThis()) {
968 result = Expression::ThisProperty();
970 result = Expression::Default();
975 case i::Token::LPAREN: {
976 ParseArguments(CHECK_OK);
977 result = Expression::Default();
981 case i::Token::PERIOD: {
982 Consume(i::Token::PERIOD);
983 ParseIdentifierName(CHECK_OK);
984 if (result.IsThis()) {
985 result = Expression::ThisProperty();
987 result = Expression::Default();
999 PreParser::Expression PreParser::ParseNewExpression(bool* ok) {
1001 // ('new')+ MemberExpression
1003 // The grammar for new expressions is pretty warped. The keyword
1004 // 'new' can either be a part of the new expression (where it isn't
1005 // followed by an argument list) or a part of the member expression,
1006 // where it must be followed by an argument list. To accommodate
1007 // this, we parse the 'new' keywords greedily and keep track of how
1008 // many we have parsed. This information is then passed on to the
1009 // member expression parser, which is only allowed to match argument
1010 // lists as long as it has 'new' prefixes left
1011 unsigned new_count = 0;
1013 Consume(i::Token::NEW);
1015 } while (peek() == i::Token::NEW);
1017 return ParseMemberWithNewPrefixesExpression(new_count, ok);
1021 PreParser::Expression PreParser::ParseMemberExpression(bool* ok) {
1022 return ParseMemberWithNewPrefixesExpression(0, ok);
1026 PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
1027 unsigned new_count, bool* ok) {
1028 // MemberExpression ::
1029 // (PrimaryExpression | FunctionLiteral)
1030 // ('[' Expression ']' | '.' Identifier | Arguments)*
1032 // Parse the initial primary or function expression.
1033 Expression result = Expression::Default();
1034 if (peek() == i::Token::FUNCTION) {
1035 Consume(i::Token::FUNCTION);
1036 Identifier identifier = Identifier::Default();
1037 if (peek_any_identifier()) {
1038 identifier = ParseIdentifier(CHECK_OK);
1040 result = ParseFunctionLiteral(CHECK_OK);
1041 if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
1042 StrictModeIdentifierViolation(scanner_->location(),
1043 "strict_function_name",
1046 return Expression::Default();
1049 result = ParsePrimaryExpression(CHECK_OK);
1054 case i::Token::LBRACK: {
1055 Consume(i::Token::LBRACK);
1056 ParseExpression(true, CHECK_OK);
1057 Expect(i::Token::RBRACK, CHECK_OK);
1058 if (result.IsThis()) {
1059 result = Expression::ThisProperty();
1061 result = Expression::Default();
1065 case i::Token::PERIOD: {
1066 Consume(i::Token::PERIOD);
1067 ParseIdentifierName(CHECK_OK);
1068 if (result.IsThis()) {
1069 result = Expression::ThisProperty();
1071 result = Expression::Default();
1075 case i::Token::LPAREN: {
1076 if (new_count == 0) return result;
1077 // Consume one of the new prefixes (already parsed).
1078 ParseArguments(CHECK_OK);
1080 result = Expression::Default();
1090 PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
1091 // PrimaryExpression ::
1102 // '(' Expression ')'
1104 Expression result = Expression::Default();
1106 case i::Token::THIS: {
1108 result = Expression::This();
1112 case i::Token::FUTURE_RESERVED_WORD: {
1114 i::Scanner::Location location = scanner_->location();
1115 ReportMessageAt(location.beg_pos, location.end_pos,
1116 "reserved_word", NULL);
1118 return Expression::Default();
1121 case i::Token::FUTURE_STRICT_RESERVED_WORD:
1122 if (!is_classic_mode()) {
1124 i::Scanner::Location location = scanner_->location();
1125 ReportMessageAt(location, "strict_reserved_word", NULL);
1127 return Expression::Default();
1130 case i::Token::IDENTIFIER: {
1131 Identifier id = ParseIdentifier(CHECK_OK);
1132 result = Expression::FromIdentifier(id);
1136 case i::Token::NULL_LITERAL:
1137 case i::Token::TRUE_LITERAL:
1138 case i::Token::FALSE_LITERAL:
1139 case i::Token::NUMBER: {
1143 case i::Token::STRING: {
1145 result = GetStringSymbol();
1149 case i::Token::ASSIGN_DIV:
1150 result = ParseRegExpLiteral(true, CHECK_OK);
1154 result = ParseRegExpLiteral(false, CHECK_OK);
1157 case i::Token::LBRACK:
1158 result = ParseArrayLiteral(CHECK_OK);
1161 case i::Token::LBRACE:
1162 result = ParseObjectLiteral(CHECK_OK);
1165 case i::Token::LPAREN:
1166 Consume(i::Token::LPAREN);
1167 parenthesized_function_ = (peek() == i::Token::FUNCTION);
1168 result = ParseExpression(true, CHECK_OK);
1169 Expect(i::Token::RPAREN, CHECK_OK);
1170 result = result.Parenthesize();
1174 result = ParseV8Intrinsic(CHECK_OK);
1180 return Expression::Default();
1188 PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
1190 // '[' Expression? (',' Expression?)* ']'
1191 Expect(i::Token::LBRACK, CHECK_OK);
1192 while (peek() != i::Token::RBRACK) {
1193 if (peek() != i::Token::COMMA) {
1194 ParseAssignmentExpression(true, CHECK_OK);
1196 if (peek() != i::Token::RBRACK) {
1197 Expect(i::Token::COMMA, CHECK_OK);
1200 Expect(i::Token::RBRACK, CHECK_OK);
1202 scope_->NextMaterializedLiteralIndex();
1203 return Expression::Default();
1206 void PreParser::CheckDuplicate(DuplicateFinder* finder,
1207 i::Token::Value property,
1211 if (property == i::Token::NUMBER) {
1212 old_type = finder->AddNumber(scanner_->literal_ascii_string(), type);
1213 } else if (scanner_->is_literal_ascii()) {
1214 old_type = finder->AddAsciiSymbol(scanner_->literal_ascii_string(),
1217 old_type = finder->AddUtf16Symbol(scanner_->literal_utf16_string(), type);
1219 if (HasConflict(old_type, type)) {
1220 if (IsDataDataConflict(old_type, type)) {
1221 // Both are data properties.
1222 if (is_classic_mode()) return;
1223 ReportMessageAt(scanner_->location(),
1224 "strict_duplicate_property", NULL);
1225 } else if (IsDataAccessorConflict(old_type, type)) {
1226 // Both a data and an accessor property with the same name.
1227 ReportMessageAt(scanner_->location(),
1228 "accessor_data_property", NULL);
1230 ASSERT(IsAccessorAccessorConflict(old_type, type));
1231 // Both accessors of the same type.
1232 ReportMessageAt(scanner_->location(),
1233 "accessor_get_set", NULL);
1240 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
1243 // ((IdentifierName | String | Number) ':' AssignmentExpression)
1244 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1247 Expect(i::Token::LBRACE, CHECK_OK);
1248 DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1249 while (peek() != i::Token::RBRACE) {
1250 i::Token::Value next = peek();
1252 case i::Token::IDENTIFIER:
1253 case i::Token::FUTURE_RESERVED_WORD:
1254 case i::Token::FUTURE_STRICT_RESERVED_WORD: {
1255 bool is_getter = false;
1256 bool is_setter = false;
1257 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
1258 if ((is_getter || is_setter) && peek() != i::Token::COLON) {
1259 i::Token::Value name = Next();
1260 bool is_keyword = i::Token::IsKeyword(name);
1261 if (name != i::Token::IDENTIFIER &&
1262 name != i::Token::FUTURE_RESERVED_WORD &&
1263 name != i::Token::FUTURE_STRICT_RESERVED_WORD &&
1264 name != i::Token::NUMBER &&
1265 name != i::Token::STRING &&
1268 return Expression::Default();
1273 PropertyType type = is_getter ? kGetterProperty : kSetterProperty;
1274 CheckDuplicate(&duplicate_finder, name, type, CHECK_OK);
1275 ParseFunctionLiteral(CHECK_OK);
1276 if (peek() != i::Token::RBRACE) {
1277 Expect(i::Token::COMMA, CHECK_OK);
1279 continue; // restart the while
1281 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1284 case i::Token::STRING:
1286 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1289 case i::Token::NUMBER:
1291 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1294 if (i::Token::IsKeyword(next)) {
1296 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1298 // Unexpected token.
1300 return Expression::Default();
1304 Expect(i::Token::COLON, CHECK_OK);
1305 ParseAssignmentExpression(true, CHECK_OK);
1307 // TODO(1240767): Consider allowing trailing comma.
1308 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
1310 Expect(i::Token::RBRACE, CHECK_OK);
1312 scope_->NextMaterializedLiteralIndex();
1313 return Expression::Default();
1317 PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
1319 if (!scanner_->ScanRegExpPattern(seen_equal)) {
1321 ReportMessageAt(scanner_->location(), "unterminated_regexp", NULL);
1323 return Expression::Default();
1326 scope_->NextMaterializedLiteralIndex();
1328 if (!scanner_->ScanRegExpFlags()) {
1330 ReportMessageAt(scanner_->location(), "invalid_regexp_flags", NULL);
1332 return Expression::Default();
1335 return Expression::Default();
1339 PreParser::Arguments PreParser::ParseArguments(bool* ok) {
1341 // '(' (AssignmentExpression)*[','] ')'
1343 Expect(i::Token::LPAREN, ok);
1344 if (!*ok) return -1;
1345 bool done = (peek() == i::Token::RPAREN);
1348 ParseAssignmentExpression(true, ok);
1349 if (!*ok) return -1;
1351 done = (peek() == i::Token::RPAREN);
1353 Expect(i::Token::COMMA, ok);
1354 if (!*ok) return -1;
1357 Expect(i::Token::RPAREN, ok);
1362 PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
1364 // '(' FormalParameterList? ')' '{' FunctionBody '}'
1366 // Parse function body.
1367 ScopeType outer_scope_type = scope_->type();
1368 bool inside_with = scope_->IsInsideWith();
1369 Scope function_scope(&scope_, kFunctionScope);
1370 // FormalParameterList ::
1371 // '(' (Identifier)*[','] ')'
1372 Expect(i::Token::LPAREN, CHECK_OK);
1373 int start_position = scanner_->location().beg_pos;
1374 bool done = (peek() == i::Token::RPAREN);
1375 DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1377 Identifier id = ParseIdentifier(CHECK_OK);
1378 if (!id.IsValidStrictVariable()) {
1379 StrictModeIdentifierViolation(scanner_->location(),
1380 "strict_param_name",
1385 if (scanner_->is_literal_ascii()) {
1387 duplicate_finder.AddAsciiSymbol(scanner_->literal_ascii_string(), 1);
1390 duplicate_finder.AddUtf16Symbol(scanner_->literal_utf16_string(), 1);
1393 if (prev_value != 0) {
1394 SetStrictModeViolation(scanner_->location(),
1395 "strict_param_dupe",
1398 done = (peek() == i::Token::RPAREN);
1400 Expect(i::Token::COMMA, CHECK_OK);
1403 Expect(i::Token::RPAREN, CHECK_OK);
1405 // Determine if the function will be lazily compiled.
1406 // Currently only happens to top-level functions.
1407 // Optimistically assume that all top-level functions are lazily compiled.
1408 bool is_lazily_compiled = (outer_scope_type == kTopLevelScope &&
1409 !inside_with && allow_lazy_ &&
1410 !parenthesized_function_);
1411 parenthesized_function_ = false;
1413 Expect(i::Token::LBRACE, CHECK_OK);
1414 if (is_lazily_compiled) {
1415 ParseLazyFunctionLiteralBody(CHECK_OK);
1417 ParseSourceElements(i::Token::RBRACE, ok);
1419 Expect(i::Token::RBRACE, CHECK_OK);
1421 if (!is_classic_mode()) {
1422 int end_position = scanner_->location().end_pos;
1423 CheckOctalLiteral(start_position, end_position, CHECK_OK);
1424 CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK);
1425 return Expression::StrictFunction();
1428 return Expression::Default();
1432 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
1433 int body_start = scanner_->location().beg_pos;
1434 log_->PauseRecording();
1435 ParseSourceElements(i::Token::RBRACE, ok);
1436 log_->ResumeRecording();
1439 // Position right after terminal '}'.
1440 ASSERT_EQ(i::Token::RBRACE, scanner_->peek());
1441 int body_end = scanner_->peek_location().end_pos;
1442 log_->LogFunction(body_start, body_end,
1443 scope_->materialized_literal_count(),
1444 scope_->expected_properties(),
1449 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
1451 // '%' Identifier Arguments
1452 Expect(i::Token::MOD, CHECK_OK);
1453 if (!allow_natives_syntax_) {
1455 return Expression::Default();
1457 ParseIdentifier(CHECK_OK);
1460 return Expression::Default();
1466 void PreParser::ExpectSemicolon(bool* ok) {
1467 // Check for automatic semicolon insertion according to
1468 // the rules given in ECMA-262, section 7.9, page 21.
1469 i::Token::Value tok = peek();
1470 if (tok == i::Token::SEMICOLON) {
1474 if (scanner_->HasAnyLineTerminatorBeforeNext() ||
1475 tok == i::Token::RBRACE ||
1476 tok == i::Token::EOS) {
1479 Expect(i::Token::SEMICOLON, ok);
1483 void PreParser::LogSymbol() {
1484 int identifier_pos = scanner_->location().beg_pos;
1485 if (scanner_->is_literal_ascii()) {
1486 log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
1488 log_->LogUtf16Symbol(identifier_pos, scanner_->literal_utf16_string());
1493 PreParser::Expression PreParser::GetStringSymbol() {
1494 const int kUseStrictLength = 10;
1495 const char* kUseStrictChars = "use strict";
1497 if (scanner_->is_literal_ascii() &&
1498 scanner_->literal_length() == kUseStrictLength &&
1499 !scanner_->literal_contains_escapes() &&
1500 !strncmp(scanner_->literal_ascii_string().start(), kUseStrictChars,
1501 kUseStrictLength)) {
1502 return Expression::UseStrictStringLiteral();
1504 return Expression::StringLiteral();
1508 PreParser::Identifier PreParser::GetIdentifierSymbol() {
1510 if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) {
1511 return Identifier::FutureReserved();
1512 } else if (scanner_->current_token() ==
1513 i::Token::FUTURE_STRICT_RESERVED_WORD) {
1514 return Identifier::FutureStrictReserved();
1516 if (scanner_->is_literal_ascii()) {
1517 // Detect strict-mode poison words.
1518 if (scanner_->literal_length() == 4 &&
1519 !strncmp(scanner_->literal_ascii_string().start(), "eval", 4)) {
1520 return Identifier::Eval();
1522 if (scanner_->literal_length() == 9 &&
1523 !strncmp(scanner_->literal_ascii_string().start(), "arguments", 9)) {
1524 return Identifier::Arguments();
1527 return Identifier::Default();
1531 PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
1532 i::Token::Value next = Next();
1534 case i::Token::FUTURE_RESERVED_WORD: {
1535 i::Scanner::Location location = scanner_->location();
1536 ReportMessageAt(location.beg_pos, location.end_pos,
1537 "reserved_word", NULL);
1539 return GetIdentifierSymbol();
1541 case i::Token::FUTURE_STRICT_RESERVED_WORD:
1542 if (!is_classic_mode()) {
1543 i::Scanner::Location location = scanner_->location();
1544 ReportMessageAt(location.beg_pos, location.end_pos,
1545 "strict_reserved_word", NULL);
1549 case i::Token::IDENTIFIER:
1550 return GetIdentifierSymbol();
1553 return Identifier::Default();
1558 void PreParser::SetStrictModeViolation(i::Scanner::Location location,
1561 if (!is_classic_mode()) {
1562 ReportMessageAt(location, type, NULL);
1566 // Delay report in case this later turns out to be strict code
1567 // (i.e., for function names and parameters prior to a "use strict"
1569 // It's safe to overwrite an existing violation.
1570 // It's either from a function that turned out to be non-strict,
1571 // or it's in the current function (and we just need to report
1572 // one error), or it's in a unclosed nesting function that wasn't
1573 // strict (otherwise we would already be in strict mode).
1574 strict_mode_violation_location_ = location;
1575 strict_mode_violation_type_ = type;
1579 void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
1582 i::Scanner::Location location = strict_mode_violation_location_;
1583 if (location.IsValid() &&
1584 location.beg_pos > beg_pos && location.end_pos < end_pos) {
1585 ReportMessageAt(location, strict_mode_violation_type_, NULL);
1591 void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
1592 const char* eval_args_type,
1593 Identifier identifier,
1595 const char* type = eval_args_type;
1596 if (identifier.IsFutureReserved()) {
1597 type = "reserved_word";
1598 } else if (identifier.IsFutureStrictReserved()) {
1599 type = "strict_reserved_word";
1601 if (!is_classic_mode()) {
1602 ReportMessageAt(location, type, NULL);
1606 strict_mode_violation_location_ = location;
1607 strict_mode_violation_type_ = type;
1611 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
1612 i::Token::Value next = Next();
1613 if (i::Token::IsKeyword(next)) {
1614 int pos = scanner_->location().beg_pos;
1615 const char* keyword = i::Token::String(next);
1616 log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword,
1617 i::StrLength(keyword)));
1618 return Identifier::Default();
1620 if (next == i::Token::IDENTIFIER ||
1621 next == i::Token::FUTURE_RESERVED_WORD ||
1622 next == i::Token::FUTURE_STRICT_RESERVED_WORD) {
1623 return GetIdentifierSymbol();
1626 return Identifier::Default();
1632 // This function reads an identifier and determines whether or not it
1633 // is 'get' or 'set'.
1634 PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get,
1637 Identifier result = ParseIdentifierName(ok);
1638 if (!*ok) return Identifier::Default();
1639 if (scanner_->is_literal_ascii() &&
1640 scanner_->literal_length() == 3) {
1641 const char* token = scanner_->literal_ascii_string().start();
1642 *is_get = strncmp(token, "get", 3) == 0;
1643 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
1648 bool PreParser::peek_any_identifier() {
1649 i::Token::Value next = peek();
1650 return next == i::Token::IDENTIFIER ||
1651 next == i::Token::FUTURE_RESERVED_WORD ||
1652 next == i::Token::FUTURE_STRICT_RESERVED_WORD;
1656 int DuplicateFinder::AddAsciiSymbol(i::Vector<const char> key, int value) {
1657 return AddSymbol(i::Vector<const byte>::cast(key), true, value);
1660 int DuplicateFinder::AddUtf16Symbol(i::Vector<const uint16_t> key, int value) {
1661 return AddSymbol(i::Vector<const byte>::cast(key), false, value);
1664 int DuplicateFinder::AddSymbol(i::Vector<const byte> key,
1667 uint32_t hash = Hash(key, is_ascii);
1668 byte* encoding = BackupKey(key, is_ascii);
1669 i::HashMap::Entry* entry = map_.Lookup(encoding, hash, true);
1670 int old_value = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1672 reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value));
1677 int DuplicateFinder::AddNumber(i::Vector<const char> key, int value) {
1678 ASSERT(key.length() > 0);
1679 // Quick check for already being in canonical form.
1680 if (IsNumberCanonical(key)) {
1681 return AddAsciiSymbol(key, value);
1684 int flags = i::ALLOW_HEX | i::ALLOW_OCTALS;
1685 double double_value = StringToDouble(unicode_constants_, key, flags, 0.0);
1688 if (!isfinite(double_value)) {
1689 string = "Infinity";
1690 length = 8; // strlen("Infinity");
1692 string = DoubleToCString(double_value,
1693 i::Vector<char>(number_buffer_, kBufferSize));
1694 length = i::StrLength(string);
1696 return AddSymbol(i::Vector<const byte>(reinterpret_cast<const byte*>(string),
1697 length), true, value);
1701 bool DuplicateFinder::IsNumberCanonical(i::Vector<const char> number) {
1702 // Test for a safe approximation of number literals that are already
1703 // in canonical form: max 15 digits, no leading zeroes, except an
1704 // integer part that is a single zero, and no trailing zeros below
1705 // the decimal point.
1707 int length = number.length();
1708 if (number.length() > 15) return false;
1709 if (number[pos] == '0') {
1712 while (pos < length &&
1713 static_cast<unsigned>(number[pos] - '0') <= ('9' - '0')) pos++;
1715 if (length == pos) return true;
1716 if (number[pos] != '.') return false;
1718 bool invalid_last_digit = true;
1719 while (pos < length) {
1720 byte digit = number[pos] - '0';
1721 if (digit > '9' - '0') return false;
1722 invalid_last_digit = (digit == 0);
1725 return !invalid_last_digit;
1729 uint32_t DuplicateFinder::Hash(i::Vector<const byte> key, bool is_ascii) {
1730 // Primitive hash function, almost identical to the one used
1731 // for strings (except that it's seeded by the length and ASCII-ness).
1732 int length = key.length();
1733 uint32_t hash = (length << 1) | (is_ascii ? 1 : 0) ;
1734 for (int i = 0; i < length; i++) {
1735 uint32_t c = key[i];
1736 hash = (hash + c) * 1025;
1737 hash ^= (hash >> 6);
1743 bool DuplicateFinder::Match(void* first, void* second) {
1745 // Length + ASCII-bit is encoded as base 128, most significant heptet first,
1746 // with a 8th bit being non-zero while there are more heptets.
1747 // The value encodes the number of bytes following, and whether the original
1749 byte* s1 = reinterpret_cast<byte*>(first);
1750 byte* s2 = reinterpret_cast<byte*>(second);
1751 uint32_t length_ascii_field = 0;
1755 if (c1 != *s2) return false;
1756 length_ascii_field = (length_ascii_field << 7) | (c1 & 0x7f);
1759 } while ((c1 & 0x80) != 0);
1760 int length = static_cast<int>(length_ascii_field >> 1);
1761 return memcmp(s1, s2, length) == 0;
1765 byte* DuplicateFinder::BackupKey(i::Vector<const byte> bytes,
1767 uint32_t ascii_length = (bytes.length() << 1) | (is_ascii ? 1 : 0);
1768 backing_store_.StartSequence();
1769 // Emit ascii_length as base-128 encoded number, with the 7th bit set
1770 // on the byte of every heptet except the last, least significant, one.
1771 if (ascii_length >= (1 << 7)) {
1772 if (ascii_length >= (1 << 14)) {
1773 if (ascii_length >= (1 << 21)) {
1774 if (ascii_length >= (1 << 28)) {
1775 backing_store_.Add(static_cast<byte>((ascii_length >> 28) | 0x80));
1777 backing_store_.Add(static_cast<byte>((ascii_length >> 21) | 0x80u));
1779 backing_store_.Add(static_cast<byte>((ascii_length >> 14) | 0x80u));
1781 backing_store_.Add(static_cast<byte>((ascii_length >> 7) | 0x80u));
1783 backing_store_.Add(static_cast<byte>(ascii_length & 0x7f));
1785 backing_store_.AddBlock(bytes);
1786 return backing_store_.EndSequence().start();
1788 } } // v8::preparser