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