blob: 463df83dbbbfeda503c8a1fee115063dc8522b84 [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
ager@chromium.orgbeb25712010-11-29 08:02:25 +000059void PreParser::ReportUnexpectedToken(i::Token::Value token) {
60 // We don't report stack overflows here, to avoid increasing the
61 // stack depth even further. Instead we report it after parsing is
62 // over, in ParseProgram.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000063 if (token == i::Token::ILLEGAL && stack_overflow_) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +000064 return;
65 }
66 i::JavaScriptScanner::Location source_location = scanner_->location();
67
68 // Four of the tokens are treated specially
69 switch (token) {
70 case i::Token::EOS:
71 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
72 "unexpected_eos", NULL);
73 case i::Token::NUMBER:
74 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
75 "unexpected_token_number", NULL);
76 case i::Token::STRING:
77 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
78 "unexpected_token_string", NULL);
79 case i::Token::IDENTIFIER:
80 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
81 "unexpected_token_identifier", NULL);
ager@chromium.org04921a82011-06-27 13:21:41 +000082 case i::Token::FUTURE_RESERVED_WORD:
83 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
84 "unexpected_reserved", NULL);
85 case i::Token::FUTURE_STRICT_RESERVED_WORD:
86 return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
87 "unexpected_strict_reserved", NULL);
ager@chromium.orgbeb25712010-11-29 08:02:25 +000088 default:
89 const char* name = i::Token::String(token);
90 ReportMessageAt(source_location.beg_pos, source_location.end_pos,
91 "unexpected_token", name);
92 }
93}
94
95
lrn@chromium.org1c092762011-05-09 09:42:16 +000096// Checks whether octal literal last seen is between beg_pos and end_pos.
97// If so, reports an error.
98void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
99 i::Scanner::Location octal = scanner_->octal_position();
100 if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
101 ReportMessageAt(octal.beg_pos, octal.end_pos, "strict_octal_literal", NULL);
102 scanner_->clear_octal_position();
103 *ok = false;
104 }
105}
106
107
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000108#define CHECK_OK ok); \
109 if (!*ok) return kUnknownSourceElements; \
110 ((void)0
111#define DUMMY ) // to make indentation work
112#undef DUMMY
113
114
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000115PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
116 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000117 // SourceElements ::
118 // (Statement)* <end_token>
119
lrn@chromium.org1c092762011-05-09 09:42:16 +0000120 bool allow_directive_prologue = true;
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000121 while (peek() != end_token) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000122 Statement statement = ParseStatement(CHECK_OK);
123 if (allow_directive_prologue) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000124 if (statement.IsUseStrictLiteral()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000125 set_strict_mode();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000126 } else if (!statement.IsStringLiteral()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000127 allow_directive_prologue = false;
128 }
129 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000130 }
131 return kUnknownSourceElements;
132}
133
134
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000135#undef CHECK_OK
136#define CHECK_OK ok); \
137 if (!*ok) return Statement::Default(); \
138 ((void)0
139#define DUMMY ) // to make indentation work
140#undef DUMMY
141
142
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000143PreParser::Statement PreParser::ParseStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000144 // Statement ::
145 // Block
146 // VariableStatement
147 // EmptyStatement
148 // ExpressionStatement
149 // IfStatement
150 // IterationStatement
151 // ContinueStatement
152 // BreakStatement
153 // ReturnStatement
154 // WithStatement
155 // LabelledStatement
156 // SwitchStatement
157 // ThrowStatement
158 // TryStatement
159 // DebuggerStatement
160
161 // Note: Since labels can only be used by 'break' and 'continue'
162 // statements, which themselves are only valid within blocks,
163 // iterations or 'switch' statements (i.e., BreakableStatements),
164 // labels can be simply ignored in all other cases; except for
165 // trivial labeled break statements 'label: break label' which is
166 // parsed into an empty statement.
167
168 // Keep the source position of the statement
169 switch (peek()) {
170 case i::Token::LBRACE:
171 return ParseBlock(ok);
172
173 case i::Token::CONST:
174 case i::Token::VAR:
175 return ParseVariableStatement(ok);
176
177 case i::Token::SEMICOLON:
178 Next();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000179 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000180
181 case i::Token::IF:
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000182 return ParseIfStatement(ok);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000183
184 case i::Token::DO:
185 return ParseDoWhileStatement(ok);
186
187 case i::Token::WHILE:
188 return ParseWhileStatement(ok);
189
190 case i::Token::FOR:
191 return ParseForStatement(ok);
192
193 case i::Token::CONTINUE:
194 return ParseContinueStatement(ok);
195
196 case i::Token::BREAK:
197 return ParseBreakStatement(ok);
198
199 case i::Token::RETURN:
200 return ParseReturnStatement(ok);
201
202 case i::Token::WITH:
203 return ParseWithStatement(ok);
204
205 case i::Token::SWITCH:
206 return ParseSwitchStatement(ok);
207
208 case i::Token::THROW:
209 return ParseThrowStatement(ok);
210
211 case i::Token::TRY:
212 return ParseTryStatement(ok);
213
214 case i::Token::FUNCTION:
215 return ParseFunctionDeclaration(ok);
216
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000217 case i::Token::DEBUGGER:
218 return ParseDebuggerStatement(ok);
219
220 default:
221 return ParseExpressionOrLabelledStatement(ok);
222 }
223}
224
225
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000226PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000227 // FunctionDeclaration ::
228 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
229 Expect(i::Token::FUNCTION, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000230
231 Identifier identifier = ParseIdentifier(CHECK_OK);
232 i::Scanner::Location location = scanner_->location();
233
234 Expression function_value = ParseFunctionLiteral(CHECK_OK);
235
236 if (function_value.IsStrictFunction() &&
237 !identifier.IsValidStrictVariable()) {
238 // Strict mode violation, using either reserved word or eval/arguments
239 // as name of strict function.
240 const char* type = "strict_function_name";
ager@chromium.org04921a82011-06-27 13:21:41 +0000241 if (identifier.IsFutureStrictReserved()) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000242 type = "strict_reserved_word";
243 }
244 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
245 *ok = false;
246 }
danno@chromium.org40cb8782011-05-25 07:58:50 +0000247 return Statement::FunctionDeclaration();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000248}
249
250
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000251PreParser::Statement PreParser::ParseBlock(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000252 // Block ::
253 // '{' Statement* '}'
254
255 // Note that a Block does not introduce a new execution scope!
256 // (ECMA-262, 3rd, 12.2)
257 //
258 Expect(i::Token::LBRACE, CHECK_OK);
259 while (peek() != i::Token::RBRACE) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000260 i::Scanner::Location start_location = scanner_->peek_location();
261 Statement statement = ParseStatement(CHECK_OK);
262 i::Scanner::Location end_location = scanner_->location();
263 if (strict_mode() && statement.IsFunctionDeclaration()) {
264 ReportMessageAt(start_location.beg_pos, end_location.end_pos,
265 "strict_function", NULL);
266 *ok = false;
267 return Statement::Default();
268 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000269 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000270 Expect(i::Token::RBRACE, ok);
271 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000272}
273
274
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000275PreParser::Statement PreParser::ParseVariableStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000276 // VariableStatement ::
277 // VariableDeclarations ';'
278
279 Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK);
280 ExpectSemicolon(CHECK_OK);
281 return result;
282}
283
284
285// If the variable declaration declares exactly one non-const
286// variable, then *var is set to that variable. In all other cases,
287// *var is untouched; in particular, it is the caller's responsibility
288// to initialize it properly. This mechanism is also used for the parsing
289// of 'for-in' loops.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000290PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN,
291 int* num_decl,
292 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000293 // VariableDeclarations ::
294 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
295
296 if (peek() == i::Token::VAR) {
297 Consume(i::Token::VAR);
298 } else if (peek() == i::Token::CONST) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000299 if (strict_mode()) {
300 i::Scanner::Location location = scanner_->peek_location();
301 ReportMessageAt(location.beg_pos, location.end_pos,
302 "strict_const", NULL);
303 *ok = false;
304 return Statement::Default();
305 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000306 Consume(i::Token::CONST);
307 } else {
308 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000309 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000310 }
311
312 // The scope of a variable/const declared anywhere inside a function
313 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). .
314 int nvars = 0; // the number of variables declared
315 do {
316 // Parse variable name.
317 if (nvars > 0) Consume(i::Token::COMMA);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000318 Identifier identifier = ParseIdentifier(CHECK_OK);
319 if (strict_mode() && !identifier.IsValidStrictVariable()) {
320 StrictModeIdentifierViolation(scanner_->location(),
321 "strict_var_name",
322 identifier,
323 ok);
324 return Statement::Default();
325 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000326 nvars++;
327 if (peek() == i::Token::ASSIGN) {
328 Expect(i::Token::ASSIGN, CHECK_OK);
329 ParseAssignmentExpression(accept_IN, CHECK_OK);
330 }
331 } while (peek() == i::Token::COMMA);
332
333 if (num_decl != NULL) *num_decl = nvars;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000334 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000335}
336
337
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000338PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000339 // ExpressionStatement | LabelledStatement ::
340 // Expression ';'
341 // Identifier ':' Statement
342
343 Expression expr = ParseExpression(true, CHECK_OK);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000344 if (expr.IsRawIdentifier()) {
345 if (peek() == i::Token::COLON &&
346 (!strict_mode() || !expr.AsIdentifier().IsFutureReserved())) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000347 Consume(i::Token::COLON);
348 i::Scanner::Location start_location = scanner_->peek_location();
349 Statement statement = ParseStatement(CHECK_OK);
350 if (strict_mode() && statement.IsFunctionDeclaration()) {
351 i::Scanner::Location end_location = scanner_->location();
352 ReportMessageAt(start_location.beg_pos, end_location.end_pos,
353 "strict_function", NULL);
354 *ok = false;
355 }
356 return Statement::Default();
357 }
whesse@chromium.org7b260152011-06-20 15:33:18 +0000358 // Preparsing is disabled for extensions (because the extension details
359 // aren't passed to lazily compiled functions), so we don't
360 // accept "native function" in the preparser.
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000361 }
362 // Parsed expression statement.
363 ExpectSemicolon(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000364 return Statement::ExpressionStatement(expr);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000365}
366
367
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000368PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000369 // IfStatement ::
370 // 'if' '(' Expression ')' Statement ('else' Statement)?
371
372 Expect(i::Token::IF, CHECK_OK);
373 Expect(i::Token::LPAREN, CHECK_OK);
374 ParseExpression(true, CHECK_OK);
375 Expect(i::Token::RPAREN, CHECK_OK);
376 ParseStatement(CHECK_OK);
377 if (peek() == i::Token::ELSE) {
378 Next();
379 ParseStatement(CHECK_OK);
380 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000381 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000382}
383
384
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000385PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000386 // ContinueStatement ::
387 // 'continue' [no line terminator] Identifier? ';'
388
389 Expect(i::Token::CONTINUE, CHECK_OK);
390 i::Token::Value tok = peek();
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000391 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000392 tok != i::Token::SEMICOLON &&
393 tok != i::Token::RBRACE &&
394 tok != i::Token::EOS) {
395 ParseIdentifier(CHECK_OK);
396 }
397 ExpectSemicolon(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000398 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000399}
400
401
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000402PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000403 // BreakStatement ::
404 // 'break' [no line terminator] Identifier? ';'
405
406 Expect(i::Token::BREAK, CHECK_OK);
407 i::Token::Value tok = peek();
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000408 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000409 tok != i::Token::SEMICOLON &&
410 tok != i::Token::RBRACE &&
411 tok != i::Token::EOS) {
412 ParseIdentifier(CHECK_OK);
413 }
414 ExpectSemicolon(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000415 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000416}
417
418
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000419PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000420 // ReturnStatement ::
421 // 'return' [no line terminator] Expression? ';'
422
423 // Consume the return token. It is necessary to do the before
424 // reporting any errors on it, because of the way errors are
425 // reported (underlining).
426 Expect(i::Token::RETURN, CHECK_OK);
427
428 // An ECMAScript program is considered syntactically incorrect if it
429 // contains a return statement that is not within the body of a
430 // function. See ECMA-262, section 12.9, page 67.
431 // This is not handled during preparsing.
432
433 i::Token::Value tok = peek();
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000434 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000435 tok != i::Token::SEMICOLON &&
436 tok != i::Token::RBRACE &&
437 tok != i::Token::EOS) {
438 ParseExpression(true, CHECK_OK);
439 }
440 ExpectSemicolon(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000441 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000442}
443
444
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000445PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000446 // WithStatement ::
447 // 'with' '(' Expression ')' Statement
448 Expect(i::Token::WITH, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000449 if (strict_mode()) {
450 i::Scanner::Location location = scanner_->location();
451 ReportMessageAt(location.beg_pos, location.end_pos,
452 "strict_mode_with", NULL);
453 *ok = false;
454 return Statement::Default();
455 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000456 Expect(i::Token::LPAREN, CHECK_OK);
457 ParseExpression(true, CHECK_OK);
458 Expect(i::Token::RPAREN, CHECK_OK);
459
460 scope_->EnterWith();
461 ParseStatement(CHECK_OK);
462 scope_->LeaveWith();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000463 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000464}
465
466
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000467PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000468 // SwitchStatement ::
469 // 'switch' '(' Expression ')' '{' CaseClause* '}'
470
471 Expect(i::Token::SWITCH, CHECK_OK);
472 Expect(i::Token::LPAREN, CHECK_OK);
473 ParseExpression(true, CHECK_OK);
474 Expect(i::Token::RPAREN, CHECK_OK);
475
476 Expect(i::Token::LBRACE, CHECK_OK);
477 i::Token::Value token = peek();
478 while (token != i::Token::RBRACE) {
479 if (token == i::Token::CASE) {
480 Expect(i::Token::CASE, CHECK_OK);
481 ParseExpression(true, CHECK_OK);
482 Expect(i::Token::COLON, CHECK_OK);
483 } else if (token == i::Token::DEFAULT) {
484 Expect(i::Token::DEFAULT, CHECK_OK);
485 Expect(i::Token::COLON, CHECK_OK);
486 } else {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000487 i::Scanner::Location start_location = scanner_->peek_location();
488 Statement statement = ParseStatement(CHECK_OK);
489 if (strict_mode() && statement.IsFunctionDeclaration()) {
490 i::Scanner::Location end_location = scanner_->location();
491 ReportMessageAt(start_location.beg_pos, end_location.end_pos,
492 "strict_function", NULL);
493 *ok = false;
494 return Statement::Default();
495 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000496 }
497 token = peek();
498 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000499 Expect(i::Token::RBRACE, ok);
500 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000501}
502
503
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000504PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000505 // DoStatement ::
506 // 'do' Statement 'while' '(' Expression ')' ';'
507
508 Expect(i::Token::DO, CHECK_OK);
509 ParseStatement(CHECK_OK);
510 Expect(i::Token::WHILE, CHECK_OK);
511 Expect(i::Token::LPAREN, CHECK_OK);
512 ParseExpression(true, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000513 Expect(i::Token::RPAREN, ok);
514 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000515}
516
517
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000518PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000519 // WhileStatement ::
520 // 'while' '(' Expression ')' Statement
521
522 Expect(i::Token::WHILE, CHECK_OK);
523 Expect(i::Token::LPAREN, CHECK_OK);
524 ParseExpression(true, CHECK_OK);
525 Expect(i::Token::RPAREN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000526 ParseStatement(ok);
527 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000528}
529
530
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000531PreParser::Statement PreParser::ParseForStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000532 // ForStatement ::
533 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
534
535 Expect(i::Token::FOR, CHECK_OK);
536 Expect(i::Token::LPAREN, CHECK_OK);
537 if (peek() != i::Token::SEMICOLON) {
538 if (peek() == i::Token::VAR || peek() == i::Token::CONST) {
539 int decl_count;
540 ParseVariableDeclarations(false, &decl_count, CHECK_OK);
541 if (peek() == i::Token::IN && decl_count == 1) {
542 Expect(i::Token::IN, CHECK_OK);
543 ParseExpression(true, CHECK_OK);
544 Expect(i::Token::RPAREN, CHECK_OK);
545
546 ParseStatement(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000547 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000548 }
549 } else {
550 ParseExpression(false, CHECK_OK);
551 if (peek() == i::Token::IN) {
552 Expect(i::Token::IN, CHECK_OK);
553 ParseExpression(true, CHECK_OK);
554 Expect(i::Token::RPAREN, CHECK_OK);
555
556 ParseStatement(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000557 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000558 }
559 }
560 }
561
562 // Parsed initializer at this point.
563 Expect(i::Token::SEMICOLON, CHECK_OK);
564
565 if (peek() != i::Token::SEMICOLON) {
566 ParseExpression(true, CHECK_OK);
567 }
568 Expect(i::Token::SEMICOLON, CHECK_OK);
569
570 if (peek() != i::Token::RPAREN) {
571 ParseExpression(true, CHECK_OK);
572 }
573 Expect(i::Token::RPAREN, CHECK_OK);
574
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000575 ParseStatement(ok);
576 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000577}
578
579
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000580PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000581 // ThrowStatement ::
582 // 'throw' [no line terminator] Expression ';'
583
584 Expect(i::Token::THROW, CHECK_OK);
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000585 if (scanner_->HasAnyLineTerminatorBeforeNext()) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000586 i::JavaScriptScanner::Location pos = scanner_->location();
587 ReportMessageAt(pos.beg_pos, pos.end_pos,
588 "newline_after_throw", NULL);
589 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000590 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000591 }
592 ParseExpression(true, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000593 ExpectSemicolon(ok);
594 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000595}
596
597
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000598PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000599 // TryStatement ::
600 // 'try' Block Catch
601 // 'try' Block Finally
602 // 'try' Block Catch Finally
603 //
604 // Catch ::
605 // 'catch' '(' Identifier ')' Block
606 //
607 // Finally ::
608 // 'finally' Block
609
610 // In preparsing, allow any number of catch/finally blocks, including zero
611 // of both.
612
613 Expect(i::Token::TRY, CHECK_OK);
614
615 ParseBlock(CHECK_OK);
616
617 bool catch_or_finally_seen = false;
618 if (peek() == i::Token::CATCH) {
619 Consume(i::Token::CATCH);
620 Expect(i::Token::LPAREN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000621 Identifier id = ParseIdentifier(CHECK_OK);
622 if (strict_mode() && !id.IsValidStrictVariable()) {
623 StrictModeIdentifierViolation(scanner_->location(),
624 "strict_catch_variable",
625 id,
626 ok);
627 return Statement::Default();
628 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000629 Expect(i::Token::RPAREN, CHECK_OK);
630 scope_->EnterWith();
631 ParseBlock(ok);
632 scope_->LeaveWith();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000633 if (!*ok) Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000634 catch_or_finally_seen = true;
635 }
636 if (peek() == i::Token::FINALLY) {
637 Consume(i::Token::FINALLY);
638 ParseBlock(CHECK_OK);
639 catch_or_finally_seen = true;
640 }
641 if (!catch_or_finally_seen) {
642 *ok = false;
643 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000644 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000645}
646
647
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000648PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000649 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
650 // contexts this is used as a statement which invokes the debugger as if a
651 // break point is present.
652 // DebuggerStatement ::
653 // 'debugger' ';'
654
655 Expect(i::Token::DEBUGGER, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000656 ExpectSemicolon(ok);
657 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000658}
659
660
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000661#undef CHECK_OK
662#define CHECK_OK ok); \
663 if (!*ok) return Expression::Default(); \
664 ((void)0
665#define DUMMY ) // to make indentation work
666#undef DUMMY
667
668
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000669// Precedence = 1
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000670PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000671 // Expression ::
672 // AssignmentExpression
673 // Expression ',' AssignmentExpression
674
675 Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
676 while (peek() == i::Token::COMMA) {
677 Expect(i::Token::COMMA, CHECK_OK);
678 ParseAssignmentExpression(accept_IN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000679 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000680 }
681 return result;
682}
683
684
685// Precedence = 2
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000686PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
687 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000688 // AssignmentExpression ::
689 // ConditionalExpression
690 // LeftHandSideExpression AssignmentOperator AssignmentExpression
691
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000692 i::Scanner::Location before = scanner_->peek_location();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000693 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
694
695 if (!i::Token::IsAssignmentOp(peek())) {
696 // Parsed conditional expression only (no assignment).
697 return expression;
698 }
699
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000700 if (strict_mode() && expression.IsIdentifier() &&
701 expression.AsIdentifier().IsEvalOrArguments()) {
702 i::Scanner::Location after = scanner_->location();
703 ReportMessageAt(before.beg_pos, after.end_pos,
704 "strict_lhs_assignment", NULL);
705 *ok = false;
706 return Expression::Default();
707 }
708
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000709 i::Token::Value op = Next(); // Get assignment operator.
710 ParseAssignmentExpression(accept_IN, CHECK_OK);
711
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000712 if ((op == i::Token::ASSIGN) && expression.IsThisProperty()) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000713 scope_->AddProperty();
714 }
715
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000716 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000717}
718
719
720// Precedence = 3
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000721PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
722 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000723 // ConditionalExpression ::
724 // LogicalOrExpression
725 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
726
727 // We start using the binary expression parser for prec >= 4 only!
728 Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
729 if (peek() != i::Token::CONDITIONAL) return expression;
730 Consume(i::Token::CONDITIONAL);
731 // In parsing the first assignment expression in conditional
732 // expressions we always accept the 'in' keyword; see ECMA-262,
733 // section 11.12, page 58.
734 ParseAssignmentExpression(true, CHECK_OK);
735 Expect(i::Token::COLON, CHECK_OK);
736 ParseAssignmentExpression(accept_IN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000737 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000738}
739
740
741int PreParser::Precedence(i::Token::Value tok, bool accept_IN) {
742 if (tok == i::Token::IN && !accept_IN)
743 return 0; // 0 precedence will terminate binary expression parsing
744
745 return i::Token::Precedence(tok);
746}
747
748
749// Precedence >= 4
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000750PreParser::Expression PreParser::ParseBinaryExpression(int prec,
751 bool accept_IN,
752 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000753 Expression result = ParseUnaryExpression(CHECK_OK);
754 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
755 // prec1 >= 4
756 while (Precedence(peek(), accept_IN) == prec1) {
757 Next();
758 ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000759 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000760 }
761 }
762 return result;
763}
764
765
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000766PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000767 // UnaryExpression ::
768 // PostfixExpression
769 // 'delete' UnaryExpression
770 // 'void' UnaryExpression
771 // 'typeof' UnaryExpression
772 // '++' UnaryExpression
773 // '--' UnaryExpression
774 // '+' UnaryExpression
775 // '-' UnaryExpression
776 // '~' UnaryExpression
777 // '!' UnaryExpression
778
779 i::Token::Value op = peek();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000780 if (i::Token::IsUnaryOp(op)) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000781 op = Next();
782 ParseUnaryExpression(ok);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000783 return Expression::Default();
784 } else if (i::Token::IsCountOp(op)) {
785 op = Next();
786 i::Scanner::Location before = scanner_->peek_location();
787 Expression expression = ParseUnaryExpression(CHECK_OK);
788 if (strict_mode() && expression.IsIdentifier() &&
789 expression.AsIdentifier().IsEvalOrArguments()) {
790 i::Scanner::Location after = scanner_->location();
791 ReportMessageAt(before.beg_pos, after.end_pos,
792 "strict_lhs_prefix", NULL);
793 *ok = false;
794 }
795 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000796 } else {
797 return ParsePostfixExpression(ok);
798 }
799}
800
801
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000802PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000803 // PostfixExpression ::
804 // LeftHandSideExpression ('++' | '--')?
805
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000806 i::Scanner::Location before = scanner_->peek_location();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000807 Expression expression = ParseLeftHandSideExpression(CHECK_OK);
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000808 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000809 i::Token::IsCountOp(peek())) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000810 if (strict_mode() && expression.IsIdentifier() &&
811 expression.AsIdentifier().IsEvalOrArguments()) {
812 i::Scanner::Location after = scanner_->location();
813 ReportMessageAt(before.beg_pos, after.end_pos,
814 "strict_lhs_postfix", NULL);
815 *ok = false;
816 return Expression::Default();
817 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000818 Next();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000819 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000820 }
821 return expression;
822}
823
824
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000825PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000826 // LeftHandSideExpression ::
827 // (NewExpression | MemberExpression) ...
828
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000829 Expression result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000830 if (peek() == i::Token::NEW) {
831 result = ParseNewExpression(CHECK_OK);
832 } else {
833 result = ParseMemberExpression(CHECK_OK);
834 }
835
836 while (true) {
837 switch (peek()) {
838 case i::Token::LBRACK: {
839 Consume(i::Token::LBRACK);
840 ParseExpression(true, CHECK_OK);
841 Expect(i::Token::RBRACK, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000842 if (result.IsThis()) {
843 result = Expression::ThisProperty();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000844 } else {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000845 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000846 }
847 break;
848 }
849
850 case i::Token::LPAREN: {
851 ParseArguments(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000852 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000853 break;
854 }
855
856 case i::Token::PERIOD: {
857 Consume(i::Token::PERIOD);
858 ParseIdentifierName(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000859 if (result.IsThis()) {
860 result = Expression::ThisProperty();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000861 } else {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000862 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000863 }
864 break;
865 }
866
867 default:
868 return result;
869 }
870 }
871}
872
873
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000874PreParser::Expression PreParser::ParseNewExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000875 // NewExpression ::
876 // ('new')+ MemberExpression
877
878 // The grammar for new expressions is pretty warped. The keyword
879 // 'new' can either be a part of the new expression (where it isn't
880 // followed by an argument list) or a part of the member expression,
881 // where it must be followed by an argument list. To accommodate
882 // this, we parse the 'new' keywords greedily and keep track of how
883 // many we have parsed. This information is then passed on to the
884 // member expression parser, which is only allowed to match argument
885 // lists as long as it has 'new' prefixes left
886 unsigned new_count = 0;
887 do {
888 Consume(i::Token::NEW);
889 new_count++;
890 } while (peek() == i::Token::NEW);
891
892 return ParseMemberWithNewPrefixesExpression(new_count, ok);
893}
894
895
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000896PreParser::Expression PreParser::ParseMemberExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000897 return ParseMemberWithNewPrefixesExpression(0, ok);
898}
899
900
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000901PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000902 unsigned new_count, bool* ok) {
903 // MemberExpression ::
904 // (PrimaryExpression | FunctionLiteral)
905 // ('[' Expression ']' | '.' Identifier | Arguments)*
906
907 // Parse the initial primary or function expression.
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000908 Expression result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000909 if (peek() == i::Token::FUNCTION) {
910 Consume(i::Token::FUNCTION);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000911 Identifier identifier = Identifier::Default();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000912 if (peek_any_identifier()) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000913 identifier = ParseIdentifier(CHECK_OK);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000914 }
915 result = ParseFunctionLiteral(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000916 if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
917 StrictModeIdentifierViolation(scanner_->location(),
918 "strict_function_name",
919 identifier,
920 ok);
921 return Expression::Default();
922 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000923 } else {
924 result = ParsePrimaryExpression(CHECK_OK);
925 }
926
927 while (true) {
928 switch (peek()) {
929 case i::Token::LBRACK: {
930 Consume(i::Token::LBRACK);
931 ParseExpression(true, CHECK_OK);
932 Expect(i::Token::RBRACK, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000933 if (result.IsThis()) {
934 result = Expression::ThisProperty();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000935 } else {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000936 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000937 }
938 break;
939 }
940 case i::Token::PERIOD: {
941 Consume(i::Token::PERIOD);
942 ParseIdentifierName(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000943 if (result.IsThis()) {
944 result = Expression::ThisProperty();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000945 } else {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000946 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000947 }
948 break;
949 }
950 case i::Token::LPAREN: {
951 if (new_count == 0) return result;
952 // Consume one of the new prefixes (already parsed).
953 ParseArguments(CHECK_OK);
954 new_count--;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000955 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000956 break;
957 }
958 default:
959 return result;
960 }
961 }
962}
963
964
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000965PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000966 // PrimaryExpression ::
967 // 'this'
968 // 'null'
969 // 'true'
970 // 'false'
971 // Identifier
972 // Number
973 // String
974 // ArrayLiteral
975 // ObjectLiteral
976 // RegExpLiteral
977 // '(' Expression ')'
978
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000979 Expression result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000980 switch (peek()) {
981 case i::Token::THIS: {
982 Next();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000983 result = Expression::This();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000984 break;
985 }
986
ager@chromium.org04921a82011-06-27 13:21:41 +0000987 case i::Token::FUTURE_RESERVED_WORD: {
988 Next();
989 i::Scanner::Location location = scanner_->location();
990 ReportMessageAt(location.beg_pos, location.end_pos,
991 "reserved_word", NULL);
992 *ok = false;
993 return Expression::Default();
994 }
995
996 case i::Token::FUTURE_STRICT_RESERVED_WORD:
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000997 if (strict_mode()) {
998 Next();
999 i::Scanner::Location location = scanner_->location();
1000 ReportMessageAt(location.beg_pos, location.end_pos,
1001 "strict_reserved_word", NULL);
1002 *ok = false;
1003 return Expression::Default();
1004 }
1005 // FALLTHROUGH
1006 case i::Token::IDENTIFIER: {
1007 Identifier id = ParseIdentifier(CHECK_OK);
1008 result = Expression::FromIdentifier(id);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001009 break;
1010 }
1011
1012 case i::Token::NULL_LITERAL:
1013 case i::Token::TRUE_LITERAL:
1014 case i::Token::FALSE_LITERAL:
1015 case i::Token::NUMBER: {
1016 Next();
1017 break;
1018 }
1019 case i::Token::STRING: {
1020 Next();
1021 result = GetStringSymbol();
1022 break;
1023 }
1024
1025 case i::Token::ASSIGN_DIV:
1026 result = ParseRegExpLiteral(true, CHECK_OK);
1027 break;
1028
1029 case i::Token::DIV:
1030 result = ParseRegExpLiteral(false, CHECK_OK);
1031 break;
1032
1033 case i::Token::LBRACK:
1034 result = ParseArrayLiteral(CHECK_OK);
1035 break;
1036
1037 case i::Token::LBRACE:
1038 result = ParseObjectLiteral(CHECK_OK);
1039 break;
1040
1041 case i::Token::LPAREN:
1042 Consume(i::Token::LPAREN);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001043 parenthesized_function_ = (peek() == i::Token::FUNCTION);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001044 result = ParseExpression(true, CHECK_OK);
1045 Expect(i::Token::RPAREN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001046 result = result.Parenthesize();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001047 break;
1048
1049 case i::Token::MOD:
1050 result = ParseV8Intrinsic(CHECK_OK);
1051 break;
1052
1053 default: {
1054 Next();
1055 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001056 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001057 }
1058 }
1059
1060 return result;
1061}
1062
1063
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001064PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001065 // ArrayLiteral ::
1066 // '[' Expression? (',' Expression?)* ']'
1067 Expect(i::Token::LBRACK, CHECK_OK);
1068 while (peek() != i::Token::RBRACK) {
1069 if (peek() != i::Token::COMMA) {
1070 ParseAssignmentExpression(true, CHECK_OK);
1071 }
1072 if (peek() != i::Token::RBRACK) {
1073 Expect(i::Token::COMMA, CHECK_OK);
1074 }
1075 }
1076 Expect(i::Token::RBRACK, CHECK_OK);
1077
1078 scope_->NextMaterializedLiteralIndex();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001079 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001080}
1081
1082
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001083PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001084 // ObjectLiteral ::
1085 // '{' (
1086 // ((IdentifierName | String | Number) ':' AssignmentExpression)
1087 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1088 // )*[','] '}'
1089
1090 Expect(i::Token::LBRACE, CHECK_OK);
1091 while (peek() != i::Token::RBRACE) {
1092 i::Token::Value next = peek();
1093 switch (next) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001094 case i::Token::IDENTIFIER:
ager@chromium.org04921a82011-06-27 13:21:41 +00001095 case i::Token::FUTURE_RESERVED_WORD:
1096 case i::Token::FUTURE_STRICT_RESERVED_WORD: {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001097 bool is_getter = false;
1098 bool is_setter = false;
ager@chromium.org04921a82011-06-27 13:21:41 +00001099 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001100 if ((is_getter || is_setter) && peek() != i::Token::COLON) {
1101 i::Token::Value name = Next();
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001102 bool is_keyword = i::Token::IsKeyword(name);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001103 if (name != i::Token::IDENTIFIER &&
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001104 name != i::Token::FUTURE_RESERVED_WORD &&
ager@chromium.org04921a82011-06-27 13:21:41 +00001105 name != i::Token::FUTURE_STRICT_RESERVED_WORD &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001106 name != i::Token::NUMBER &&
1107 name != i::Token::STRING &&
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001108 !is_keyword) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001109 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001110 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001111 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001112 if (!is_keyword) {
1113 LogSymbol();
1114 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001115 ParseFunctionLiteral(CHECK_OK);
1116 if (peek() != i::Token::RBRACE) {
1117 Expect(i::Token::COMMA, CHECK_OK);
1118 }
1119 continue; // restart the while
1120 }
1121 break;
1122 }
1123 case i::Token::STRING:
1124 Consume(next);
1125 GetStringSymbol();
1126 break;
1127 case i::Token::NUMBER:
1128 Consume(next);
1129 break;
1130 default:
1131 if (i::Token::IsKeyword(next)) {
1132 Consume(next);
1133 } else {
1134 // Unexpected token.
1135 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001136 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001137 }
1138 }
1139
1140 Expect(i::Token::COLON, CHECK_OK);
1141 ParseAssignmentExpression(true, CHECK_OK);
1142
1143 // TODO(1240767): Consider allowing trailing comma.
1144 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
1145 }
1146 Expect(i::Token::RBRACE, CHECK_OK);
1147
1148 scope_->NextMaterializedLiteralIndex();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001149 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001150}
1151
1152
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001153PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
1154 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001155 if (!scanner_->ScanRegExpPattern(seen_equal)) {
1156 Next();
1157 i::JavaScriptScanner::Location location = scanner_->location();
1158 ReportMessageAt(location.beg_pos, location.end_pos,
1159 "unterminated_regexp", NULL);
1160 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001161 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001162 }
1163
1164 scope_->NextMaterializedLiteralIndex();
1165
1166 if (!scanner_->ScanRegExpFlags()) {
1167 Next();
1168 i::JavaScriptScanner::Location location = scanner_->location();
1169 ReportMessageAt(location.beg_pos, location.end_pos,
1170 "invalid_regexp_flags", NULL);
1171 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001172 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001173 }
1174 Next();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001175 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001176}
1177
1178
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001179PreParser::Arguments PreParser::ParseArguments(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001180 // Arguments ::
1181 // '(' (AssignmentExpression)*[','] ')'
1182
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001183 Expect(i::Token::LPAREN, ok);
1184 if (!*ok) return -1;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001185 bool done = (peek() == i::Token::RPAREN);
1186 int argc = 0;
1187 while (!done) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001188 ParseAssignmentExpression(true, ok);
1189 if (!*ok) return -1;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001190 argc++;
1191 done = (peek() == i::Token::RPAREN);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001192 if (!done) {
1193 Expect(i::Token::COMMA, ok);
1194 if (!*ok) return -1;
1195 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001196 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001197 Expect(i::Token::RPAREN, ok);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001198 return argc;
1199}
1200
1201
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001202PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001203 // Function ::
1204 // '(' FormalParameterList? ')' '{' FunctionBody '}'
1205
1206 // Parse function body.
1207 ScopeType outer_scope_type = scope_->type();
1208 bool inside_with = scope_->IsInsideWith();
1209 Scope function_scope(&scope_, kFunctionScope);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001210 // FormalParameterList ::
1211 // '(' (Identifier)*[','] ')'
1212 Expect(i::Token::LPAREN, CHECK_OK);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001213 int start_position = scanner_->location().beg_pos;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001214 bool done = (peek() == i::Token::RPAREN);
1215 while (!done) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001216 Identifier id = ParseIdentifier(CHECK_OK);
1217 if (!id.IsValidStrictVariable()) {
1218 StrictModeIdentifierViolation(scanner_->location(),
1219 "strict_param_name",
1220 id,
1221 CHECK_OK);
1222 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001223 done = (peek() == i::Token::RPAREN);
1224 if (!done) {
1225 Expect(i::Token::COMMA, CHECK_OK);
1226 }
1227 }
1228 Expect(i::Token::RPAREN, CHECK_OK);
1229
1230 Expect(i::Token::LBRACE, CHECK_OK);
1231 int function_block_pos = scanner_->location().beg_pos;
1232
1233 // Determine if the function will be lazily compiled.
1234 // Currently only happens to top-level functions.
1235 // Optimistically assume that all top-level functions are lazily compiled.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001236 bool is_lazily_compiled = (outer_scope_type == kTopLevelScope &&
1237 !inside_with && allow_lazy_ &&
1238 !parenthesized_function_);
1239 parenthesized_function_ = false;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001240
1241 if (is_lazily_compiled) {
1242 log_->PauseRecording();
1243 ParseSourceElements(i::Token::RBRACE, ok);
1244 log_->ResumeRecording();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001245 if (!*ok) Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001246
1247 Expect(i::Token::RBRACE, CHECK_OK);
1248
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001249 // Position right after terminal '}'.
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001250 int end_pos = scanner_->location().end_pos;
1251 log_->LogFunction(function_block_pos, end_pos,
1252 function_scope.materialized_literal_count(),
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001253 function_scope.expected_properties(),
1254 strict_mode() ? 1 : 0);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001255 } else {
1256 ParseSourceElements(i::Token::RBRACE, CHECK_OK);
1257 Expect(i::Token::RBRACE, CHECK_OK);
1258 }
lrn@chromium.org1c092762011-05-09 09:42:16 +00001259
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001260 if (strict_mode()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +00001261 int end_position = scanner_->location().end_pos;
1262 CheckOctalLiteral(start_position, end_position, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001263 CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK);
1264 return Expression::StrictFunction();
lrn@chromium.org1c092762011-05-09 09:42:16 +00001265 }
1266
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001267 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001268}
1269
1270
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001271PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001272 // CallRuntime ::
1273 // '%' Identifier Arguments
1274
1275 Expect(i::Token::MOD, CHECK_OK);
1276 ParseIdentifier(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001277 ParseArguments(ok);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001278
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001279 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001280}
1281
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001282#undef CHECK_OK
1283
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001284
1285void PreParser::ExpectSemicolon(bool* ok) {
1286 // Check for automatic semicolon insertion according to
1287 // the rules given in ECMA-262, section 7.9, page 21.
1288 i::Token::Value tok = peek();
1289 if (tok == i::Token::SEMICOLON) {
1290 Next();
1291 return;
1292 }
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +00001293 if (scanner_->HasAnyLineTerminatorBeforeNext() ||
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001294 tok == i::Token::RBRACE ||
1295 tok == i::Token::EOS) {
1296 return;
1297 }
1298 Expect(i::Token::SEMICOLON, ok);
1299}
1300
1301
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001302void PreParser::LogSymbol() {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001303 int identifier_pos = scanner_->location().beg_pos;
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001304 if (scanner_->is_literal_ascii()) {
1305 log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
1306 } else {
1307 log_->LogUC16Symbol(identifier_pos, scanner_->literal_uc16_string());
1308 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001309}
1310
1311
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001312PreParser::Expression PreParser::GetStringSymbol() {
lrn@chromium.org1c092762011-05-09 09:42:16 +00001313 const int kUseStrictLength = 10;
1314 const char* kUseStrictChars = "use strict";
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001315 LogSymbol();
lrn@chromium.org1c092762011-05-09 09:42:16 +00001316 if (scanner_->is_literal_ascii() &&
1317 scanner_->literal_length() == kUseStrictLength &&
1318 !scanner_->literal_contains_escapes() &&
1319 !strncmp(scanner_->literal_ascii_string().start(), kUseStrictChars,
1320 kUseStrictLength)) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001321 return Expression::UseStrictStringLiteral();
lrn@chromium.org1c092762011-05-09 09:42:16 +00001322 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001323 return Expression::StringLiteral();
1324}
1325
1326
1327PreParser::Identifier PreParser::GetIdentifierSymbol() {
1328 LogSymbol();
1329 if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) {
1330 return Identifier::FutureReserved();
ager@chromium.org04921a82011-06-27 13:21:41 +00001331 } else if (scanner_->current_token() ==
1332 i::Token::FUTURE_STRICT_RESERVED_WORD) {
1333 return Identifier::FutureStrictReserved();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001334 }
1335 if (scanner_->is_literal_ascii()) {
1336 // Detect strict-mode poison words.
1337 if (scanner_->literal_length() == 4 &&
1338 !strncmp(scanner_->literal_ascii_string().start(), "eval", 4)) {
1339 return Identifier::Eval();
1340 }
1341 if (scanner_->literal_length() == 9 &&
1342 !strncmp(scanner_->literal_ascii_string().start(), "arguments", 9)) {
1343 return Identifier::Arguments();
1344 }
1345 }
1346 return Identifier::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001347}
1348
1349
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001350PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
ager@chromium.org04921a82011-06-27 13:21:41 +00001351 i::Token::Value next = Next();
1352 switch (next) {
1353 case i::Token::FUTURE_RESERVED_WORD: {
1354 i::Scanner::Location location = scanner_->location();
1355 ReportMessageAt(location.beg_pos, location.end_pos,
1356 "reserved_word", NULL);
1357 *ok = false;
1358 }
1359 // FALLTHROUGH
1360 case i::Token::FUTURE_STRICT_RESERVED_WORD:
1361 case i::Token::IDENTIFIER:
1362 return GetIdentifierSymbol();
1363 default:
1364 *ok = false;
1365 return Identifier::Default();
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001366 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001367}
1368
1369
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001370void PreParser::SetStrictModeViolation(i::Scanner::Location location,
1371 const char* type,
1372 bool* ok) {
1373 if (strict_mode()) {
1374 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
1375 *ok = false;
1376 return;
1377 }
1378 // Delay report in case this later turns out to be strict code
1379 // (i.e., for function names and parameters prior to a "use strict"
1380 // directive).
1381 strict_mode_violation_location_ = location;
1382 strict_mode_violation_type_ = type;
1383}
1384
1385
1386void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
1387 int end_pos,
1388 bool* ok) {
1389 i::Scanner::Location location = strict_mode_violation_location_;
1390 if (location.IsValid() &&
1391 location.beg_pos > beg_pos && location.end_pos < end_pos) {
1392 ReportMessageAt(location.beg_pos, location.end_pos,
1393 strict_mode_violation_type_, NULL);
1394 *ok = false;
1395 }
1396 strict_mode_violation_location_ = i::Scanner::Location::invalid();
1397}
1398
1399
1400void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
1401 const char* eval_args_type,
1402 Identifier identifier,
1403 bool* ok) {
1404 const char* type = eval_args_type;
1405 if (identifier.IsFutureReserved()) {
ager@chromium.org04921a82011-06-27 13:21:41 +00001406 type = "reserved_word";
1407 } else if (identifier.IsFutureStrictReserved()) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001408 type = "strict_reserved_word";
1409 }
1410 if (strict_mode()) {
1411 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
1412 *ok = false;
1413 return;
1414 }
1415 strict_mode_violation_location_ = location;
1416 strict_mode_violation_type_ = type;
1417}
1418
1419
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001420PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001421 i::Token::Value next = Next();
1422 if (i::Token::IsKeyword(next)) {
1423 int pos = scanner_->location().beg_pos;
1424 const char* keyword = i::Token::String(next);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001425 log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword,
1426 i::StrLength(keyword)));
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001427 return Identifier::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001428 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001429 if (next == i::Token::IDENTIFIER ||
ager@chromium.org04921a82011-06-27 13:21:41 +00001430 next == i::Token::FUTURE_RESERVED_WORD ||
1431 next == i::Token::FUTURE_STRICT_RESERVED_WORD) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001432 return GetIdentifierSymbol();
1433 }
1434 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001435 return Identifier::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001436}
1437
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001438#undef CHECK_OK
1439
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001440
1441// This function reads an identifier and determines whether or not it
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001442// is 'get' or 'set'.
ager@chromium.org04921a82011-06-27 13:21:41 +00001443PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get,
1444 bool* is_set,
1445 bool* ok) {
1446 Identifier result = ParseIdentifierName(ok);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001447 if (!*ok) return Identifier::Default();
1448 if (scanner_->is_literal_ascii() &&
1449 scanner_->literal_length() == 3) {
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001450 const char* token = scanner_->literal_ascii_string().start();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001451 *is_get = strncmp(token, "get", 3) == 0;
1452 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
1453 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001454 return result;
1455}
1456
1457bool PreParser::peek_any_identifier() {
1458 i::Token::Value next = peek();
1459 return next == i::Token::IDENTIFIER ||
ager@chromium.org04921a82011-06-27 13:21:41 +00001460 next == i::Token::FUTURE_RESERVED_WORD ||
1461 next == i::Token::FUTURE_STRICT_RESERVED_WORD;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001462}
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001463} } // v8::preparser