OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 13 matching lines...) Expand all Loading... |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #ifndef V8_PREPARSER_H | 28 #ifndef V8_PREPARSER_H |
29 #define V8_PREPARSER_H | 29 #define V8_PREPARSER_H |
30 | 30 |
31 #include "unicode.h" | 31 #include "unicode.h" |
32 | 32 |
33 namespace v8 { | 33 namespace v8 { |
34 namespace internal { | |
35 namespace preparser { | 34 namespace preparser { |
36 | 35 |
37 // Preparsing checks a JavaScript program and emits preparse-data that helps | 36 // Preparsing checks a JavaScript program and emits preparse-data that helps |
38 // a later parsing to be faster. | 37 // a later parsing to be faster. |
39 // See preparser-data.h for the data. | 38 // See preparser-data.h for the data. |
40 | 39 |
41 // The PreParser checks that the syntax follows the grammar for JavaScript, | 40 // The PreParser checks that the syntax follows the grammar for JavaScript, |
42 // and collects some information about the program along the way. | 41 // and collects some information about the program along the way. |
43 // The grammar check is only performed in order to understand the program | 42 // The grammar check is only performed in order to understand the program |
44 // sufficiently to deduce some information about it, that can be used | 43 // sufficiently to deduce some information about it, that can be used |
45 // to speed up later parsing. Finding errors is not the goal of pre-parsing, | 44 // to speed up later parsing. Finding errors is not the goal of pre-parsing, |
46 // rather it is to speed up properly written and correct programs. | 45 // rather it is to speed up properly written and correct programs. |
47 // That means that contextual checks (like a label being declared where | 46 // That means that contextual checks (like a label being declared where |
48 // it is used) are generally omitted. | 47 // it is used) are generally omitted. |
49 | 48 |
| 49 namespace i = v8::internal; |
| 50 |
50 enum StatementType { | 51 enum StatementType { |
51 kUnknownStatement | 52 kUnknownStatement |
52 }; | 53 }; |
53 | 54 |
54 enum ExpressionType { | 55 enum ExpressionType { |
55 kUnknownExpression, | 56 kUnknownExpression, |
56 kIdentifierExpression, // Used to detect labels. | 57 kIdentifierExpression, // Used to detect labels. |
57 kThisExpression, | 58 kThisExpression, |
58 kThisPropertyExpression | 59 kThisPropertyExpression |
59 }; | 60 }; |
(...skipping 25 matching lines...) Expand all Loading... |
85 // captured the syntax error), and false if a stack-overflow happened | 86 // captured the syntax error), and false if a stack-overflow happened |
86 // during parsing. | 87 // during parsing. |
87 bool PreParseProgram(Scanner* scanner, | 88 bool PreParseProgram(Scanner* scanner, |
88 PreParserLog* log, | 89 PreParserLog* log, |
89 bool allow_lazy) { | 90 bool allow_lazy) { |
90 allow_lazy_ = allow_lazy; | 91 allow_lazy_ = allow_lazy; |
91 scanner_ = scanner; | 92 scanner_ = scanner; |
92 log_ = log; | 93 log_ = log; |
93 Scope top_scope(&scope_, kTopLevelScope); | 94 Scope top_scope(&scope_, kTopLevelScope); |
94 bool ok = true; | 95 bool ok = true; |
95 ParseSourceElements(Token::EOS, &ok); | 96 ParseSourceElements(i::Token::EOS, &ok); |
96 bool stack_overflow = scanner_->stack_overflow(); | 97 bool stack_overflow = scanner_->stack_overflow(); |
97 if (!ok && !stack_overflow) { | 98 if (!ok && !stack_overflow) { |
98 ReportUnexpectedToken(scanner_->current_token()); | 99 ReportUnexpectedToken(scanner_->current_token()); |
99 } | 100 } |
100 return !stack_overflow; | 101 return !stack_overflow; |
101 } | 102 } |
102 | 103 |
103 private: | 104 private: |
104 enum ScopeType { | 105 enum ScopeType { |
105 kTopLevelScope, | 106 kTopLevelScope, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 }; | 138 }; |
138 | 139 |
139 // Types that allow us to recognize simple this-property assignments. | 140 // Types that allow us to recognize simple this-property assignments. |
140 // A simple this-property assignment is a statement on the form | 141 // A simple this-property assignment is a statement on the form |
141 // "this.propertyName = {primitive constant or function parameter name);" | 142 // "this.propertyName = {primitive constant or function parameter name);" |
142 // where propertyName isn't "__proto__". | 143 // where propertyName isn't "__proto__". |
143 // The result is only relevant if the function body contains only | 144 // The result is only relevant if the function body contains only |
144 // simple this-property assignments. | 145 // simple this-property assignments. |
145 | 146 |
146 // Report syntax error | 147 // Report syntax error |
147 void ReportUnexpectedToken(Token::Value token); | 148 void ReportUnexpectedToken(i::Token::Value token); |
148 void ReportMessageAt(int start_pos, | 149 void ReportMessageAt(int start_pos, |
149 int end_pos, | 150 int end_pos, |
150 const char* type, | 151 const char* type, |
151 const char* name_opt) { | 152 const char* name_opt) { |
152 log_->LogMessage(start_pos, end_pos, type, name_opt); | 153 log_->LogMessage(start_pos, end_pos, type, name_opt); |
153 } | 154 } |
154 | 155 |
155 // All ParseXXX functions take as the last argument an *ok parameter | 156 // All ParseXXX functions take as the last argument an *ok parameter |
156 // which is set to false if parsing failed; it is unchanged otherwise. | 157 // which is set to false if parsing failed; it is unchanged otherwise. |
157 // By making the 'exception handling' explicit, we are forced to check | 158 // By making the 'exception handling' explicit, we are forced to check |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 | 199 |
199 Identifier ParseIdentifier(bool* ok); | 200 Identifier ParseIdentifier(bool* ok); |
200 Identifier ParseIdentifierName(bool* ok); | 201 Identifier ParseIdentifierName(bool* ok); |
201 Identifier ParseIdentifierOrGetOrSet(bool* is_get, bool* is_set, bool* ok); | 202 Identifier ParseIdentifierOrGetOrSet(bool* is_get, bool* is_set, bool* ok); |
202 | 203 |
203 Identifier GetIdentifierSymbol(); | 204 Identifier GetIdentifierSymbol(); |
204 unsigned int HexDigitValue(char digit); | 205 unsigned int HexDigitValue(char digit); |
205 Expression GetStringSymbol(); | 206 Expression GetStringSymbol(); |
206 | 207 |
207 | 208 |
208 Token::Value peek() { return scanner_->peek(); } | 209 i::Token::Value peek() { return scanner_->peek(); } |
209 Token::Value Next() { | 210 i::Token::Value Next() { |
210 Token::Value next = scanner_->Next(); | 211 i::Token::Value next = scanner_->Next(); |
211 return next; | 212 return next; |
212 } | 213 } |
213 | 214 |
214 void Consume(Token::Value token) { | 215 void Consume(i::Token::Value token) { |
215 Next(); | 216 Next(); |
216 } | 217 } |
217 | 218 |
218 void Expect(Token::Value token, bool* ok) { | 219 void Expect(i::Token::Value token, bool* ok) { |
219 if (Next() != token) { | 220 if (Next() != token) { |
220 *ok = false; | 221 *ok = false; |
221 } | 222 } |
222 } | 223 } |
223 | 224 |
224 bool Check(Token::Value token) { | 225 bool Check(i::Token::Value token) { |
225 Token::Value next = peek(); | 226 i::Token::Value next = peek(); |
226 if (next == token) { | 227 if (next == token) { |
227 Consume(next); | 228 Consume(next); |
228 return true; | 229 return true; |
229 } | 230 } |
230 return false; | 231 return false; |
231 } | 232 } |
232 void ExpectSemicolon(bool* ok); | 233 void ExpectSemicolon(bool* ok); |
233 | 234 |
234 static int Precedence(Token::Value tok, bool accept_IN); | 235 static int Precedence(i::Token::Value tok, bool accept_IN); |
235 | 236 |
236 Scanner* scanner_; | 237 Scanner* scanner_; |
237 PreParserLog* log_; | 238 PreParserLog* log_; |
238 Scope* scope_; | 239 Scope* scope_; |
239 bool allow_lazy_; | 240 bool allow_lazy_; |
240 }; | 241 }; |
241 | 242 |
242 | 243 |
243 #define CHECK_OK ok); \ | 244 #define CHECK_OK ok); \ |
244 if (!*ok) return -1; \ | 245 if (!*ok) return -1; \ |
245 ((void)0 | 246 ((void)0 |
246 #define DUMMY ) // to make indentation work | 247 #define DUMMY ) // to make indentation work |
247 #undef DUMMY | 248 #undef DUMMY |
248 | 249 |
249 | 250 |
250 template <typename Scanner, typename Log> | 251 template <typename Scanner, typename Log> |
251 void PreParser<Scanner, Log>::ReportUnexpectedToken(Token::Value token) { | 252 void PreParser<Scanner, Log>::ReportUnexpectedToken(i::Token::Value token) { |
252 // We don't report stack overflows here, to avoid increasing the | 253 // We don't report stack overflows here, to avoid increasing the |
253 // stack depth even further. Instead we report it after parsing is | 254 // stack depth even further. Instead we report it after parsing is |
254 // over, in ParseProgram. | 255 // over, in ParseProgram. |
255 if (token == Token::ILLEGAL && scanner_->stack_overflow()) { | 256 if (token == i::Token::ILLEGAL && scanner_->stack_overflow()) { |
256 return; | 257 return; |
257 } | 258 } |
258 typename Scanner::Location source_location = scanner_->location(); | 259 typename Scanner::Location source_location = scanner_->location(); |
259 | 260 |
260 // Four of the tokens are treated specially | 261 // Four of the tokens are treated specially |
261 switch (token) { | 262 switch (token) { |
262 case Token::EOS: | 263 case i::Token::EOS: |
263 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 264 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
264 "unexpected_eos", NULL); | 265 "unexpected_eos", NULL); |
265 case Token::NUMBER: | 266 case i::Token::NUMBER: |
266 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 267 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
267 "unexpected_token_number", NULL); | 268 "unexpected_token_number", NULL); |
268 case Token::STRING: | 269 case i::Token::STRING: |
269 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 270 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
270 "unexpected_token_string", NULL); | 271 "unexpected_token_string", NULL); |
271 case Token::IDENTIFIER: | 272 case i::Token::IDENTIFIER: |
272 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 273 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
273 "unexpected_token_identifier", NULL); | 274 "unexpected_token_identifier", NULL); |
274 default: | 275 default: |
275 const char* name = Token::String(token); | 276 const char* name = i::Token::String(token); |
276 ReportMessageAt(source_location.beg_pos, source_location.end_pos, | 277 ReportMessageAt(source_location.beg_pos, source_location.end_pos, |
277 "unexpected_token", name); | 278 "unexpected_token", name); |
278 } | 279 } |
279 } | 280 } |
280 | 281 |
281 | 282 |
282 template <typename Scanner, typename Log> | 283 template <typename Scanner, typename Log> |
283 SourceElements PreParser<Scanner, Log>::ParseSourceElements(int end_token, | 284 SourceElements PreParser<Scanner, Log>::ParseSourceElements(int end_token, |
284 bool* ok) { | 285 bool* ok) { |
285 // SourceElements :: | 286 // SourceElements :: |
(...skipping 27 matching lines...) Expand all Loading... |
313 | 314 |
314 // Note: Since labels can only be used by 'break' and 'continue' | 315 // Note: Since labels can only be used by 'break' and 'continue' |
315 // statements, which themselves are only valid within blocks, | 316 // statements, which themselves are only valid within blocks, |
316 // iterations or 'switch' statements (i.e., BreakableStatements), | 317 // iterations or 'switch' statements (i.e., BreakableStatements), |
317 // labels can be simply ignored in all other cases; except for | 318 // labels can be simply ignored in all other cases; except for |
318 // trivial labeled break statements 'label: break label' which is | 319 // trivial labeled break statements 'label: break label' which is |
319 // parsed into an empty statement. | 320 // parsed into an empty statement. |
320 | 321 |
321 // Keep the source position of the statement | 322 // Keep the source position of the statement |
322 switch (peek()) { | 323 switch (peek()) { |
323 case Token::LBRACE: | 324 case i::Token::LBRACE: |
324 return ParseBlock(ok); | 325 return ParseBlock(ok); |
325 | 326 |
326 case Token::CONST: | 327 case i::Token::CONST: |
327 case Token::VAR: | 328 case i::Token::VAR: |
328 return ParseVariableStatement(ok); | 329 return ParseVariableStatement(ok); |
329 | 330 |
330 case Token::SEMICOLON: | 331 case i::Token::SEMICOLON: |
331 Next(); | 332 Next(); |
332 return kUnknownStatement; | 333 return kUnknownStatement; |
333 | 334 |
334 case Token::IF: | 335 case i::Token::IF: |
335 return ParseIfStatement(ok); | 336 return ParseIfStatement(ok); |
336 | 337 |
337 case Token::DO: | 338 case i::Token::DO: |
338 return ParseDoWhileStatement(ok); | 339 return ParseDoWhileStatement(ok); |
339 | 340 |
340 case Token::WHILE: | 341 case i::Token::WHILE: |
341 return ParseWhileStatement(ok); | 342 return ParseWhileStatement(ok); |
342 | 343 |
343 case Token::FOR: | 344 case i::Token::FOR: |
344 return ParseForStatement(ok); | 345 return ParseForStatement(ok); |
345 | 346 |
346 case Token::CONTINUE: | 347 case i::Token::CONTINUE: |
347 return ParseContinueStatement(ok); | 348 return ParseContinueStatement(ok); |
348 | 349 |
349 case Token::BREAK: | 350 case i::Token::BREAK: |
350 return ParseBreakStatement(ok); | 351 return ParseBreakStatement(ok); |
351 | 352 |
352 case Token::RETURN: | 353 case i::Token::RETURN: |
353 return ParseReturnStatement(ok); | 354 return ParseReturnStatement(ok); |
354 | 355 |
355 case Token::WITH: | 356 case i::Token::WITH: |
356 return ParseWithStatement(ok); | 357 return ParseWithStatement(ok); |
357 | 358 |
358 case Token::SWITCH: | 359 case i::Token::SWITCH: |
359 return ParseSwitchStatement(ok); | 360 return ParseSwitchStatement(ok); |
360 | 361 |
361 case Token::THROW: | 362 case i::Token::THROW: |
362 return ParseThrowStatement(ok); | 363 return ParseThrowStatement(ok); |
363 | 364 |
364 case Token::TRY: | 365 case i::Token::TRY: |
365 return ParseTryStatement(ok); | 366 return ParseTryStatement(ok); |
366 | 367 |
367 case Token::FUNCTION: | 368 case i::Token::FUNCTION: |
368 return ParseFunctionDeclaration(ok); | 369 return ParseFunctionDeclaration(ok); |
369 | 370 |
370 case Token::NATIVE: | 371 case i::Token::NATIVE: |
371 return ParseNativeDeclaration(ok); | 372 return ParseNativeDeclaration(ok); |
372 | 373 |
373 case Token::DEBUGGER: | 374 case i::Token::DEBUGGER: |
374 return ParseDebuggerStatement(ok); | 375 return ParseDebuggerStatement(ok); |
375 | 376 |
376 default: | 377 default: |
377 return ParseExpressionOrLabelledStatement(ok); | 378 return ParseExpressionOrLabelledStatement(ok); |
378 } | 379 } |
379 } | 380 } |
380 | 381 |
381 | 382 |
382 template <typename Scanner, typename Log> | 383 template <typename Scanner, typename Log> |
383 Statement PreParser<Scanner, Log>::ParseFunctionDeclaration(bool* ok) { | 384 Statement PreParser<Scanner, Log>::ParseFunctionDeclaration(bool* ok) { |
384 // FunctionDeclaration :: | 385 // FunctionDeclaration :: |
385 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 386 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
386 Expect(Token::FUNCTION, CHECK_OK); | 387 Expect(i::Token::FUNCTION, CHECK_OK); |
387 ParseIdentifier(CHECK_OK); | 388 ParseIdentifier(CHECK_OK); |
388 ParseFunctionLiteral(CHECK_OK); | 389 ParseFunctionLiteral(CHECK_OK); |
389 return kUnknownStatement; | 390 return kUnknownStatement; |
390 } | 391 } |
391 | 392 |
392 | 393 |
393 // Language extension which is only enabled for source files loaded | 394 // Language extension which is only enabled for source files loaded |
394 // through the API's extension mechanism. A native function | 395 // through the API's extension mechanism. A native function |
395 // declaration is resolved by looking up the function through a | 396 // declaration is resolved by looking up the function through a |
396 // callback provided by the extension. | 397 // callback provided by the extension. |
397 template <typename Scanner, typename Log> | 398 template <typename Scanner, typename Log> |
398 Statement PreParser<Scanner, Log>::ParseNativeDeclaration(bool* ok) { | 399 Statement PreParser<Scanner, Log>::ParseNativeDeclaration(bool* ok) { |
399 Expect(Token::NATIVE, CHECK_OK); | 400 Expect(i::Token::NATIVE, CHECK_OK); |
400 Expect(Token::FUNCTION, CHECK_OK); | 401 Expect(i::Token::FUNCTION, CHECK_OK); |
401 ParseIdentifier(CHECK_OK); | 402 ParseIdentifier(CHECK_OK); |
402 Expect(Token::LPAREN, CHECK_OK); | 403 Expect(i::Token::LPAREN, CHECK_OK); |
403 bool done = (peek() == Token::RPAREN); | 404 bool done = (peek() == i::Token::RPAREN); |
404 while (!done) { | 405 while (!done) { |
405 ParseIdentifier(CHECK_OK); | 406 ParseIdentifier(CHECK_OK); |
406 done = (peek() == Token::RPAREN); | 407 done = (peek() == i::Token::RPAREN); |
407 if (!done) { | 408 if (!done) { |
408 Expect(Token::COMMA, CHECK_OK); | 409 Expect(i::Token::COMMA, CHECK_OK); |
409 } | 410 } |
410 } | 411 } |
411 Expect(Token::RPAREN, CHECK_OK); | 412 Expect(i::Token::RPAREN, CHECK_OK); |
412 Expect(Token::SEMICOLON, CHECK_OK); | 413 Expect(i::Token::SEMICOLON, CHECK_OK); |
413 return kUnknownStatement; | 414 return kUnknownStatement; |
414 } | 415 } |
415 | 416 |
416 | 417 |
417 template <typename Scanner, typename Log> | 418 template <typename Scanner, typename Log> |
418 Statement PreParser<Scanner, Log>::ParseBlock(bool* ok) { | 419 Statement PreParser<Scanner, Log>::ParseBlock(bool* ok) { |
419 // Block :: | 420 // Block :: |
420 // '{' Statement* '}' | 421 // '{' Statement* '}' |
421 | 422 |
422 // Note that a Block does not introduce a new execution scope! | 423 // Note that a Block does not introduce a new execution scope! |
423 // (ECMA-262, 3rd, 12.2) | 424 // (ECMA-262, 3rd, 12.2) |
424 // | 425 // |
425 Expect(Token::LBRACE, CHECK_OK); | 426 Expect(i::Token::LBRACE, CHECK_OK); |
426 while (peek() != Token::RBRACE) { | 427 while (peek() != i::Token::RBRACE) { |
427 ParseStatement(CHECK_OK); | 428 ParseStatement(CHECK_OK); |
428 } | 429 } |
429 Expect(Token::RBRACE, CHECK_OK); | 430 Expect(i::Token::RBRACE, CHECK_OK); |
430 return kUnknownStatement; | 431 return kUnknownStatement; |
431 } | 432 } |
432 | 433 |
433 | 434 |
434 template <typename Scanner, typename Log> | 435 template <typename Scanner, typename Log> |
435 Statement PreParser<Scanner, Log>::ParseVariableStatement(bool* ok) { | 436 Statement PreParser<Scanner, Log>::ParseVariableStatement(bool* ok) { |
436 // VariableStatement :: | 437 // VariableStatement :: |
437 // VariableDeclarations ';' | 438 // VariableDeclarations ';' |
438 | 439 |
439 Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK); | 440 Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK); |
440 ExpectSemicolon(CHECK_OK); | 441 ExpectSemicolon(CHECK_OK); |
441 return result; | 442 return result; |
442 } | 443 } |
443 | 444 |
444 | 445 |
445 // If the variable declaration declares exactly one non-const | 446 // If the variable declaration declares exactly one non-const |
446 // variable, then *var is set to that variable. In all other cases, | 447 // variable, then *var is set to that variable. In all other cases, |
447 // *var is untouched; in particular, it is the caller's responsibility | 448 // *var is untouched; in particular, it is the caller's responsibility |
448 // to initialize it properly. This mechanism is also used for the parsing | 449 // to initialize it properly. This mechanism is also used for the parsing |
449 // of 'for-in' loops. | 450 // of 'for-in' loops. |
450 template <typename Scanner, typename Log> | 451 template <typename Scanner, typename Log> |
451 Statement PreParser<Scanner, Log>::ParseVariableDeclarations(bool accept_IN, | 452 Statement PreParser<Scanner, Log>::ParseVariableDeclarations(bool accept_IN, |
452 int* num_decl, | 453 int* num_decl, |
453 bool* ok) { | 454 bool* ok) { |
454 // VariableDeclarations :: | 455 // VariableDeclarations :: |
455 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] | 456 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
456 | 457 |
457 if (peek() == Token::VAR) { | 458 if (peek() == i::Token::VAR) { |
458 Consume(Token::VAR); | 459 Consume(i::Token::VAR); |
459 } else if (peek() == Token::CONST) { | 460 } else if (peek() == i::Token::CONST) { |
460 Consume(Token::CONST); | 461 Consume(i::Token::CONST); |
461 } else { | 462 } else { |
462 *ok = false; | 463 *ok = false; |
463 return 0; | 464 return 0; |
464 } | 465 } |
465 | 466 |
466 // The scope of a variable/const declared anywhere inside a function | 467 // The scope of a variable/const declared anywhere inside a function |
467 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). . | 468 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). . |
468 int nvars = 0; // the number of variables declared | 469 int nvars = 0; // the number of variables declared |
469 do { | 470 do { |
470 // Parse variable name. | 471 // Parse variable name. |
471 if (nvars > 0) Consume(Token::COMMA); | 472 if (nvars > 0) Consume(i::Token::COMMA); |
472 ParseIdentifier(CHECK_OK); | 473 ParseIdentifier(CHECK_OK); |
473 nvars++; | 474 nvars++; |
474 if (peek() == Token::ASSIGN) { | 475 if (peek() == i::Token::ASSIGN) { |
475 Expect(Token::ASSIGN, CHECK_OK); | 476 Expect(i::Token::ASSIGN, CHECK_OK); |
476 ParseAssignmentExpression(accept_IN, CHECK_OK); | 477 ParseAssignmentExpression(accept_IN, CHECK_OK); |
477 } | 478 } |
478 } while (peek() == Token::COMMA); | 479 } while (peek() == i::Token::COMMA); |
479 | 480 |
480 if (num_decl != NULL) *num_decl = nvars; | 481 if (num_decl != NULL) *num_decl = nvars; |
481 return kUnknownStatement; | 482 return kUnknownStatement; |
482 } | 483 } |
483 | 484 |
484 | 485 |
485 template <typename Scanner, typename Log> | 486 template <typename Scanner, typename Log> |
486 Statement PreParser<Scanner, Log>::ParseExpressionOrLabelledStatement( | 487 Statement PreParser<Scanner, Log>::ParseExpressionOrLabelledStatement( |
487 bool* ok) { | 488 bool* ok) { |
488 // ExpressionStatement | LabelledStatement :: | 489 // ExpressionStatement | LabelledStatement :: |
489 // Expression ';' | 490 // Expression ';' |
490 // Identifier ':' Statement | 491 // Identifier ':' Statement |
491 | 492 |
492 Expression expr = ParseExpression(true, CHECK_OK); | 493 Expression expr = ParseExpression(true, CHECK_OK); |
493 if (peek() == Token::COLON && expr == kIdentifierExpression) { | 494 if (peek() == i::Token::COLON && expr == kIdentifierExpression) { |
494 Consume(Token::COLON); | 495 Consume(i::Token::COLON); |
495 return ParseStatement(ok); | 496 return ParseStatement(ok); |
496 } | 497 } |
497 // Parsed expression statement. | 498 // Parsed expression statement. |
498 ExpectSemicolon(CHECK_OK); | 499 ExpectSemicolon(CHECK_OK); |
499 return kUnknownStatement; | 500 return kUnknownStatement; |
500 } | 501 } |
501 | 502 |
502 | 503 |
503 template <typename Scanner, typename Log> | 504 template <typename Scanner, typename Log> |
504 Statement PreParser<Scanner, Log>::ParseIfStatement(bool* ok) { | 505 Statement PreParser<Scanner, Log>::ParseIfStatement(bool* ok) { |
505 // IfStatement :: | 506 // IfStatement :: |
506 // 'if' '(' Expression ')' Statement ('else' Statement)? | 507 // 'if' '(' Expression ')' Statement ('else' Statement)? |
507 | 508 |
508 Expect(Token::IF, CHECK_OK); | 509 Expect(i::Token::IF, CHECK_OK); |
509 Expect(Token::LPAREN, CHECK_OK); | 510 Expect(i::Token::LPAREN, CHECK_OK); |
510 ParseExpression(true, CHECK_OK); | 511 ParseExpression(true, CHECK_OK); |
511 Expect(Token::RPAREN, CHECK_OK); | 512 Expect(i::Token::RPAREN, CHECK_OK); |
512 ParseStatement(CHECK_OK); | 513 ParseStatement(CHECK_OK); |
513 if (peek() == Token::ELSE) { | 514 if (peek() == i::Token::ELSE) { |
514 Next(); | 515 Next(); |
515 ParseStatement(CHECK_OK); | 516 ParseStatement(CHECK_OK); |
516 } | 517 } |
517 return kUnknownStatement; | 518 return kUnknownStatement; |
518 } | 519 } |
519 | 520 |
520 | 521 |
521 template <typename Scanner, typename Log> | 522 template <typename Scanner, typename Log> |
522 Statement PreParser<Scanner, Log>::ParseContinueStatement(bool* ok) { | 523 Statement PreParser<Scanner, Log>::ParseContinueStatement(bool* ok) { |
523 // ContinueStatement :: | 524 // ContinueStatement :: |
524 // 'continue' [no line terminator] Identifier? ';' | 525 // 'continue' [no line terminator] Identifier? ';' |
525 | 526 |
526 Expect(Token::CONTINUE, CHECK_OK); | 527 Expect(i::Token::CONTINUE, CHECK_OK); |
527 Token::Value tok = peek(); | 528 i::Token::Value tok = peek(); |
528 if (!scanner_->has_line_terminator_before_next() && | 529 if (!scanner_->has_line_terminator_before_next() && |
529 tok != Token::SEMICOLON && | 530 tok != i::Token::SEMICOLON && |
530 tok != Token::RBRACE && | 531 tok != i::Token::RBRACE && |
531 tok != Token::EOS) { | 532 tok != i::Token::EOS) { |
532 ParseIdentifier(CHECK_OK); | 533 ParseIdentifier(CHECK_OK); |
533 } | 534 } |
534 ExpectSemicolon(CHECK_OK); | 535 ExpectSemicolon(CHECK_OK); |
535 return kUnknownStatement; | 536 return kUnknownStatement; |
536 } | 537 } |
537 | 538 |
538 | 539 |
539 template <typename Scanner, typename Log> | 540 template <typename Scanner, typename Log> |
540 Statement PreParser<Scanner, Log>::ParseBreakStatement(bool* ok) { | 541 Statement PreParser<Scanner, Log>::ParseBreakStatement(bool* ok) { |
541 // BreakStatement :: | 542 // BreakStatement :: |
542 // 'break' [no line terminator] Identifier? ';' | 543 // 'break' [no line terminator] Identifier? ';' |
543 | 544 |
544 Expect(Token::BREAK, CHECK_OK); | 545 Expect(i::Token::BREAK, CHECK_OK); |
545 Token::Value tok = peek(); | 546 i::Token::Value tok = peek(); |
546 if (!scanner_->has_line_terminator_before_next() && | 547 if (!scanner_->has_line_terminator_before_next() && |
547 tok != Token::SEMICOLON && | 548 tok != i::Token::SEMICOLON && |
548 tok != Token::RBRACE && | 549 tok != i::Token::RBRACE && |
549 tok != Token::EOS) { | 550 tok != i::Token::EOS) { |
550 ParseIdentifier(CHECK_OK); | 551 ParseIdentifier(CHECK_OK); |
551 } | 552 } |
552 ExpectSemicolon(CHECK_OK); | 553 ExpectSemicolon(CHECK_OK); |
553 return kUnknownStatement; | 554 return kUnknownStatement; |
554 } | 555 } |
555 | 556 |
556 | 557 |
557 template <typename Scanner, typename Log> | 558 template <typename Scanner, typename Log> |
558 Statement PreParser<Scanner, Log>::ParseReturnStatement(bool* ok) { | 559 Statement PreParser<Scanner, Log>::ParseReturnStatement(bool* ok) { |
559 // ReturnStatement :: | 560 // ReturnStatement :: |
560 // 'return' [no line terminator] Expression? ';' | 561 // 'return' [no line terminator] Expression? ';' |
561 | 562 |
562 // Consume the return token. It is necessary to do the before | 563 // Consume the return token. It is necessary to do the before |
563 // reporting any errors on it, because of the way errors are | 564 // reporting any errors on it, because of the way errors are |
564 // reported (underlining). | 565 // reported (underlining). |
565 Expect(Token::RETURN, CHECK_OK); | 566 Expect(i::Token::RETURN, CHECK_OK); |
566 | 567 |
567 // An ECMAScript program is considered syntactically incorrect if it | 568 // An ECMAScript program is considered syntactically incorrect if it |
568 // contains a return statement that is not within the body of a | 569 // contains a return statement that is not within the body of a |
569 // function. See ECMA-262, section 12.9, page 67. | 570 // function. See ECMA-262, section 12.9, page 67. |
570 // This is not handled during preparsing. | 571 // This is not handled during preparsing. |
571 | 572 |
572 Token::Value tok = peek(); | 573 i::Token::Value tok = peek(); |
573 if (!scanner_->has_line_terminator_before_next() && | 574 if (!scanner_->has_line_terminator_before_next() && |
574 tok != Token::SEMICOLON && | 575 tok != i::Token::SEMICOLON && |
575 tok != Token::RBRACE && | 576 tok != i::Token::RBRACE && |
576 tok != Token::EOS) { | 577 tok != i::Token::EOS) { |
577 ParseExpression(true, CHECK_OK); | 578 ParseExpression(true, CHECK_OK); |
578 } | 579 } |
579 ExpectSemicolon(CHECK_OK); | 580 ExpectSemicolon(CHECK_OK); |
580 return kUnknownStatement; | 581 return kUnknownStatement; |
581 } | 582 } |
582 | 583 |
583 | 584 |
584 template <typename Scanner, typename Log> | 585 template <typename Scanner, typename Log> |
585 Statement PreParser<Scanner, Log>::ParseWithStatement(bool* ok) { | 586 Statement PreParser<Scanner, Log>::ParseWithStatement(bool* ok) { |
586 // WithStatement :: | 587 // WithStatement :: |
587 // 'with' '(' Expression ')' Statement | 588 // 'with' '(' Expression ')' Statement |
588 Expect(Token::WITH, CHECK_OK); | 589 Expect(i::Token::WITH, CHECK_OK); |
589 Expect(Token::LPAREN, CHECK_OK); | 590 Expect(i::Token::LPAREN, CHECK_OK); |
590 ParseExpression(true, CHECK_OK); | 591 ParseExpression(true, CHECK_OK); |
591 Expect(Token::RPAREN, CHECK_OK); | 592 Expect(i::Token::RPAREN, CHECK_OK); |
592 | 593 |
593 scope_->EnterWith(); | 594 scope_->EnterWith(); |
594 ParseStatement(CHECK_OK); | 595 ParseStatement(CHECK_OK); |
595 scope_->LeaveWith(); | 596 scope_->LeaveWith(); |
596 return kUnknownStatement; | 597 return kUnknownStatement; |
597 } | 598 } |
598 | 599 |
599 | 600 |
600 template <typename Scanner, typename Log> | 601 template <typename Scanner, typename Log> |
601 Statement PreParser<Scanner, Log>::ParseSwitchStatement(bool* ok) { | 602 Statement PreParser<Scanner, Log>::ParseSwitchStatement(bool* ok) { |
602 // SwitchStatement :: | 603 // SwitchStatement :: |
603 // 'switch' '(' Expression ')' '{' CaseClause* '}' | 604 // 'switch' '(' Expression ')' '{' CaseClause* '}' |
604 | 605 |
605 Expect(Token::SWITCH, CHECK_OK); | 606 Expect(i::Token::SWITCH, CHECK_OK); |
606 Expect(Token::LPAREN, CHECK_OK); | 607 Expect(i::Token::LPAREN, CHECK_OK); |
607 ParseExpression(true, CHECK_OK); | 608 ParseExpression(true, CHECK_OK); |
608 Expect(Token::RPAREN, CHECK_OK); | 609 Expect(i::Token::RPAREN, CHECK_OK); |
609 | 610 |
610 Expect(Token::LBRACE, CHECK_OK); | 611 Expect(i::Token::LBRACE, CHECK_OK); |
611 Token::Value token = peek(); | 612 i::Token::Value token = peek(); |
612 while (token != Token::RBRACE) { | 613 while (token != i::Token::RBRACE) { |
613 if (token == Token::CASE) { | 614 if (token == i::Token::CASE) { |
614 Expect(Token::CASE, CHECK_OK); | 615 Expect(i::Token::CASE, CHECK_OK); |
615 ParseExpression(true, CHECK_OK); | 616 ParseExpression(true, CHECK_OK); |
616 Expect(Token::COLON, CHECK_OK); | 617 Expect(i::Token::COLON, CHECK_OK); |
617 } else if (token == Token::DEFAULT) { | 618 } else if (token == i::Token::DEFAULT) { |
618 Expect(Token::DEFAULT, CHECK_OK); | 619 Expect(i::Token::DEFAULT, CHECK_OK); |
619 Expect(Token::COLON, CHECK_OK); | 620 Expect(i::Token::COLON, CHECK_OK); |
620 } else { | 621 } else { |
621 ParseStatement(CHECK_OK); | 622 ParseStatement(CHECK_OK); |
622 } | 623 } |
623 token = peek(); | 624 token = peek(); |
624 } | 625 } |
625 Expect(Token::RBRACE, CHECK_OK); | 626 Expect(i::Token::RBRACE, CHECK_OK); |
626 | 627 |
627 return kUnknownStatement; | 628 return kUnknownStatement; |
628 } | 629 } |
629 | 630 |
630 | 631 |
631 template <typename Scanner, typename Log> | 632 template <typename Scanner, typename Log> |
632 Statement PreParser<Scanner, Log>::ParseDoWhileStatement(bool* ok) { | 633 Statement PreParser<Scanner, Log>::ParseDoWhileStatement(bool* ok) { |
633 // DoStatement :: | 634 // DoStatement :: |
634 // 'do' Statement 'while' '(' Expression ')' ';' | 635 // 'do' Statement 'while' '(' Expression ')' ';' |
635 | 636 |
636 Expect(Token::DO, CHECK_OK); | 637 Expect(i::Token::DO, CHECK_OK); |
637 ParseStatement(CHECK_OK); | 638 ParseStatement(CHECK_OK); |
638 Expect(Token::WHILE, CHECK_OK); | 639 Expect(i::Token::WHILE, CHECK_OK); |
639 Expect(Token::LPAREN, CHECK_OK); | 640 Expect(i::Token::LPAREN, CHECK_OK); |
640 ParseExpression(true, CHECK_OK); | 641 ParseExpression(true, CHECK_OK); |
641 Expect(Token::RPAREN, CHECK_OK); | 642 Expect(i::Token::RPAREN, CHECK_OK); |
642 return kUnknownStatement; | 643 return kUnknownStatement; |
643 } | 644 } |
644 | 645 |
645 | 646 |
646 template <typename Scanner, typename Log> | 647 template <typename Scanner, typename Log> |
647 Statement PreParser<Scanner, Log>::ParseWhileStatement(bool* ok) { | 648 Statement PreParser<Scanner, Log>::ParseWhileStatement(bool* ok) { |
648 // WhileStatement :: | 649 // WhileStatement :: |
649 // 'while' '(' Expression ')' Statement | 650 // 'while' '(' Expression ')' Statement |
650 | 651 |
651 Expect(Token::WHILE, CHECK_OK); | 652 Expect(i::Token::WHILE, CHECK_OK); |
652 Expect(Token::LPAREN, CHECK_OK); | 653 Expect(i::Token::LPAREN, CHECK_OK); |
653 ParseExpression(true, CHECK_OK); | 654 ParseExpression(true, CHECK_OK); |
654 Expect(Token::RPAREN, CHECK_OK); | 655 Expect(i::Token::RPAREN, CHECK_OK); |
655 ParseStatement(CHECK_OK); | 656 ParseStatement(CHECK_OK); |
656 return kUnknownStatement; | 657 return kUnknownStatement; |
657 } | 658 } |
658 | 659 |
659 | 660 |
660 template <typename Scanner, typename Log> | 661 template <typename Scanner, typename Log> |
661 Statement PreParser<Scanner, Log>::ParseForStatement(bool* ok) { | 662 Statement PreParser<Scanner, Log>::ParseForStatement(bool* ok) { |
662 // ForStatement :: | 663 // ForStatement :: |
663 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 664 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
664 | 665 |
665 Expect(Token::FOR, CHECK_OK); | 666 Expect(i::Token::FOR, CHECK_OK); |
666 Expect(Token::LPAREN, CHECK_OK); | 667 Expect(i::Token::LPAREN, CHECK_OK); |
667 if (peek() != Token::SEMICOLON) { | 668 if (peek() != i::Token::SEMICOLON) { |
668 if (peek() == Token::VAR || peek() == Token::CONST) { | 669 if (peek() == i::Token::VAR || peek() == i::Token::CONST) { |
669 int decl_count; | 670 int decl_count; |
670 ParseVariableDeclarations(false, &decl_count, CHECK_OK); | 671 ParseVariableDeclarations(false, &decl_count, CHECK_OK); |
671 if (peek() == Token::IN && decl_count == 1) { | 672 if (peek() == i::Token::IN && decl_count == 1) { |
672 Expect(Token::IN, CHECK_OK); | 673 Expect(i::Token::IN, CHECK_OK); |
673 ParseExpression(true, CHECK_OK); | 674 ParseExpression(true, CHECK_OK); |
674 Expect(Token::RPAREN, CHECK_OK); | 675 Expect(i::Token::RPAREN, CHECK_OK); |
675 | 676 |
676 ParseStatement(CHECK_OK); | 677 ParseStatement(CHECK_OK); |
677 return kUnknownStatement; | 678 return kUnknownStatement; |
678 } | 679 } |
679 } else { | 680 } else { |
680 ParseExpression(false, CHECK_OK); | 681 ParseExpression(false, CHECK_OK); |
681 if (peek() == Token::IN) { | 682 if (peek() == i::Token::IN) { |
682 Expect(Token::IN, CHECK_OK); | 683 Expect(i::Token::IN, CHECK_OK); |
683 ParseExpression(true, CHECK_OK); | 684 ParseExpression(true, CHECK_OK); |
684 Expect(Token::RPAREN, CHECK_OK); | 685 Expect(i::Token::RPAREN, CHECK_OK); |
685 | 686 |
686 ParseStatement(CHECK_OK); | 687 ParseStatement(CHECK_OK); |
687 return kUnknownStatement; | 688 return kUnknownStatement; |
688 } | 689 } |
689 } | 690 } |
690 } | 691 } |
691 | 692 |
692 // Parsed initializer at this point. | 693 // Parsed initializer at this point. |
693 Expect(Token::SEMICOLON, CHECK_OK); | 694 Expect(i::Token::SEMICOLON, CHECK_OK); |
694 | 695 |
695 if (peek() != Token::SEMICOLON) { | 696 if (peek() != i::Token::SEMICOLON) { |
696 ParseExpression(true, CHECK_OK); | 697 ParseExpression(true, CHECK_OK); |
697 } | 698 } |
698 Expect(Token::SEMICOLON, CHECK_OK); | 699 Expect(i::Token::SEMICOLON, CHECK_OK); |
699 | 700 |
700 if (peek() != Token::RPAREN) { | 701 if (peek() != i::Token::RPAREN) { |
701 ParseExpression(true, CHECK_OK); | 702 ParseExpression(true, CHECK_OK); |
702 } | 703 } |
703 Expect(Token::RPAREN, CHECK_OK); | 704 Expect(i::Token::RPAREN, CHECK_OK); |
704 | 705 |
705 ParseStatement(CHECK_OK); | 706 ParseStatement(CHECK_OK); |
706 return kUnknownStatement; | 707 return kUnknownStatement; |
707 } | 708 } |
708 | 709 |
709 | 710 |
710 template <typename Scanner, typename Log> | 711 template <typename Scanner, typename Log> |
711 Statement PreParser<Scanner, Log>::ParseThrowStatement(bool* ok) { | 712 Statement PreParser<Scanner, Log>::ParseThrowStatement(bool* ok) { |
712 // ThrowStatement :: | 713 // ThrowStatement :: |
713 // 'throw' [no line terminator] Expression ';' | 714 // 'throw' [no line terminator] Expression ';' |
714 | 715 |
715 Expect(Token::THROW, CHECK_OK); | 716 Expect(i::Token::THROW, CHECK_OK); |
716 if (scanner_->has_line_terminator_before_next()) { | 717 if (scanner_->has_line_terminator_before_next()) { |
717 typename Scanner::Location pos = scanner_->location(); | 718 typename Scanner::Location pos = scanner_->location(); |
718 ReportMessageAt(pos.beg_pos, pos.end_pos, | 719 ReportMessageAt(pos.beg_pos, pos.end_pos, |
719 "newline_after_throw", NULL); | 720 "newline_after_throw", NULL); |
720 *ok = false; | 721 *ok = false; |
721 return NULL; | 722 return NULL; |
722 } | 723 } |
723 ParseExpression(true, CHECK_OK); | 724 ParseExpression(true, CHECK_OK); |
724 ExpectSemicolon(CHECK_OK); | 725 ExpectSemicolon(CHECK_OK); |
725 | 726 |
(...skipping 10 matching lines...) Expand all Loading... |
736 // | 737 // |
737 // Catch :: | 738 // Catch :: |
738 // 'catch' '(' Identifier ')' Block | 739 // 'catch' '(' Identifier ')' Block |
739 // | 740 // |
740 // Finally :: | 741 // Finally :: |
741 // 'finally' Block | 742 // 'finally' Block |
742 | 743 |
743 // In preparsing, allow any number of catch/finally blocks, including zero | 744 // In preparsing, allow any number of catch/finally blocks, including zero |
744 // of both. | 745 // of both. |
745 | 746 |
746 Expect(Token::TRY, CHECK_OK); | 747 Expect(i::Token::TRY, CHECK_OK); |
747 | 748 |
748 ParseBlock(CHECK_OK); | 749 ParseBlock(CHECK_OK); |
749 | 750 |
750 bool catch_or_finally_seen = false; | 751 bool catch_or_finally_seen = false; |
751 if (peek() == Token::CATCH) { | 752 if (peek() == i::Token::CATCH) { |
752 Expect(Token::CATCH, CHECK_OK); | 753 Expect(i::Token::CATCH, CHECK_OK); |
753 Expect(Token::LPAREN, CHECK_OK); | 754 Expect(i::Token::LPAREN, CHECK_OK); |
754 ParseIdentifier(CHECK_OK); | 755 ParseIdentifier(CHECK_OK); |
755 Expect(Token::RPAREN, CHECK_OK); | 756 Expect(i::Token::RPAREN, CHECK_OK); |
756 ParseBlock(CHECK_OK); | 757 ParseBlock(CHECK_OK); |
757 catch_or_finally_seen = true; | 758 catch_or_finally_seen = true; |
758 } | 759 } |
759 if (peek() == Token::FINALLY) { | 760 if (peek() == i::Token::FINALLY) { |
760 Expect(Token::FINALLY, CHECK_OK); | 761 Expect(i::Token::FINALLY, CHECK_OK); |
761 ParseBlock(CHECK_OK); | 762 ParseBlock(CHECK_OK); |
762 catch_or_finally_seen = true; | 763 catch_or_finally_seen = true; |
763 } | 764 } |
764 if (!catch_or_finally_seen) { | 765 if (!catch_or_finally_seen) { |
765 *ok = false; | 766 *ok = false; |
766 } | 767 } |
767 return kUnknownStatement; | 768 return kUnknownStatement; |
768 } | 769 } |
769 | 770 |
770 | 771 |
771 template <typename Scanner, typename Log> | 772 template <typename Scanner, typename Log> |
772 Statement PreParser<Scanner, Log>::ParseDebuggerStatement(bool* ok) { | 773 Statement PreParser<Scanner, Log>::ParseDebuggerStatement(bool* ok) { |
773 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser | 774 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser |
774 // contexts this is used as a statement which invokes the debugger as if a | 775 // contexts this is used as a statement which invokes the debugger as if a |
775 // break point is present. | 776 // break point is present. |
776 // DebuggerStatement :: | 777 // DebuggerStatement :: |
777 // 'debugger' ';' | 778 // 'debugger' ';' |
778 | 779 |
779 Expect(Token::DEBUGGER, CHECK_OK); | 780 Expect(i::Token::DEBUGGER, CHECK_OK); |
780 ExpectSemicolon(CHECK_OK); | 781 ExpectSemicolon(CHECK_OK); |
781 return kUnknownStatement; | 782 return kUnknownStatement; |
782 } | 783 } |
783 | 784 |
784 | 785 |
785 // Precedence = 1 | 786 // Precedence = 1 |
786 template <typename Scanner, typename Log> | 787 template <typename Scanner, typename Log> |
787 Expression PreParser<Scanner, Log>::ParseExpression(bool accept_IN, bool* ok) { | 788 Expression PreParser<Scanner, Log>::ParseExpression(bool accept_IN, bool* ok) { |
788 // Expression :: | 789 // Expression :: |
789 // AssignmentExpression | 790 // AssignmentExpression |
790 // Expression ',' AssignmentExpression | 791 // Expression ',' AssignmentExpression |
791 | 792 |
792 Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK); | 793 Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK); |
793 while (peek() == Token::COMMA) { | 794 while (peek() == i::Token::COMMA) { |
794 Expect(Token::COMMA, CHECK_OK); | 795 Expect(i::Token::COMMA, CHECK_OK); |
795 ParseAssignmentExpression(accept_IN, CHECK_OK); | 796 ParseAssignmentExpression(accept_IN, CHECK_OK); |
796 result = kUnknownExpression; | 797 result = kUnknownExpression; |
797 } | 798 } |
798 return result; | 799 return result; |
799 } | 800 } |
800 | 801 |
801 | 802 |
802 // Precedence = 2 | 803 // Precedence = 2 |
803 template <typename Scanner, typename Log> | 804 template <typename Scanner, typename Log> |
804 Expression PreParser<Scanner, Log>::ParseAssignmentExpression(bool accept_IN, | 805 Expression PreParser<Scanner, Log>::ParseAssignmentExpression(bool accept_IN, |
805 bool* ok) { | 806 bool* ok) { |
806 // AssignmentExpression :: | 807 // AssignmentExpression :: |
807 // ConditionalExpression | 808 // ConditionalExpression |
808 // LeftHandSideExpression AssignmentOperator AssignmentExpression | 809 // LeftHandSideExpression AssignmentOperator AssignmentExpression |
809 | 810 |
810 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK); | 811 Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK); |
811 | 812 |
812 if (!Token::IsAssignmentOp(peek())) { | 813 if (!i::Token::IsAssignmentOp(peek())) { |
813 // Parsed conditional expression only (no assignment). | 814 // Parsed conditional expression only (no assignment). |
814 return expression; | 815 return expression; |
815 } | 816 } |
816 | 817 |
817 Token::Value op = Next(); // Get assignment operator. | 818 i::Token::Value op = Next(); // Get assignment operator. |
818 ParseAssignmentExpression(accept_IN, CHECK_OK); | 819 ParseAssignmentExpression(accept_IN, CHECK_OK); |
819 | 820 |
820 if ((op == Token::ASSIGN) && (expression == kThisPropertyExpression)) { | 821 if ((op == i::Token::ASSIGN) && (expression == kThisPropertyExpression)) { |
821 scope_->AddProperty(); | 822 scope_->AddProperty(); |
822 } | 823 } |
823 | 824 |
824 return kUnknownExpression; | 825 return kUnknownExpression; |
825 } | 826 } |
826 | 827 |
827 | 828 |
828 // Precedence = 3 | 829 // Precedence = 3 |
829 template <typename Scanner, typename Log> | 830 template <typename Scanner, typename Log> |
830 Expression PreParser<Scanner, Log>::ParseConditionalExpression(bool accept_IN, | 831 Expression PreParser<Scanner, Log>::ParseConditionalExpression(bool accept_IN, |
831 bool* ok) { | 832 bool* ok) { |
832 // ConditionalExpression :: | 833 // ConditionalExpression :: |
833 // LogicalOrExpression | 834 // LogicalOrExpression |
834 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression | 835 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression |
835 | 836 |
836 // We start using the binary expression parser for prec >= 4 only! | 837 // We start using the binary expression parser for prec >= 4 only! |
837 Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK); | 838 Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK); |
838 if (peek() != Token::CONDITIONAL) return expression; | 839 if (peek() != i::Token::CONDITIONAL) return expression; |
839 Consume(Token::CONDITIONAL); | 840 Consume(i::Token::CONDITIONAL); |
840 // In parsing the first assignment expression in conditional | 841 // In parsing the first assignment expression in conditional |
841 // expressions we always accept the 'in' keyword; see ECMA-262, | 842 // expressions we always accept the 'in' keyword; see ECMA-262, |
842 // section 11.12, page 58. | 843 // section 11.12, page 58. |
843 ParseAssignmentExpression(true, CHECK_OK); | 844 ParseAssignmentExpression(true, CHECK_OK); |
844 Expect(Token::COLON, CHECK_OK); | 845 Expect(i::Token::COLON, CHECK_OK); |
845 ParseAssignmentExpression(accept_IN, CHECK_OK); | 846 ParseAssignmentExpression(accept_IN, CHECK_OK); |
846 return kUnknownExpression; | 847 return kUnknownExpression; |
847 } | 848 } |
848 | 849 |
849 | 850 |
850 template <typename Scanner, typename Log> | 851 template <typename Scanner, typename Log> |
851 int PreParser<Scanner, Log>::Precedence(Token::Value tok, bool accept_IN) { | 852 int PreParser<Scanner, Log>::Precedence(i::Token::Value tok, bool accept_IN) { |
852 if (tok == Token::IN && !accept_IN) | 853 if (tok == i::Token::IN && !accept_IN) |
853 return 0; // 0 precedence will terminate binary expression parsing | 854 return 0; // 0 precedence will terminate binary expression parsing |
854 | 855 |
855 return Token::Precedence(tok); | 856 return i::Token::Precedence(tok); |
856 } | 857 } |
857 | 858 |
858 | 859 |
859 // Precedence >= 4 | 860 // Precedence >= 4 |
860 template <typename Scanner, typename Log> | 861 template <typename Scanner, typename Log> |
861 Expression PreParser<Scanner, Log>::ParseBinaryExpression(int prec, | 862 Expression PreParser<Scanner, Log>::ParseBinaryExpression(int prec, |
862 bool accept_IN, | 863 bool accept_IN, |
863 bool* ok) { | 864 bool* ok) { |
864 Expression result = ParseUnaryExpression(CHECK_OK); | 865 Expression result = ParseUnaryExpression(CHECK_OK); |
865 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { | 866 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { |
(...skipping 15 matching lines...) Expand all Loading... |
881 // 'delete' UnaryExpression | 882 // 'delete' UnaryExpression |
882 // 'void' UnaryExpression | 883 // 'void' UnaryExpression |
883 // 'typeof' UnaryExpression | 884 // 'typeof' UnaryExpression |
884 // '++' UnaryExpression | 885 // '++' UnaryExpression |
885 // '--' UnaryExpression | 886 // '--' UnaryExpression |
886 // '+' UnaryExpression | 887 // '+' UnaryExpression |
887 // '-' UnaryExpression | 888 // '-' UnaryExpression |
888 // '~' UnaryExpression | 889 // '~' UnaryExpression |
889 // '!' UnaryExpression | 890 // '!' UnaryExpression |
890 | 891 |
891 Token::Value op = peek(); | 892 i::Token::Value op = peek(); |
892 if (Token::IsUnaryOp(op) || Token::IsCountOp(op)) { | 893 if (i::Token::IsUnaryOp(op) || i::Token::IsCountOp(op)) { |
893 op = Next(); | 894 op = Next(); |
894 ParseUnaryExpression(ok); | 895 ParseUnaryExpression(ok); |
895 return kUnknownExpression; | 896 return kUnknownExpression; |
896 } else { | 897 } else { |
897 return ParsePostfixExpression(ok); | 898 return ParsePostfixExpression(ok); |
898 } | 899 } |
899 } | 900 } |
900 | 901 |
901 | 902 |
902 template <typename Scanner, typename Log> | 903 template <typename Scanner, typename Log> |
903 Expression PreParser<Scanner, Log>::ParsePostfixExpression(bool* ok) { | 904 Expression PreParser<Scanner, Log>::ParsePostfixExpression(bool* ok) { |
904 // PostfixExpression :: | 905 // PostfixExpression :: |
905 // LeftHandSideExpression ('++' | '--')? | 906 // LeftHandSideExpression ('++' | '--')? |
906 | 907 |
907 Expression expression = ParseLeftHandSideExpression(CHECK_OK); | 908 Expression expression = ParseLeftHandSideExpression(CHECK_OK); |
908 if (!scanner_->has_line_terminator_before_next() && | 909 if (!scanner_->has_line_terminator_before_next() && |
909 Token::IsCountOp(peek())) { | 910 i::Token::IsCountOp(peek())) { |
910 Next(); | 911 Next(); |
911 return kUnknownExpression; | 912 return kUnknownExpression; |
912 } | 913 } |
913 return expression; | 914 return expression; |
914 } | 915 } |
915 | 916 |
916 | 917 |
917 template <typename Scanner, typename Log> | 918 template <typename Scanner, typename Log> |
918 Expression PreParser<Scanner, Log>::ParseLeftHandSideExpression(bool* ok) { | 919 Expression PreParser<Scanner, Log>::ParseLeftHandSideExpression(bool* ok) { |
919 // LeftHandSideExpression :: | 920 // LeftHandSideExpression :: |
920 // (NewExpression | MemberExpression) ... | 921 // (NewExpression | MemberExpression) ... |
921 | 922 |
922 Expression result; | 923 Expression result; |
923 if (peek() == Token::NEW) { | 924 if (peek() == i::Token::NEW) { |
924 result = ParseNewExpression(CHECK_OK); | 925 result = ParseNewExpression(CHECK_OK); |
925 } else { | 926 } else { |
926 result = ParseMemberExpression(CHECK_OK); | 927 result = ParseMemberExpression(CHECK_OK); |
927 } | 928 } |
928 | 929 |
929 while (true) { | 930 while (true) { |
930 switch (peek()) { | 931 switch (peek()) { |
931 case Token::LBRACK: { | 932 case i::Token::LBRACK: { |
932 Consume(Token::LBRACK); | 933 Consume(i::Token::LBRACK); |
933 ParseExpression(true, CHECK_OK); | 934 ParseExpression(true, CHECK_OK); |
934 Expect(Token::RBRACK, CHECK_OK); | 935 Expect(i::Token::RBRACK, CHECK_OK); |
935 if (result == kThisExpression) { | 936 if (result == kThisExpression) { |
936 result = kThisPropertyExpression; | 937 result = kThisPropertyExpression; |
937 } else { | 938 } else { |
938 result = kUnknownExpression; | 939 result = kUnknownExpression; |
939 } | 940 } |
940 break; | 941 break; |
941 } | 942 } |
942 | 943 |
943 case Token::LPAREN: { | 944 case i::Token::LPAREN: { |
944 ParseArguments(CHECK_OK); | 945 ParseArguments(CHECK_OK); |
945 result = kUnknownExpression; | 946 result = kUnknownExpression; |
946 break; | 947 break; |
947 } | 948 } |
948 | 949 |
949 case Token::PERIOD: { | 950 case i::Token::PERIOD: { |
950 Consume(Token::PERIOD); | 951 Consume(i::Token::PERIOD); |
951 ParseIdentifierName(CHECK_OK); | 952 ParseIdentifierName(CHECK_OK); |
952 if (result == kThisExpression) { | 953 if (result == kThisExpression) { |
953 result = kThisPropertyExpression; | 954 result = kThisPropertyExpression; |
954 } else { | 955 } else { |
955 result = kUnknownExpression; | 956 result = kUnknownExpression; |
956 } | 957 } |
957 break; | 958 break; |
958 } | 959 } |
959 | 960 |
960 default: | 961 default: |
(...skipping 11 matching lines...) Expand all Loading... |
972 // The grammar for new expressions is pretty warped. The keyword | 973 // The grammar for new expressions is pretty warped. The keyword |
973 // 'new' can either be a part of the new expression (where it isn't | 974 // 'new' can either be a part of the new expression (where it isn't |
974 // followed by an argument list) or a part of the member expression, | 975 // followed by an argument list) or a part of the member expression, |
975 // where it must be followed by an argument list. To accommodate | 976 // where it must be followed by an argument list. To accommodate |
976 // this, we parse the 'new' keywords greedily and keep track of how | 977 // this, we parse the 'new' keywords greedily and keep track of how |
977 // many we have parsed. This information is then passed on to the | 978 // many we have parsed. This information is then passed on to the |
978 // member expression parser, which is only allowed to match argument | 979 // member expression parser, which is only allowed to match argument |
979 // lists as long as it has 'new' prefixes left | 980 // lists as long as it has 'new' prefixes left |
980 unsigned new_count = 0; | 981 unsigned new_count = 0; |
981 do { | 982 do { |
982 Consume(Token::NEW); | 983 Consume(i::Token::NEW); |
983 new_count++; | 984 new_count++; |
984 } while (peek() == Token::NEW); | 985 } while (peek() == i::Token::NEW); |
985 | 986 |
986 return ParseMemberWithNewPrefixesExpression(new_count, ok); | 987 return ParseMemberWithNewPrefixesExpression(new_count, ok); |
987 } | 988 } |
988 | 989 |
989 | 990 |
990 template <typename Scanner, typename Log> | 991 template <typename Scanner, typename Log> |
991 Expression PreParser<Scanner, Log>::ParseMemberExpression(bool* ok) { | 992 Expression PreParser<Scanner, Log>::ParseMemberExpression(bool* ok) { |
992 return ParseMemberWithNewPrefixesExpression(0, ok); | 993 return ParseMemberWithNewPrefixesExpression(0, ok); |
993 } | 994 } |
994 | 995 |
995 | 996 |
996 template <typename Scanner, typename Log> | 997 template <typename Scanner, typename Log> |
997 Expression PreParser<Scanner, Log>::ParseMemberWithNewPrefixesExpression( | 998 Expression PreParser<Scanner, Log>::ParseMemberWithNewPrefixesExpression( |
998 unsigned new_count, bool* ok) { | 999 unsigned new_count, bool* ok) { |
999 // MemberExpression :: | 1000 // MemberExpression :: |
1000 // (PrimaryExpression | FunctionLiteral) | 1001 // (PrimaryExpression | FunctionLiteral) |
1001 // ('[' Expression ']' | '.' Identifier | Arguments)* | 1002 // ('[' Expression ']' | '.' Identifier | Arguments)* |
1002 | 1003 |
1003 // Parse the initial primary or function expression. | 1004 // Parse the initial primary or function expression. |
1004 Expression result = NULL; | 1005 Expression result = NULL; |
1005 if (peek() == Token::FUNCTION) { | 1006 if (peek() == i::Token::FUNCTION) { |
1006 Consume(Token::FUNCTION); | 1007 Consume(i::Token::FUNCTION); |
1007 if (peek() == Token::IDENTIFIER) { | 1008 if (peek() == i::Token::IDENTIFIER) { |
1008 ParseIdentifier(CHECK_OK); | 1009 ParseIdentifier(CHECK_OK); |
1009 } | 1010 } |
1010 result = ParseFunctionLiteral(CHECK_OK); | 1011 result = ParseFunctionLiteral(CHECK_OK); |
1011 } else { | 1012 } else { |
1012 result = ParsePrimaryExpression(CHECK_OK); | 1013 result = ParsePrimaryExpression(CHECK_OK); |
1013 } | 1014 } |
1014 | 1015 |
1015 while (true) { | 1016 while (true) { |
1016 switch (peek()) { | 1017 switch (peek()) { |
1017 case Token::LBRACK: { | 1018 case i::Token::LBRACK: { |
1018 Consume(Token::LBRACK); | 1019 Consume(i::Token::LBRACK); |
1019 ParseExpression(true, CHECK_OK); | 1020 ParseExpression(true, CHECK_OK); |
1020 Expect(Token::RBRACK, CHECK_OK); | 1021 Expect(i::Token::RBRACK, CHECK_OK); |
1021 if (result == kThisExpression) { | 1022 if (result == kThisExpression) { |
1022 result = kThisPropertyExpression; | 1023 result = kThisPropertyExpression; |
1023 } else { | 1024 } else { |
1024 result = kUnknownExpression; | 1025 result = kUnknownExpression; |
1025 } | 1026 } |
1026 break; | 1027 break; |
1027 } | 1028 } |
1028 case Token::PERIOD: { | 1029 case i::Token::PERIOD: { |
1029 Consume(Token::PERIOD); | 1030 Consume(i::Token::PERIOD); |
1030 ParseIdentifierName(CHECK_OK); | 1031 ParseIdentifierName(CHECK_OK); |
1031 if (result == kThisExpression) { | 1032 if (result == kThisExpression) { |
1032 result = kThisPropertyExpression; | 1033 result = kThisPropertyExpression; |
1033 } else { | 1034 } else { |
1034 result = kUnknownExpression; | 1035 result = kUnknownExpression; |
1035 } | 1036 } |
1036 break; | 1037 break; |
1037 } | 1038 } |
1038 case Token::LPAREN: { | 1039 case i::Token::LPAREN: { |
1039 if (new_count == 0) return result; | 1040 if (new_count == 0) return result; |
1040 // Consume one of the new prefixes (already parsed). | 1041 // Consume one of the new prefixes (already parsed). |
1041 ParseArguments(CHECK_OK); | 1042 ParseArguments(CHECK_OK); |
1042 new_count--; | 1043 new_count--; |
1043 result = kUnknownExpression; | 1044 result = kUnknownExpression; |
1044 break; | 1045 break; |
1045 } | 1046 } |
1046 default: | 1047 default: |
1047 return result; | 1048 return result; |
1048 } | 1049 } |
(...skipping 11 matching lines...) Expand all Loading... |
1060 // Identifier | 1061 // Identifier |
1061 // Number | 1062 // Number |
1062 // String | 1063 // String |
1063 // ArrayLiteral | 1064 // ArrayLiteral |
1064 // ObjectLiteral | 1065 // ObjectLiteral |
1065 // RegExpLiteral | 1066 // RegExpLiteral |
1066 // '(' Expression ')' | 1067 // '(' Expression ')' |
1067 | 1068 |
1068 Expression result = kUnknownExpression; | 1069 Expression result = kUnknownExpression; |
1069 switch (peek()) { | 1070 switch (peek()) { |
1070 case Token::THIS: { | 1071 case i::Token::THIS: { |
1071 Next(); | 1072 Next(); |
1072 result = kThisExpression; | 1073 result = kThisExpression; |
1073 break; | 1074 break; |
1074 } | 1075 } |
1075 | 1076 |
1076 case Token::IDENTIFIER: { | 1077 case i::Token::IDENTIFIER: { |
1077 ParseIdentifier(CHECK_OK); | 1078 ParseIdentifier(CHECK_OK); |
1078 result = kIdentifierExpression; | 1079 result = kIdentifierExpression; |
1079 break; | 1080 break; |
1080 } | 1081 } |
1081 | 1082 |
1082 case Token::NULL_LITERAL: | 1083 case i::Token::NULL_LITERAL: |
1083 case Token::TRUE_LITERAL: | 1084 case i::Token::TRUE_LITERAL: |
1084 case Token::FALSE_LITERAL: | 1085 case i::Token::FALSE_LITERAL: |
1085 case Token::NUMBER: { | 1086 case i::Token::NUMBER: { |
1086 Next(); | 1087 Next(); |
1087 break; | 1088 break; |
1088 } | 1089 } |
1089 case Token::STRING: { | 1090 case i::Token::STRING: { |
1090 Next(); | 1091 Next(); |
1091 result = GetStringSymbol(); | 1092 result = GetStringSymbol(); |
1092 break; | 1093 break; |
1093 } | 1094 } |
1094 | 1095 |
1095 case Token::ASSIGN_DIV: | 1096 case i::Token::ASSIGN_DIV: |
1096 result = ParseRegExpLiteral(true, CHECK_OK); | 1097 result = ParseRegExpLiteral(true, CHECK_OK); |
1097 break; | 1098 break; |
1098 | 1099 |
1099 case Token::DIV: | 1100 case i::Token::DIV: |
1100 result = ParseRegExpLiteral(false, CHECK_OK); | 1101 result = ParseRegExpLiteral(false, CHECK_OK); |
1101 break; | 1102 break; |
1102 | 1103 |
1103 case Token::LBRACK: | 1104 case i::Token::LBRACK: |
1104 result = ParseArrayLiteral(CHECK_OK); | 1105 result = ParseArrayLiteral(CHECK_OK); |
1105 break; | 1106 break; |
1106 | 1107 |
1107 case Token::LBRACE: | 1108 case i::Token::LBRACE: |
1108 result = ParseObjectLiteral(CHECK_OK); | 1109 result = ParseObjectLiteral(CHECK_OK); |
1109 break; | 1110 break; |
1110 | 1111 |
1111 case Token::LPAREN: | 1112 case i::Token::LPAREN: |
1112 Consume(Token::LPAREN); | 1113 Consume(i::Token::LPAREN); |
1113 result = ParseExpression(true, CHECK_OK); | 1114 result = ParseExpression(true, CHECK_OK); |
1114 Expect(Token::RPAREN, CHECK_OK); | 1115 Expect(i::Token::RPAREN, CHECK_OK); |
1115 if (result == kIdentifierExpression) result = kUnknownExpression; | 1116 if (result == kIdentifierExpression) result = kUnknownExpression; |
1116 break; | 1117 break; |
1117 | 1118 |
1118 case Token::MOD: | 1119 case i::Token::MOD: |
1119 result = ParseV8Intrinsic(CHECK_OK); | 1120 result = ParseV8Intrinsic(CHECK_OK); |
1120 break; | 1121 break; |
1121 | 1122 |
1122 default: { | 1123 default: { |
1123 Next(); | 1124 Next(); |
1124 *ok = false; | 1125 *ok = false; |
1125 return kUnknownExpression; | 1126 return kUnknownExpression; |
1126 } | 1127 } |
1127 } | 1128 } |
1128 | 1129 |
1129 return result; | 1130 return result; |
1130 } | 1131 } |
1131 | 1132 |
1132 | 1133 |
1133 template <typename Scanner, typename Log> | 1134 template <typename Scanner, typename Log> |
1134 Expression PreParser<Scanner, Log>::ParseArrayLiteral(bool* ok) { | 1135 Expression PreParser<Scanner, Log>::ParseArrayLiteral(bool* ok) { |
1135 // ArrayLiteral :: | 1136 // ArrayLiteral :: |
1136 // '[' Expression? (',' Expression?)* ']' | 1137 // '[' Expression? (',' Expression?)* ']' |
1137 Expect(Token::LBRACK, CHECK_OK); | 1138 Expect(i::Token::LBRACK, CHECK_OK); |
1138 while (peek() != Token::RBRACK) { | 1139 while (peek() != i::Token::RBRACK) { |
1139 if (peek() != Token::COMMA) { | 1140 if (peek() != i::Token::COMMA) { |
1140 ParseAssignmentExpression(true, CHECK_OK); | 1141 ParseAssignmentExpression(true, CHECK_OK); |
1141 } | 1142 } |
1142 if (peek() != Token::RBRACK) { | 1143 if (peek() != i::Token::RBRACK) { |
1143 Expect(Token::COMMA, CHECK_OK); | 1144 Expect(i::Token::COMMA, CHECK_OK); |
1144 } | 1145 } |
1145 } | 1146 } |
1146 Expect(Token::RBRACK, CHECK_OK); | 1147 Expect(i::Token::RBRACK, CHECK_OK); |
1147 | 1148 |
1148 scope_->NextMaterializedLiteralIndex(); | 1149 scope_->NextMaterializedLiteralIndex(); |
1149 return kUnknownExpression; | 1150 return kUnknownExpression; |
1150 } | 1151 } |
1151 | 1152 |
1152 | 1153 |
1153 template <typename Scanner, typename Log> | 1154 template <typename Scanner, typename Log> |
1154 Expression PreParser<Scanner, Log>::ParseObjectLiteral(bool* ok) { | 1155 Expression PreParser<Scanner, Log>::ParseObjectLiteral(bool* ok) { |
1155 // ObjectLiteral :: | 1156 // ObjectLiteral :: |
1156 // '{' ( | 1157 // '{' ( |
1157 // ((IdentifierName | String | Number) ':' AssignmentExpression) | 1158 // ((IdentifierName | String | Number) ':' AssignmentExpression) |
1158 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | 1159 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
1159 // )*[','] '}' | 1160 // )*[','] '}' |
1160 | 1161 |
1161 Expect(Token::LBRACE, CHECK_OK); | 1162 Expect(i::Token::LBRACE, CHECK_OK); |
1162 while (peek() != Token::RBRACE) { | 1163 while (peek() != i::Token::RBRACE) { |
1163 Token::Value next = peek(); | 1164 i::Token::Value next = peek(); |
1164 switch (next) { | 1165 switch (next) { |
1165 case Token::IDENTIFIER: { | 1166 case i::Token::IDENTIFIER: { |
1166 bool is_getter = false; | 1167 bool is_getter = false; |
1167 bool is_setter = false; | 1168 bool is_setter = false; |
1168 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | 1169 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
1169 if ((is_getter || is_setter) && peek() != Token::COLON) { | 1170 if ((is_getter || is_setter) && peek() != i::Token::COLON) { |
1170 Token::Value name = Next(); | 1171 i::Token::Value name = Next(); |
1171 if (name != Token::IDENTIFIER && | 1172 if (name != i::Token::IDENTIFIER && |
1172 name != Token::NUMBER && | 1173 name != i::Token::NUMBER && |
1173 name != Token::STRING && | 1174 name != i::Token::STRING && |
1174 !Token::IsKeyword(name)) { | 1175 !i::Token::IsKeyword(name)) { |
1175 *ok = false; | 1176 *ok = false; |
1176 return kUnknownExpression; | 1177 return kUnknownExpression; |
1177 } | 1178 } |
1178 ParseFunctionLiteral(CHECK_OK); | 1179 ParseFunctionLiteral(CHECK_OK); |
1179 if (peek() != Token::RBRACE) { | 1180 if (peek() != i::Token::RBRACE) { |
1180 Expect(Token::COMMA, CHECK_OK); | 1181 Expect(i::Token::COMMA, CHECK_OK); |
1181 } | 1182 } |
1182 continue; // restart the while | 1183 continue; // restart the while |
1183 } | 1184 } |
1184 break; | 1185 break; |
1185 } | 1186 } |
1186 case Token::STRING: | 1187 case i::Token::STRING: |
1187 Consume(next); | 1188 Consume(next); |
1188 GetStringSymbol(); | 1189 GetStringSymbol(); |
1189 break; | 1190 break; |
1190 case Token::NUMBER: | 1191 case i::Token::NUMBER: |
1191 Consume(next); | 1192 Consume(next); |
1192 break; | 1193 break; |
1193 default: | 1194 default: |
1194 if (Token::IsKeyword(next)) { | 1195 if (i::Token::IsKeyword(next)) { |
1195 Consume(next); | 1196 Consume(next); |
1196 } else { | 1197 } else { |
1197 // Unexpected token. | 1198 // Unexpected token. |
1198 *ok = false; | 1199 *ok = false; |
1199 return kUnknownExpression; | 1200 return kUnknownExpression; |
1200 } | 1201 } |
1201 } | 1202 } |
1202 | 1203 |
1203 Expect(Token::COLON, CHECK_OK); | 1204 Expect(i::Token::COLON, CHECK_OK); |
1204 ParseAssignmentExpression(true, CHECK_OK); | 1205 ParseAssignmentExpression(true, CHECK_OK); |
1205 | 1206 |
1206 // TODO(1240767): Consider allowing trailing comma. | 1207 // TODO(1240767): Consider allowing trailing comma. |
1207 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | 1208 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK); |
1208 } | 1209 } |
1209 Expect(Token::RBRACE, CHECK_OK); | 1210 Expect(i::Token::RBRACE, CHECK_OK); |
1210 | 1211 |
1211 scope_->NextMaterializedLiteralIndex(); | 1212 scope_->NextMaterializedLiteralIndex(); |
1212 return kUnknownExpression; | 1213 return kUnknownExpression; |
1213 } | 1214 } |
1214 | 1215 |
1215 | 1216 |
1216 template <typename Scanner, typename Log> | 1217 template <typename Scanner, typename Log> |
1217 Expression PreParser<Scanner, Log>::ParseRegExpLiteral(bool seen_equal, | 1218 Expression PreParser<Scanner, Log>::ParseRegExpLiteral(bool seen_equal, |
1218 bool* ok) { | 1219 bool* ok) { |
1219 if (!scanner_->ScanRegExpPattern(seen_equal)) { | 1220 if (!scanner_->ScanRegExpPattern(seen_equal)) { |
(...skipping 18 matching lines...) Expand all Loading... |
1238 Next(); | 1239 Next(); |
1239 return kUnknownExpression; | 1240 return kUnknownExpression; |
1240 } | 1241 } |
1241 | 1242 |
1242 | 1243 |
1243 template <typename Scanner, typename Log> | 1244 template <typename Scanner, typename Log> |
1244 Arguments PreParser<Scanner, Log>::ParseArguments(bool* ok) { | 1245 Arguments PreParser<Scanner, Log>::ParseArguments(bool* ok) { |
1245 // Arguments :: | 1246 // Arguments :: |
1246 // '(' (AssignmentExpression)*[','] ')' | 1247 // '(' (AssignmentExpression)*[','] ')' |
1247 | 1248 |
1248 Expect(Token::LPAREN, CHECK_OK); | 1249 Expect(i::Token::LPAREN, CHECK_OK); |
1249 bool done = (peek() == Token::RPAREN); | 1250 bool done = (peek() == i::Token::RPAREN); |
1250 int argc = 0; | 1251 int argc = 0; |
1251 while (!done) { | 1252 while (!done) { |
1252 ParseAssignmentExpression(true, CHECK_OK); | 1253 ParseAssignmentExpression(true, CHECK_OK); |
1253 argc++; | 1254 argc++; |
1254 done = (peek() == Token::RPAREN); | 1255 done = (peek() == i::Token::RPAREN); |
1255 if (!done) Expect(Token::COMMA, CHECK_OK); | 1256 if (!done) Expect(i::Token::COMMA, CHECK_OK); |
1256 } | 1257 } |
1257 Expect(Token::RPAREN, CHECK_OK); | 1258 Expect(i::Token::RPAREN, CHECK_OK); |
1258 return argc; | 1259 return argc; |
1259 } | 1260 } |
1260 | 1261 |
1261 | 1262 |
1262 template <typename Scanner, typename Log> | 1263 template <typename Scanner, typename Log> |
1263 Expression PreParser<Scanner, Log>::ParseFunctionLiteral(bool* ok) { | 1264 Expression PreParser<Scanner, Log>::ParseFunctionLiteral(bool* ok) { |
1264 // Function :: | 1265 // Function :: |
1265 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 1266 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
1266 | 1267 |
1267 // Parse function body. | 1268 // Parse function body. |
1268 ScopeType outer_scope_type = scope_->type(); | 1269 ScopeType outer_scope_type = scope_->type(); |
1269 bool inside_with = scope_->IsInsideWith(); | 1270 bool inside_with = scope_->IsInsideWith(); |
1270 Scope function_scope(&scope_, kFunctionScope); | 1271 Scope function_scope(&scope_, kFunctionScope); |
1271 | 1272 |
1272 // FormalParameterList :: | 1273 // FormalParameterList :: |
1273 // '(' (Identifier)*[','] ')' | 1274 // '(' (Identifier)*[','] ')' |
1274 Expect(Token::LPAREN, CHECK_OK); | 1275 Expect(i::Token::LPAREN, CHECK_OK); |
1275 bool done = (peek() == Token::RPAREN); | 1276 bool done = (peek() == i::Token::RPAREN); |
1276 while (!done) { | 1277 while (!done) { |
1277 ParseIdentifier(CHECK_OK); | 1278 ParseIdentifier(CHECK_OK); |
1278 done = (peek() == Token::RPAREN); | 1279 done = (peek() == i::Token::RPAREN); |
1279 if (!done) { | 1280 if (!done) { |
1280 Expect(Token::COMMA, CHECK_OK); | 1281 Expect(i::Token::COMMA, CHECK_OK); |
1281 } | 1282 } |
1282 } | 1283 } |
1283 Expect(Token::RPAREN, CHECK_OK); | 1284 Expect(i::Token::RPAREN, CHECK_OK); |
1284 | 1285 |
1285 Expect(Token::LBRACE, CHECK_OK); | 1286 Expect(i::Token::LBRACE, CHECK_OK); |
1286 int function_block_pos = scanner_->location().beg_pos; | 1287 int function_block_pos = scanner_->location().beg_pos; |
1287 | 1288 |
1288 // Determine if the function will be lazily compiled. | 1289 // Determine if the function will be lazily compiled. |
1289 // Currently only happens to top-level functions. | 1290 // Currently only happens to top-level functions. |
1290 // Optimistically assume that all top-level functions are lazily compiled. | 1291 // Optimistically assume that all top-level functions are lazily compiled. |
1291 bool is_lazily_compiled = | 1292 bool is_lazily_compiled = |
1292 (outer_scope_type == kTopLevelScope && !inside_with && allow_lazy_); | 1293 (outer_scope_type == kTopLevelScope && !inside_with && allow_lazy_); |
1293 | 1294 |
1294 if (is_lazily_compiled) { | 1295 if (is_lazily_compiled) { |
1295 log_->PauseRecording(); | 1296 log_->PauseRecording(); |
1296 ParseSourceElements(Token::RBRACE, ok); | 1297 ParseSourceElements(i::Token::RBRACE, ok); |
1297 log_->ResumeRecording(); | 1298 log_->ResumeRecording(); |
1298 if (!*ok) return kUnknownExpression; | 1299 if (!*ok) return kUnknownExpression; |
1299 | 1300 |
1300 Expect(Token::RBRACE, CHECK_OK); | 1301 Expect(i::Token::RBRACE, CHECK_OK); |
1301 | 1302 |
1302 int end_pos = scanner_->location().end_pos; | 1303 int end_pos = scanner_->location().end_pos; |
1303 log_->LogFunction(function_block_pos, end_pos, | 1304 log_->LogFunction(function_block_pos, end_pos, |
1304 function_scope.materialized_literal_count(), | 1305 function_scope.materialized_literal_count(), |
1305 function_scope.expected_properties()); | 1306 function_scope.expected_properties()); |
1306 } else { | 1307 } else { |
1307 ParseSourceElements(Token::RBRACE, CHECK_OK); | 1308 ParseSourceElements(i::Token::RBRACE, CHECK_OK); |
1308 Expect(Token::RBRACE, CHECK_OK); | 1309 Expect(i::Token::RBRACE, CHECK_OK); |
1309 } | 1310 } |
1310 return kUnknownExpression; | 1311 return kUnknownExpression; |
1311 } | 1312 } |
1312 | 1313 |
1313 | 1314 |
1314 template <typename Scanner, typename Log> | 1315 template <typename Scanner, typename Log> |
1315 Expression PreParser<Scanner, Log>::ParseV8Intrinsic(bool* ok) { | 1316 Expression PreParser<Scanner, Log>::ParseV8Intrinsic(bool* ok) { |
1316 // CallRuntime :: | 1317 // CallRuntime :: |
1317 // '%' Identifier Arguments | 1318 // '%' Identifier Arguments |
1318 | 1319 |
1319 Expect(Token::MOD, CHECK_OK); | 1320 Expect(i::Token::MOD, CHECK_OK); |
1320 ParseIdentifier(CHECK_OK); | 1321 ParseIdentifier(CHECK_OK); |
1321 ParseArguments(CHECK_OK); | 1322 ParseArguments(CHECK_OK); |
1322 | 1323 |
1323 return kUnknownExpression; | 1324 return kUnknownExpression; |
1324 } | 1325 } |
1325 | 1326 |
1326 | 1327 |
1327 template <typename Scanner, typename Log> | 1328 template <typename Scanner, typename Log> |
1328 void PreParser<Scanner, Log>::ExpectSemicolon(bool* ok) { | 1329 void PreParser<Scanner, Log>::ExpectSemicolon(bool* ok) { |
1329 // Check for automatic semicolon insertion according to | 1330 // Check for automatic semicolon insertion according to |
1330 // the rules given in ECMA-262, section 7.9, page 21. | 1331 // the rules given in ECMA-262, section 7.9, page 21. |
1331 Token::Value tok = peek(); | 1332 i::Token::Value tok = peek(); |
1332 if (tok == Token::SEMICOLON) { | 1333 if (tok == i::Token::SEMICOLON) { |
1333 Next(); | 1334 Next(); |
1334 return; | 1335 return; |
1335 } | 1336 } |
1336 if (scanner_->has_line_terminator_before_next() || | 1337 if (scanner_->has_line_terminator_before_next() || |
1337 tok == Token::RBRACE || | 1338 tok == i::Token::RBRACE || |
1338 tok == Token::EOS) { | 1339 tok == i::Token::EOS) { |
1339 return; | 1340 return; |
1340 } | 1341 } |
1341 Expect(Token::SEMICOLON, ok); | 1342 Expect(i::Token::SEMICOLON, ok); |
1342 } | 1343 } |
1343 | 1344 |
1344 | 1345 |
1345 template <typename Scanner, typename Log> | 1346 template <typename Scanner, typename Log> |
1346 Identifier PreParser<Scanner, Log>::GetIdentifierSymbol() { | 1347 Identifier PreParser<Scanner, Log>::GetIdentifierSymbol() { |
1347 const char* literal_chars = scanner_->literal_string(); | 1348 const char* literal_chars = scanner_->literal_string(); |
1348 int literal_length = scanner_->literal_length(); | 1349 int literal_length = scanner_->literal_length(); |
1349 int identifier_pos = scanner_->location().beg_pos; | 1350 int identifier_pos = scanner_->location().beg_pos; |
1350 | 1351 |
1351 log_->LogSymbol(identifier_pos, literal_chars, literal_length); | 1352 log_->LogSymbol(identifier_pos, literal_chars, literal_length); |
1352 | 1353 |
1353 return kUnknownExpression; | 1354 return kUnknownExpression; |
1354 } | 1355 } |
1355 | 1356 |
1356 | 1357 |
1357 template <typename Scanner, typename Log> | 1358 template <typename Scanner, typename Log> |
1358 Expression PreParser<Scanner, Log>::GetStringSymbol() { | 1359 Expression PreParser<Scanner, Log>::GetStringSymbol() { |
1359 const char* literal_chars = scanner_->literal_string(); | 1360 const char* literal_chars = scanner_->literal_string(); |
1360 int literal_length = scanner_->literal_length(); | 1361 int literal_length = scanner_->literal_length(); |
1361 | 1362 |
1362 int literal_position = scanner_->location().beg_pos; | 1363 int literal_position = scanner_->location().beg_pos; |
1363 log_->LogSymbol(literal_position, literal_chars, literal_length); | 1364 log_->LogSymbol(literal_position, literal_chars, literal_length); |
1364 | 1365 |
1365 return kUnknownExpression; | 1366 return kUnknownExpression; |
1366 } | 1367 } |
1367 | 1368 |
1368 | 1369 |
1369 template <typename Scanner, typename Log> | 1370 template <typename Scanner, typename Log> |
1370 Identifier PreParser<Scanner, Log>::ParseIdentifier(bool* ok) { | 1371 Identifier PreParser<Scanner, Log>::ParseIdentifier(bool* ok) { |
1371 Expect(Token::IDENTIFIER, ok); | 1372 Expect(i::Token::IDENTIFIER, ok); |
1372 return GetIdentifierSymbol(); | 1373 return GetIdentifierSymbol(); |
1373 } | 1374 } |
1374 | 1375 |
1375 | 1376 |
1376 template <typename Scanner, typename Log> | 1377 template <typename Scanner, typename Log> |
1377 Identifier PreParser<Scanner, Log>::ParseIdentifierName(bool* ok) { | 1378 Identifier PreParser<Scanner, Log>::ParseIdentifierName(bool* ok) { |
1378 Token::Value next = Next(); | 1379 i::Token::Value next = Next(); |
1379 if (Token::IsKeyword(next)) { | 1380 if (i::Token::IsKeyword(next)) { |
1380 int pos = scanner_->location().beg_pos; | 1381 int pos = scanner_->location().beg_pos; |
1381 const char* keyword = Token::String(next); | 1382 const char* keyword = i::Token::String(next); |
1382 log_->LogSymbol(pos, keyword, strlen(keyword)); | 1383 log_->LogSymbol(pos, keyword, strlen(keyword)); |
1383 return kUnknownExpression; | 1384 return kUnknownExpression; |
1384 } | 1385 } |
1385 if (next == Token::IDENTIFIER) { | 1386 if (next == i::Token::IDENTIFIER) { |
1386 return GetIdentifierSymbol(); | 1387 return GetIdentifierSymbol(); |
1387 } | 1388 } |
1388 *ok = false; | 1389 *ok = false; |
1389 return kUnknownIdentifier; | 1390 return kUnknownIdentifier; |
1390 } | 1391 } |
1391 | 1392 |
1392 | 1393 |
1393 // This function reads an identifier and determines whether or not it | 1394 // This function reads an identifier and determines whether or not it |
1394 // is 'get' or 'set'. The reason for not using ParseIdentifier and | 1395 // is 'get' or 'set'. The reason for not using ParseIdentifier and |
1395 // checking on the output is that this involves heap allocation which | 1396 // checking on the output is that this involves heap allocation which |
1396 // we can't do during preparsing. | 1397 // we can't do during preparsing. |
1397 template <typename Scanner, typename Log> | 1398 template <typename Scanner, typename Log> |
1398 Identifier PreParser<Scanner, Log>::ParseIdentifierOrGetOrSet(bool* is_get, | 1399 Identifier PreParser<Scanner, Log>::ParseIdentifierOrGetOrSet(bool* is_get, |
1399 bool* is_set, | 1400 bool* is_set, |
1400 bool* ok) { | 1401 bool* ok) { |
1401 Expect(Token::IDENTIFIER, CHECK_OK); | 1402 Expect(i::Token::IDENTIFIER, CHECK_OK); |
1402 if (scanner_->literal_length() == 3) { | 1403 if (scanner_->literal_length() == 3) { |
1403 const char* token = scanner_->literal_string(); | 1404 const char* token = scanner_->literal_string(); |
1404 *is_get = strncmp(token, "get", 3) == 0; | 1405 *is_get = strncmp(token, "get", 3) == 0; |
1405 *is_set = !*is_get && strncmp(token, "set", 3) == 0; | 1406 *is_set = !*is_get && strncmp(token, "set", 3) == 0; |
1406 } | 1407 } |
1407 return GetIdentifierSymbol(); | 1408 return GetIdentifierSymbol(); |
1408 } | 1409 } |
1409 | 1410 |
1410 #undef CHECK_OK | 1411 #undef CHECK_OK |
1411 } } } // v8::internal::preparser | 1412 } } // v8::preparser |
1412 | 1413 |
1413 #endif // V8_PREPARSER_H | 1414 #endif // V8_PREPARSER_H |
OLD | NEW |