blob: 1a3dd737c5d75f998bbda9361fa04fbb5289e88e [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
danno@chromium.orgb6451162011-08-17 14:33:23 +0000115PreParser::Statement PreParser::ParseSourceElement(bool* ok) {
116 switch (peek()) {
117 case i::Token::LET:
118 return ParseVariableStatement(kSourceElement, ok);
119 default:
120 return ParseStatement(ok);
121 }
122}
123
124
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000125PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
126 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000127 // SourceElements ::
128 // (Statement)* <end_token>
129
lrn@chromium.org1c092762011-05-09 09:42:16 +0000130 bool allow_directive_prologue = true;
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000131 while (peek() != end_token) {
danno@chromium.orgb6451162011-08-17 14:33:23 +0000132 Statement statement = ParseSourceElement(CHECK_OK);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000133 if (allow_directive_prologue) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000134 if (statement.IsUseStrictLiteral()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000135 set_strict_mode();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000136 } else if (!statement.IsStringLiteral()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000137 allow_directive_prologue = false;
138 }
139 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000140 }
141 return kUnknownSourceElements;
142}
143
144
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000145#undef CHECK_OK
146#define CHECK_OK ok); \
147 if (!*ok) return Statement::Default(); \
148 ((void)0
149#define DUMMY ) // to make indentation work
150#undef DUMMY
151
152
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000153PreParser::Statement PreParser::ParseStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000154 // Statement ::
155 // Block
156 // VariableStatement
157 // EmptyStatement
158 // ExpressionStatement
159 // IfStatement
160 // IterationStatement
161 // ContinueStatement
162 // BreakStatement
163 // ReturnStatement
164 // WithStatement
165 // LabelledStatement
166 // SwitchStatement
167 // ThrowStatement
168 // TryStatement
169 // DebuggerStatement
170
171 // Note: Since labels can only be used by 'break' and 'continue'
172 // statements, which themselves are only valid within blocks,
173 // iterations or 'switch' statements (i.e., BreakableStatements),
174 // labels can be simply ignored in all other cases; except for
175 // trivial labeled break statements 'label: break label' which is
176 // parsed into an empty statement.
177
178 // Keep the source position of the statement
179 switch (peek()) {
180 case i::Token::LBRACE:
181 return ParseBlock(ok);
182
183 case i::Token::CONST:
184 case i::Token::VAR:
danno@chromium.orgb6451162011-08-17 14:33:23 +0000185 return ParseVariableStatement(kStatement, ok);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000186
187 case i::Token::SEMICOLON:
188 Next();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000189 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000190
191 case i::Token::IF:
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000192 return ParseIfStatement(ok);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000193
194 case i::Token::DO:
195 return ParseDoWhileStatement(ok);
196
197 case i::Token::WHILE:
198 return ParseWhileStatement(ok);
199
200 case i::Token::FOR:
201 return ParseForStatement(ok);
202
203 case i::Token::CONTINUE:
204 return ParseContinueStatement(ok);
205
206 case i::Token::BREAK:
207 return ParseBreakStatement(ok);
208
209 case i::Token::RETURN:
210 return ParseReturnStatement(ok);
211
212 case i::Token::WITH:
213 return ParseWithStatement(ok);
214
215 case i::Token::SWITCH:
216 return ParseSwitchStatement(ok);
217
218 case i::Token::THROW:
219 return ParseThrowStatement(ok);
220
221 case i::Token::TRY:
222 return ParseTryStatement(ok);
223
224 case i::Token::FUNCTION:
225 return ParseFunctionDeclaration(ok);
226
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000227 case i::Token::DEBUGGER:
228 return ParseDebuggerStatement(ok);
229
230 default:
231 return ParseExpressionOrLabelledStatement(ok);
232 }
233}
234
235
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000236PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000237 // FunctionDeclaration ::
238 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
239 Expect(i::Token::FUNCTION, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000240
241 Identifier identifier = ParseIdentifier(CHECK_OK);
242 i::Scanner::Location location = scanner_->location();
243
244 Expression function_value = ParseFunctionLiteral(CHECK_OK);
245
246 if (function_value.IsStrictFunction() &&
247 !identifier.IsValidStrictVariable()) {
248 // Strict mode violation, using either reserved word or eval/arguments
249 // as name of strict function.
250 const char* type = "strict_function_name";
ager@chromium.org04921a82011-06-27 13:21:41 +0000251 if (identifier.IsFutureStrictReserved()) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000252 type = "strict_reserved_word";
253 }
254 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
255 *ok = false;
256 }
danno@chromium.org40cb8782011-05-25 07:58:50 +0000257 return Statement::FunctionDeclaration();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000258}
259
260
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000261PreParser::Statement PreParser::ParseBlock(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000262 // Block ::
263 // '{' Statement* '}'
264
265 // Note that a Block does not introduce a new execution scope!
266 // (ECMA-262, 3rd, 12.2)
267 //
268 Expect(i::Token::LBRACE, CHECK_OK);
269 while (peek() != i::Token::RBRACE) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000270 i::Scanner::Location start_location = scanner_->peek_location();
danno@chromium.orgb6451162011-08-17 14:33:23 +0000271 Statement statement = ParseSourceElement(CHECK_OK);
danno@chromium.org40cb8782011-05-25 07:58:50 +0000272 i::Scanner::Location end_location = scanner_->location();
273 if (strict_mode() && statement.IsFunctionDeclaration()) {
274 ReportMessageAt(start_location.beg_pos, end_location.end_pos,
275 "strict_function", NULL);
276 *ok = false;
277 return Statement::Default();
278 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000279 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000280 Expect(i::Token::RBRACE, ok);
281 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000282}
283
284
danno@chromium.orgb6451162011-08-17 14:33:23 +0000285PreParser::Statement PreParser::ParseVariableStatement(
286 VariableDeclarationContext var_context,
287 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000288 // VariableStatement ::
289 // VariableDeclarations ';'
290
danno@chromium.orgb6451162011-08-17 14:33:23 +0000291 Statement result = ParseVariableDeclarations(var_context,
292 NULL,
293 CHECK_OK);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000294 ExpectSemicolon(CHECK_OK);
295 return result;
296}
297
298
299// If the variable declaration declares exactly one non-const
300// variable, then *var is set to that variable. In all other cases,
301// *var is untouched; in particular, it is the caller's responsibility
302// to initialize it properly. This mechanism is also used for the parsing
303// of 'for-in' loops.
danno@chromium.orgb6451162011-08-17 14:33:23 +0000304PreParser::Statement PreParser::ParseVariableDeclarations(
305 VariableDeclarationContext var_context,
306 int* num_decl,
307 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000308 // VariableDeclarations ::
309 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
310
311 if (peek() == i::Token::VAR) {
312 Consume(i::Token::VAR);
313 } else if (peek() == i::Token::CONST) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000314 if (strict_mode()) {
315 i::Scanner::Location location = scanner_->peek_location();
316 ReportMessageAt(location.beg_pos, location.end_pos,
317 "strict_const", NULL);
318 *ok = false;
319 return Statement::Default();
320 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000321 Consume(i::Token::CONST);
danno@chromium.orgb6451162011-08-17 14:33:23 +0000322 } else if (peek() == i::Token::LET) {
323 if (var_context != kSourceElement &&
324 var_context != kForStatement) {
325 i::Scanner::Location location = scanner_->peek_location();
326 ReportMessageAt(location.beg_pos, location.end_pos,
327 "unprotected_let", NULL);
328 *ok = false;
329 return Statement::Default();
330 }
331 Consume(i::Token::LET);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000332 } else {
333 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000334 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000335 }
336
danno@chromium.orgb6451162011-08-17 14:33:23 +0000337 // The scope of a var/const declared variable anywhere inside a function
338 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
339 // of a let declared variable is the scope of the immediately enclosing
340 // block.
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000341 int nvars = 0; // the number of variables declared
342 do {
343 // Parse variable name.
344 if (nvars > 0) Consume(i::Token::COMMA);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000345 Identifier identifier = ParseIdentifier(CHECK_OK);
346 if (strict_mode() && !identifier.IsValidStrictVariable()) {
347 StrictModeIdentifierViolation(scanner_->location(),
348 "strict_var_name",
349 identifier,
350 ok);
351 return Statement::Default();
352 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000353 nvars++;
354 if (peek() == i::Token::ASSIGN) {
355 Expect(i::Token::ASSIGN, CHECK_OK);
danno@chromium.orgb6451162011-08-17 14:33:23 +0000356 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000357 }
358 } while (peek() == i::Token::COMMA);
359
360 if (num_decl != NULL) *num_decl = nvars;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000361 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000362}
363
364
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000365PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000366 // ExpressionStatement | LabelledStatement ::
367 // Expression ';'
368 // Identifier ':' Statement
369
370 Expression expr = ParseExpression(true, CHECK_OK);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000371 if (expr.IsRawIdentifier()) {
372 if (peek() == i::Token::COLON &&
373 (!strict_mode() || !expr.AsIdentifier().IsFutureReserved())) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000374 Consume(i::Token::COLON);
375 i::Scanner::Location start_location = scanner_->peek_location();
376 Statement statement = ParseStatement(CHECK_OK);
377 if (strict_mode() && statement.IsFunctionDeclaration()) {
378 i::Scanner::Location end_location = scanner_->location();
379 ReportMessageAt(start_location.beg_pos, end_location.end_pos,
380 "strict_function", NULL);
381 *ok = false;
382 }
383 return Statement::Default();
384 }
whesse@chromium.org7b260152011-06-20 15:33:18 +0000385 // Preparsing is disabled for extensions (because the extension details
386 // aren't passed to lazily compiled functions), so we don't
387 // accept "native function" in the preparser.
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000388 }
389 // Parsed expression statement.
390 ExpectSemicolon(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000391 return Statement::ExpressionStatement(expr);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000392}
393
394
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000395PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000396 // IfStatement ::
397 // 'if' '(' Expression ')' Statement ('else' Statement)?
398
399 Expect(i::Token::IF, CHECK_OK);
400 Expect(i::Token::LPAREN, CHECK_OK);
401 ParseExpression(true, CHECK_OK);
402 Expect(i::Token::RPAREN, CHECK_OK);
403 ParseStatement(CHECK_OK);
404 if (peek() == i::Token::ELSE) {
405 Next();
406 ParseStatement(CHECK_OK);
407 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000408 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000409}
410
411
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000412PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000413 // ContinueStatement ::
414 // 'continue' [no line terminator] Identifier? ';'
415
416 Expect(i::Token::CONTINUE, CHECK_OK);
417 i::Token::Value tok = peek();
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000418 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000419 tok != i::Token::SEMICOLON &&
420 tok != i::Token::RBRACE &&
421 tok != i::Token::EOS) {
422 ParseIdentifier(CHECK_OK);
423 }
424 ExpectSemicolon(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000425 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000426}
427
428
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000429PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000430 // BreakStatement ::
431 // 'break' [no line terminator] Identifier? ';'
432
433 Expect(i::Token::BREAK, CHECK_OK);
434 i::Token::Value tok = peek();
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000435 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000436 tok != i::Token::SEMICOLON &&
437 tok != i::Token::RBRACE &&
438 tok != i::Token::EOS) {
439 ParseIdentifier(CHECK_OK);
440 }
441 ExpectSemicolon(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000442 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000443}
444
445
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000446PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000447 // ReturnStatement ::
448 // 'return' [no line terminator] Expression? ';'
449
450 // Consume the return token. It is necessary to do the before
451 // reporting any errors on it, because of the way errors are
452 // reported (underlining).
453 Expect(i::Token::RETURN, CHECK_OK);
454
455 // An ECMAScript program is considered syntactically incorrect if it
456 // contains a return statement that is not within the body of a
457 // function. See ECMA-262, section 12.9, page 67.
458 // This is not handled during preparsing.
459
460 i::Token::Value tok = peek();
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000461 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000462 tok != i::Token::SEMICOLON &&
463 tok != i::Token::RBRACE &&
464 tok != i::Token::EOS) {
465 ParseExpression(true, CHECK_OK);
466 }
467 ExpectSemicolon(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000468 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000469}
470
471
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000472PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000473 // WithStatement ::
474 // 'with' '(' Expression ')' Statement
475 Expect(i::Token::WITH, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000476 if (strict_mode()) {
477 i::Scanner::Location location = scanner_->location();
478 ReportMessageAt(location.beg_pos, location.end_pos,
479 "strict_mode_with", NULL);
480 *ok = false;
481 return Statement::Default();
482 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000483 Expect(i::Token::LPAREN, CHECK_OK);
484 ParseExpression(true, CHECK_OK);
485 Expect(i::Token::RPAREN, CHECK_OK);
486
487 scope_->EnterWith();
488 ParseStatement(CHECK_OK);
489 scope_->LeaveWith();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000490 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000491}
492
493
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000494PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000495 // SwitchStatement ::
496 // 'switch' '(' Expression ')' '{' CaseClause* '}'
497
498 Expect(i::Token::SWITCH, CHECK_OK);
499 Expect(i::Token::LPAREN, CHECK_OK);
500 ParseExpression(true, CHECK_OK);
501 Expect(i::Token::RPAREN, CHECK_OK);
502
503 Expect(i::Token::LBRACE, CHECK_OK);
504 i::Token::Value token = peek();
505 while (token != i::Token::RBRACE) {
506 if (token == i::Token::CASE) {
507 Expect(i::Token::CASE, CHECK_OK);
508 ParseExpression(true, CHECK_OK);
509 Expect(i::Token::COLON, CHECK_OK);
510 } else if (token == i::Token::DEFAULT) {
511 Expect(i::Token::DEFAULT, CHECK_OK);
512 Expect(i::Token::COLON, CHECK_OK);
513 } else {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000514 i::Scanner::Location start_location = scanner_->peek_location();
515 Statement statement = ParseStatement(CHECK_OK);
516 if (strict_mode() && statement.IsFunctionDeclaration()) {
517 i::Scanner::Location end_location = scanner_->location();
518 ReportMessageAt(start_location.beg_pos, end_location.end_pos,
519 "strict_function", NULL);
520 *ok = false;
521 return Statement::Default();
522 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000523 }
524 token = peek();
525 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000526 Expect(i::Token::RBRACE, 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::ParseDoWhileStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000532 // DoStatement ::
533 // 'do' Statement 'while' '(' Expression ')' ';'
534
535 Expect(i::Token::DO, CHECK_OK);
536 ParseStatement(CHECK_OK);
537 Expect(i::Token::WHILE, CHECK_OK);
538 Expect(i::Token::LPAREN, CHECK_OK);
539 ParseExpression(true, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000540 Expect(i::Token::RPAREN, ok);
541 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000542}
543
544
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000545PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000546 // WhileStatement ::
547 // 'while' '(' Expression ')' Statement
548
549 Expect(i::Token::WHILE, CHECK_OK);
550 Expect(i::Token::LPAREN, CHECK_OK);
551 ParseExpression(true, CHECK_OK);
552 Expect(i::Token::RPAREN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000553 ParseStatement(ok);
554 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000555}
556
557
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000558PreParser::Statement PreParser::ParseForStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000559 // ForStatement ::
560 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
561
562 Expect(i::Token::FOR, CHECK_OK);
563 Expect(i::Token::LPAREN, CHECK_OK);
564 if (peek() != i::Token::SEMICOLON) {
danno@chromium.orgb6451162011-08-17 14:33:23 +0000565 if (peek() == i::Token::VAR || peek() == i::Token::CONST ||
566 peek() == i::Token::LET) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000567 int decl_count;
danno@chromium.orgb6451162011-08-17 14:33:23 +0000568 ParseVariableDeclarations(kForStatement, &decl_count, CHECK_OK);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000569 if (peek() == i::Token::IN && decl_count == 1) {
570 Expect(i::Token::IN, CHECK_OK);
571 ParseExpression(true, CHECK_OK);
572 Expect(i::Token::RPAREN, CHECK_OK);
573
574 ParseStatement(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000575 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000576 }
577 } else {
578 ParseExpression(false, CHECK_OK);
579 if (peek() == i::Token::IN) {
580 Expect(i::Token::IN, CHECK_OK);
581 ParseExpression(true, CHECK_OK);
582 Expect(i::Token::RPAREN, CHECK_OK);
583
584 ParseStatement(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000585 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000586 }
587 }
588 }
589
590 // Parsed initializer at this point.
591 Expect(i::Token::SEMICOLON, CHECK_OK);
592
593 if (peek() != i::Token::SEMICOLON) {
594 ParseExpression(true, CHECK_OK);
595 }
596 Expect(i::Token::SEMICOLON, CHECK_OK);
597
598 if (peek() != i::Token::RPAREN) {
599 ParseExpression(true, CHECK_OK);
600 }
601 Expect(i::Token::RPAREN, CHECK_OK);
602
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000603 ParseStatement(ok);
604 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000605}
606
607
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000608PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000609 // ThrowStatement ::
610 // 'throw' [no line terminator] Expression ';'
611
612 Expect(i::Token::THROW, CHECK_OK);
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000613 if (scanner_->HasAnyLineTerminatorBeforeNext()) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000614 i::JavaScriptScanner::Location pos = scanner_->location();
615 ReportMessageAt(pos.beg_pos, pos.end_pos,
616 "newline_after_throw", NULL);
617 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000618 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000619 }
620 ParseExpression(true, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000621 ExpectSemicolon(ok);
622 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000623}
624
625
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000626PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000627 // TryStatement ::
628 // 'try' Block Catch
629 // 'try' Block Finally
630 // 'try' Block Catch Finally
631 //
632 // Catch ::
633 // 'catch' '(' Identifier ')' Block
634 //
635 // Finally ::
636 // 'finally' Block
637
638 // In preparsing, allow any number of catch/finally blocks, including zero
639 // of both.
640
641 Expect(i::Token::TRY, CHECK_OK);
642
643 ParseBlock(CHECK_OK);
644
645 bool catch_or_finally_seen = false;
646 if (peek() == i::Token::CATCH) {
647 Consume(i::Token::CATCH);
648 Expect(i::Token::LPAREN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000649 Identifier id = ParseIdentifier(CHECK_OK);
650 if (strict_mode() && !id.IsValidStrictVariable()) {
651 StrictModeIdentifierViolation(scanner_->location(),
652 "strict_catch_variable",
653 id,
654 ok);
655 return Statement::Default();
656 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000657 Expect(i::Token::RPAREN, CHECK_OK);
658 scope_->EnterWith();
659 ParseBlock(ok);
660 scope_->LeaveWith();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000661 if (!*ok) Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000662 catch_or_finally_seen = true;
663 }
664 if (peek() == i::Token::FINALLY) {
665 Consume(i::Token::FINALLY);
666 ParseBlock(CHECK_OK);
667 catch_or_finally_seen = true;
668 }
669 if (!catch_or_finally_seen) {
670 *ok = false;
671 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000672 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000673}
674
675
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000676PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000677 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
678 // contexts this is used as a statement which invokes the debugger as if a
679 // break point is present.
680 // DebuggerStatement ::
681 // 'debugger' ';'
682
683 Expect(i::Token::DEBUGGER, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000684 ExpectSemicolon(ok);
685 return Statement::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000686}
687
688
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000689#undef CHECK_OK
690#define CHECK_OK ok); \
691 if (!*ok) return Expression::Default(); \
692 ((void)0
693#define DUMMY ) // to make indentation work
694#undef DUMMY
695
696
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000697// Precedence = 1
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000698PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000699 // Expression ::
700 // AssignmentExpression
701 // Expression ',' AssignmentExpression
702
703 Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
704 while (peek() == i::Token::COMMA) {
705 Expect(i::Token::COMMA, CHECK_OK);
706 ParseAssignmentExpression(accept_IN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000707 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000708 }
709 return result;
710}
711
712
713// Precedence = 2
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000714PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
715 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000716 // AssignmentExpression ::
717 // ConditionalExpression
718 // LeftHandSideExpression AssignmentOperator AssignmentExpression
719
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000720 i::Scanner::Location before = scanner_->peek_location();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000721 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
722
723 if (!i::Token::IsAssignmentOp(peek())) {
724 // Parsed conditional expression only (no assignment).
725 return expression;
726 }
727
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000728 if (strict_mode() && expression.IsIdentifier() &&
729 expression.AsIdentifier().IsEvalOrArguments()) {
730 i::Scanner::Location after = scanner_->location();
731 ReportMessageAt(before.beg_pos, after.end_pos,
732 "strict_lhs_assignment", NULL);
733 *ok = false;
734 return Expression::Default();
735 }
736
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000737 i::Token::Value op = Next(); // Get assignment operator.
738 ParseAssignmentExpression(accept_IN, CHECK_OK);
739
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000740 if ((op == i::Token::ASSIGN) && expression.IsThisProperty()) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000741 scope_->AddProperty();
742 }
743
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000744 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000745}
746
747
748// Precedence = 3
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000749PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
750 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000751 // ConditionalExpression ::
752 // LogicalOrExpression
753 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
754
755 // We start using the binary expression parser for prec >= 4 only!
756 Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
757 if (peek() != i::Token::CONDITIONAL) return expression;
758 Consume(i::Token::CONDITIONAL);
759 // In parsing the first assignment expression in conditional
760 // expressions we always accept the 'in' keyword; see ECMA-262,
761 // section 11.12, page 58.
762 ParseAssignmentExpression(true, CHECK_OK);
763 Expect(i::Token::COLON, CHECK_OK);
764 ParseAssignmentExpression(accept_IN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000765 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000766}
767
768
769int PreParser::Precedence(i::Token::Value tok, bool accept_IN) {
770 if (tok == i::Token::IN && !accept_IN)
771 return 0; // 0 precedence will terminate binary expression parsing
772
773 return i::Token::Precedence(tok);
774}
775
776
777// Precedence >= 4
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000778PreParser::Expression PreParser::ParseBinaryExpression(int prec,
779 bool accept_IN,
780 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000781 Expression result = ParseUnaryExpression(CHECK_OK);
782 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
783 // prec1 >= 4
784 while (Precedence(peek(), accept_IN) == prec1) {
785 Next();
786 ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000787 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000788 }
789 }
790 return result;
791}
792
793
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000794PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000795 // UnaryExpression ::
796 // PostfixExpression
797 // 'delete' UnaryExpression
798 // 'void' UnaryExpression
799 // 'typeof' UnaryExpression
800 // '++' UnaryExpression
801 // '--' UnaryExpression
802 // '+' UnaryExpression
803 // '-' UnaryExpression
804 // '~' UnaryExpression
805 // '!' UnaryExpression
806
807 i::Token::Value op = peek();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000808 if (i::Token::IsUnaryOp(op)) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000809 op = Next();
810 ParseUnaryExpression(ok);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000811 return Expression::Default();
812 } else if (i::Token::IsCountOp(op)) {
813 op = Next();
814 i::Scanner::Location before = scanner_->peek_location();
815 Expression expression = ParseUnaryExpression(CHECK_OK);
816 if (strict_mode() && expression.IsIdentifier() &&
817 expression.AsIdentifier().IsEvalOrArguments()) {
818 i::Scanner::Location after = scanner_->location();
819 ReportMessageAt(before.beg_pos, after.end_pos,
820 "strict_lhs_prefix", NULL);
821 *ok = false;
822 }
823 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000824 } else {
825 return ParsePostfixExpression(ok);
826 }
827}
828
829
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000830PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000831 // PostfixExpression ::
832 // LeftHandSideExpression ('++' | '--')?
833
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000834 i::Scanner::Location before = scanner_->peek_location();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000835 Expression expression = ParseLeftHandSideExpression(CHECK_OK);
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +0000836 if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000837 i::Token::IsCountOp(peek())) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000838 if (strict_mode() && expression.IsIdentifier() &&
839 expression.AsIdentifier().IsEvalOrArguments()) {
840 i::Scanner::Location after = scanner_->location();
841 ReportMessageAt(before.beg_pos, after.end_pos,
842 "strict_lhs_postfix", NULL);
843 *ok = false;
844 return Expression::Default();
845 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000846 Next();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000847 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000848 }
849 return expression;
850}
851
852
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000853PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000854 // LeftHandSideExpression ::
855 // (NewExpression | MemberExpression) ...
856
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000857 Expression result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000858 if (peek() == i::Token::NEW) {
859 result = ParseNewExpression(CHECK_OK);
860 } else {
861 result = ParseMemberExpression(CHECK_OK);
862 }
863
864 while (true) {
865 switch (peek()) {
866 case i::Token::LBRACK: {
867 Consume(i::Token::LBRACK);
868 ParseExpression(true, CHECK_OK);
869 Expect(i::Token::RBRACK, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000870 if (result.IsThis()) {
871 result = Expression::ThisProperty();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000872 } else {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000873 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000874 }
875 break;
876 }
877
878 case i::Token::LPAREN: {
879 ParseArguments(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000880 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000881 break;
882 }
883
884 case i::Token::PERIOD: {
885 Consume(i::Token::PERIOD);
886 ParseIdentifierName(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000887 if (result.IsThis()) {
888 result = Expression::ThisProperty();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000889 } else {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000890 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000891 }
892 break;
893 }
894
895 default:
896 return result;
897 }
898 }
899}
900
901
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000902PreParser::Expression PreParser::ParseNewExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000903 // NewExpression ::
904 // ('new')+ MemberExpression
905
906 // The grammar for new expressions is pretty warped. The keyword
907 // 'new' can either be a part of the new expression (where it isn't
908 // followed by an argument list) or a part of the member expression,
909 // where it must be followed by an argument list. To accommodate
910 // this, we parse the 'new' keywords greedily and keep track of how
911 // many we have parsed. This information is then passed on to the
912 // member expression parser, which is only allowed to match argument
913 // lists as long as it has 'new' prefixes left
914 unsigned new_count = 0;
915 do {
916 Consume(i::Token::NEW);
917 new_count++;
918 } while (peek() == i::Token::NEW);
919
920 return ParseMemberWithNewPrefixesExpression(new_count, ok);
921}
922
923
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000924PreParser::Expression PreParser::ParseMemberExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000925 return ParseMemberWithNewPrefixesExpression(0, ok);
926}
927
928
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000929PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000930 unsigned new_count, bool* ok) {
931 // MemberExpression ::
932 // (PrimaryExpression | FunctionLiteral)
933 // ('[' Expression ']' | '.' Identifier | Arguments)*
934
935 // Parse the initial primary or function expression.
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000936 Expression result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000937 if (peek() == i::Token::FUNCTION) {
938 Consume(i::Token::FUNCTION);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000939 Identifier identifier = Identifier::Default();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000940 if (peek_any_identifier()) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000941 identifier = ParseIdentifier(CHECK_OK);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000942 }
943 result = ParseFunctionLiteral(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000944 if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
945 StrictModeIdentifierViolation(scanner_->location(),
946 "strict_function_name",
947 identifier,
948 ok);
949 return Expression::Default();
950 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000951 } else {
952 result = ParsePrimaryExpression(CHECK_OK);
953 }
954
955 while (true) {
956 switch (peek()) {
957 case i::Token::LBRACK: {
958 Consume(i::Token::LBRACK);
959 ParseExpression(true, CHECK_OK);
960 Expect(i::Token::RBRACK, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000961 if (result.IsThis()) {
962 result = Expression::ThisProperty();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000963 } else {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000964 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000965 }
966 break;
967 }
968 case i::Token::PERIOD: {
969 Consume(i::Token::PERIOD);
970 ParseIdentifierName(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000971 if (result.IsThis()) {
972 result = Expression::ThisProperty();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000973 } else {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000974 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000975 }
976 break;
977 }
978 case i::Token::LPAREN: {
979 if (new_count == 0) return result;
980 // Consume one of the new prefixes (already parsed).
981 ParseArguments(CHECK_OK);
982 new_count--;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000983 result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000984 break;
985 }
986 default:
987 return result;
988 }
989 }
990}
991
992
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000993PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000994 // PrimaryExpression ::
995 // 'this'
996 // 'null'
997 // 'true'
998 // 'false'
999 // Identifier
1000 // Number
1001 // String
1002 // ArrayLiteral
1003 // ObjectLiteral
1004 // RegExpLiteral
1005 // '(' Expression ')'
1006
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001007 Expression result = Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001008 switch (peek()) {
1009 case i::Token::THIS: {
1010 Next();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001011 result = Expression::This();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001012 break;
1013 }
1014
ager@chromium.org04921a82011-06-27 13:21:41 +00001015 case i::Token::FUTURE_RESERVED_WORD: {
1016 Next();
1017 i::Scanner::Location location = scanner_->location();
1018 ReportMessageAt(location.beg_pos, location.end_pos,
1019 "reserved_word", NULL);
1020 *ok = false;
1021 return Expression::Default();
1022 }
1023
1024 case i::Token::FUTURE_STRICT_RESERVED_WORD:
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001025 if (strict_mode()) {
1026 Next();
1027 i::Scanner::Location location = scanner_->location();
1028 ReportMessageAt(location.beg_pos, location.end_pos,
1029 "strict_reserved_word", NULL);
1030 *ok = false;
1031 return Expression::Default();
1032 }
1033 // FALLTHROUGH
1034 case i::Token::IDENTIFIER: {
1035 Identifier id = ParseIdentifier(CHECK_OK);
1036 result = Expression::FromIdentifier(id);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001037 break;
1038 }
1039
1040 case i::Token::NULL_LITERAL:
1041 case i::Token::TRUE_LITERAL:
1042 case i::Token::FALSE_LITERAL:
1043 case i::Token::NUMBER: {
1044 Next();
1045 break;
1046 }
1047 case i::Token::STRING: {
1048 Next();
1049 result = GetStringSymbol();
1050 break;
1051 }
1052
1053 case i::Token::ASSIGN_DIV:
1054 result = ParseRegExpLiteral(true, CHECK_OK);
1055 break;
1056
1057 case i::Token::DIV:
1058 result = ParseRegExpLiteral(false, CHECK_OK);
1059 break;
1060
1061 case i::Token::LBRACK:
1062 result = ParseArrayLiteral(CHECK_OK);
1063 break;
1064
1065 case i::Token::LBRACE:
1066 result = ParseObjectLiteral(CHECK_OK);
1067 break;
1068
1069 case i::Token::LPAREN:
1070 Consume(i::Token::LPAREN);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001071 parenthesized_function_ = (peek() == i::Token::FUNCTION);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001072 result = ParseExpression(true, CHECK_OK);
1073 Expect(i::Token::RPAREN, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001074 result = result.Parenthesize();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001075 break;
1076
1077 case i::Token::MOD:
1078 result = ParseV8Intrinsic(CHECK_OK);
1079 break;
1080
1081 default: {
1082 Next();
1083 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001084 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001085 }
1086 }
1087
1088 return result;
1089}
1090
1091
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001092PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001093 // ArrayLiteral ::
1094 // '[' Expression? (',' Expression?)* ']'
1095 Expect(i::Token::LBRACK, CHECK_OK);
1096 while (peek() != i::Token::RBRACK) {
1097 if (peek() != i::Token::COMMA) {
1098 ParseAssignmentExpression(true, CHECK_OK);
1099 }
1100 if (peek() != i::Token::RBRACK) {
1101 Expect(i::Token::COMMA, CHECK_OK);
1102 }
1103 }
1104 Expect(i::Token::RBRACK, CHECK_OK);
1105
1106 scope_->NextMaterializedLiteralIndex();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001107 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001108}
1109
1110
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001111PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001112 // ObjectLiteral ::
1113 // '{' (
1114 // ((IdentifierName | String | Number) ':' AssignmentExpression)
1115 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1116 // )*[','] '}'
1117
1118 Expect(i::Token::LBRACE, CHECK_OK);
1119 while (peek() != i::Token::RBRACE) {
1120 i::Token::Value next = peek();
1121 switch (next) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001122 case i::Token::IDENTIFIER:
ager@chromium.org04921a82011-06-27 13:21:41 +00001123 case i::Token::FUTURE_RESERVED_WORD:
1124 case i::Token::FUTURE_STRICT_RESERVED_WORD: {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001125 bool is_getter = false;
1126 bool is_setter = false;
ager@chromium.org04921a82011-06-27 13:21:41 +00001127 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001128 if ((is_getter || is_setter) && peek() != i::Token::COLON) {
1129 i::Token::Value name = Next();
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001130 bool is_keyword = i::Token::IsKeyword(name);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001131 if (name != i::Token::IDENTIFIER &&
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001132 name != i::Token::FUTURE_RESERVED_WORD &&
ager@chromium.org04921a82011-06-27 13:21:41 +00001133 name != i::Token::FUTURE_STRICT_RESERVED_WORD &&
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001134 name != i::Token::NUMBER &&
1135 name != i::Token::STRING &&
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001136 !is_keyword) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001137 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001138 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001139 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001140 if (!is_keyword) {
1141 LogSymbol();
1142 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001143 ParseFunctionLiteral(CHECK_OK);
1144 if (peek() != i::Token::RBRACE) {
1145 Expect(i::Token::COMMA, CHECK_OK);
1146 }
1147 continue; // restart the while
1148 }
1149 break;
1150 }
1151 case i::Token::STRING:
1152 Consume(next);
1153 GetStringSymbol();
1154 break;
1155 case i::Token::NUMBER:
1156 Consume(next);
1157 break;
1158 default:
1159 if (i::Token::IsKeyword(next)) {
1160 Consume(next);
1161 } else {
1162 // Unexpected token.
1163 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001164 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001165 }
1166 }
1167
1168 Expect(i::Token::COLON, CHECK_OK);
1169 ParseAssignmentExpression(true, CHECK_OK);
1170
1171 // TODO(1240767): Consider allowing trailing comma.
1172 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
1173 }
1174 Expect(i::Token::RBRACE, CHECK_OK);
1175
1176 scope_->NextMaterializedLiteralIndex();
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::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
1182 bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001183 if (!scanner_->ScanRegExpPattern(seen_equal)) {
1184 Next();
1185 i::JavaScriptScanner::Location location = scanner_->location();
1186 ReportMessageAt(location.beg_pos, location.end_pos,
1187 "unterminated_regexp", NULL);
1188 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001189 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001190 }
1191
1192 scope_->NextMaterializedLiteralIndex();
1193
1194 if (!scanner_->ScanRegExpFlags()) {
1195 Next();
1196 i::JavaScriptScanner::Location location = scanner_->location();
1197 ReportMessageAt(location.beg_pos, location.end_pos,
1198 "invalid_regexp_flags", NULL);
1199 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001200 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001201 }
1202 Next();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001203 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001204}
1205
1206
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001207PreParser::Arguments PreParser::ParseArguments(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001208 // Arguments ::
1209 // '(' (AssignmentExpression)*[','] ')'
1210
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001211 Expect(i::Token::LPAREN, ok);
1212 if (!*ok) return -1;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001213 bool done = (peek() == i::Token::RPAREN);
1214 int argc = 0;
1215 while (!done) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001216 ParseAssignmentExpression(true, ok);
1217 if (!*ok) return -1;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001218 argc++;
1219 done = (peek() == i::Token::RPAREN);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001220 if (!done) {
1221 Expect(i::Token::COMMA, ok);
1222 if (!*ok) return -1;
1223 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001224 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001225 Expect(i::Token::RPAREN, ok);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001226 return argc;
1227}
1228
1229
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001230PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001231 // Function ::
1232 // '(' FormalParameterList? ')' '{' FunctionBody '}'
1233
1234 // Parse function body.
1235 ScopeType outer_scope_type = scope_->type();
1236 bool inside_with = scope_->IsInsideWith();
1237 Scope function_scope(&scope_, kFunctionScope);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001238 // FormalParameterList ::
1239 // '(' (Identifier)*[','] ')'
1240 Expect(i::Token::LPAREN, CHECK_OK);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001241 int start_position = scanner_->location().beg_pos;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001242 bool done = (peek() == i::Token::RPAREN);
1243 while (!done) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001244 Identifier id = ParseIdentifier(CHECK_OK);
1245 if (!id.IsValidStrictVariable()) {
1246 StrictModeIdentifierViolation(scanner_->location(),
1247 "strict_param_name",
1248 id,
1249 CHECK_OK);
1250 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001251 done = (peek() == i::Token::RPAREN);
1252 if (!done) {
1253 Expect(i::Token::COMMA, CHECK_OK);
1254 }
1255 }
1256 Expect(i::Token::RPAREN, CHECK_OK);
1257
1258 Expect(i::Token::LBRACE, CHECK_OK);
1259 int function_block_pos = scanner_->location().beg_pos;
1260
1261 // Determine if the function will be lazily compiled.
1262 // Currently only happens to top-level functions.
1263 // Optimistically assume that all top-level functions are lazily compiled.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001264 bool is_lazily_compiled = (outer_scope_type == kTopLevelScope &&
1265 !inside_with && allow_lazy_ &&
1266 !parenthesized_function_);
1267 parenthesized_function_ = false;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001268
1269 if (is_lazily_compiled) {
1270 log_->PauseRecording();
1271 ParseSourceElements(i::Token::RBRACE, ok);
1272 log_->ResumeRecording();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001273 if (!*ok) Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001274
1275 Expect(i::Token::RBRACE, CHECK_OK);
1276
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001277 // Position right after terminal '}'.
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001278 int end_pos = scanner_->location().end_pos;
1279 log_->LogFunction(function_block_pos, end_pos,
1280 function_scope.materialized_literal_count(),
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001281 function_scope.expected_properties(),
1282 strict_mode() ? 1 : 0);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001283 } else {
1284 ParseSourceElements(i::Token::RBRACE, CHECK_OK);
1285 Expect(i::Token::RBRACE, CHECK_OK);
1286 }
lrn@chromium.org1c092762011-05-09 09:42:16 +00001287
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001288 if (strict_mode()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +00001289 int end_position = scanner_->location().end_pos;
1290 CheckOctalLiteral(start_position, end_position, CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001291 CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK);
1292 return Expression::StrictFunction();
lrn@chromium.org1c092762011-05-09 09:42:16 +00001293 }
1294
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001295 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001296}
1297
1298
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001299PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001300 // CallRuntime ::
1301 // '%' Identifier Arguments
1302
1303 Expect(i::Token::MOD, CHECK_OK);
1304 ParseIdentifier(CHECK_OK);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001305 ParseArguments(ok);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001306
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001307 return Expression::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001308}
1309
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001310#undef CHECK_OK
1311
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001312
1313void PreParser::ExpectSemicolon(bool* ok) {
1314 // Check for automatic semicolon insertion according to
1315 // the rules given in ECMA-262, section 7.9, page 21.
1316 i::Token::Value tok = peek();
1317 if (tok == i::Token::SEMICOLON) {
1318 Next();
1319 return;
1320 }
whesse@chromium.orgdf8c03c2011-06-21 14:36:03 +00001321 if (scanner_->HasAnyLineTerminatorBeforeNext() ||
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001322 tok == i::Token::RBRACE ||
1323 tok == i::Token::EOS) {
1324 return;
1325 }
1326 Expect(i::Token::SEMICOLON, ok);
1327}
1328
1329
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001330void PreParser::LogSymbol() {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001331 int identifier_pos = scanner_->location().beg_pos;
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001332 if (scanner_->is_literal_ascii()) {
1333 log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
1334 } else {
1335 log_->LogUC16Symbol(identifier_pos, scanner_->literal_uc16_string());
1336 }
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001337}
1338
1339
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001340PreParser::Expression PreParser::GetStringSymbol() {
lrn@chromium.org1c092762011-05-09 09:42:16 +00001341 const int kUseStrictLength = 10;
1342 const char* kUseStrictChars = "use strict";
lrn@chromium.org5d00b602011-01-05 09:51:43 +00001343 LogSymbol();
lrn@chromium.org1c092762011-05-09 09:42:16 +00001344 if (scanner_->is_literal_ascii() &&
1345 scanner_->literal_length() == kUseStrictLength &&
1346 !scanner_->literal_contains_escapes() &&
1347 !strncmp(scanner_->literal_ascii_string().start(), kUseStrictChars,
1348 kUseStrictLength)) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001349 return Expression::UseStrictStringLiteral();
lrn@chromium.org1c092762011-05-09 09:42:16 +00001350 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001351 return Expression::StringLiteral();
1352}
1353
1354
1355PreParser::Identifier PreParser::GetIdentifierSymbol() {
1356 LogSymbol();
1357 if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) {
1358 return Identifier::FutureReserved();
ager@chromium.org04921a82011-06-27 13:21:41 +00001359 } else if (scanner_->current_token() ==
1360 i::Token::FUTURE_STRICT_RESERVED_WORD) {
1361 return Identifier::FutureStrictReserved();
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001362 }
1363 if (scanner_->is_literal_ascii()) {
1364 // Detect strict-mode poison words.
1365 if (scanner_->literal_length() == 4 &&
1366 !strncmp(scanner_->literal_ascii_string().start(), "eval", 4)) {
1367 return Identifier::Eval();
1368 }
1369 if (scanner_->literal_length() == 9 &&
1370 !strncmp(scanner_->literal_ascii_string().start(), "arguments", 9)) {
1371 return Identifier::Arguments();
1372 }
1373 }
1374 return Identifier::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001375}
1376
1377
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001378PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
ager@chromium.org04921a82011-06-27 13:21:41 +00001379 i::Token::Value next = Next();
1380 switch (next) {
1381 case i::Token::FUTURE_RESERVED_WORD: {
1382 i::Scanner::Location location = scanner_->location();
1383 ReportMessageAt(location.beg_pos, location.end_pos,
1384 "reserved_word", NULL);
1385 *ok = false;
1386 }
1387 // FALLTHROUGH
1388 case i::Token::FUTURE_STRICT_RESERVED_WORD:
1389 case i::Token::IDENTIFIER:
1390 return GetIdentifierSymbol();
1391 default:
1392 *ok = false;
1393 return Identifier::Default();
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001394 }
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001395}
1396
1397
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001398void PreParser::SetStrictModeViolation(i::Scanner::Location location,
1399 const char* type,
1400 bool* ok) {
1401 if (strict_mode()) {
1402 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
1403 *ok = false;
1404 return;
1405 }
1406 // Delay report in case this later turns out to be strict code
1407 // (i.e., for function names and parameters prior to a "use strict"
1408 // directive).
1409 strict_mode_violation_location_ = location;
1410 strict_mode_violation_type_ = type;
1411}
1412
1413
1414void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
1415 int end_pos,
1416 bool* ok) {
1417 i::Scanner::Location location = strict_mode_violation_location_;
1418 if (location.IsValid() &&
1419 location.beg_pos > beg_pos && location.end_pos < end_pos) {
1420 ReportMessageAt(location.beg_pos, location.end_pos,
1421 strict_mode_violation_type_, NULL);
1422 *ok = false;
1423 }
1424 strict_mode_violation_location_ = i::Scanner::Location::invalid();
1425}
1426
1427
1428void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
1429 const char* eval_args_type,
1430 Identifier identifier,
1431 bool* ok) {
1432 const char* type = eval_args_type;
1433 if (identifier.IsFutureReserved()) {
ager@chromium.org04921a82011-06-27 13:21:41 +00001434 type = "reserved_word";
1435 } else if (identifier.IsFutureStrictReserved()) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001436 type = "strict_reserved_word";
1437 }
1438 if (strict_mode()) {
1439 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
1440 *ok = false;
1441 return;
1442 }
1443 strict_mode_violation_location_ = location;
1444 strict_mode_violation_type_ = type;
1445}
1446
1447
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001448PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001449 i::Token::Value next = Next();
1450 if (i::Token::IsKeyword(next)) {
1451 int pos = scanner_->location().beg_pos;
1452 const char* keyword = i::Token::String(next);
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001453 log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword,
1454 i::StrLength(keyword)));
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001455 return Identifier::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001456 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001457 if (next == i::Token::IDENTIFIER ||
ager@chromium.org04921a82011-06-27 13:21:41 +00001458 next == i::Token::FUTURE_RESERVED_WORD ||
1459 next == i::Token::FUTURE_STRICT_RESERVED_WORD) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001460 return GetIdentifierSymbol();
1461 }
1462 *ok = false;
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001463 return Identifier::Default();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001464}
1465
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001466#undef CHECK_OK
1467
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001468
1469// This function reads an identifier and determines whether or not it
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001470// is 'get' or 'set'.
ager@chromium.org04921a82011-06-27 13:21:41 +00001471PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get,
1472 bool* is_set,
1473 bool* ok) {
1474 Identifier result = ParseIdentifierName(ok);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001475 if (!*ok) return Identifier::Default();
1476 if (scanner_->is_literal_ascii() &&
1477 scanner_->literal_length() == 3) {
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00001478 const char* token = scanner_->literal_ascii_string().start();
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001479 *is_get = strncmp(token, "get", 3) == 0;
1480 *is_set = !*is_get && strncmp(token, "set", 3) == 0;
1481 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001482 return result;
1483}
1484
1485bool PreParser::peek_any_identifier() {
1486 i::Token::Value next = peek();
1487 return next == i::Token::IDENTIFIER ||
ager@chromium.org04921a82011-06-27 13:21:41 +00001488 next == i::Token::FUTURE_RESERVED_WORD ||
1489 next == i::Token::FUTURE_STRICT_RESERVED_WORD;
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001490}
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001491} } // v8::preparser