blob: c741b4655a0556d4450c94608a69ad6316d4e9fa [file] [log] [blame]
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001// Copyright 2011 the V8 project authors. All rights reserved.
ager@chromium.orgbeb25712010-11-29 08:02:25 +00002// 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
28#include "../include/v8stdint.h"
29#include "unicode.h"
30#include "globals.h"
31#include "checks.h"
32#include "allocation.h"
33#include "utils.h"
34#include "list.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000035
ager@chromium.orgbeb25712010-11-29 08:02:25 +000036#include "scanner-base.h"
lrn@chromium.org1c092762011-05-09 09:42:16 +000037#include "preparse-data-format.h"
ager@chromium.orgbeb25712010-11-29 08:02:25 +000038#include "preparse-data.h"
39#include "preparser.h"
40
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +000041#include "conversions-inl.h"
42
ager@chromium.orgbeb25712010-11-29 08:02:25 +000043namespace v8 {
44namespace preparser {
45
46// Preparsing checks a JavaScript program and emits preparse-data that helps
47// a later parsing to be faster.
48// See preparser-data.h for the data.
49
50// The PreParser checks that the syntax follows the grammar for JavaScript,
51// and collects some information about the program along the way.
52// The grammar check is only performed in order to understand the program
53// sufficiently to deduce some information about it, that can be used
54// to speed up later parsing. Finding errors is not the goal of pre-parsing,
55// rather it is to speed up properly written and correct programs.
56// That means that contextual checks (like a label being declared where
57// it is used) are generally omitted.
58
59namespace i = ::v8::internal;
60
ager@chromium.orgbeb25712010-11-29 08:02:25 +000061void PreParser::ReportUnexpectedToken(i::Token::Value token) {
62 // We don't report stack overflows here, to avoid increasing the
63 // stack depth even further. Instead we report it after parsing is
64 // over, in ParseProgram.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000065 if (token == i::Token::ILLEGAL && stack_overflow_) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +000066 return;
67 }
68 i::JavaScriptScanner::Location source_location = scanner_->location();
69
70 // Four of the tokens are treated specially
71 switch (token) {
72 case i::Token::EOS:
73 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
74 "unexpected_eos", NULL);
75 case i::Token::NUMBER:
76 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
77 "unexpected_token_number", NULL);
78 case i::Token::STRING:
79 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
80 "unexpected_token_string", NULL);
81 case i::Token::IDENTIFIER:
82 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
83 "unexpected_token_identifier", NULL);
ager@chromium.org04921a82011-06-27 13:21:41 +000084 case i::Token::FUTURE_RESERVED_WORD:
85 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
86 "unexpected_reserved", NULL);
87 case i::Token::FUTURE_STRICT_RESERVED_WORD:
88 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
89 "unexpected_strict_reserved", NULL);
ager@chromium.orgbeb25712010-11-29 08:02:25 +000090 default:
91 const char* name = i::Token::String(token);
92 ReportMessageAt(source_location.beg_pos, source_location.end_pos,
93 "unexpected_token", name);
94 }
95}
96
97
lrn@chromium.org1c092762011-05-09 09:42:16 +000098// Checks whether octal literal last seen is between beg_pos and end_pos.
99// If so, reports an error.
100void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
101 i::Scanner::Location octal = scanner_->octal_position();
102 if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
103 ReportMessageAt(octal.beg_pos, octal.end_pos, "strict_octal_literal", NULL);
104 scanner_->clear_octal_position();
105 *ok = false;
106 }
107}
108
109
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000110#define CHECK_OK ok); \
111 if (!*ok) return kUnknownSourceElements; \
112 ((void)0
113#define DUMMY ) // to make indentation work
114#undef DUMMY
115
116
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000117PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
118 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000119 // SourceElements ::
120 // (Statement)* <end_token>
121
lrn@chromium.org1c092762011-05-09 09:42:16 +0000122 bool allow_directive_prologue = true;
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000123 while (peek() != end_token) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000124 Statement statement = ParseStatement(CHECK_OK);
125 if (allow_directive_prologue) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000126 if (statement.IsUseStrictLiteral()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000127 set_strict_mode();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000128 } else if (!statement.IsStringLiteral()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000129 allow_directive_prologue = false;
130 }
131 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000132 }
133 return kUnknownSourceElements;
134}
135
136
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000137#undef CHECK_OK
138#define CHECK_OK ok); \
139 if (!*ok) return Statement::Default(); \
140 ((void)0
141#define DUMMY ) // to make indentation work
142#undef DUMMY
143
144
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000145PreParser::Statement PreParser::ParseStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000146 // Statement ::
147 // Block
148 // VariableStatement
149 // EmptyStatement
150 // ExpressionStatement
151 // IfStatement
152 // IterationStatement
153 // ContinueStatement
154 // BreakStatement
155 // ReturnStatement
156 // WithStatement
157 // LabelledStatement
158 // SwitchStatement
159 // ThrowStatement
160 // TryStatement
161 // DebuggerStatement
162
163 // Note: Since labels can only be used by 'break' and 'continue'
164 // statements, which themselves are only valid within blocks,
165 // iterations or 'switch' statements (i.e., BreakableStatements),
166 // labels can be simply ignored in all other cases; except for
167 // trivial labeled break statements 'label: break label' which is
168 // parsed into an empty statement.
169
170 // Keep the source position of the statement
171 switch (peek()) {
172 case i::Token::LBRACE:
173 return ParseBlock(ok);
174
175 case i::Token::CONST:
176 case i::Token::VAR:
177 return ParseVariableStatement(ok);
178
179 case i::Token::SEMICOLON:
180 Next();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000181 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000182
183 case i::Token::IF:
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000184 return ParseIfStatement(ok);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000185
186 case i::Token::DO:
187 return ParseDoWhileStatement(ok);
188
189 case i::Token::WHILE:
190 return ParseWhileStatement(ok);
191
192 case i::Token::FOR:
193 return ParseForStatement(ok);
194
195 case i::Token::CONTINUE:
196 return ParseContinueStatement(ok);
197
198 case i::Token::BREAK:
199 return ParseBreakStatement(ok);
200
201 case i::Token::RETURN:
202 return ParseReturnStatement(ok);
203
204 case i::Token::WITH:
205 return ParseWithStatement(ok);
206
207 case i::Token::SWITCH:
208 return ParseSwitchStatement(ok);
209
210 case i::Token::THROW:
211 return ParseThrowStatement(ok);
212
213 case i::Token::TRY:
214 return ParseTryStatement(ok);
215
216 case i::Token::FUNCTION:
217 return ParseFunctionDeclaration(ok);
218
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000219 case i::Token::DEBUGGER:
220 return ParseDebuggerStatement(ok);
221
222 default:
223 return ParseExpressionOrLabelledStatement(ok);
224 }
225}
226
227
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000228PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000229 // FunctionDeclaration ::
230 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
231 Expect(i::Token::FUNCTION, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000232
233 Identifier identifier = ParseIdentifier(CHECK_OK);
234 i::Scanner::Location location = scanner_->location();
235
236 Expression function_value = ParseFunctionLiteral(CHECK_OK);
237
238 if (function_value.IsStrictFunction() &&
239 !identifier.IsValidStrictVariable()) {
240 // Strict mode violation, using either reserved word or eval/arguments
241 // as name of strict function.
242 const char* type = "strict_function_name";
ager@chromium.org04921a82011-06-27 13:21:41 +0000243 if (identifier.IsFutureStrictReserved()) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000244 type = "strict_reserved_word";
245 }
246 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
247 *ok = false;
248 }
danno@chromium.org40cb8782011-05-25 07:58:50 +0000249 return Statement::FunctionDeclaration();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000250}
251
252
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000253PreParser::Statement PreParser::ParseBlock(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000254 // Block ::
255 // '{' Statement* '}'
256
257 // Note that a Block does not introduce a new execution scope!
258 // (ECMA-262, 3rd, 12.2)
259 //
260 Expect(i::Token::LBRACE, CHECK_OK);
261 while (peek() != i::Token::RBRACE) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000262 i::Scanner::Location start_location = scanner_->peek_location();
263 Statement statement = ParseStatement(CHECK_OK);
264 i::Scanner::Location end_location = scanner_->location();
265 if (strict_mode() && statement.IsFunctionDeclaration()) {
266 ReportMessageAt(start_location.beg_pos, end_location.end_pos,
267 "strict_function", NULL);
268 *ok = false;
269 return Statement::Default();
270 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000271 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000272 Expect(i::Token::RBRACE, ok);
273 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000274}
275
276
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000277PreParser::Statement PreParser::ParseVariableStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000278 // VariableStatement ::
279 // VariableDeclarations ';'
280
281 Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK);
282 ExpectSemicolon(CHECK_OK);
283 return result;
284}
285
286
287// If the variable declaration declares exactly one non-const
288// variable, then *var is set to that variable. In all other cases,
289// *var is untouched; in particular, it is the caller's responsibility
290// to initialize it properly. This mechanism is also used for the parsing
291// of 'for-in' loops.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000292PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN,
293 int* num_decl,
294 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000295 // VariableDeclarations ::
296 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
297
298 if (peek() == i::Token::VAR) {
299 Consume(i::Token::VAR);
300 } else if (peek() == i::Token::CONST) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000301 if (strict_mode()) {
302 i::Scanner::Location location = scanner_->peek_location();
303 ReportMessageAt(location.beg_pos, location.end_pos,
304 "strict_const", NULL);
305 *ok = false;
306 return Statement::Default();
307 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000308 Consume(i::Token::CONST);
309 } else {
310 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000311 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000312 }
313
314 // The scope of a variable/const declared anywhere inside a function
315 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). .
316 int nvars = 0; // the number of variables declared
317 do {
318 // Parse variable name.
319 if (nvars > 0) Consume(i::Token::COMMA);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000320 Identifier identifier = ParseIdentifier(CHECK_OK);
321 if (strict_mode() && !identifier.IsValidStrictVariable()) {
322 StrictModeIdentifierViolation(scanner_->location(),
323 "strict_var_name",
324 identifier,
325 ok);
326 return Statement::Default();
327 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000328 nvars++;
329 if (peek() == i::Token::ASSIGN) {
330 Expect(i::Token::ASSIGN, CHECK_OK);
331 ParseAssignmentExpression(accept_IN, CHECK_OK);
332 }
333 } while (peek() == i::Token::COMMA);
334
335 if (num_decl != NULL) *num_decl = nvars;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000336 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000337}
338
339
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000340PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000341 // ExpressionStatement | LabelledStatement ::
342 // Expression ';'
343 // Identifier ':' Statement
344
345 Expression expr = ParseExpression(true, CHECK_OK);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000346 if (expr.IsRawIdentifier()) {
347 if (peek() == i::Token::COLON &&
348 (!strict_mode() || !expr.AsIdentifier().IsFutureReserved())) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000349 Consume(i::Token::COLON);
350 i::Scanner::Location start_location = scanner_->peek_location();
351 Statement statement = ParseStatement(CHECK_OK);
352 if (strict_mode() && statement.IsFunctionDeclaration()) {
353 i::Scanner::Location end_location = scanner_->location();
354 ReportMessageAt(start_location.beg_pos, end_location.end_pos,
355 "strict_function", NULL);
356 *ok = false;
357 }
358 return Statement::Default();
359 }
whesse@chromium.org7b260152011-06-20 15:33:18 +0000360 // Preparsing is disabled for extensions (because the extension details
361 // aren't passed to lazily compiled functions), so we don't
362 // accept "native function" in the preparser.
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000363 }
364 // Parsed expression statement.
365 ExpectSemicolon(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000366 return Statement::ExpressionStatement(expr);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000367}
368
369
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000370PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000371 // IfStatement ::
372 // 'if' '(' Expression ')' Statement ('else' Statement)?
373
374 Expect(i::Token::IF, CHECK_OK);
375 Expect(i::Token::LPAREN, CHECK_OK);
376 ParseExpression(true, CHECK_OK);
377 Expect(i::Token::RPAREN, CHECK_OK);
378 ParseStatement(CHECK_OK);
379 if (peek() == i::Token::ELSE) {
380 Next();
381 ParseStatement(CHECK_OK);
382 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000383 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000384}
385
386
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000387PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000388 // ContinueStatement ::
389 // 'continue' [no line terminator] Identifier? ';'
390
391 Expect(i::Token::CONTINUE, CHECK_OK);
392 i::Token::Value tok = peek();
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000393 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000394 tok != i::Token::SEMICOLON &&
395 tok != i::Token::RBRACE &&
396 tok != i::Token::EOS) {
397 ParseIdentifier(CHECK_OK);
398 }
399 ExpectSemicolon(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000400 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000401}
402
403
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000404PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000405 // BreakStatement ::
406 // 'break' [no line terminator] Identifier? ';'
407
408 Expect(i::Token::BREAK, CHECK_OK);
409 i::Token::Value tok = peek();
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000410 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000411 tok != i::Token::SEMICOLON &&
412 tok != i::Token::RBRACE &&
413 tok != i::Token::EOS) {
414 ParseIdentifier(CHECK_OK);
415 }
416 ExpectSemicolon(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000417 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000418}
419
420
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000421PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000422 // ReturnStatement ::
423 // 'return' [no line terminator] Expression? ';'
424
425 // Consume the return token. It is necessary to do the before
426 // reporting any errors on it, because of the way errors are
427 // reported (underlining).
428 Expect(i::Token::RETURN, CHECK_OK);
429
430 // An ECMAScript program is considered syntactically incorrect if it
431 // contains a return statement that is not within the body of a
432 // function. See ECMA-262, section 12.9, page 67.
433 // This is not handled during preparsing.
434
435 i::Token::Value tok = peek();
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000436 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000437 tok != i::Token::SEMICOLON &&
438 tok != i::Token::RBRACE &&
439 tok != i::Token::EOS) {
440 ParseExpression(true, CHECK_OK);
441 }
442 ExpectSemicolon(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000443 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000444}
445
446
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000447PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000448 // WithStatement ::
449 // 'with' '(' Expression ')' Statement
450 Expect(i::Token::WITH, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000451 if (strict_mode()) {
452 i::Scanner::Location location = scanner_->location();
453 ReportMessageAt(location.beg_pos, location.end_pos,
454 "strict_mode_with", NULL);
455 *ok = false;
456 return Statement::Default();
457 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000458 Expect(i::Token::LPAREN, CHECK_OK);
459 ParseExpression(true, CHECK_OK);
460 Expect(i::Token::RPAREN, CHECK_OK);
461
462 scope_->EnterWith();
463 ParseStatement(CHECK_OK);
464 scope_->LeaveWith();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000465 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000466}
467
468
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000469PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000470 // SwitchStatement ::
471 // 'switch' '(' Expression ')' '{' CaseClause* '}'
472
473 Expect(i::Token::SWITCH, CHECK_OK);
474 Expect(i::Token::LPAREN, CHECK_OK);
475 ParseExpression(true, CHECK_OK);
476 Expect(i::Token::RPAREN, CHECK_OK);
477
478 Expect(i::Token::LBRACE, CHECK_OK);
479 i::Token::Value token = peek();
480 while (token != i::Token::RBRACE) {
481 if (token == i::Token::CASE) {
482 Expect(i::Token::CASE, CHECK_OK);
483 ParseExpression(true, CHECK_OK);
484 Expect(i::Token::COLON, CHECK_OK);
485 } else if (token == i::Token::DEFAULT) {
486 Expect(i::Token::DEFAULT, CHECK_OK);
487 Expect(i::Token::COLON, CHECK_OK);
488 } else {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000489 i::Scanner::Location start_location = scanner_->peek_location();
490 Statement statement = ParseStatement(CHECK_OK);
491 if (strict_mode() && statement.IsFunctionDeclaration()) {
492 i::Scanner::Location end_location = scanner_->location();
493 ReportMessageAt(start_location.beg_pos, end_location.end_pos,
494 "strict_function", NULL);
495 *ok = false;
496 return Statement::Default();
497 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000498 }
499 token = peek();
500 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000501 Expect(i::Token::RBRACE, ok);
502 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000503}
504
505
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000506PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000507 // DoStatement ::
508 // 'do' Statement 'while' '(' Expression ')' ';'
509
510 Expect(i::Token::DO, CHECK_OK);
511 ParseStatement(CHECK_OK);
512 Expect(i::Token::WHILE, CHECK_OK);
513 Expect(i::Token::LPAREN, CHECK_OK);
514 ParseExpression(true, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000515 Expect(i::Token::RPAREN, ok);
516 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000517}
518
519
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000520PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000521 // WhileStatement ::
522 // 'while' '(' Expression ')' Statement
523
524 Expect(i::Token::WHILE, CHECK_OK);
525 Expect(i::Token::LPAREN, CHECK_OK);
526 ParseExpression(true, CHECK_OK);
527 Expect(i::Token::RPAREN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000528 ParseStatement(ok);
529 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000530}
531
532
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000533PreParser::Statement PreParser::ParseForStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000534 // ForStatement ::
535 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
536
537 Expect(i::Token::FOR, CHECK_OK);
538 Expect(i::Token::LPAREN, CHECK_OK);
539 if (peek() != i::Token::SEMICOLON) {
540 if (peek() == i::Token::VAR || peek() == i::Token::CONST) {
541 int decl_count;
542 ParseVariableDeclarations(false, &decl_count, CHECK_OK);
543 if (peek() == i::Token::IN && decl_count == 1) {
544 Expect(i::Token::IN, CHECK_OK);
545 ParseExpression(true, CHECK_OK);
546 Expect(i::Token::RPAREN, CHECK_OK);
547
548 ParseStatement(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000549 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000550 }
551 } else {
552 ParseExpression(false, CHECK_OK);
553 if (peek() == i::Token::IN) {
554 Expect(i::Token::IN, CHECK_OK);
555 ParseExpression(true, CHECK_OK);
556 Expect(i::Token::RPAREN, CHECK_OK);
557
558 ParseStatement(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000559 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000560 }
561 }
562 }
563
564 // Parsed initializer at this point.
565 Expect(i::Token::SEMICOLON, CHECK_OK);
566
567 if (peek() != i::Token::SEMICOLON) {
568 ParseExpression(true, CHECK_OK);
569 }
570 Expect(i::Token::SEMICOLON, CHECK_OK);
571
572 if (peek() != i::Token::RPAREN) {
573 ParseExpression(true, CHECK_OK);
574 }
575 Expect(i::Token::RPAREN, CHECK_OK);
576
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000577 ParseStatement(ok);
578 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000579}
580
581
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000582PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000583 // ThrowStatement ::
584 // 'throw' [no line terminator] Expression ';'
585
586 Expect(i::Token::THROW, CHECK_OK);
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000587 if (scanner_->HasAnyLineTerminatorBeforeNext()) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000588 i::JavaScriptScanner::Location pos = scanner_->location();
589 ReportMessageAt(pos.beg_pos, pos.end_pos,
590 "newline_after_throw", NULL);
591 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000592 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000593 }
594 ParseExpression(true, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000595 ExpectSemicolon(ok);
596 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000597}
598
599
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000600PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000601 // TryStatement ::
602 // 'try' Block Catch
603 // 'try' Block Finally
604 // 'try' Block Catch Finally
605 //
606 // Catch ::
607 // 'catch' '(' Identifier ')' Block
608 //
609 // Finally ::
610 // 'finally' Block
611
612 // In preparsing, allow any number of catch/finally blocks, including zero
613 // of both.
614
615 Expect(i::Token::TRY, CHECK_OK);
616
617 ParseBlock(CHECK_OK);
618
619 bool catch_or_finally_seen = false;
620 if (peek() == i::Token::CATCH) {
621 Consume(i::Token::CATCH);
622 Expect(i::Token::LPAREN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000623 Identifier id = ParseIdentifier(CHECK_OK);
624 if (strict_mode() && !id.IsValidStrictVariable()) {
625 StrictModeIdentifierViolation(scanner_->location(),
626 "strict_catch_variable",
627 id,
628 ok);
629 return Statement::Default();
630 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000631 Expect(i::Token::RPAREN, CHECK_OK);
632 scope_->EnterWith();
633 ParseBlock(ok);
634 scope_->LeaveWith();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000635 if (!*ok) Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000636 catch_or_finally_seen = true;
637 }
638 if (peek() == i::Token::FINALLY) {
639 Consume(i::Token::FINALLY);
640 ParseBlock(CHECK_OK);
641 catch_or_finally_seen = true;
642 }
643 if (!catch_or_finally_seen) {
644 *ok = false;
645 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000646 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000647}
648
649
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000650PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000651 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
652 // contexts this is used as a statement which invokes the debugger as if a
653 // break point is present.
654 // DebuggerStatement ::
655 // 'debugger' ';'
656
657 Expect(i::Token::DEBUGGER, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000658 ExpectSemicolon(ok);
659 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000660}
661
662
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000663#undef CHECK_OK
664#define CHECK_OK ok); \
665 if (!*ok) return Expression::Default(); \
666 ((void)0
667#define DUMMY ) // to make indentation work
668#undef DUMMY
669
670
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000671// Precedence = 1
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000672PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000673 // Expression ::
674 // AssignmentExpression
675 // Expression ',' AssignmentExpression
676
677 Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
678 while (peek() == i::Token::COMMA) {
679 Expect(i::Token::COMMA, CHECK_OK);
680 ParseAssignmentExpression(accept_IN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000681 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000682 }
683 return result;
684}
685
686
687// Precedence = 2
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000688PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
689 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000690 // AssignmentExpression ::
691 // ConditionalExpression
692 // LeftHandSideExpression AssignmentOperator AssignmentExpression
693
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000694 i::Scanner::Location before = scanner_->peek_location();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000695 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
696
697 if (!i::Token::IsAssignmentOp(peek())) {
698 // Parsed conditional expression only (no assignment).
699 return expression;
700 }
701
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000702 if (strict_mode() && expression.IsIdentifier() &&
703 expression.AsIdentifier().IsEvalOrArguments()) {
704 i::Scanner::Location after = scanner_->location();
705 ReportMessageAt(before.beg_pos, after.end_pos,
706 "strict_lhs_assignment", NULL);
707 *ok = false;
708 return Expression::Default();
709 }
710
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000711 i::Token::Value op = Next(); // Get assignment operator.
712 ParseAssignmentExpression(accept_IN, CHECK_OK);
713
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000714 if ((op == i::Token::ASSIGN) && expression.IsThisProperty()) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000715 scope_->AddProperty();
716 }
717
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000718 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000719}
720
721
722// Precedence = 3
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000723PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
724 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000725 // ConditionalExpression ::
726 // LogicalOrExpression
727 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
728
729 // We start using the binary expression parser for prec >= 4 only!
730 Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
731 if (peek() != i::Token::CONDITIONAL) return expression;
732 Consume(i::Token::CONDITIONAL);
733 // In parsing the first assignment expression in conditional
734 // expressions we always accept the 'in' keyword; see ECMA-262,
735 // section 11.12, page 58.
736 ParseAssignmentExpression(true, CHECK_OK);
737 Expect(i::Token::COLON, CHECK_OK);
738 ParseAssignmentExpression(accept_IN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000739 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000740}
741
742
743int PreParser::Precedence(i::Token::Value tok, bool accept_IN) {
744 if (tok == i::Token::IN && !accept_IN)
745 return 0; // 0 precedence will terminate binary expression parsing
746
747 return i::Token::Precedence(tok);
748}
749
750
751// Precedence >= 4
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000752PreParser::Expression PreParser::ParseBinaryExpression(int prec,
753 bool accept_IN,
754 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000755 Expression result = ParseUnaryExpression(CHECK_OK);
756 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
757 // prec1 >= 4
758 while (Precedence(peek(), accept_IN) == prec1) {
759 Next();
760 ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000761 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000762 }
763 }
764 return result;
765}
766
767
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000768PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000769 // UnaryExpression ::
770 // PostfixExpression
771 // 'delete' UnaryExpression
772 // 'void' UnaryExpression
773 // 'typeof' UnaryExpression
774 // '++' UnaryExpression
775 // '--' UnaryExpression
776 // '+' UnaryExpression
777 // '-' UnaryExpression
778 // '~' UnaryExpression
779 // '!' UnaryExpression
780
781 i::Token::Value op = peek();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000782 if (i::Token::IsUnaryOp(op)) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000783 op = Next();
784 ParseUnaryExpression(ok);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000785 return Expression::Default();
786 } else if (i::Token::IsCountOp(op)) {
787 op = Next();
788 i::Scanner::Location before = scanner_->peek_location();
789 Expression expression = ParseUnaryExpression(CHECK_OK);
790 if (strict_mode() && expression.IsIdentifier() &&
791 expression.AsIdentifier().IsEvalOrArguments()) {
792 i::Scanner::Location after = scanner_->location();
793 ReportMessageAt(before.beg_pos, after.end_pos,
794 "strict_lhs_prefix", NULL);
795 *ok = false;
796 }
797 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000798 } else {
799 return ParsePostfixExpression(ok);
800 }
801}
802
803
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000804PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000805 // PostfixExpression ::
806 // LeftHandSideExpression ('++' | '--')?
807
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000808 i::Scanner::Location before = scanner_->peek_location();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000809 Expression expression = ParseLeftHandSideExpression(CHECK_OK);
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000810 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000811 i::Token::IsCountOp(peek())) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000812 if (strict_mode() && expression.IsIdentifier() &&
813 expression.AsIdentifier().IsEvalOrArguments()) {
814 i::Scanner::Location after = scanner_->location();
815 ReportMessageAt(before.beg_pos, after.end_pos,
816 "strict_lhs_postfix", NULL);
817 *ok = false;
818 return Expression::Default();
819 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000820 Next();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000821 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000822 }
823 return expression;
824}
825
826
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000827PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000828 // LeftHandSideExpression ::
829 // (NewExpression | MemberExpression) ...
830
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000831 Expression result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000832 if (peek() == i::Token::NEW) {
833 result = ParseNewExpression(CHECK_OK);
834 } else {
835 result = ParseMemberExpression(CHECK_OK);
836 }
837
838 while (true) {
839 switch (peek()) {
840 case i::Token::LBRACK: {
841 Consume(i::Token::LBRACK);
842 ParseExpression(true, CHECK_OK);
843 Expect(i::Token::RBRACK, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000844 if (result.IsThis()) {
845 result = Expression::ThisProperty();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000846 } else {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000847 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000848 }
849 break;
850 }
851
852 case i::Token::LPAREN: {
853 ParseArguments(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000854 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000855 break;
856 }
857
858 case i::Token::PERIOD: {
859 Consume(i::Token::PERIOD);
860 ParseIdentifierName(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000861 if (result.IsThis()) {
862 result = Expression::ThisProperty();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000863 } else {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000864 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000865 }
866 break;
867 }
868
869 default:
870 return result;
871 }
872 }
873}
874
875
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000876PreParser::Expression PreParser::ParseNewExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000877 // NewExpression ::
878 // ('new')+ MemberExpression
879
880 // The grammar for new expressions is pretty warped. The keyword
881 // 'new' can either be a part of the new expression (where it isn't
882 // followed by an argument list) or a part of the member expression,
883 // where it must be followed by an argument list. To accommodate
884 // this, we parse the 'new' keywords greedily and keep track of how
885 // many we have parsed. This information is then passed on to the
886 // member expression parser, which is only allowed to match argument
887 // lists as long as it has 'new' prefixes left
888 unsigned new_count = 0;
889 do {
890 Consume(i::Token::NEW);
891 new_count++;
892 } while (peek() == i::Token::NEW);
893
894 return ParseMemberWithNewPrefixesExpression(new_count, ok);
895}
896
897
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000898PreParser::Expression PreParser::ParseMemberExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000899 return ParseMemberWithNewPrefixesExpression(0, ok);
900}
901
902
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000903PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000904 unsigned new_count, bool* ok) {
905 // MemberExpression ::
906 // (PrimaryExpression | FunctionLiteral)
907 // ('[' Expression ']' | '.' Identifier | Arguments)*
908
909 // Parse the initial primary or function expression.
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000910 Expression result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000911 if (peek() == i::Token::FUNCTION) {
912 Consume(i::Token::FUNCTION);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000913 Identifier identifier = Identifier::Default();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000914 if (peek_any_identifier()) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000915 identifier = ParseIdentifier(CHECK_OK);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000916 }
917 result = ParseFunctionLiteral(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000918 if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
919 StrictModeIdentifierViolation(scanner_->location(),
920 "strict_function_name",
921 identifier,
922 ok);
923 return Expression::Default();
924 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000925 } else {
926 result = ParsePrimaryExpression(CHECK_OK);
927 }
928
929 while (true) {
930 switch (peek()) {
931 case i::Token::LBRACK: {
932 Consume(i::Token::LBRACK);
933 ParseExpression(true, CHECK_OK);
934 Expect(i::Token::RBRACK, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000935 if (result.IsThis()) {
936 result = Expression::ThisProperty();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000937 } else {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000938 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000939 }
940 break;
941 }
942 case i::Token::PERIOD: {
943 Consume(i::Token::PERIOD);
944 ParseIdentifierName(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000945 if (result.IsThis()) {
946 result = Expression::ThisProperty();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000947 } else {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000948 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000949 }
950 break;
951 }
952 case i::Token::LPAREN: {
953 if (new_count == 0) return result;
954 // Consume one of the new prefixes (already parsed).
955 ParseArguments(CHECK_OK);
956 new_count--;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000957 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000958 break;
959 }
960 default:
961 return result;
962 }
963 }
964}
965
966
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000967PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000968 // PrimaryExpression ::
969 // 'this'
970 // 'null'
971 // 'true'
972 // 'false'
973 // Identifier
974 // Number
975 // String
976 // ArrayLiteral
977 // ObjectLiteral
978 // RegExpLiteral
979 // '(' Expression ')'
980
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000981 Expression result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000982 switch (peek()) {
983 case i::Token::THIS: {
984 Next();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000985 result = Expression::This();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000986 break;
987 }
988
ager@chromium.org04921a82011-06-27 13:21:41 +0000989 case i::Token::FUTURE_RESERVED_WORD: {
990 Next();
991 i::Scanner::Location location = scanner_->location();
992 ReportMessageAt(location.beg_pos, location.end_pos,
993 "reserved_word", NULL);
994 *ok = false;
995 return Expression::Default();
996 }
997
998 case i::Token::FUTURE_STRICT_RESERVED_WORD:
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000999 if (strict_mode()) {
1000 Next();
1001 i::Scanner::Location location = scanner_->location();
1002 ReportMessageAt(location.beg_pos, location.end_pos,
1003 "strict_reserved_word", NULL);
1004 *ok = false;
1005 return Expression::Default();
1006 }
1007 // FALLTHROUGH
1008 case i::Token::IDENTIFIER: {
1009 Identifier id = ParseIdentifier(CHECK_OK);
1010 result = Expression::FromIdentifier(id);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001011 break;
1012 }
1013
1014 case i::Token::NULL_LITERAL:
1015 case i::Token::TRUE_LITERAL:
1016 case i::Token::FALSE_LITERAL:
1017 case i::Token::NUMBER: {
1018 Next();
1019 break;
1020 }
1021 case i::Token::STRING: {
1022 Next();
1023 result = GetStringSymbol();
1024 break;
1025 }
1026
1027 case i::Token::ASSIGN_DIV:
1028 result = ParseRegExpLiteral(true, CHECK_OK);
1029 break;
1030
1031 case i::Token::DIV:
1032 result = ParseRegExpLiteral(false, CHECK_OK);
1033 break;
1034
1035 case i::Token::LBRACK:
1036 result = ParseArrayLiteral(CHECK_OK);
1037 break;
1038
1039 case i::Token::LBRACE:
1040 result = ParseObjectLiteral(CHECK_OK);
1041 break;
1042
1043 case i::Token::LPAREN:
1044 Consume(i::Token::LPAREN);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001045 parenthesized_function_ = (peek() == i::Token::FUNCTION);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001046 result = ParseExpression(true, CHECK_OK);
1047 Expect(i::Token::RPAREN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001048 result = result.Parenthesize();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001049 break;
1050
1051 case i::Token::MOD:
1052 result = ParseV8Intrinsic(CHECK_OK);
1053 break;
1054
1055 default: {
1056 Next();
1057 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001058 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001059 }
1060 }
1061
1062 return result;
1063}
1064
1065
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001066PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001067 // ArrayLiteral ::
1068 // '[' Expression? (',' Expression?)* ']'
1069 Expect(i::Token::LBRACK, CHECK_OK);
1070 while (peek() != i::Token::RBRACK) {
1071 if (peek() != i::Token::COMMA) {
1072 ParseAssignmentExpression(true, CHECK_OK);
1073 }
1074 if (peek() != i::Token::RBRACK) {
1075 Expect(i::Token::COMMA, CHECK_OK);
1076 }
1077 }
1078 Expect(i::Token::RBRACK, CHECK_OK);
1079
1080 scope_->NextMaterializedLiteralIndex();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001081 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001082}
1083
1084
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001085PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001086 // ObjectLiteral ::
1087 // '{' (
1088 // ((IdentifierName | String | Number) ':' AssignmentExpression)
1089 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1090 // )*[','] '}'
1091
1092 Expect(i::Token::LBRACE, CHECK_OK);
1093 while (peek() != i::Token::RBRACE) {
1094 i::Token::Value next = peek();
1095 switch (next) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001096 case i::Token::IDENTIFIER:
ager@chromium.org04921a82011-06-27 13:21:41 +00001097 case i::Token::FUTURE_RESERVED_WORD:
1098 case i::Token::FUTURE_STRICT_RESERVED_WORD: {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001099 bool is_getter = false;
1100 bool is_setter = false;
ager@chromium.org04921a82011-06-27 13:21:41 +00001101 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001102 if ((is_getter || is_setter) && peek() != i::Token::COLON) {
1103 i::Token::Value name = Next();
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001104 bool is_keyword = i::Token::IsKeyword(name);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001105 if (name != i::Token::IDENTIFIER &&
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001106 name != i::Token::FUTURE_RESERVED_WORD &&
ager@chromium.org04921a82011-06-27 13:21:41 +00001107 name != i::Token::FUTURE_STRICT_RESERVED_WORD &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001108 name != i::Token::NUMBER &&
1109 name != i::Token::STRING &&
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001110 !is_keyword) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001111 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001112 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001113 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001114 if (!is_keyword) {
1115 LogSymbol();
1116 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001117 ParseFunctionLiteral(CHECK_OK);
1118 if (peek() != i::Token::RBRACE) {
1119 Expect(i::Token::COMMA, CHECK_OK);
1120 }
1121 continue; // restart the while
1122 }
1123 break;
1124 }
1125 case i::Token::STRING:
1126 Consume(next);
1127 GetStringSymbol();
1128 break;
1129 case i::Token::NUMBER:
1130 Consume(next);
1131 break;
1132 default:
1133 if (i::Token::IsKeyword(next)) {
1134 Consume(next);
1135 } else {
1136 // Unexpected token.
1137 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001138 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001139 }
1140 }
1141
1142 Expect(i::Token::COLON, CHECK_OK);
1143 ParseAssignmentExpression(true, CHECK_OK);
1144
1145 // TODO(1240767): Consider allowing trailing comma.
1146 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
1147 }
1148 Expect(i::Token::RBRACE, CHECK_OK);
1149
1150 scope_->NextMaterializedLiteralIndex();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001151 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001152}
1153
1154
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001155PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
1156 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001157 if (!scanner_->ScanRegExpPattern(seen_equal)) {
1158 Next();
1159 i::JavaScriptScanner::Location location = scanner_->location();
1160 ReportMessageAt(location.beg_pos, location.end_pos,
1161 "unterminated_regexp", NULL);
1162 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001163 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001164 }
1165
1166 scope_->NextMaterializedLiteralIndex();
1167
1168 if (!scanner_->ScanRegExpFlags()) {
1169 Next();
1170 i::JavaScriptScanner::Location location = scanner_->location();
1171 ReportMessageAt(location.beg_pos, location.end_pos,
1172 "invalid_regexp_flags", NULL);
1173 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001174 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001175 }
1176 Next();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001177 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001178}
1179
1180
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001181PreParser::Arguments PreParser::ParseArguments(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001182 // Arguments ::
1183 // '(' (AssignmentExpression)*[','] ')'
1184
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001185 Expect(i::Token::LPAREN, ok);
1186 if (!*ok) return -1;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001187 bool done = (peek() == i::Token::RPAREN);
1188 int argc = 0;
1189 while (!done) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001190 ParseAssignmentExpression(true, ok);
1191 if (!*ok) return -1;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001192 argc++;
1193 done = (peek() == i::Token::RPAREN);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001194 if (!done) {
1195 Expect(i::Token::COMMA, ok);
1196 if (!*ok) return -1;
1197 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001198 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001199 Expect(i::Token::RPAREN, ok);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001200 return argc;
1201}
1202
1203
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001204PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001205 // Function ::
1206 // '(' FormalParameterList? ')' '{' FunctionBody '}'
1207
1208 // Parse function body.
1209 ScopeType outer_scope_type = scope_->type();
1210 bool inside_with = scope_->IsInsideWith();
1211 Scope function_scope(&scope_, kFunctionScope);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001212 // FormalParameterList ::
1213 // '(' (Identifier)*[','] ')'
1214 Expect(i::Token::LPAREN, CHECK_OK);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001215 int start_position = scanner_->location().beg_pos;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001216 bool done = (peek() == i::Token::RPAREN);
1217 while (!done) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001218 Identifier id = ParseIdentifier(CHECK_OK);
1219 if (!id.IsValidStrictVariable()) {
1220 StrictModeIdentifierViolation(scanner_->location(),
1221 "strict_param_name",
1222 id,
1223 CHECK_OK);
1224 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001225 done = (peek() == i::Token::RPAREN);
1226 if (!done) {
1227 Expect(i::Token::COMMA, CHECK_OK);
1228 }
1229 }
1230 Expect(i::Token::RPAREN, CHECK_OK);
1231
1232 Expect(i::Token::LBRACE, CHECK_OK);
1233 int function_block_pos = scanner_->location().beg_pos;
1234
1235 // Determine if the function will be lazily compiled.
1236 // Currently only happens to top-level functions.
1237 // Optimistically assume that all top-level functions are lazily compiled.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001238 bool is_lazily_compiled = (outer_scope_type == kTopLevelScope &&
1239 !inside_with && allow_lazy_ &&
1240 !parenthesized_function_);
1241 parenthesized_function_ = false;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001242
1243 if (is_lazily_compiled) {
1244 log_->PauseRecording();
1245 ParseSourceElements(i::Token::RBRACE, ok);
1246 log_->ResumeRecording();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001247 if (!*ok) Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001248
1249 Expect(i::Token::RBRACE, CHECK_OK);
1250
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001251 // Position right after terminal '}'.
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001252 int end_pos = scanner_->location().end_pos;
1253 log_->LogFunction(function_block_pos, end_pos,
1254 function_scope.materialized_literal_count(),
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001255 function_scope.expected_properties(),
1256 strict_mode() ? 1 : 0);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001257 } else {
1258 ParseSourceElements(i::Token::RBRACE, CHECK_OK);
1259 Expect(i::Token::RBRACE, CHECK_OK);
1260 }
lrn@chromium.org1c092762011-05-09 09:42:16 +00001261
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001262 if (strict_mode()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +00001263 int end_position = scanner_->location().end_pos;
1264 CheckOctalLiteral(start_position, end_position, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001265 CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK);
1266 return Expression::StrictFunction();
lrn@chromium.org1c092762011-05-09 09:42:16 +00001267 }
1268
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001269 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001270}
1271
1272
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001273PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001274 // CallRuntime ::
1275 // '%' Identifier Arguments
1276
1277 Expect(i::Token::MOD, CHECK_OK);
1278 ParseIdentifier(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001279 ParseArguments(ok);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001280
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001281 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001282}
1283
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001284#undef CHECK_OK
1285
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001286
1287void PreParser::ExpectSemicolon(bool* ok) {
1288 // Check for automatic semicolon insertion according to
1289 // the rules given in ECMA-262, section 7.9, page 21.
1290 i::Token::Value tok = peek();
1291 if (tok == i::Token::SEMICOLON) {
1292 Next();
1293 return;
1294 }
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +00001295 if (scanner_->HasAnyLineTerminatorBeforeNext() ||
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001296 tok == i::Token::RBRACE ||
1297 tok == i::Token::EOS) {
1298 return;
1299 }
1300 Expect(i::Token::SEMICOLON, ok);
1301}
1302
1303
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001304void PreParser::LogSymbol() {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001305 int identifier_pos = scanner_->location().beg_pos;
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001306 if (scanner_->is_literal_ascii()) {
1307 log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
1308 } else {
1309 log_->LogUC16Symbol(identifier_pos, scanner_->literal_uc16_string());
1310 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001311}
1312
1313
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001314PreParser::Expression PreParser::GetStringSymbol() {
lrn@chromium.org1c092762011-05-09 09:42:16 +00001315 const int kUseStrictLength = 10;
1316 const char* kUseStrictChars = "use strict";
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001317 LogSymbol();
lrn@chromium.org1c092762011-05-09 09:42:16 +00001318 if (scanner_->is_literal_ascii() &&
1319 scanner_->literal_length() == kUseStrictLength &&
1320 !scanner_->literal_contains_escapes() &&
1321 !strncmp(scanner_->literal_ascii_string().start(), kUseStrictChars,
1322 kUseStrictLength)) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001323 return Expression::UseStrictStringLiteral();
lrn@chromium.org1c092762011-05-09 09:42:16 +00001324 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001325 return Expression::StringLiteral();
1326}
1327
1328
1329PreParser::Identifier PreParser::GetIdentifierSymbol() {
1330 LogSymbol();
1331 if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) {
1332 return Identifier::FutureReserved();
ager@chromium.org04921a82011-06-27 13:21:41 +00001333 } else if (scanner_->current_token() ==
1334 i::Token::FUTURE_STRICT_RESERVED_WORD) {
1335 return Identifier::FutureStrictReserved();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001336 }
1337 if (scanner_->is_literal_ascii()) {
1338 // Detect strict-mode poison words.
1339 if (scanner_->literal_length() == 4 &&
1340 !strncmp(scanner_->literal_ascii_string().start(), "eval", 4)) {
1341 return Identifier::Eval();
1342 }
1343 if (scanner_->literal_length() == 9 &&
1344 !strncmp(scanner_->literal_ascii_string().start(), "arguments", 9)) {
1345 return Identifier::Arguments();
1346 }
1347 }
1348 return Identifier::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001349}
1350
1351
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001352PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
ager@chromium.org04921a82011-06-27 13:21:41 +00001353 i::Token::Value next = Next();
1354 switch (next) {
1355 case i::Token::FUTURE_RESERVED_WORD: {
1356 i::Scanner::Location location = scanner_->location();
1357 ReportMessageAt(location.beg_pos, location.end_pos,
1358 "reserved_word", NULL);
1359 *ok = false;
1360 }
1361 // FALLTHROUGH
1362 case i::Token::FUTURE_STRICT_RESERVED_WORD:
1363 case i::Token::IDENTIFIER:
1364 return GetIdentifierSymbol();
1365 default:
1366 *ok = false;
1367 return Identifier::Default();
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001368 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001369}
1370
1371
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001372void PreParser::SetStrictModeViolation(i::Scanner::Location location,
1373 const char* type,
1374 bool* ok) {
1375 if (strict_mode()) {
1376 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
1377 *ok = false;
1378 return;
1379 }
1380 // Delay report in case this later turns out to be strict code
1381 // (i.e., for function names and parameters prior to a "use strict"
1382 // directive).
1383 strict_mode_violation_location_ = location;
1384 strict_mode_violation_type_ = type;
1385}
1386
1387
1388void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
1389 int end_pos,
1390 bool* ok) {
1391 i::Scanner::Location location = strict_mode_violation_location_;
1392 if (location.IsValid() &&
1393 location.beg_pos > beg_pos && location.end_pos < end_pos) {
1394 ReportMessageAt(location.beg_pos, location.end_pos,
1395 strict_mode_violation_type_, NULL);
1396 *ok = false;
1397 }
1398 strict_mode_violation_location_ = i::Scanner::Location::invalid();
1399}
1400
1401
1402void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
1403 const char* eval_args_type,
1404 Identifier identifier,
1405 bool* ok) {
1406 const char* type = eval_args_type;
1407 if (identifier.IsFutureReserved()) {
ager@chromium.org04921a82011-06-27 13:21:41 +00001408 type = "reserved_word";
1409 } else if (identifier.IsFutureStrictReserved()) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001410 type = "strict_reserved_word";
1411 }
1412 if (strict_mode()) {
1413 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
1414 *ok = false;
1415 return;
1416 }
1417 strict_mode_violation_location_ = location;
1418 strict_mode_violation_type_ = type;
1419}
1420
1421
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001422PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001423 i::Token::Value next = Next();
1424 if (i::Token::IsKeyword(next)) {
1425 int pos = scanner_->location().beg_pos;
1426 const char* keyword = i::Token::String(next);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001427 log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword,
1428 i::StrLength(keyword)));
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001429 return Identifier::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001430 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001431 if (next == i::Token::IDENTIFIER ||
ager@chromium.org04921a82011-06-27 13:21:41 +00001432 next == i::Token::FUTURE_RESERVED_WORD ||
1433 next == i::Token::FUTURE_STRICT_RESERVED_WORD) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001434 return GetIdentifierSymbol();
1435 }
1436 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001437 return Identifier::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001438}
1439
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001440#undef CHECK_OK
1441
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001442
1443// This function reads an identifier and determines whether or not it
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001444// is 'get' or 'set'.
ager@chromium.org04921a82011-06-27 13:21:41 +00001445PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get,
1446 bool* is_set,
1447 bool* ok) {
1448 Identifier result = ParseIdentifierName(ok);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001449 if (!*ok) return Identifier::Default();
1450 if (scanner_->is_literal_ascii() &&
1451 scanner_->literal_length() == 3) {
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001452 const char* token = scanner_->literal_ascii_string().start();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001453 *is_get = strncmp(token, "get", 3) == 0;
1454 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
1455 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001456 return result;
1457}
1458
1459bool PreParser::peek_any_identifier() {
1460 i::Token::Value next = peek();
1461 return next == i::Token::IDENTIFIER ||
ager@chromium.org04921a82011-06-27 13:21:41 +00001462 next == i::Token::FUTURE_RESERVED_WORD ||
1463 next == i::Token::FUTURE_STRICT_RESERVED_WORD;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001464}
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001465} } // v8::preparser