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);
606
Expect(i::Token::DEFAULT, CHECK_OK);
608
Expect(i::Token::COLON, CHECK_OK);
610
while (token != i::Token::CASE &&
611
token != i::Token::DEFAULT &&
612
token != i::Token::RBRACE) {
613
ParseStatement(CHECK_OK);
617
Expect(i::Token::RBRACE, ok);
618
return Statement::Default();
622
PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
624
// 'do' Statement 'while' '(' Expression ')' ';'
626
Expect(i::Token::DO, CHECK_OK);
627
ParseStatement(CHECK_OK);
628
Expect(i::Token::WHILE, CHECK_OK);
629
Expect(i::Token::LPAREN, CHECK_OK);
630
ParseExpression(true, CHECK_OK);
631
Expect(i::Token::RPAREN, ok);
632
if (peek() == i::Token::SEMICOLON) Consume(i::Token::SEMICOLON);
633
return Statement::Default();
637
PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
639
// 'while' '(' Expression ')' Statement
641
Expect(i::Token::WHILE, CHECK_OK);
642
Expect(i::Token::LPAREN, CHECK_OK);
643
ParseExpression(true, CHECK_OK);
644
Expect(i::Token::RPAREN, CHECK_OK);
646
return Statement::Default();
650
PreParser::Statement PreParser::ParseForStatement(bool* ok) {
652
// 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
654
Expect(i::Token::FOR, CHECK_OK);
655
Expect(i::Token::LPAREN, CHECK_OK);
656
if (peek() != i::Token::SEMICOLON) {
657
if (peek() == i::Token::VAR || peek() == i::Token::CONST ||
658
peek() == i::Token::LET) {
659
bool is_let = peek() == i::Token::LET;
661
VariableDeclarationProperties decl_props = kHasNoInitializers;
662
ParseVariableDeclarations(
663
kForStatement, &decl_props, &decl_count, CHECK_OK);
664
bool accept_IN = decl_count == 1 &&
665
!(is_let && decl_props == kHasInitializers);
666
if (peek() == i::Token::IN && accept_IN) {
667
Expect(i::Token::IN, CHECK_OK);
668
ParseExpression(true, CHECK_OK);
669
Expect(i::Token::RPAREN, CHECK_OK);
671
ParseStatement(CHECK_OK);
672
return Statement::Default();
675
ParseExpression(false, CHECK_OK);
676
if (peek() == i::Token::IN) {
677
Expect(i::Token::IN, CHECK_OK);
678
ParseExpression(true, CHECK_OK);
679
Expect(i::Token::RPAREN, CHECK_OK);
681
ParseStatement(CHECK_OK);
682
return Statement::Default();
687
// Parsed initializer at this point.
688
Expect(i::Token::SEMICOLON, CHECK_OK);
690
if (peek() != i::Token::SEMICOLON) {
691
ParseExpression(true, CHECK_OK);
693
Expect(i::Token::SEMICOLON, CHECK_OK);
695
if (peek() != i::Token::RPAREN) {
696
ParseExpression(true, CHECK_OK);
698
Expect(i::Token::RPAREN, CHECK_OK);
701
return Statement::Default();
705
PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
707
// 'throw' [no line terminator] Expression ';'
709
Expect(i::Token::THROW, CHECK_OK);
710
if (scanner_->HasAnyLineTerminatorBeforeNext()) {
711
i::Scanner::Location pos = scanner_->location();
712
ReportMessageAt(pos, "newline_after_throw", NULL);
714
return Statement::Default();
716
ParseExpression(true, CHECK_OK);
718
return Statement::Default();
722
PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
725
// 'try' Block Finally
726
// 'try' Block Catch Finally
729
// 'catch' '(' Identifier ')' Block
734
// In preparsing, allow any number of catch/finally blocks, including zero
737
Expect(i::Token::TRY, CHECK_OK);
739
ParseBlock(CHECK_OK);
741
bool catch_or_finally_seen = false;
742
if (peek() == i::Token::CATCH) {
743
Consume(i::Token::CATCH);
744
Expect(i::Token::LPAREN, CHECK_OK);
745
Identifier id = ParseIdentifier(CHECK_OK);
746
if (!is_classic_mode() && !id.IsValidStrictVariable()) {
747
StrictModeIdentifierViolation(scanner_->location(),
748
"strict_catch_variable",
751
return Statement::Default();
753
Expect(i::Token::RPAREN, CHECK_OK);
754
{ Scope::InsideWith iw(scope_);
755
ParseBlock(CHECK_OK);
757
catch_or_finally_seen = true;
759
if (peek() == i::Token::FINALLY) {
760
Consume(i::Token::FINALLY);
761
ParseBlock(CHECK_OK);
762
catch_or_finally_seen = true;
764
if (!catch_or_finally_seen) {
767
return Statement::Default();
771
PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
772
// In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
773
// contexts this is used as a statement which invokes the debugger as if a
774
// break point is present.
775
// DebuggerStatement ::
778
Expect(i::Token::DEBUGGER, CHECK_OK);
780
return Statement::Default();
785
#define CHECK_OK ok); \
786
if (!*ok) return Expression::Default(); \
788
#define DUMMY ) // to make indentation work
793
PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) {
795
// AssignmentExpression
796
// Expression ',' AssignmentExpression
798
Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
799
while (peek() == i::Token::COMMA) {
800
Expect(i::Token::COMMA, CHECK_OK);
801
ParseAssignmentExpression(accept_IN, CHECK_OK);
802
result = Expression::Default();
809
PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
811
// AssignmentExpression ::
812
// ConditionalExpression
813
// LeftHandSideExpression AssignmentOperator AssignmentExpression
815
i::Scanner::Location before = scanner_->peek_location();
816
Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
818
if (!i::Token::IsAssignmentOp(peek())) {
819
// Parsed conditional expression only (no assignment).
823
if (!is_classic_mode() &&
824
expression.IsIdentifier() &&
825
expression.AsIdentifier().IsEvalOrArguments()) {
826
i::Scanner::Location after = scanner_->location();
827
ReportMessageAt(before.beg_pos, after.end_pos,
828
"strict_lhs_assignment", NULL);
830
return Expression::Default();
833
i::Token::Value op = Next(); // Get assignment operator.
834
ParseAssignmentExpression(accept_IN, CHECK_OK);
836
if ((op == i::Token::ASSIGN) && expression.IsThisProperty()) {
837
scope_->AddProperty();
840
return Expression::Default();
845
PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
847
// ConditionalExpression ::
848
// LogicalOrExpression
849
// LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
851
// We start using the binary expression parser for prec >= 4 only!
852
Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
853
if (peek() != i::Token::CONDITIONAL) return expression;
854
Consume(i::Token::CONDITIONAL);
855
// In parsing the first assignment expression in conditional
856
// expressions we always accept the 'in' keyword; see ECMA-262,
857
// section 11.12, page 58.
858
ParseAssignmentExpression(true, CHECK_OK);
859
Expect(i::Token::COLON, CHECK_OK);
860
ParseAssignmentExpression(accept_IN, CHECK_OK);
861
return Expression::Default();
865
int PreParser::Precedence(i::Token::Value tok, bool accept_IN) {
866
if (tok == i::Token::IN && !accept_IN)
867
return 0; // 0 precedence will terminate binary expression parsing
869
return i::Token::Precedence(tok);
874
PreParser::Expression PreParser::ParseBinaryExpression(int prec,
877
Expression result = ParseUnaryExpression(CHECK_OK);
878
for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
880
while (Precedence(peek(), accept_IN) == prec1) {
882
ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
883
result = Expression::Default();
890
PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
891
// UnaryExpression ::
893
// 'delete' UnaryExpression
894
// 'void' UnaryExpression
895
// 'typeof' UnaryExpression
896
// '++' UnaryExpression
897
// '--' UnaryExpression
898
// '+' UnaryExpression
899
// '-' UnaryExpression
900
// '~' UnaryExpression
901
// '!' UnaryExpression
903
i::Token::Value op = peek();
904
if (i::Token::IsUnaryOp(op)) {
906
ParseUnaryExpression(ok);
907
return Expression::Default();
908
} else if (i::Token::IsCountOp(op)) {
910
i::Scanner::Location before = scanner_->peek_location();
911
Expression expression = ParseUnaryExpression(CHECK_OK);
912
if (!is_classic_mode() &&
913
expression.IsIdentifier() &&
914
expression.AsIdentifier().IsEvalOrArguments()) {
915
i::Scanner::Location after = scanner_->location();
916
ReportMessageAt(before.beg_pos, after.end_pos,
917
"strict_lhs_prefix", NULL);
920
return Expression::Default();
922
return ParsePostfixExpression(ok);
927
PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
928
// PostfixExpression ::
929
// LeftHandSideExpression ('++' | '--')?
931
i::Scanner::Location before = scanner_->peek_location();
932
Expression expression = ParseLeftHandSideExpression(CHECK_OK);
933
if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
934
i::Token::IsCountOp(peek())) {
935
if (!is_classic_mode() &&
936
expression.IsIdentifier() &&
937
expression.AsIdentifier().IsEvalOrArguments()) {
938
i::Scanner::Location after = scanner_->location();
939
ReportMessageAt(before.beg_pos, after.end_pos,
940
"strict_lhs_postfix", NULL);
942
return Expression::Default();
945
return Expression::Default();
951
PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) {
952
// LeftHandSideExpression ::
953
// (NewExpression | MemberExpression) ...
955
Expression result = Expression::Default();
956
if (peek() == i::Token::NEW) {
957
result = ParseNewExpression(CHECK_OK);
959
result = ParseMemberExpression(CHECK_OK);
964
case i::Token::LBRACK: {
965
Consume(i::Token::LBRACK);
966
ParseExpression(true, CHECK_OK);
967
Expect(i::Token::RBRACK, CHECK_OK);
968
if (result.IsThis()) {
969
result = Expression::ThisProperty();
971
result = Expression::Default();
976
case i::Token::LPAREN: {
977
ParseArguments(CHECK_OK);
978
result = Expression::Default();
982
case i::Token::PERIOD: {
983
Consume(i::Token::PERIOD);
984
ParseIdentifierName(CHECK_OK);
985
if (result.IsThis()) {
986
result = Expression::ThisProperty();
988
result = Expression::Default();
1000
PreParser::Expression PreParser::ParseNewExpression(bool* ok) {
1002
// ('new')+ MemberExpression
1004
// The grammar for new expressions is pretty warped. The keyword
1005
// 'new' can either be a part of the new expression (where it isn't
1006
// followed by an argument list) or a part of the member expression,
1007
// where it must be followed by an argument list. To accommodate
1008
// this, we parse the 'new' keywords greedily and keep track of how
1009
// many we have parsed. This information is then passed on to the
1010
// member expression parser, which is only allowed to match argument
1011
// lists as long as it has 'new' prefixes left
1012
unsigned new_count = 0;
1014
Consume(i::Token::NEW);
1016
} while (peek() == i::Token::NEW);
1018
return ParseMemberWithNewPrefixesExpression(new_count, ok);
1022
PreParser::Expression PreParser::ParseMemberExpression(bool* ok) {
1023
return ParseMemberWithNewPrefixesExpression(0, ok);
1027
PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
1028
unsigned new_count, bool* ok) {
1029
// MemberExpression ::
1030
// (PrimaryExpression | FunctionLiteral)
1031
// ('[' Expression ']' | '.' Identifier | Arguments)*
1033
// Parse the initial primary or function expression.
1034
Expression result = Expression::Default();
1035
if (peek() == i::Token::FUNCTION) {
1036
Consume(i::Token::FUNCTION);
1037
Identifier identifier = Identifier::Default();
1038
if (peek_any_identifier()) {
1039
identifier = ParseIdentifier(CHECK_OK);
1041
result = ParseFunctionLiteral(CHECK_OK);
1042
if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
1043
StrictModeIdentifierViolation(scanner_->location(),
1044
"strict_function_name",
1047
return Expression::Default();
1050
result = ParsePrimaryExpression(CHECK_OK);
1055
case i::Token::LBRACK: {
1056
Consume(i::Token::LBRACK);
1057
ParseExpression(true, CHECK_OK);
1058
Expect(i::Token::RBRACK, CHECK_OK);
1059
if (result.IsThis()) {
1060
result = Expression::ThisProperty();
1062
result = Expression::Default();
1066
case i::Token::PERIOD: {
1067
Consume(i::Token::PERIOD);
1068
ParseIdentifierName(CHECK_OK);
1069
if (result.IsThis()) {
1070
result = Expression::ThisProperty();
1072
result = Expression::Default();
1076
case i::Token::LPAREN: {
1077
if (new_count == 0) return result;
1078
// Consume one of the new prefixes (already parsed).
1079
ParseArguments(CHECK_OK);
1081
result = Expression::Default();
1091
PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
1092
// PrimaryExpression ::
1103
// '(' Expression ')'
1105
Expression result = Expression::Default();
1107
case i::Token::THIS: {
1109
result = Expression::This();
1113
case i::Token::FUTURE_RESERVED_WORD: {
1115
i::Scanner::Location location = scanner_->location();
1116
ReportMessageAt(location.beg_pos, location.end_pos,
1117
"reserved_word", NULL);
1119
return Expression::Default();
1122
case i::Token::FUTURE_STRICT_RESERVED_WORD:
1123
if (!is_classic_mode()) {
1125
i::Scanner::Location location = scanner_->location();
1126
ReportMessageAt(location, "strict_reserved_word", NULL);
1128
return Expression::Default();
1131
case i::Token::IDENTIFIER: {
1132
Identifier id = ParseIdentifier(CHECK_OK);
1133
result = Expression::FromIdentifier(id);
1137
case i::Token::NULL_LITERAL:
1138
case i::Token::TRUE_LITERAL:
1139
case i::Token::FALSE_LITERAL:
1140
case i::Token::NUMBER: {
1144
case i::Token::STRING: {
1146
result = GetStringSymbol();
1150
case i::Token::ASSIGN_DIV:
1151
result = ParseRegExpLiteral(true, CHECK_OK);
1155
result = ParseRegExpLiteral(false, CHECK_OK);
1158
case i::Token::LBRACK:
1159
result = ParseArrayLiteral(CHECK_OK);
1162
case i::Token::LBRACE:
1163
result = ParseObjectLiteral(CHECK_OK);
1166
case i::Token::LPAREN:
1167
Consume(i::Token::LPAREN);
1168
parenthesized_function_ = (peek() == i::Token::FUNCTION);
1169
result = ParseExpression(true, CHECK_OK);
1170
Expect(i::Token::RPAREN, CHECK_OK);
1171
result = result.Parenthesize();
1175
result = ParseV8Intrinsic(CHECK_OK);
1181
return Expression::Default();
1189
PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
1191
// '[' Expression? (',' Expression?)* ']'
1192
Expect(i::Token::LBRACK, CHECK_OK);
1193
while (peek() != i::Token::RBRACK) {
1194
if (peek() != i::Token::COMMA) {
1195
ParseAssignmentExpression(true, CHECK_OK);
1197
if (peek() != i::Token::RBRACK) {
1198
Expect(i::Token::COMMA, CHECK_OK);
1201
Expect(i::Token::RBRACK, CHECK_OK);
1203
scope_->NextMaterializedLiteralIndex();
1204
return Expression::Default();
1207
void PreParser::CheckDuplicate(DuplicateFinder* finder,
1208
i::Token::Value property,
1212
if (property == i::Token::NUMBER) {
1213
old_type = finder->AddNumber(scanner_->literal_ascii_string(), type);
1214
} else if (scanner_->is_literal_ascii()) {
1215
old_type = finder->AddAsciiSymbol(scanner_->literal_ascii_string(),
1218
old_type = finder->AddUtf16Symbol(scanner_->literal_utf16_string(), type);
1220
if (HasConflict(old_type, type)) {
1221
if (IsDataDataConflict(old_type, type)) {
1222
// Both are data properties.
1223
if (is_classic_mode()) return;
1224
ReportMessageAt(scanner_->location(),
1225
"strict_duplicate_property", NULL);
1226
} else if (IsDataAccessorConflict(old_type, type)) {
1227
// Both a data and an accessor property with the same name.
1228
ReportMessageAt(scanner_->location(),
1229
"accessor_data_property", NULL);
1231
ASSERT(IsAccessorAccessorConflict(old_type, type));
1232
// Both accessors of the same type.
1233
ReportMessageAt(scanner_->location(),
1234
"accessor_get_set", NULL);
1241
PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
1244
// ((IdentifierName | String | Number) ':' AssignmentExpression)
1245
// | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1248
Expect(i::Token::LBRACE, CHECK_OK);
1249
DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1250
while (peek() != i::Token::RBRACE) {
1251
i::Token::Value next = peek();
1253
case i::Token::IDENTIFIER:
1254
case i::Token::FUTURE_RESERVED_WORD:
1255
case i::Token::FUTURE_STRICT_RESERVED_WORD: {
1256
bool is_getter = false;
1257
bool is_setter = false;
1258
ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
1259
if ((is_getter || is_setter) && peek() != i::Token::COLON) {
1260
i::Token::Value name = Next();
1261
bool is_keyword = i::Token::IsKeyword(name);
1262
if (name != i::Token::IDENTIFIER &&
1263
name != i::Token::FUTURE_RESERVED_WORD &&
1264
name != i::Token::FUTURE_STRICT_RESERVED_WORD &&
1265
name != i::Token::NUMBER &&
1266
name != i::Token::STRING &&
1269
return Expression::Default();
1274
PropertyType type = is_getter ? kGetterProperty : kSetterProperty;
1275
CheckDuplicate(&duplicate_finder, name, type, CHECK_OK);
1276
ParseFunctionLiteral(CHECK_OK);
1277
if (peek() != i::Token::RBRACE) {
1278
Expect(i::Token::COMMA, CHECK_OK);
1280
continue; // restart the while
1282
CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1285
case i::Token::STRING:
1287
CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1290
case i::Token::NUMBER:
1292
CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1295
if (i::Token::IsKeyword(next)) {
1297
CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1299
// Unexpected token.
1301
return Expression::Default();
1305
Expect(i::Token::COLON, CHECK_OK);
1306
ParseAssignmentExpression(true, CHECK_OK);
1308
// TODO(1240767): Consider allowing trailing comma.
1309
if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
1311
Expect(i::Token::RBRACE, CHECK_OK);
1313
scope_->NextMaterializedLiteralIndex();
1314
return Expression::Default();
1318
PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
1320
if (!scanner_->ScanRegExpPattern(seen_equal)) {
1322
ReportMessageAt(scanner_->location(), "unterminated_regexp", NULL);
1324
return Expression::Default();
1327
scope_->NextMaterializedLiteralIndex();
1329
if (!scanner_->ScanRegExpFlags()) {
1331
ReportMessageAt(scanner_->location(), "invalid_regexp_flags", NULL);
1333
return Expression::Default();
1336
return Expression::Default();
1340
PreParser::Arguments PreParser::ParseArguments(bool* ok) {
1342
// '(' (AssignmentExpression)*[','] ')'
1344
Expect(i::Token::LPAREN, ok);
1345
if (!*ok) return -1;
1346
bool done = (peek() == i::Token::RPAREN);
1349
ParseAssignmentExpression(true, ok);
1350
if (!*ok) return -1;
1352
done = (peek() == i::Token::RPAREN);
1354
Expect(i::Token::COMMA, ok);
1355
if (!*ok) return -1;
1358
Expect(i::Token::RPAREN, ok);
1363
PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
1365
// '(' FormalParameterList? ')' '{' FunctionBody '}'
1367
// Parse function body.
1368
ScopeType outer_scope_type = scope_->type();
1369
bool inside_with = scope_->IsInsideWith();
1370
Scope function_scope(&scope_, kFunctionScope);
1371
// FormalParameterList ::
1372
// '(' (Identifier)*[','] ')'
1373
Expect(i::Token::LPAREN, CHECK_OK);
1374
int start_position = scanner_->location().beg_pos;
1375
bool done = (peek() == i::Token::RPAREN);
1376
DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1378
Identifier id = ParseIdentifier(CHECK_OK);
1379
if (!id.IsValidStrictVariable()) {
1380
StrictModeIdentifierViolation(scanner_->location(),
1381
"strict_param_name",
1386
if (scanner_->is_literal_ascii()) {
1388
duplicate_finder.AddAsciiSymbol(scanner_->literal_ascii_string(), 1);
1391
duplicate_finder.AddUtf16Symbol(scanner_->literal_utf16_string(), 1);
1394
if (prev_value != 0) {
1395
SetStrictModeViolation(scanner_->location(),
1396
"strict_param_dupe",
1399
done = (peek() == i::Token::RPAREN);
1401
Expect(i::Token::COMMA, CHECK_OK);
1404
Expect(i::Token::RPAREN, CHECK_OK);
1406
// Determine if the function will be lazily compiled.
1407
// Currently only happens to top-level functions.
1408
// Optimistically assume that all top-level functions are lazily compiled.
1409
bool is_lazily_compiled = (outer_scope_type == kTopLevelScope &&
1410
!inside_with && allow_lazy_ &&
1411
!parenthesized_function_);
1412
parenthesized_function_ = false;
1414
Expect(i::Token::LBRACE, CHECK_OK);
1415
if (is_lazily_compiled) {
1416
ParseLazyFunctionLiteralBody(CHECK_OK);
1418
ParseSourceElements(i::Token::RBRACE, ok);
1420
Expect(i::Token::RBRACE, CHECK_OK);
1422
if (!is_classic_mode()) {
1423
int end_position = scanner_->location().end_pos;
1424
CheckOctalLiteral(start_position, end_position, CHECK_OK);
1425
CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK);
1426
return Expression::StrictFunction();
1429
return Expression::Default();
1433
void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
1434
int body_start = scanner_->location().beg_pos;
1435
log_->PauseRecording();
1436
ParseSourceElements(i::Token::RBRACE, ok);
1437
log_->ResumeRecording();
1440
// Position right after terminal '}'.
1441
ASSERT_EQ(i::Token::RBRACE, scanner_->peek());
1442
int body_end = scanner_->peek_location().end_pos;
1443
log_->LogFunction(body_start, body_end,
1444
scope_->materialized_literal_count(),
1445
scope_->expected_properties(),
1450
PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
1452
// '%' Identifier Arguments
1453
Expect(i::Token::MOD, CHECK_OK);
1454
if (!allow_natives_syntax_) {
1456
return Expression::Default();
1458
ParseIdentifier(CHECK_OK);
1461
return Expression::Default();
1467
void PreParser::ExpectSemicolon(bool* ok) {
1468
// Check for automatic semicolon insertion according to
1469
// the rules given in ECMA-262, section 7.9, page 21.
1470
i::Token::Value tok = peek();
1471
if (tok == i::Token::SEMICOLON) {
1475
if (scanner_->HasAnyLineTerminatorBeforeNext() ||
1476
tok == i::Token::RBRACE ||
1477
tok == i::Token::EOS) {
1480
Expect(i::Token::SEMICOLON, ok);
1484
void PreParser::LogSymbol() {
1485
int identifier_pos = scanner_->location().beg_pos;
1486
if (scanner_->is_literal_ascii()) {
1487
log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
1489
log_->LogUtf16Symbol(identifier_pos, scanner_->literal_utf16_string());
1494
PreParser::Expression PreParser::GetStringSymbol() {
1495
const int kUseStrictLength = 10;
1496
const char* kUseStrictChars = "use strict";
1498
if (scanner_->is_literal_ascii() &&
1499
scanner_->literal_length() == kUseStrictLength &&
1500
!scanner_->literal_contains_escapes() &&
1501
!strncmp(scanner_->literal_ascii_string().start(), kUseStrictChars,
1502
kUseStrictLength)) {
1503
return Expression::UseStrictStringLiteral();
1505
return Expression::StringLiteral();
1509
PreParser::Identifier PreParser::GetIdentifierSymbol() {
1511
if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) {
1512
return Identifier::FutureReserved();
1513
} else if (scanner_->current_token() ==
1514
i::Token::FUTURE_STRICT_RESERVED_WORD) {
1515
return Identifier::FutureStrictReserved();
1517
if (scanner_->is_literal_ascii()) {
1518
// Detect strict-mode poison words.
1519
if (scanner_->literal_length() == 4 &&
1520
!strncmp(scanner_->literal_ascii_string().start(), "eval", 4)) {
1521
return Identifier::Eval();
1523
if (scanner_->literal_length() == 9 &&
1524
!strncmp(scanner_->literal_ascii_string().start(), "arguments", 9)) {
1525
return Identifier::Arguments();
1528
return Identifier::Default();
1532
PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
1533
i::Token::Value next = Next();
1535
case i::Token::FUTURE_RESERVED_WORD: {
1536
i::Scanner::Location location = scanner_->location();
1537
ReportMessageAt(location.beg_pos, location.end_pos,
1538
"reserved_word", NULL);
1540
return GetIdentifierSymbol();
1542
case i::Token::FUTURE_STRICT_RESERVED_WORD:
1543
if (!is_classic_mode()) {
1544
i::Scanner::Location location = scanner_->location();
1545
ReportMessageAt(location.beg_pos, location.end_pos,
1546
"strict_reserved_word", NULL);
1550
case i::Token::IDENTIFIER:
1551
return GetIdentifierSymbol();
1554
return Identifier::Default();
1559
void PreParser::SetStrictModeViolation(i::Scanner::Location location,
1562
if (!is_classic_mode()) {
1563
ReportMessageAt(location, type, NULL);
1567
// Delay report in case this later turns out to be strict code
1568
// (i.e., for function names and parameters prior to a "use strict"
1570
// It's safe to overwrite an existing violation.
1571
// It's either from a function that turned out to be non-strict,
1572
// or it's in the current function (and we just need to report
1573
// one error), or it's in a unclosed nesting function that wasn't
1574
// strict (otherwise we would already be in strict mode).
1575
strict_mode_violation_location_ = location;
1576
strict_mode_violation_type_ = type;
1580
void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
1583
i::Scanner::Location location = strict_mode_violation_location_;
1584
if (location.IsValid() &&
1585
location.beg_pos > beg_pos && location.end_pos < end_pos) {
1586
ReportMessageAt(location, strict_mode_violation_type_, NULL);
1592
void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
1593
const char* eval_args_type,
1594
Identifier identifier,
1596
const char* type = eval_args_type;
1597
if (identifier.IsFutureReserved()) {
1598
type = "reserved_word";
1599
} else if (identifier.IsFutureStrictReserved()) {
1600
type = "strict_reserved_word";
1602
if (!is_classic_mode()) {
1603
ReportMessageAt(location, type, NULL);
1607
strict_mode_violation_location_ = location;
1608
strict_mode_violation_type_ = type;
1612
PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
1613
i::Token::Value next = Next();
1614
if (i::Token::IsKeyword(next)) {
1615
int pos = scanner_->location().beg_pos;
1616
const char* keyword = i::Token::String(next);
1617
log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword,
1618
i::StrLength(keyword)));
1619
return Identifier::Default();
1621
if (next == i::Token::IDENTIFIER ||
1622
next == i::Token::FUTURE_RESERVED_WORD ||
1623
next == i::Token::FUTURE_STRICT_RESERVED_WORD) {
1624
return GetIdentifierSymbol();
1627
return Identifier::Default();
1633
// This function reads an identifier and determines whether or not it
1634
// is 'get' or 'set'.
1635
PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get,
1638
Identifier result = ParseIdentifierName(ok);
1639
if (!*ok) return Identifier::Default();
1640
if (scanner_->is_literal_ascii() &&
1641
scanner_->literal_length() == 3) {
1642
const char* token = scanner_->literal_ascii_string().start();
1643
*is_get = strncmp(token, "get", 3) == 0;
1644
*is_set = !*is_get && strncmp(token, "set", 3) == 0;
1649
bool PreParser::peek_any_identifier() {
1650
i::Token::Value next = peek();
1651
return next == i::Token::IDENTIFIER ||
1652
next == i::Token::FUTURE_RESERVED_WORD ||
1653
next == i::Token::FUTURE_STRICT_RESERVED_WORD;
1657
int DuplicateFinder::AddAsciiSymbol(i::Vector<const char> key, int value) {
1658
return AddSymbol(i::Vector<const byte>::cast(key), true, value);
1661
int DuplicateFinder::AddUtf16Symbol(i::Vector<const uint16_t> key, int value) {
1662
return AddSymbol(i::Vector<const byte>::cast(key), false, value);
1665
int DuplicateFinder::AddSymbol(i::Vector<const byte> key,
1668
uint32_t hash = Hash(key, is_ascii);
1669
byte* encoding = BackupKey(key, is_ascii);
1670
i::HashMap::Entry* entry = map_.Lookup(encoding, hash, true);
1671
int old_value = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1673
reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value));
1678
int DuplicateFinder::AddNumber(i::Vector<const char> key, int value) {
1679
ASSERT(key.length() > 0);
1680
// Quick check for already being in canonical form.
1681
if (IsNumberCanonical(key)) {
1682
return AddAsciiSymbol(key, value);
1685
int flags = i::ALLOW_HEX | i::ALLOW_OCTALS;
1686
double double_value = StringToDouble(unicode_constants_, key, flags, 0.0);
1689
if (!isfinite(double_value)) {
1690
string = "Infinity";
1691
length = 8; // strlen("Infinity");
1693
string = DoubleToCString(double_value,
1694
i::Vector<char>(number_buffer_, kBufferSize));
1695
length = i::StrLength(string);
1697
return AddSymbol(i::Vector<const byte>(reinterpret_cast<const byte*>(string),
1698
length), true, value);
1702
bool DuplicateFinder::IsNumberCanonical(i::Vector<const char> number) {
1703
// Test for a safe approximation of number literals that are already
1704
// in canonical form: max 15 digits, no leading zeroes, except an
1705
// integer part that is a single zero, and no trailing zeros below
1706
// the decimal point.
1708
int length = number.length();
1709
if (number.length() > 15) return false;
1710
if (number[pos] == '0') {
1713
while (pos < length &&
1714
static_cast<unsigned>(number[pos] - '0') <= ('9' - '0')) pos++;
1716
if (length == pos) return true;
1717
if (number[pos] != '.') return false;
1719
bool invalid_last_digit = true;
1720
while (pos < length) {
1721
byte digit = number[pos] - '0';
1722
if (digit > '9' - '0') return false;
1723
invalid_last_digit = (digit == 0);
1726
return !invalid_last_digit;
1730
uint32_t DuplicateFinder::Hash(i::Vector<const byte> key, bool is_ascii) {
1731
// Primitive hash function, almost identical to the one used
1732
// for strings (except that it's seeded by the length and ASCII-ness).
1733
int length = key.length();
1734
uint32_t hash = (length << 1) | (is_ascii ? 1 : 0) ;
1735
for (int i = 0; i < length; i++) {
1736
uint32_t c = key[i];
1737
hash = (hash + c) * 1025;
1738
hash ^= (hash >> 6);
1744
bool DuplicateFinder::Match(void* first, void* second) {
1746
// Length + ASCII-bit is encoded as base 128, most significant heptet first,
1747
// with a 8th bit being non-zero while there are more heptets.
1748
// The value encodes the number of bytes following, and whether the original
1750
byte* s1 = reinterpret_cast<byte*>(first);
1751
byte* s2 = reinterpret_cast<byte*>(second);
1752
uint32_t length_ascii_field = 0;
1756
if (c1 != *s2) return false;
1757
length_ascii_field = (length_ascii_field << 7) | (c1 & 0x7f);
1760
} while ((c1 & 0x80) != 0);
1761
int length = static_cast<int>(length_ascii_field >> 1);
1762
return memcmp(s1, s2, length) == 0;
1766
byte* DuplicateFinder::BackupKey(i::Vector<const byte> bytes,
1768
uint32_t ascii_length = (bytes.length() << 1) | (is_ascii ? 1 : 0);
1769
backing_store_.StartSequence();
1770
// Emit ascii_length as base-128 encoded number, with the 7th bit set
1771
// on the byte of every heptet except the last, least significant, one.
1772
if (ascii_length >= (1 << 7)) {
1773
if (ascii_length >= (1 << 14)) {
1774
if (ascii_length >= (1 << 21)) {
1775
if (ascii_length >= (1 << 28)) {
1776
backing_store_.Add(static_cast<byte>((ascii_length >> 28) | 0x80));
1778
backing_store_.Add(static_cast<byte>((ascii_length >> 21) | 0x80u));
1780
backing_store_.Add(static_cast<byte>((ascii_length >> 14) | 0x80u));
1782
backing_store_.Add(static_cast<byte>((ascii_length >> 7) | 0x80u));
1784
backing_store_.Add(static_cast<byte>(ascii_length & 0x7f));
1786
backing_store_.AddBlock(bytes);
1787
return backing_store_.EndSequence().start();
1789
} } // v8::preparser