blob: 20d3b9c59c40916ea5eabad11fc8dcd8bf5fae65 [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
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.
15//
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.
27
Ben Murdoch589d6972011-11-30 16:04:58 +000028#include <math.h>
Steve Block44f0eee2011-05-26 01:26:41 +010029
Ben Murdoch589d6972011-11-30 16:04:58 +000030#include "../include/v8stdint.h"
31
32#include "allocation.h"
33#include "checks.h"
34#include "conversions.h"
35#include "conversions-inl.h"
36#include "globals.h"
37#include "hashmap.h"
38#include "list.h"
Ben Murdoch257744e2011-11-30 15:57:28 +000039#include "preparse-data-format.h"
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080040#include "preparse-data.h"
41#include "preparser.h"
Ben Murdoch589d6972011-11-30 16:04:58 +000042#include "unicode.h"
43#include "utils.h"
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000044
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080045namespace v8 {
Ben Murdoch589d6972011-11-30 16:04:58 +000046
47#ifdef _MSC_VER
48// Usually defined in math.h, but not in MSVC.
49// Abstracted to work
50int isfinite(double value);
51#endif
52
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080053namespace preparser {
54
Ben Murdoch3ef787d2012-04-12 10:51:47 +010055PreParser::PreParseResult PreParser::PreParseLazyFunction(
56 i::LanguageMode mode, i::ParserRecorder* log) {
57 log_ = 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());
63 bool ok = true;
64 int start_position = scanner_->peek_location().beg_pos;
65 ParseLazyFunctionLiteralBody(&ok);
66 if (stack_overflow_) return kPreParseStackOverflow;
67 if (!ok) {
68 ReportUnexpectedToken(scanner_->current_token());
69 } else {
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);
74 if (ok) {
75 CheckDelayedStrictModeViolation(start_position, end_pos, &ok);
76 }
77 }
78 }
79 return kPreParseSuccess;
80}
81
82
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080083// 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.
86
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.
95
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080096void 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.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100100 if (token == i::Token::ILLEGAL && stack_overflow_) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800101 return;
102 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100103 i::Scanner::Location source_location = scanner_->location();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800104
105 // Four of the tokens are treated specially
106 switch (token) {
107 case i::Token::EOS:
Ben Murdoch589d6972011-11-30 16:04:58 +0000108 return ReportMessageAt(source_location, "unexpected_eos", NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800109 case i::Token::NUMBER:
Ben Murdoch589d6972011-11-30 16:04:58 +0000110 return ReportMessageAt(source_location, "unexpected_token_number", NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800111 case i::Token::STRING:
Ben Murdoch589d6972011-11-30 16:04:58 +0000112 return ReportMessageAt(source_location, "unexpected_token_string", NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800113 case i::Token::IDENTIFIER:
Ben Murdoch589d6972011-11-30 16:04:58 +0000114 return ReportMessageAt(source_location,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800115 "unexpected_token_identifier", NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000116 case i::Token::FUTURE_RESERVED_WORD:
Ben Murdoch589d6972011-11-30 16:04:58 +0000117 return ReportMessageAt(source_location, "unexpected_reserved", NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000118 case i::Token::FUTURE_STRICT_RESERVED_WORD:
Ben Murdoch589d6972011-11-30 16:04:58 +0000119 return ReportMessageAt(source_location,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000120 "unexpected_strict_reserved", NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800121 default:
122 const char* name = i::Token::String(token);
Ben Murdoch589d6972011-11-30 16:04:58 +0000123 ReportMessageAt(source_location, "unexpected_token", name);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800124 }
125}
126
127
Ben Murdoch257744e2011-11-30 15:57:28 +0000128// Checks whether octal literal last seen is between beg_pos and end_pos.
129// If so, reports an error.
130void 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) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000133 ReportMessageAt(octal, "strict_octal_literal", NULL);
Ben Murdoch257744e2011-11-30 15:57:28 +0000134 scanner_->clear_octal_position();
135 *ok = false;
136 }
137}
138
139
140#define CHECK_OK ok); \
141 if (!*ok) return kUnknownSourceElements; \
142 ((void)0
143#define DUMMY ) // to make indentation work
144#undef DUMMY
145
146
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000147PreParser::Statement PreParser::ParseSourceElement(bool* ok) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100148 // (Ecma 262 5th Edition, clause 14):
149 // SourceElement:
150 // Statement
151 // FunctionDeclaration
152 //
153 // In harmony mode we allow additionally the following productions
154 // SourceElement:
155 // LetDeclaration
156 // ConstDeclaration
157
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000158 switch (peek()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100159 case i::Token::FUNCTION:
160 return ParseFunctionDeclaration(ok);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000161 case i::Token::LET:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100162 case i::Token::CONST:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000163 return ParseVariableStatement(kSourceElement, ok);
164 default:
165 return ParseStatement(ok);
166 }
167}
168
169
Ben Murdochb0fe1622011-05-05 13:52:32 +0100170PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
171 bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800172 // SourceElements ::
173 // (Statement)* <end_token>
174
Ben Murdoch257744e2011-11-30 15:57:28 +0000175 bool allow_directive_prologue = true;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800176 while (peek() != end_token) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000177 Statement statement = ParseSourceElement(CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000178 if (allow_directive_prologue) {
179 if (statement.IsUseStrictLiteral()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100180 set_language_mode(harmony_scoping_ ?
181 i::EXTENDED_MODE : i::STRICT_MODE);
Ben Murdoch257744e2011-11-30 15:57:28 +0000182 } else if (!statement.IsStringLiteral()) {
183 allow_directive_prologue = false;
184 }
185 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800186 }
187 return kUnknownSourceElements;
188}
189
190
Ben Murdoch257744e2011-11-30 15:57:28 +0000191#undef CHECK_OK
192#define CHECK_OK ok); \
193 if (!*ok) return Statement::Default(); \
194 ((void)0
195#define DUMMY ) // to make indentation work
196#undef DUMMY
197
198
Ben Murdochb0fe1622011-05-05 13:52:32 +0100199PreParser::Statement PreParser::ParseStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800200 // Statement ::
201 // Block
202 // VariableStatement
203 // EmptyStatement
204 // ExpressionStatement
205 // IfStatement
206 // IterationStatement
207 // ContinueStatement
208 // BreakStatement
209 // ReturnStatement
210 // WithStatement
211 // LabelledStatement
212 // SwitchStatement
213 // ThrowStatement
214 // TryStatement
215 // DebuggerStatement
216
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.
223
224 // Keep the source position of the statement
225 switch (peek()) {
226 case i::Token::LBRACE:
227 return ParseBlock(ok);
228
229 case i::Token::CONST:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100230 case i::Token::LET:
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800231 case i::Token::VAR:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000232 return ParseVariableStatement(kStatement, ok);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800233
234 case i::Token::SEMICOLON:
235 Next();
Ben Murdoch257744e2011-11-30 15:57:28 +0000236 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800237
238 case i::Token::IF:
Ben Murdoch257744e2011-11-30 15:57:28 +0000239 return ParseIfStatement(ok);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800240
241 case i::Token::DO:
242 return ParseDoWhileStatement(ok);
243
244 case i::Token::WHILE:
245 return ParseWhileStatement(ok);
246
247 case i::Token::FOR:
248 return ParseForStatement(ok);
249
250 case i::Token::CONTINUE:
251 return ParseContinueStatement(ok);
252
253 case i::Token::BREAK:
254 return ParseBreakStatement(ok);
255
256 case i::Token::RETURN:
257 return ParseReturnStatement(ok);
258
259 case i::Token::WITH:
260 return ParseWithStatement(ok);
261
262 case i::Token::SWITCH:
263 return ParseSwitchStatement(ok);
264
265 case i::Token::THROW:
266 return ParseThrowStatement(ok);
267
268 case i::Token::TRY:
269 return ParseTryStatement(ok);
270
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100271 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);
278 *ok = false;
279 return Statement::Default();
280 } else {
281 return statement;
282 }
283 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800284
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800285 case i::Token::DEBUGGER:
286 return ParseDebuggerStatement(ok);
287
288 default:
289 return ParseExpressionOrLabelledStatement(ok);
290 }
291}
292
293
Ben Murdochb0fe1622011-05-05 13:52:32 +0100294PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800295 // FunctionDeclaration ::
296 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
297 Expect(i::Token::FUNCTION, CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000298
299 Identifier identifier = ParseIdentifier(CHECK_OK);
300 i::Scanner::Location location = scanner_->location();
301
302 Expression function_value = ParseFunctionLiteral(CHECK_OK);
303
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";
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000309 if (identifier.IsFutureStrictReserved()) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000310 type = "strict_reserved_word";
311 }
Ben Murdoch589d6972011-11-30 16:04:58 +0000312 ReportMessageAt(location, type, NULL);
Ben Murdoch257744e2011-11-30 15:57:28 +0000313 *ok = false;
314 }
315 return Statement::FunctionDeclaration();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800316}
317
318
Ben Murdochb0fe1622011-05-05 13:52:32 +0100319PreParser::Statement PreParser::ParseBlock(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800320 // Block ::
321 // '{' Statement* '}'
322
323 // Note that a Block does not introduce a new execution scope!
324 // (ECMA-262, 3rd, 12.2)
325 //
326 Expect(i::Token::LBRACE, CHECK_OK);
327 while (peek() != i::Token::RBRACE) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100328 if (is_extended_mode()) {
329 ParseSourceElement(CHECK_OK);
330 } else {
331 ParseStatement(CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000332 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800333 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000334 Expect(i::Token::RBRACE, ok);
335 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800336}
337
338
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000339PreParser::Statement PreParser::ParseVariableStatement(
340 VariableDeclarationContext var_context,
341 bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800342 // VariableStatement ::
343 // VariableDeclarations ';'
344
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000345 Statement result = ParseVariableDeclarations(var_context,
346 NULL,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100347 NULL,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000348 CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800349 ExpectSemicolon(CHECK_OK);
350 return result;
351}
352
353
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.
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000359PreParser::Statement PreParser::ParseVariableDeclarations(
360 VariableDeclarationContext var_context,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100361 VariableDeclarationProperties* decl_props,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000362 int* num_decl,
363 bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800364 // VariableDeclarations ::
365 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100366 //
367 // The ES6 Draft Rev3 specifies the following grammar for const declarations
368 //
369 // ConstDeclaration ::
370 // const ConstBinding (',' ConstBinding)* ';'
371 // ConstBinding ::
372 // Identifier '=' AssignmentExpression
373 //
374 // TODO(ES6):
375 // ConstBinding ::
376 // BindingPattern '=' AssignmentExpression
377 bool require_initializer = false;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800378 if (peek() == i::Token::VAR) {
379 Consume(i::Token::VAR);
380 } else if (peek() == i::Token::CONST) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100381 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
382 //
383 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
384 //
385 // * It is a Syntax Error if the code that matches this production is not
386 // contained in extended code.
387 //
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:
394 break;
395 case i::STRICT_MODE: {
396 i::Scanner::Location location = scanner_->peek_location();
397 ReportMessageAt(location, "strict_const", NULL);
398 *ok = false;
399 return Statement::Default();
400 }
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);
407 *ok = false;
408 return Statement::Default();
409 }
410 require_initializer = true;
411 break;
412 }
413 } else if (peek() == i::Token::LET) {
414 // ES6 Draft Rev4 section 12.2.1:
415 //
416 // LetDeclaration : let LetBindingList ;
417 //
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()) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000421 i::Scanner::Location location = scanner_->peek_location();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100422 ReportMessageAt(location.beg_pos, location.end_pos,
423 "illegal_let", NULL);
Ben Murdoch257744e2011-11-30 15:57:28 +0000424 *ok = false;
425 return Statement::Default();
426 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100427 Consume(i::Token::LET);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000428 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);
433 *ok = false;
434 return Statement::Default();
435 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800436 } else {
437 *ok = false;
Ben Murdoch257744e2011-11-30 15:57:28 +0000438 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800439 }
440
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000441 // 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
444 // block.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800445 int nvars = 0; // the number of variables declared
446 do {
447 // Parse variable name.
448 if (nvars > 0) Consume(i::Token::COMMA);
Ben Murdoch257744e2011-11-30 15:57:28 +0000449 Identifier identifier = ParseIdentifier(CHECK_OK);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100450 if (!is_classic_mode() && !identifier.IsValidStrictVariable()) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000451 StrictModeIdentifierViolation(scanner_->location(),
452 "strict_var_name",
453 identifier,
454 ok);
455 return Statement::Default();
456 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800457 nvars++;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100458 if (peek() == i::Token::ASSIGN || require_initializer) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800459 Expect(i::Token::ASSIGN, CHECK_OK);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000460 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100461 if (decl_props != NULL) *decl_props = kHasInitializers;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800462 }
463 } while (peek() == i::Token::COMMA);
464
465 if (num_decl != NULL) *num_decl = nvars;
Ben Murdoch257744e2011-11-30 15:57:28 +0000466 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800467}
468
469
Ben Murdoch257744e2011-11-30 15:57:28 +0000470PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800471 // ExpressionStatement | LabelledStatement ::
472 // Expression ';'
473 // Identifier ':' Statement
474
475 Expression expr = ParseExpression(true, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000476 if (expr.IsRawIdentifier()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100477 ASSERT(!expr.AsIdentifier().IsFutureReserved());
478 ASSERT(is_classic_mode() || !expr.AsIdentifier().IsFutureStrictReserved());
479 if (peek() == i::Token::COLON) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000480 Consume(i::Token::COLON);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100481 return ParseStatement(ok);
Ben Murdoch257744e2011-11-30 15:57:28 +0000482 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000483 // 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.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800486 }
487 // Parsed expression statement.
488 ExpectSemicolon(CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000489 return Statement::ExpressionStatement(expr);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800490}
491
492
Ben Murdochb0fe1622011-05-05 13:52:32 +0100493PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800494 // IfStatement ::
495 // 'if' '(' Expression ')' Statement ('else' Statement)?
496
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) {
503 Next();
504 ParseStatement(CHECK_OK);
505 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000506 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800507}
508
509
Ben Murdochb0fe1622011-05-05 13:52:32 +0100510PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800511 // ContinueStatement ::
512 // 'continue' [no line terminator] Identifier? ';'
513
514 Expect(i::Token::CONTINUE, CHECK_OK);
515 i::Token::Value tok = peek();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000516 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800517 tok != i::Token::SEMICOLON &&
518 tok != i::Token::RBRACE &&
519 tok != i::Token::EOS) {
520 ParseIdentifier(CHECK_OK);
521 }
522 ExpectSemicolon(CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000523 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800524}
525
526
Ben Murdochb0fe1622011-05-05 13:52:32 +0100527PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800528 // BreakStatement ::
529 // 'break' [no line terminator] Identifier? ';'
530
531 Expect(i::Token::BREAK, CHECK_OK);
532 i::Token::Value tok = peek();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000533 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800534 tok != i::Token::SEMICOLON &&
535 tok != i::Token::RBRACE &&
536 tok != i::Token::EOS) {
537 ParseIdentifier(CHECK_OK);
538 }
539 ExpectSemicolon(CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000540 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800541}
542
543
Ben Murdochb0fe1622011-05-05 13:52:32 +0100544PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800545 // ReturnStatement ::
546 // 'return' [no line terminator] Expression? ';'
547
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);
552
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.
557
558 i::Token::Value tok = peek();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000559 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800560 tok != i::Token::SEMICOLON &&
561 tok != i::Token::RBRACE &&
562 tok != i::Token::EOS) {
563 ParseExpression(true, CHECK_OK);
564 }
565 ExpectSemicolon(CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000566 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800567}
568
569
Ben Murdochb0fe1622011-05-05 13:52:32 +0100570PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800571 // WithStatement ::
572 // 'with' '(' Expression ')' Statement
573 Expect(i::Token::WITH, CHECK_OK);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100574 if (!is_classic_mode()) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000575 i::Scanner::Location location = scanner_->location();
Ben Murdoch589d6972011-11-30 16:04:58 +0000576 ReportMessageAt(location, "strict_mode_with", NULL);
Ben Murdoch257744e2011-11-30 15:57:28 +0000577 *ok = false;
578 return Statement::Default();
579 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800580 Expect(i::Token::LPAREN, CHECK_OK);
581 ParseExpression(true, CHECK_OK);
582 Expect(i::Token::RPAREN, CHECK_OK);
583
584 scope_->EnterWith();
585 ParseStatement(CHECK_OK);
586 scope_->LeaveWith();
Ben Murdoch257744e2011-11-30 15:57:28 +0000587 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800588}
589
590
Ben Murdochb0fe1622011-05-05 13:52:32 +0100591PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800592 // SwitchStatement ::
593 // 'switch' '(' Expression ')' '{' CaseClause* '}'
594
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);
599
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);
610 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100611 ParseStatement(CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800612 }
613 token = peek();
614 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000615 Expect(i::Token::RBRACE, ok);
616 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800617}
618
619
Ben Murdochb0fe1622011-05-05 13:52:32 +0100620PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800621 // DoStatement ::
622 // 'do' Statement 'while' '(' Expression ')' ';'
623
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);
Ben Murdoch257744e2011-11-30 15:57:28 +0000629 Expect(i::Token::RPAREN, ok);
Ben Murdoch692be652012-01-10 18:47:50 +0000630 if (peek() == i::Token::SEMICOLON) Consume(i::Token::SEMICOLON);
Ben Murdoch257744e2011-11-30 15:57:28 +0000631 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800632}
633
634
Ben Murdochb0fe1622011-05-05 13:52:32 +0100635PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800636 // WhileStatement ::
637 // 'while' '(' Expression ')' Statement
638
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);
Ben Murdoch257744e2011-11-30 15:57:28 +0000643 ParseStatement(ok);
644 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800645}
646
647
Ben Murdochb0fe1622011-05-05 13:52:32 +0100648PreParser::Statement PreParser::ParseForStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800649 // ForStatement ::
650 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
651
652 Expect(i::Token::FOR, CHECK_OK);
653 Expect(i::Token::LPAREN, CHECK_OK);
654 if (peek() != i::Token::SEMICOLON) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000655 if (peek() == i::Token::VAR || peek() == i::Token::CONST ||
656 peek() == i::Token::LET) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100657 bool is_let = peek() == i::Token::LET;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800658 int decl_count;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100659 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) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800665 Expect(i::Token::IN, CHECK_OK);
666 ParseExpression(true, CHECK_OK);
667 Expect(i::Token::RPAREN, CHECK_OK);
668
669 ParseStatement(CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000670 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800671 }
672 } else {
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);
678
679 ParseStatement(CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000680 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800681 }
682 }
683 }
684
685 // Parsed initializer at this point.
686 Expect(i::Token::SEMICOLON, CHECK_OK);
687
688 if (peek() != i::Token::SEMICOLON) {
689 ParseExpression(true, CHECK_OK);
690 }
691 Expect(i::Token::SEMICOLON, CHECK_OK);
692
693 if (peek() != i::Token::RPAREN) {
694 ParseExpression(true, CHECK_OK);
695 }
696 Expect(i::Token::RPAREN, CHECK_OK);
697
Ben Murdoch257744e2011-11-30 15:57:28 +0000698 ParseStatement(ok);
699 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800700}
701
702
Ben Murdochb0fe1622011-05-05 13:52:32 +0100703PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800704 // ThrowStatement ::
705 // 'throw' [no line terminator] Expression ';'
706
707 Expect(i::Token::THROW, CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000708 if (scanner_->HasAnyLineTerminatorBeforeNext()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100709 i::Scanner::Location pos = scanner_->location();
Ben Murdoch589d6972011-11-30 16:04:58 +0000710 ReportMessageAt(pos, "newline_after_throw", NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800711 *ok = false;
Ben Murdoch257744e2011-11-30 15:57:28 +0000712 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800713 }
714 ParseExpression(true, CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000715 ExpectSemicolon(ok);
716 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800717}
718
719
Ben Murdochb0fe1622011-05-05 13:52:32 +0100720PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800721 // TryStatement ::
722 // 'try' Block Catch
723 // 'try' Block Finally
724 // 'try' Block Catch Finally
725 //
726 // Catch ::
727 // 'catch' '(' Identifier ')' Block
728 //
729 // Finally ::
730 // 'finally' Block
731
732 // In preparsing, allow any number of catch/finally blocks, including zero
733 // of both.
734
735 Expect(i::Token::TRY, CHECK_OK);
736
737 ParseBlock(CHECK_OK);
738
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);
Ben Murdoch257744e2011-11-30 15:57:28 +0000743 Identifier id = ParseIdentifier(CHECK_OK);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100744 if (!is_classic_mode() && !id.IsValidStrictVariable()) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000745 StrictModeIdentifierViolation(scanner_->location(),
746 "strict_catch_variable",
747 id,
748 ok);
749 return Statement::Default();
750 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800751 Expect(i::Token::RPAREN, CHECK_OK);
752 scope_->EnterWith();
753 ParseBlock(ok);
754 scope_->LeaveWith();
Ben Murdoch257744e2011-11-30 15:57:28 +0000755 if (!*ok) Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800756 catch_or_finally_seen = true;
757 }
758 if (peek() == i::Token::FINALLY) {
759 Consume(i::Token::FINALLY);
760 ParseBlock(CHECK_OK);
761 catch_or_finally_seen = true;
762 }
763 if (!catch_or_finally_seen) {
764 *ok = false;
765 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000766 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800767}
768
769
Ben Murdochb0fe1622011-05-05 13:52:32 +0100770PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800771 // 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 ::
775 // 'debugger' ';'
776
777 Expect(i::Token::DEBUGGER, CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000778 ExpectSemicolon(ok);
779 return Statement::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800780}
781
782
Ben Murdoch257744e2011-11-30 15:57:28 +0000783#undef CHECK_OK
784#define CHECK_OK ok); \
785 if (!*ok) return Expression::Default(); \
786 ((void)0
787#define DUMMY ) // to make indentation work
788#undef DUMMY
789
790
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800791// Precedence = 1
Ben Murdochb0fe1622011-05-05 13:52:32 +0100792PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800793 // Expression ::
794 // AssignmentExpression
795 // Expression ',' AssignmentExpression
796
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);
Ben Murdoch257744e2011-11-30 15:57:28 +0000801 result = Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800802 }
803 return result;
804}
805
806
807// Precedence = 2
Ben Murdochb0fe1622011-05-05 13:52:32 +0100808PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
809 bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800810 // AssignmentExpression ::
811 // ConditionalExpression
812 // LeftHandSideExpression AssignmentOperator AssignmentExpression
813
Ben Murdoch257744e2011-11-30 15:57:28 +0000814 i::Scanner::Location before = scanner_->peek_location();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800815 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
816
817 if (!i::Token::IsAssignmentOp(peek())) {
818 // Parsed conditional expression only (no assignment).
819 return expression;
820 }
821
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100822 if (!is_classic_mode() &&
823 expression.IsIdentifier() &&
Ben Murdoch257744e2011-11-30 15:57:28 +0000824 expression.AsIdentifier().IsEvalOrArguments()) {
825 i::Scanner::Location after = scanner_->location();
826 ReportMessageAt(before.beg_pos, after.end_pos,
827 "strict_lhs_assignment", NULL);
828 *ok = false;
829 return Expression::Default();
830 }
831
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800832 i::Token::Value op = Next(); // Get assignment operator.
833 ParseAssignmentExpression(accept_IN, CHECK_OK);
834
Ben Murdoch257744e2011-11-30 15:57:28 +0000835 if ((op == i::Token::ASSIGN) && expression.IsThisProperty()) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800836 scope_->AddProperty();
837 }
838
Ben Murdoch257744e2011-11-30 15:57:28 +0000839 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800840}
841
842
843// Precedence = 3
Ben Murdochb0fe1622011-05-05 13:52:32 +0100844PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
845 bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800846 // ConditionalExpression ::
847 // LogicalOrExpression
848 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
849
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);
Ben Murdoch257744e2011-11-30 15:57:28 +0000860 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800861}
862
863
864int 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
867
868 return i::Token::Precedence(tok);
869}
870
871
872// Precedence >= 4
Ben Murdochb0fe1622011-05-05 13:52:32 +0100873PreParser::Expression PreParser::ParseBinaryExpression(int prec,
874 bool accept_IN,
875 bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800876 Expression result = ParseUnaryExpression(CHECK_OK);
877 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
878 // prec1 >= 4
879 while (Precedence(peek(), accept_IN) == prec1) {
880 Next();
881 ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000882 result = Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800883 }
884 }
885 return result;
886}
887
888
Ben Murdochb0fe1622011-05-05 13:52:32 +0100889PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800890 // UnaryExpression ::
891 // PostfixExpression
892 // 'delete' UnaryExpression
893 // 'void' UnaryExpression
894 // 'typeof' UnaryExpression
895 // '++' UnaryExpression
896 // '--' UnaryExpression
897 // '+' UnaryExpression
898 // '-' UnaryExpression
899 // '~' UnaryExpression
900 // '!' UnaryExpression
901
902 i::Token::Value op = peek();
Ben Murdoch257744e2011-11-30 15:57:28 +0000903 if (i::Token::IsUnaryOp(op)) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800904 op = Next();
905 ParseUnaryExpression(ok);
Ben Murdoch257744e2011-11-30 15:57:28 +0000906 return Expression::Default();
907 } else if (i::Token::IsCountOp(op)) {
908 op = Next();
909 i::Scanner::Location before = scanner_->peek_location();
910 Expression expression = ParseUnaryExpression(CHECK_OK);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100911 if (!is_classic_mode() &&
912 expression.IsIdentifier() &&
Ben Murdoch257744e2011-11-30 15:57:28 +0000913 expression.AsIdentifier().IsEvalOrArguments()) {
914 i::Scanner::Location after = scanner_->location();
915 ReportMessageAt(before.beg_pos, after.end_pos,
916 "strict_lhs_prefix", NULL);
917 *ok = false;
918 }
919 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800920 } else {
921 return ParsePostfixExpression(ok);
922 }
923}
924
925
Ben Murdochb0fe1622011-05-05 13:52:32 +0100926PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800927 // PostfixExpression ::
928 // LeftHandSideExpression ('++' | '--')?
929
Ben Murdoch257744e2011-11-30 15:57:28 +0000930 i::Scanner::Location before = scanner_->peek_location();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800931 Expression expression = ParseLeftHandSideExpression(CHECK_OK);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000932 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800933 i::Token::IsCountOp(peek())) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100934 if (!is_classic_mode() &&
935 expression.IsIdentifier() &&
Ben Murdoch257744e2011-11-30 15:57:28 +0000936 expression.AsIdentifier().IsEvalOrArguments()) {
937 i::Scanner::Location after = scanner_->location();
938 ReportMessageAt(before.beg_pos, after.end_pos,
939 "strict_lhs_postfix", NULL);
940 *ok = false;
941 return Expression::Default();
942 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800943 Next();
Ben Murdoch257744e2011-11-30 15:57:28 +0000944 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800945 }
946 return expression;
947}
948
949
Ben Murdochb0fe1622011-05-05 13:52:32 +0100950PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800951 // LeftHandSideExpression ::
952 // (NewExpression | MemberExpression) ...
953
Ben Murdoch257744e2011-11-30 15:57:28 +0000954 Expression result = Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800955 if (peek() == i::Token::NEW) {
956 result = ParseNewExpression(CHECK_OK);
957 } else {
958 result = ParseMemberExpression(CHECK_OK);
959 }
960
961 while (true) {
962 switch (peek()) {
963 case i::Token::LBRACK: {
964 Consume(i::Token::LBRACK);
965 ParseExpression(true, CHECK_OK);
966 Expect(i::Token::RBRACK, CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000967 if (result.IsThis()) {
968 result = Expression::ThisProperty();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800969 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +0000970 result = Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800971 }
972 break;
973 }
974
975 case i::Token::LPAREN: {
976 ParseArguments(CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000977 result = Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800978 break;
979 }
980
981 case i::Token::PERIOD: {
982 Consume(i::Token::PERIOD);
983 ParseIdentifierName(CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +0000984 if (result.IsThis()) {
985 result = Expression::ThisProperty();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800986 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +0000987 result = Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800988 }
989 break;
990 }
991
992 default:
993 return result;
994 }
995 }
996}
997
998
Ben Murdochb0fe1622011-05-05 13:52:32 +0100999PreParser::Expression PreParser::ParseNewExpression(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001000 // NewExpression ::
1001 // ('new')+ MemberExpression
1002
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;
1012 do {
1013 Consume(i::Token::NEW);
1014 new_count++;
1015 } while (peek() == i::Token::NEW);
1016
1017 return ParseMemberWithNewPrefixesExpression(new_count, ok);
1018}
1019
1020
Ben Murdochb0fe1622011-05-05 13:52:32 +01001021PreParser::Expression PreParser::ParseMemberExpression(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001022 return ParseMemberWithNewPrefixesExpression(0, ok);
1023}
1024
1025
Ben Murdochb0fe1622011-05-05 13:52:32 +01001026PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001027 unsigned new_count, bool* ok) {
1028 // MemberExpression ::
1029 // (PrimaryExpression | FunctionLiteral)
1030 // ('[' Expression ']' | '.' Identifier | Arguments)*
1031
1032 // Parse the initial primary or function expression.
Ben Murdoch257744e2011-11-30 15:57:28 +00001033 Expression result = Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001034 if (peek() == i::Token::FUNCTION) {
1035 Consume(i::Token::FUNCTION);
Ben Murdoch257744e2011-11-30 15:57:28 +00001036 Identifier identifier = Identifier::Default();
Steve Block1e0659c2011-05-24 12:43:12 +01001037 if (peek_any_identifier()) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001038 identifier = ParseIdentifier(CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001039 }
1040 result = ParseFunctionLiteral(CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +00001041 if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
1042 StrictModeIdentifierViolation(scanner_->location(),
1043 "strict_function_name",
1044 identifier,
1045 ok);
1046 return Expression::Default();
1047 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001048 } else {
1049 result = ParsePrimaryExpression(CHECK_OK);
1050 }
1051
1052 while (true) {
1053 switch (peek()) {
1054 case i::Token::LBRACK: {
1055 Consume(i::Token::LBRACK);
1056 ParseExpression(true, CHECK_OK);
1057 Expect(i::Token::RBRACK, CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +00001058 if (result.IsThis()) {
1059 result = Expression::ThisProperty();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001060 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +00001061 result = Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001062 }
1063 break;
1064 }
1065 case i::Token::PERIOD: {
1066 Consume(i::Token::PERIOD);
1067 ParseIdentifierName(CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +00001068 if (result.IsThis()) {
1069 result = Expression::ThisProperty();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001070 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +00001071 result = Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001072 }
1073 break;
1074 }
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);
1079 new_count--;
Ben Murdoch257744e2011-11-30 15:57:28 +00001080 result = Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001081 break;
1082 }
1083 default:
1084 return result;
1085 }
1086 }
1087}
1088
1089
Ben Murdochb0fe1622011-05-05 13:52:32 +01001090PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001091 // PrimaryExpression ::
1092 // 'this'
1093 // 'null'
1094 // 'true'
1095 // 'false'
1096 // Identifier
1097 // Number
1098 // String
1099 // ArrayLiteral
1100 // ObjectLiteral
1101 // RegExpLiteral
1102 // '(' Expression ')'
1103
Ben Murdoch257744e2011-11-30 15:57:28 +00001104 Expression result = Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001105 switch (peek()) {
1106 case i::Token::THIS: {
1107 Next();
Ben Murdoch257744e2011-11-30 15:57:28 +00001108 result = Expression::This();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001109 break;
1110 }
1111
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001112 case i::Token::FUTURE_RESERVED_WORD: {
1113 Next();
1114 i::Scanner::Location location = scanner_->location();
1115 ReportMessageAt(location.beg_pos, location.end_pos,
1116 "reserved_word", NULL);
1117 *ok = false;
1118 return Expression::Default();
1119 }
1120
1121 case i::Token::FUTURE_STRICT_RESERVED_WORD:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001122 if (!is_classic_mode()) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001123 Next();
1124 i::Scanner::Location location = scanner_->location();
Ben Murdoch589d6972011-11-30 16:04:58 +00001125 ReportMessageAt(location, "strict_reserved_word", NULL);
Ben Murdoch257744e2011-11-30 15:57:28 +00001126 *ok = false;
1127 return Expression::Default();
1128 }
1129 // FALLTHROUGH
1130 case i::Token::IDENTIFIER: {
1131 Identifier id = ParseIdentifier(CHECK_OK);
1132 result = Expression::FromIdentifier(id);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001133 break;
1134 }
1135
1136 case i::Token::NULL_LITERAL:
1137 case i::Token::TRUE_LITERAL:
1138 case i::Token::FALSE_LITERAL:
1139 case i::Token::NUMBER: {
1140 Next();
1141 break;
1142 }
1143 case i::Token::STRING: {
1144 Next();
1145 result = GetStringSymbol();
1146 break;
1147 }
1148
1149 case i::Token::ASSIGN_DIV:
1150 result = ParseRegExpLiteral(true, CHECK_OK);
1151 break;
1152
1153 case i::Token::DIV:
1154 result = ParseRegExpLiteral(false, CHECK_OK);
1155 break;
1156
1157 case i::Token::LBRACK:
1158 result = ParseArrayLiteral(CHECK_OK);
1159 break;
1160
1161 case i::Token::LBRACE:
1162 result = ParseObjectLiteral(CHECK_OK);
1163 break;
1164
1165 case i::Token::LPAREN:
1166 Consume(i::Token::LPAREN);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001167 parenthesized_function_ = (peek() == i::Token::FUNCTION);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001168 result = ParseExpression(true, CHECK_OK);
1169 Expect(i::Token::RPAREN, CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +00001170 result = result.Parenthesize();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001171 break;
1172
1173 case i::Token::MOD:
1174 result = ParseV8Intrinsic(CHECK_OK);
1175 break;
1176
1177 default: {
1178 Next();
1179 *ok = false;
Ben Murdoch257744e2011-11-30 15:57:28 +00001180 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001181 }
1182 }
1183
1184 return result;
1185}
1186
1187
Ben Murdochb0fe1622011-05-05 13:52:32 +01001188PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001189 // ArrayLiteral ::
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);
1195 }
1196 if (peek() != i::Token::RBRACK) {
1197 Expect(i::Token::COMMA, CHECK_OK);
1198 }
1199 }
1200 Expect(i::Token::RBRACK, CHECK_OK);
1201
1202 scope_->NextMaterializedLiteralIndex();
Ben Murdoch257744e2011-11-30 15:57:28 +00001203 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001204}
1205
Ben Murdoch589d6972011-11-30 16:04:58 +00001206void PreParser::CheckDuplicate(DuplicateFinder* finder,
1207 i::Token::Value property,
1208 int type,
1209 bool* ok) {
1210 int old_type;
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(),
1215 type);
1216 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001217 old_type = finder->AddUtf16Symbol(scanner_->literal_utf16_string(), type);
Ben Murdoch589d6972011-11-30 16:04:58 +00001218 }
1219 if (HasConflict(old_type, type)) {
1220 if (IsDataDataConflict(old_type, type)) {
1221 // Both are data properties.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001222 if (is_classic_mode()) return;
Ben Murdoch589d6972011-11-30 16:04:58 +00001223 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);
1229 } else {
1230 ASSERT(IsAccessorAccessorConflict(old_type, type));
1231 // Both accessors of the same type.
1232 ReportMessageAt(scanner_->location(),
1233 "accessor_get_set", NULL);
1234 }
1235 *ok = false;
1236 }
1237}
1238
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001239
Ben Murdochb0fe1622011-05-05 13:52:32 +01001240PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001241 // ObjectLiteral ::
1242 // '{' (
1243 // ((IdentifierName | String | Number) ':' AssignmentExpression)
1244 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1245 // )*[','] '}'
1246
1247 Expect(i::Token::LBRACE, CHECK_OK);
Ben Murdoch589d6972011-11-30 16:04:58 +00001248 DuplicateFinder duplicate_finder(scanner_->unicode_cache());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001249 while (peek() != i::Token::RBRACE) {
1250 i::Token::Value next = peek();
1251 switch (next) {
Steve Block1e0659c2011-05-24 12:43:12 +01001252 case i::Token::IDENTIFIER:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001253 case i::Token::FUTURE_RESERVED_WORD:
1254 case i::Token::FUTURE_STRICT_RESERVED_WORD: {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001255 bool is_getter = false;
1256 bool is_setter = false;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001257 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001258 if ((is_getter || is_setter) && peek() != i::Token::COLON) {
1259 i::Token::Value name = Next();
Steve Block9fac8402011-05-12 15:51:54 +01001260 bool is_keyword = i::Token::IsKeyword(name);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001261 if (name != i::Token::IDENTIFIER &&
Steve Block1e0659c2011-05-24 12:43:12 +01001262 name != i::Token::FUTURE_RESERVED_WORD &&
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001263 name != i::Token::FUTURE_STRICT_RESERVED_WORD &&
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001264 name != i::Token::NUMBER &&
1265 name != i::Token::STRING &&
Steve Block9fac8402011-05-12 15:51:54 +01001266 !is_keyword) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001267 *ok = false;
Ben Murdoch257744e2011-11-30 15:57:28 +00001268 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001269 }
Steve Block9fac8402011-05-12 15:51:54 +01001270 if (!is_keyword) {
1271 LogSymbol();
1272 }
Ben Murdoch589d6972011-11-30 16:04:58 +00001273 PropertyType type = is_getter ? kGetterProperty : kSetterProperty;
1274 CheckDuplicate(&duplicate_finder, name, type, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001275 ParseFunctionLiteral(CHECK_OK);
1276 if (peek() != i::Token::RBRACE) {
1277 Expect(i::Token::COMMA, CHECK_OK);
1278 }
1279 continue; // restart the while
1280 }
Ben Murdoch589d6972011-11-30 16:04:58 +00001281 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001282 break;
1283 }
1284 case i::Token::STRING:
1285 Consume(next);
Ben Murdoch589d6972011-11-30 16:04:58 +00001286 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001287 GetStringSymbol();
1288 break;
1289 case i::Token::NUMBER:
1290 Consume(next);
Ben Murdoch589d6972011-11-30 16:04:58 +00001291 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001292 break;
1293 default:
1294 if (i::Token::IsKeyword(next)) {
1295 Consume(next);
Ben Murdoch589d6972011-11-30 16:04:58 +00001296 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001297 } else {
1298 // Unexpected token.
1299 *ok = false;
Ben Murdoch257744e2011-11-30 15:57:28 +00001300 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001301 }
1302 }
1303
1304 Expect(i::Token::COLON, CHECK_OK);
1305 ParseAssignmentExpression(true, CHECK_OK);
1306
1307 // TODO(1240767): Consider allowing trailing comma.
1308 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
1309 }
1310 Expect(i::Token::RBRACE, CHECK_OK);
1311
1312 scope_->NextMaterializedLiteralIndex();
Ben Murdoch257744e2011-11-30 15:57:28 +00001313 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001314}
1315
1316
Ben Murdochb0fe1622011-05-05 13:52:32 +01001317PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
1318 bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001319 if (!scanner_->ScanRegExpPattern(seen_equal)) {
1320 Next();
Ben Murdoch589d6972011-11-30 16:04:58 +00001321 ReportMessageAt(scanner_->location(), "unterminated_regexp", NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001322 *ok = false;
Ben Murdoch257744e2011-11-30 15:57:28 +00001323 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001324 }
1325
1326 scope_->NextMaterializedLiteralIndex();
1327
1328 if (!scanner_->ScanRegExpFlags()) {
1329 Next();
Ben Murdoch589d6972011-11-30 16:04:58 +00001330 ReportMessageAt(scanner_->location(), "invalid_regexp_flags", NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001331 *ok = false;
Ben Murdoch257744e2011-11-30 15:57:28 +00001332 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001333 }
1334 Next();
Ben Murdoch257744e2011-11-30 15:57:28 +00001335 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001336}
1337
1338
Ben Murdochb0fe1622011-05-05 13:52:32 +01001339PreParser::Arguments PreParser::ParseArguments(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001340 // Arguments ::
1341 // '(' (AssignmentExpression)*[','] ')'
1342
Ben Murdoch257744e2011-11-30 15:57:28 +00001343 Expect(i::Token::LPAREN, ok);
1344 if (!*ok) return -1;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001345 bool done = (peek() == i::Token::RPAREN);
1346 int argc = 0;
1347 while (!done) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001348 ParseAssignmentExpression(true, ok);
1349 if (!*ok) return -1;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001350 argc++;
1351 done = (peek() == i::Token::RPAREN);
Ben Murdoch257744e2011-11-30 15:57:28 +00001352 if (!done) {
1353 Expect(i::Token::COMMA, ok);
1354 if (!*ok) return -1;
1355 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001356 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001357 Expect(i::Token::RPAREN, ok);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001358 return argc;
1359}
1360
1361
Ben Murdochb0fe1622011-05-05 13:52:32 +01001362PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001363 // Function ::
1364 // '(' FormalParameterList? ')' '{' FunctionBody '}'
1365
1366 // Parse function body.
1367 ScopeType outer_scope_type = scope_->type();
1368 bool inside_with = scope_->IsInsideWith();
1369 Scope function_scope(&scope_, kFunctionScope);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001370 // FormalParameterList ::
1371 // '(' (Identifier)*[','] ')'
1372 Expect(i::Token::LPAREN, CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +00001373 int start_position = scanner_->location().beg_pos;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001374 bool done = (peek() == i::Token::RPAREN);
Ben Murdoch589d6972011-11-30 16:04:58 +00001375 DuplicateFinder duplicate_finder(scanner_->unicode_cache());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001376 while (!done) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001377 Identifier id = ParseIdentifier(CHECK_OK);
1378 if (!id.IsValidStrictVariable()) {
1379 StrictModeIdentifierViolation(scanner_->location(),
1380 "strict_param_name",
1381 id,
1382 CHECK_OK);
1383 }
Ben Murdoch589d6972011-11-30 16:04:58 +00001384 int prev_value;
1385 if (scanner_->is_literal_ascii()) {
1386 prev_value =
1387 duplicate_finder.AddAsciiSymbol(scanner_->literal_ascii_string(), 1);
1388 } else {
1389 prev_value =
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001390 duplicate_finder.AddUtf16Symbol(scanner_->literal_utf16_string(), 1);
Ben Murdoch589d6972011-11-30 16:04:58 +00001391 }
1392
1393 if (prev_value != 0) {
1394 SetStrictModeViolation(scanner_->location(),
1395 "strict_param_dupe",
1396 CHECK_OK);
1397 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001398 done = (peek() == i::Token::RPAREN);
1399 if (!done) {
1400 Expect(i::Token::COMMA, CHECK_OK);
1401 }
1402 }
1403 Expect(i::Token::RPAREN, CHECK_OK);
1404
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001405 // 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.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001408 bool is_lazily_compiled = (outer_scope_type == kTopLevelScope &&
1409 !inside_with && allow_lazy_ &&
1410 !parenthesized_function_);
1411 parenthesized_function_ = false;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001412
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001413 Expect(i::Token::LBRACE, CHECK_OK);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001414 if (is_lazily_compiled) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001415 ParseLazyFunctionLiteralBody(CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01001416 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001417 ParseSourceElements(i::Token::RBRACE, ok);
Ben Murdoch85b71792012-04-11 18:30:58 +01001418 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001419 Expect(i::Token::RBRACE, CHECK_OK);
Ben Murdoch85b71792012-04-11 18:30:58 +01001420
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001421 if (!is_classic_mode()) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001422 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();
1426 }
1427
1428 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001429}
1430
1431
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001432void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
1433 int body_start = scanner_->location().beg_pos;
1434 log_->PauseRecording();
1435 ParseSourceElements(i::Token::RBRACE, ok);
1436 log_->ResumeRecording();
1437 if (!*ok) return;
1438
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(),
1445 language_mode());
1446}
1447
1448
Ben Murdochb0fe1622011-05-05 13:52:32 +01001449PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001450 // CallRuntime ::
1451 // '%' Identifier Arguments
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001452 Expect(i::Token::MOD, CHECK_OK);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001453 if (!allow_natives_syntax_) {
1454 *ok = false;
1455 return Expression::Default();
1456 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001457 ParseIdentifier(CHECK_OK);
Ben Murdoch257744e2011-11-30 15:57:28 +00001458 ParseArguments(ok);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001459
Ben Murdoch257744e2011-11-30 15:57:28 +00001460 return Expression::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001461}
1462
Ben Murdoch257744e2011-11-30 15:57:28 +00001463#undef CHECK_OK
1464
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001465
1466void 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) {
1471 Next();
1472 return;
1473 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001474 if (scanner_->HasAnyLineTerminatorBeforeNext() ||
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001475 tok == i::Token::RBRACE ||
1476 tok == i::Token::EOS) {
1477 return;
1478 }
1479 Expect(i::Token::SEMICOLON, ok);
1480}
1481
1482
Steve Block9fac8402011-05-12 15:51:54 +01001483void PreParser::LogSymbol() {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001484 int identifier_pos = scanner_->location().beg_pos;
Steve Block9fac8402011-05-12 15:51:54 +01001485 if (scanner_->is_literal_ascii()) {
1486 log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
1487 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001488 log_->LogUtf16Symbol(identifier_pos, scanner_->literal_utf16_string());
Steve Block9fac8402011-05-12 15:51:54 +01001489 }
1490}
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001491
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001492
Ben Murdoch257744e2011-11-30 15:57:28 +00001493PreParser::Expression PreParser::GetStringSymbol() {
1494 const int kUseStrictLength = 10;
1495 const char* kUseStrictChars = "use strict";
Steve Block9fac8402011-05-12 15:51:54 +01001496 LogSymbol();
Ben Murdoch257744e2011-11-30 15:57:28 +00001497 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();
1503 }
1504 return Expression::StringLiteral();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001505}
1506
1507
Ben Murdoch257744e2011-11-30 15:57:28 +00001508PreParser::Identifier PreParser::GetIdentifierSymbol() {
Steve Block9fac8402011-05-12 15:51:54 +01001509 LogSymbol();
Ben Murdoch257744e2011-11-30 15:57:28 +00001510 if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) {
1511 return Identifier::FutureReserved();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001512 } else if (scanner_->current_token() ==
1513 i::Token::FUTURE_STRICT_RESERVED_WORD) {
1514 return Identifier::FutureStrictReserved();
Ben Murdoch257744e2011-11-30 15:57:28 +00001515 }
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();
1521 }
1522 if (scanner_->literal_length() == 9 &&
1523 !strncmp(scanner_->literal_ascii_string().start(), "arguments", 9)) {
1524 return Identifier::Arguments();
1525 }
1526 }
1527 return Identifier::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001528}
1529
1530
Ben Murdochb0fe1622011-05-05 13:52:32 +01001531PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001532 i::Token::Value next = Next();
1533 switch (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);
1538 *ok = false;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001539 return GetIdentifierSymbol();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001540 }
Ben Murdoch85b71792012-04-11 18:30:58 +01001541 case i::Token::FUTURE_STRICT_RESERVED_WORD:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001542 if (!is_classic_mode()) {
1543 i::Scanner::Location location = scanner_->location();
1544 ReportMessageAt(location.beg_pos, location.end_pos,
1545 "strict_reserved_word", NULL);
1546 *ok = false;
1547 }
1548 // FALLTHROUGH
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001549 case i::Token::IDENTIFIER:
1550 return GetIdentifierSymbol();
1551 default:
1552 *ok = false;
1553 return Identifier::Default();
Steve Block1e0659c2011-05-24 12:43:12 +01001554 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001555}
1556
1557
Ben Murdoch257744e2011-11-30 15:57:28 +00001558void PreParser::SetStrictModeViolation(i::Scanner::Location location,
1559 const char* type,
1560 bool* ok) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001561 if (!is_classic_mode()) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001562 ReportMessageAt(location, type, NULL);
Ben Murdoch257744e2011-11-30 15:57:28 +00001563 *ok = false;
1564 return;
1565 }
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"
1568 // directive).
Ben Murdoch589d6972011-11-30 16:04:58 +00001569 // 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).
Ben Murdoch257744e2011-11-30 15:57:28 +00001574 strict_mode_violation_location_ = location;
1575 strict_mode_violation_type_ = type;
1576}
1577
1578
1579void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
1580 int end_pos,
1581 bool* ok) {
1582 i::Scanner::Location location = strict_mode_violation_location_;
1583 if (location.IsValid() &&
1584 location.beg_pos > beg_pos && location.end_pos < end_pos) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001585 ReportMessageAt(location, strict_mode_violation_type_, NULL);
Ben Murdoch257744e2011-11-30 15:57:28 +00001586 *ok = false;
1587 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001588}
1589
1590
1591void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
1592 const char* eval_args_type,
1593 Identifier identifier,
1594 bool* ok) {
1595 const char* type = eval_args_type;
1596 if (identifier.IsFutureReserved()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001597 type = "reserved_word";
1598 } else if (identifier.IsFutureStrictReserved()) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001599 type = "strict_reserved_word";
1600 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001601 if (!is_classic_mode()) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001602 ReportMessageAt(location, type, NULL);
Ben Murdoch257744e2011-11-30 15:57:28 +00001603 *ok = false;
1604 return;
1605 }
1606 strict_mode_violation_location_ = location;
1607 strict_mode_violation_type_ = type;
1608}
1609
1610
Ben Murdochb0fe1622011-05-05 13:52:32 +01001611PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001612 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);
Steve Block9fac8402011-05-12 15:51:54 +01001616 log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword,
1617 i::StrLength(keyword)));
Ben Murdoch257744e2011-11-30 15:57:28 +00001618 return Identifier::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001619 }
Steve Block1e0659c2011-05-24 12:43:12 +01001620 if (next == i::Token::IDENTIFIER ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001621 next == i::Token::FUTURE_RESERVED_WORD ||
1622 next == i::Token::FUTURE_STRICT_RESERVED_WORD) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001623 return GetIdentifierSymbol();
1624 }
1625 *ok = false;
Ben Murdoch257744e2011-11-30 15:57:28 +00001626 return Identifier::Default();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001627}
1628
Ben Murdoch257744e2011-11-30 15:57:28 +00001629#undef CHECK_OK
1630
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001631
1632// This function reads an identifier and determines whether or not it
Steve Block1e0659c2011-05-24 12:43:12 +01001633// is 'get' or 'set'.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001634PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get,
1635 bool* is_set,
1636 bool* ok) {
1637 Identifier result = ParseIdentifierName(ok);
Ben Murdoch257744e2011-11-30 15:57:28 +00001638 if (!*ok) return Identifier::Default();
1639 if (scanner_->is_literal_ascii() &&
1640 scanner_->literal_length() == 3) {
Steve Block9fac8402011-05-12 15:51:54 +01001641 const char* token = scanner_->literal_ascii_string().start();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001642 *is_get = strncmp(token, "get", 3) == 0;
1643 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
1644 }
Steve Block1e0659c2011-05-24 12:43:12 +01001645 return result;
1646}
1647
1648bool PreParser::peek_any_identifier() {
1649 i::Token::Value next = peek();
1650 return next == i::Token::IDENTIFIER ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001651 next == i::Token::FUTURE_RESERVED_WORD ||
1652 next == i::Token::FUTURE_STRICT_RESERVED_WORD;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001653}
Ben Murdoch589d6972011-11-30 16:04:58 +00001654
1655
1656int DuplicateFinder::AddAsciiSymbol(i::Vector<const char> key, int value) {
1657 return AddSymbol(i::Vector<const byte>::cast(key), true, value);
1658}
1659
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001660int DuplicateFinder::AddUtf16Symbol(i::Vector<const uint16_t> key, int value) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001661 return AddSymbol(i::Vector<const byte>::cast(key), false, value);
1662}
1663
1664int DuplicateFinder::AddSymbol(i::Vector<const byte> key,
1665 bool is_ascii,
1666 int value) {
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));
1671 entry->value =
1672 reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value));
1673 return old_value;
1674}
1675
1676
1677int 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);
1682 }
1683
1684 int flags = i::ALLOW_HEX | i::ALLOW_OCTALS;
1685 double double_value = StringToDouble(unicode_constants_, key, flags, 0.0);
1686 int length;
1687 const char* string;
1688 if (!isfinite(double_value)) {
1689 string = "Infinity";
1690 length = 8; // strlen("Infinity");
1691 } else {
1692 string = DoubleToCString(double_value,
1693 i::Vector<char>(number_buffer_, kBufferSize));
1694 length = i::StrLength(string);
1695 }
1696 return AddSymbol(i::Vector<const byte>(reinterpret_cast<const byte*>(string),
1697 length), true, value);
1698}
1699
1700
1701bool 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.
1706 int pos = 0;
1707 int length = number.length();
1708 if (number.length() > 15) return false;
1709 if (number[pos] == '0') {
1710 pos++;
1711 } else {
1712 while (pos < length &&
1713 static_cast<unsigned>(number[pos] - '0') <= ('9' - '0')) pos++;
1714 }
1715 if (length == pos) return true;
1716 if (number[pos] != '.') return false;
1717 pos++;
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);
1723 pos++;
1724 }
1725 return !invalid_last_digit;
1726}
1727
1728
1729uint32_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);
1738 }
1739 return hash;
1740}
1741
1742
1743bool DuplicateFinder::Match(void* first, void* second) {
1744 // Decode lengths.
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
1748 // was ASCII.
1749 byte* s1 = reinterpret_cast<byte*>(first);
1750 byte* s2 = reinterpret_cast<byte*>(second);
1751 uint32_t length_ascii_field = 0;
1752 byte c1;
1753 do {
1754 c1 = *s1;
1755 if (c1 != *s2) return false;
1756 length_ascii_field = (length_ascii_field << 7) | (c1 & 0x7f);
1757 s1++;
1758 s2++;
1759 } while ((c1 & 0x80) != 0);
1760 int length = static_cast<int>(length_ascii_field >> 1);
1761 return memcmp(s1, s2, length) == 0;
1762}
1763
1764
1765byte* DuplicateFinder::BackupKey(i::Vector<const byte> bytes,
1766 bool is_ascii) {
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));
1776 }
1777 backing_store_.Add(static_cast<byte>((ascii_length >> 21) | 0x80u));
1778 }
1779 backing_store_.Add(static_cast<byte>((ascii_length >> 14) | 0x80u));
1780 }
1781 backing_store_.Add(static_cast<byte>((ascii_length >> 7) | 0x80u));
1782 }
1783 backing_store_.Add(static_cast<byte>(ascii_length & 0x7f));
1784
1785 backing_store_.AddBlock(bytes);
1786 return backing_store_.EndSequence().start();
1787}
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001788} } // v8::preparser