• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <cmath>
6 
7 #include "include/v8stdint.h"
8 
9 #include "src/allocation.h"
10 #include "src/base/logging.h"
11 #include "src/conversions-inl.h"
12 #include "src/conversions.h"
13 #include "src/globals.h"
14 #include "src/hashmap.h"
15 #include "src/list.h"
16 #include "src/preparse-data.h"
17 #include "src/preparse-data-format.h"
18 #include "src/preparser.h"
19 #include "src/unicode.h"
20 #include "src/utils.h"
21 
22 #if V8_LIBC_MSVCRT && (_MSC_VER < 1800)
23 namespace std {
24 
25 // Usually defined in math.h, but not in MSVC until VS2013+.
26 // Abstracted to work
27 int isfinite(double value);
28 
29 }  // namespace std
30 #endif
31 
32 namespace v8 {
33 namespace internal {
34 
35 class PreParserTraits::Checkpoint
36     : public ParserBase<PreParserTraits>::CheckpointBase {
37  public:
Checkpoint(ParserBase<PreParserTraits> * parser)38   explicit Checkpoint(ParserBase<PreParserTraits>* parser)
39       : ParserBase<PreParserTraits>::CheckpointBase(parser) {}
40 };
41 
ReportMessageAt(Scanner::Location location,const char * message,const char * arg,bool is_reference_error)42 void PreParserTraits::ReportMessageAt(Scanner::Location location,
43                                       const char* message,
44                                       const char* arg,
45                                       bool is_reference_error) {
46   ReportMessageAt(location.beg_pos,
47                   location.end_pos,
48                   message,
49                   arg,
50                   is_reference_error);
51 }
52 
53 
ReportMessageAt(int start_pos,int end_pos,const char * message,const char * arg,bool is_reference_error)54 void PreParserTraits::ReportMessageAt(int start_pos,
55                                       int end_pos,
56                                       const char* message,
57                                       const char* arg,
58                                       bool is_reference_error) {
59   pre_parser_->log_->LogMessage(start_pos, end_pos, message, arg,
60                                 is_reference_error);
61 }
62 
63 
GetSymbol(Scanner * scanner)64 PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
65   if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) {
66     return PreParserIdentifier::FutureReserved();
67   } else if (scanner->current_token() ==
68              Token::FUTURE_STRICT_RESERVED_WORD) {
69     return PreParserIdentifier::FutureStrictReserved();
70   } else if (scanner->current_token() == Token::LET) {
71     return PreParserIdentifier::Let();
72   } else if (scanner->current_token() == Token::YIELD) {
73     return PreParserIdentifier::Yield();
74   }
75   if (scanner->UnescapedLiteralMatches("eval", 4)) {
76     return PreParserIdentifier::Eval();
77   }
78   if (scanner->UnescapedLiteralMatches("arguments", 9)) {
79     return PreParserIdentifier::Arguments();
80   }
81   if (scanner->UnescapedLiteralMatches("prototype", 9)) {
82     return PreParserIdentifier::Prototype();
83   }
84   if (scanner->UnescapedLiteralMatches("constructor", 11)) {
85     return PreParserIdentifier::Constructor();
86   }
87   return PreParserIdentifier::Default();
88 }
89 
90 
GetNumberAsSymbol(Scanner * scanner)91 PreParserIdentifier PreParserTraits::GetNumberAsSymbol(Scanner* scanner) {
92   return PreParserIdentifier::Default();
93 }
94 
95 
ExpressionFromString(int pos,Scanner * scanner,PreParserFactory * factory)96 PreParserExpression PreParserTraits::ExpressionFromString(
97     int pos, Scanner* scanner, PreParserFactory* factory) {
98   if (scanner->UnescapedLiteralMatches("use strict", 10)) {
99     return PreParserExpression::UseStrictStringLiteral();
100   }
101   return PreParserExpression::StringLiteral();
102 }
103 
104 
ParseV8Intrinsic(bool * ok)105 PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
106   return pre_parser_->ParseV8Intrinsic(ok);
107 }
108 
109 
ParseFunctionLiteral(PreParserIdentifier name,Scanner::Location function_name_location,bool name_is_strict_reserved,FunctionKind kind,int function_token_position,FunctionLiteral::FunctionType type,FunctionLiteral::ArityRestriction arity_restriction,bool * ok)110 PreParserExpression PreParserTraits::ParseFunctionLiteral(
111     PreParserIdentifier name, Scanner::Location function_name_location,
112     bool name_is_strict_reserved, FunctionKind kind,
113     int function_token_position, FunctionLiteral::FunctionType type,
114     FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
115   return pre_parser_->ParseFunctionLiteral(
116       name, function_name_location, name_is_strict_reserved, kind,
117       function_token_position, type, arity_restriction, ok);
118 }
119 
120 
PreParseLazyFunction(StrictMode strict_mode,bool is_generator,ParserRecorder * log)121 PreParser::PreParseResult PreParser::PreParseLazyFunction(
122     StrictMode strict_mode, bool is_generator, ParserRecorder* log) {
123   log_ = log;
124   // Lazy functions always have trivial outer scopes (no with/catch scopes).
125   PreParserScope top_scope(scope_, GLOBAL_SCOPE);
126   FunctionState top_state(&function_state_, &scope_, &top_scope, NULL,
127                           this->ast_value_factory());
128   scope_->SetStrictMode(strict_mode);
129   PreParserScope function_scope(scope_, FUNCTION_SCOPE);
130   FunctionState function_state(&function_state_, &scope_, &function_scope, NULL,
131                                this->ast_value_factory());
132   function_state.set_is_generator(is_generator);
133   DCHECK_EQ(Token::LBRACE, scanner()->current_token());
134   bool ok = true;
135   int start_position = peek_position();
136   ParseLazyFunctionLiteralBody(&ok);
137   if (stack_overflow()) return kPreParseStackOverflow;
138   if (!ok) {
139     ReportUnexpectedToken(scanner()->current_token());
140   } else {
141     DCHECK_EQ(Token::RBRACE, scanner()->peek());
142     if (scope_->strict_mode() == STRICT) {
143       int end_pos = scanner()->location().end_pos;
144       CheckOctalLiteral(start_position, end_pos, &ok);
145     }
146   }
147   return kPreParseSuccess;
148 }
149 
150 
151 // Preparsing checks a JavaScript program and emits preparse-data that helps
152 // a later parsing to be faster.
153 // See preparser-data.h for the data.
154 
155 // The PreParser checks that the syntax follows the grammar for JavaScript,
156 // and collects some information about the program along the way.
157 // The grammar check is only performed in order to understand the program
158 // sufficiently to deduce some information about it, that can be used
159 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
160 // rather it is to speed up properly written and correct programs.
161 // That means that contextual checks (like a label being declared where
162 // it is used) are generally omitted.
163 
164 
165 #define CHECK_OK  ok);                      \
166   if (!*ok) return kUnknownSourceElements;  \
167   ((void)0
168 #define DUMMY )  // to make indentation work
169 #undef DUMMY
170 
171 
ParseSourceElement(bool * ok)172 PreParser::Statement PreParser::ParseSourceElement(bool* ok) {
173   // (Ecma 262 5th Edition, clause 14):
174   // SourceElement:
175   //    Statement
176   //    FunctionDeclaration
177   //
178   // In harmony mode we allow additionally the following productions
179   // SourceElement:
180   //    LetDeclaration
181   //    ConstDeclaration
182   //    GeneratorDeclaration
183 
184   switch (peek()) {
185     case Token::FUNCTION:
186       return ParseFunctionDeclaration(ok);
187     case Token::CLASS:
188       return ParseClassDeclaration(ok);
189     case Token::CONST:
190       return ParseVariableStatement(kSourceElement, ok);
191     case Token::LET:
192       DCHECK(allow_harmony_scoping());
193       if (strict_mode() == STRICT) {
194         return ParseVariableStatement(kSourceElement, ok);
195       }
196       // Fall through.
197     default:
198       return ParseStatement(ok);
199   }
200 }
201 
202 
ParseSourceElements(int end_token,bool * ok)203 PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
204                                                          bool* ok) {
205   // SourceElements ::
206   //   (Statement)* <end_token>
207 
208   bool directive_prologue = true;
209   while (peek() != end_token) {
210     if (directive_prologue && peek() != Token::STRING) {
211       directive_prologue = false;
212     }
213     Statement statement = ParseSourceElement(CHECK_OK);
214     if (directive_prologue) {
215       if (statement.IsUseStrictLiteral()) {
216         scope_->SetStrictMode(STRICT);
217       } else if (!statement.IsStringLiteral()) {
218         directive_prologue = false;
219       }
220     }
221   }
222   return kUnknownSourceElements;
223 }
224 
225 
226 #undef CHECK_OK
227 #define CHECK_OK  ok);                   \
228   if (!*ok) return Statement::Default();  \
229   ((void)0
230 #define DUMMY )  // to make indentation work
231 #undef DUMMY
232 
233 
ParseStatement(bool * ok)234 PreParser::Statement PreParser::ParseStatement(bool* ok) {
235   // Statement ::
236   //   Block
237   //   VariableStatement
238   //   EmptyStatement
239   //   ExpressionStatement
240   //   IfStatement
241   //   IterationStatement
242   //   ContinueStatement
243   //   BreakStatement
244   //   ReturnStatement
245   //   WithStatement
246   //   LabelledStatement
247   //   SwitchStatement
248   //   ThrowStatement
249   //   TryStatement
250   //   DebuggerStatement
251 
252   // Note: Since labels can only be used by 'break' and 'continue'
253   // statements, which themselves are only valid within blocks,
254   // iterations or 'switch' statements (i.e., BreakableStatements),
255   // labels can be simply ignored in all other cases; except for
256   // trivial labeled break statements 'label: break label' which is
257   // parsed into an empty statement.
258 
259   // Keep the source position of the statement
260   switch (peek()) {
261     case Token::LBRACE:
262       return ParseBlock(ok);
263 
264     case Token::SEMICOLON:
265       Next();
266       return Statement::Default();
267 
268     case Token::IF:
269       return ParseIfStatement(ok);
270 
271     case Token::DO:
272       return ParseDoWhileStatement(ok);
273 
274     case Token::WHILE:
275       return ParseWhileStatement(ok);
276 
277     case Token::FOR:
278       return ParseForStatement(ok);
279 
280     case Token::CONTINUE:
281       return ParseContinueStatement(ok);
282 
283     case Token::BREAK:
284       return ParseBreakStatement(ok);
285 
286     case Token::RETURN:
287       return ParseReturnStatement(ok);
288 
289     case Token::WITH:
290       return ParseWithStatement(ok);
291 
292     case Token::SWITCH:
293       return ParseSwitchStatement(ok);
294 
295     case Token::THROW:
296       return ParseThrowStatement(ok);
297 
298     case Token::TRY:
299       return ParseTryStatement(ok);
300 
301     case Token::FUNCTION: {
302       Scanner::Location start_location = scanner()->peek_location();
303       Statement statement = ParseFunctionDeclaration(CHECK_OK);
304       Scanner::Location end_location = scanner()->location();
305       if (strict_mode() == STRICT) {
306         PreParserTraits::ReportMessageAt(start_location.beg_pos,
307                                          end_location.end_pos,
308                                          "strict_function");
309         *ok = false;
310         return Statement::Default();
311       } else {
312         return statement;
313       }
314     }
315 
316     case Token::CLASS:
317       return ParseClassDeclaration(CHECK_OK);
318 
319     case Token::DEBUGGER:
320       return ParseDebuggerStatement(ok);
321 
322     case Token::VAR:
323     case Token::CONST:
324       return ParseVariableStatement(kStatement, ok);
325 
326     case Token::LET:
327       DCHECK(allow_harmony_scoping());
328       if (strict_mode() == STRICT) {
329         return ParseVariableStatement(kStatement, ok);
330       }
331       // Fall through.
332     default:
333       return ParseExpressionOrLabelledStatement(ok);
334   }
335 }
336 
337 
ParseFunctionDeclaration(bool * ok)338 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
339   // FunctionDeclaration ::
340   //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
341   // GeneratorDeclaration ::
342   //   'function' '*' Identifier '(' FormalParameterListopt ')'
343   //      '{' FunctionBody '}'
344   Expect(Token::FUNCTION, CHECK_OK);
345   int pos = position();
346   bool is_generator = Check(Token::MUL);
347   bool is_strict_reserved = false;
348   Identifier name = ParseIdentifierOrStrictReservedWord(
349       &is_strict_reserved, CHECK_OK);
350   ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
351                        is_generator ? FunctionKind::kGeneratorFunction
352                                     : FunctionKind::kNormalFunction,
353                        pos, FunctionLiteral::DECLARATION,
354                        FunctionLiteral::NORMAL_ARITY, CHECK_OK);
355   return Statement::FunctionDeclaration();
356 }
357 
358 
ParseClassDeclaration(bool * ok)359 PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
360   Expect(Token::CLASS, CHECK_OK);
361   int pos = position();
362   bool is_strict_reserved = false;
363   Identifier name =
364       ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
365   ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos,
366                     CHECK_OK);
367   return Statement::Default();
368 }
369 
370 
ParseBlock(bool * ok)371 PreParser::Statement PreParser::ParseBlock(bool* ok) {
372   // Block ::
373   //   '{' Statement* '}'
374 
375   // Note that a Block does not introduce a new execution scope!
376   // (ECMA-262, 3rd, 12.2)
377   //
378   Expect(Token::LBRACE, CHECK_OK);
379   while (peek() != Token::RBRACE) {
380     if (allow_harmony_scoping() && strict_mode() == STRICT) {
381       ParseSourceElement(CHECK_OK);
382     } else {
383       ParseStatement(CHECK_OK);
384     }
385   }
386   Expect(Token::RBRACE, ok);
387   return Statement::Default();
388 }
389 
390 
ParseVariableStatement(VariableDeclarationContext var_context,bool * ok)391 PreParser::Statement PreParser::ParseVariableStatement(
392     VariableDeclarationContext var_context,
393     bool* ok) {
394   // VariableStatement ::
395   //   VariableDeclarations ';'
396 
397   Statement result = ParseVariableDeclarations(var_context,
398                                                NULL,
399                                                NULL,
400                                                CHECK_OK);
401   ExpectSemicolon(CHECK_OK);
402   return result;
403 }
404 
405 
406 // If the variable declaration declares exactly one non-const
407 // variable, then *var is set to that variable. In all other cases,
408 // *var is untouched; in particular, it is the caller's responsibility
409 // to initialize it properly. This mechanism is also used for the parsing
410 // of 'for-in' loops.
ParseVariableDeclarations(VariableDeclarationContext var_context,VariableDeclarationProperties * decl_props,int * num_decl,bool * ok)411 PreParser::Statement PreParser::ParseVariableDeclarations(
412     VariableDeclarationContext var_context,
413     VariableDeclarationProperties* decl_props,
414     int* num_decl,
415     bool* ok) {
416   // VariableDeclarations ::
417   //   ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
418   //
419   // The ES6 Draft Rev3 specifies the following grammar for const declarations
420   //
421   // ConstDeclaration ::
422   //   const ConstBinding (',' ConstBinding)* ';'
423   // ConstBinding ::
424   //   Identifier '=' AssignmentExpression
425   //
426   // TODO(ES6):
427   // ConstBinding ::
428   //   BindingPattern '=' AssignmentExpression
429   bool require_initializer = false;
430   if (peek() == Token::VAR) {
431     Consume(Token::VAR);
432   } else if (peek() == Token::CONST) {
433     // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
434     //
435     // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
436     //
437     // * It is a Syntax Error if the code that matches this production is not
438     //   contained in extended code.
439     //
440     // However disallowing const in sloppy mode will break compatibility with
441     // existing pages. Therefore we keep allowing const with the old
442     // non-harmony semantics in sloppy mode.
443     Consume(Token::CONST);
444     if (strict_mode() == STRICT) {
445       if (allow_harmony_scoping()) {
446         if (var_context != kSourceElement && var_context != kForStatement) {
447           ReportMessageAt(scanner()->peek_location(), "unprotected_const");
448           *ok = false;
449           return Statement::Default();
450         }
451         require_initializer = true;
452       } else {
453         Scanner::Location location = scanner()->peek_location();
454         ReportMessageAt(location, "strict_const");
455         *ok = false;
456         return Statement::Default();
457       }
458     }
459   } else if (peek() == Token::LET && strict_mode() == STRICT) {
460     Consume(Token::LET);
461     if (var_context != kSourceElement && var_context != kForStatement) {
462       ReportMessageAt(scanner()->peek_location(), "unprotected_let");
463       *ok = false;
464       return Statement::Default();
465     }
466   } else {
467     *ok = false;
468     return Statement::Default();
469   }
470 
471   // The scope of a var/const declared variable anywhere inside a function
472   // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
473   // of a let declared variable is the scope of the immediately enclosing
474   // block.
475   int nvars = 0;  // the number of variables declared
476   do {
477     // Parse variable name.
478     if (nvars > 0) Consume(Token::COMMA);
479     ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
480     nvars++;
481     if (peek() == Token::ASSIGN || require_initializer) {
482       Expect(Token::ASSIGN, CHECK_OK);
483       ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
484       if (decl_props != NULL) *decl_props = kHasInitializers;
485     }
486   } while (peek() == Token::COMMA);
487 
488   if (num_decl != NULL) *num_decl = nvars;
489   return Statement::Default();
490 }
491 
492 
ParseExpressionOrLabelledStatement(bool * ok)493 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
494   // ExpressionStatement | LabelledStatement ::
495   //   Expression ';'
496   //   Identifier ':' Statement
497 
498   bool starts_with_identifier = peek_any_identifier();
499   Expression expr = ParseExpression(true, CHECK_OK);
500   // Even if the expression starts with an identifier, it is not necessarily an
501   // identifier. For example, "foo + bar" starts with an identifier but is not
502   // an identifier.
503   if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) {
504     // Expression is a single identifier, and not, e.g., a parenthesized
505     // identifier.
506     DCHECK(!expr.AsIdentifier().IsFutureReserved());
507     DCHECK(strict_mode() == SLOPPY ||
508            (!expr.AsIdentifier().IsFutureStrictReserved() &&
509             !expr.AsIdentifier().IsYield()));
510     Consume(Token::COLON);
511     return ParseStatement(ok);
512     // Preparsing is disabled for extensions (because the extension details
513     // aren't passed to lazily compiled functions), so we don't
514     // accept "native function" in the preparser.
515   }
516   // Parsed expression statement.
517   ExpectSemicolon(CHECK_OK);
518   return Statement::ExpressionStatement(expr);
519 }
520 
521 
ParseIfStatement(bool * ok)522 PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
523   // IfStatement ::
524   //   'if' '(' Expression ')' Statement ('else' Statement)?
525 
526   Expect(Token::IF, CHECK_OK);
527   Expect(Token::LPAREN, CHECK_OK);
528   ParseExpression(true, CHECK_OK);
529   Expect(Token::RPAREN, CHECK_OK);
530   ParseStatement(CHECK_OK);
531   if (peek() == Token::ELSE) {
532     Next();
533     ParseStatement(CHECK_OK);
534   }
535   return Statement::Default();
536 }
537 
538 
ParseContinueStatement(bool * ok)539 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
540   // ContinueStatement ::
541   //   'continue' [no line terminator] Identifier? ';'
542 
543   Expect(Token::CONTINUE, CHECK_OK);
544   Token::Value tok = peek();
545   if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
546       tok != Token::SEMICOLON &&
547       tok != Token::RBRACE &&
548       tok != Token::EOS) {
549     // ECMA allows "eval" or "arguments" as labels even in strict mode.
550     ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
551   }
552   ExpectSemicolon(CHECK_OK);
553   return Statement::Default();
554 }
555 
556 
ParseBreakStatement(bool * ok)557 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
558   // BreakStatement ::
559   //   'break' [no line terminator] Identifier? ';'
560 
561   Expect(Token::BREAK, CHECK_OK);
562   Token::Value tok = peek();
563   if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
564       tok != Token::SEMICOLON &&
565       tok != Token::RBRACE &&
566       tok != Token::EOS) {
567     // ECMA allows "eval" or "arguments" as labels even in strict mode.
568     ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
569   }
570   ExpectSemicolon(CHECK_OK);
571   return Statement::Default();
572 }
573 
574 
ParseReturnStatement(bool * ok)575 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
576   // ReturnStatement ::
577   //   'return' [no line terminator] Expression? ';'
578 
579   // Consume the return token. It is necessary to do before
580   // reporting any errors on it, because of the way errors are
581   // reported (underlining).
582   Expect(Token::RETURN, CHECK_OK);
583 
584   // An ECMAScript program is considered syntactically incorrect if it
585   // contains a return statement that is not within the body of a
586   // function. See ECMA-262, section 12.9, page 67.
587   // This is not handled during preparsing.
588 
589   Token::Value tok = peek();
590   if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
591       tok != Token::SEMICOLON &&
592       tok != Token::RBRACE &&
593       tok != Token::EOS) {
594     ParseExpression(true, CHECK_OK);
595   }
596   ExpectSemicolon(CHECK_OK);
597   return Statement::Default();
598 }
599 
600 
ParseWithStatement(bool * ok)601 PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
602   // WithStatement ::
603   //   'with' '(' Expression ')' Statement
604   Expect(Token::WITH, CHECK_OK);
605   if (strict_mode() == STRICT) {
606     ReportMessageAt(scanner()->location(), "strict_mode_with");
607     *ok = false;
608     return Statement::Default();
609   }
610   Expect(Token::LPAREN, CHECK_OK);
611   ParseExpression(true, CHECK_OK);
612   Expect(Token::RPAREN, CHECK_OK);
613 
614   PreParserScope with_scope(scope_, WITH_SCOPE);
615   BlockState block_state(&scope_, &with_scope);
616   ParseStatement(CHECK_OK);
617   return Statement::Default();
618 }
619 
620 
ParseSwitchStatement(bool * ok)621 PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
622   // SwitchStatement ::
623   //   'switch' '(' Expression ')' '{' CaseClause* '}'
624 
625   Expect(Token::SWITCH, CHECK_OK);
626   Expect(Token::LPAREN, CHECK_OK);
627   ParseExpression(true, CHECK_OK);
628   Expect(Token::RPAREN, CHECK_OK);
629 
630   Expect(Token::LBRACE, CHECK_OK);
631   Token::Value token = peek();
632   while (token != Token::RBRACE) {
633     if (token == Token::CASE) {
634       Expect(Token::CASE, CHECK_OK);
635       ParseExpression(true, CHECK_OK);
636     } else {
637       Expect(Token::DEFAULT, CHECK_OK);
638     }
639     Expect(Token::COLON, CHECK_OK);
640     token = peek();
641     while (token != Token::CASE &&
642            token != Token::DEFAULT &&
643            token != Token::RBRACE) {
644       ParseStatement(CHECK_OK);
645       token = peek();
646     }
647   }
648   Expect(Token::RBRACE, ok);
649   return Statement::Default();
650 }
651 
652 
ParseDoWhileStatement(bool * ok)653 PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
654   // DoStatement ::
655   //   'do' Statement 'while' '(' Expression ')' ';'
656 
657   Expect(Token::DO, CHECK_OK);
658   ParseStatement(CHECK_OK);
659   Expect(Token::WHILE, CHECK_OK);
660   Expect(Token::LPAREN, CHECK_OK);
661   ParseExpression(true, CHECK_OK);
662   Expect(Token::RPAREN, ok);
663   if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
664   return Statement::Default();
665 }
666 
667 
ParseWhileStatement(bool * ok)668 PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
669   // WhileStatement ::
670   //   'while' '(' Expression ')' Statement
671 
672   Expect(Token::WHILE, CHECK_OK);
673   Expect(Token::LPAREN, CHECK_OK);
674   ParseExpression(true, CHECK_OK);
675   Expect(Token::RPAREN, CHECK_OK);
676   ParseStatement(ok);
677   return Statement::Default();
678 }
679 
680 
CheckInOrOf(bool accept_OF)681 bool PreParser::CheckInOrOf(bool accept_OF) {
682   if (Check(Token::IN) ||
683       (accept_OF && CheckContextualKeyword(CStrVector("of")))) {
684     return true;
685   }
686   return false;
687 }
688 
689 
ParseForStatement(bool * ok)690 PreParser::Statement PreParser::ParseForStatement(bool* ok) {
691   // ForStatement ::
692   //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
693 
694   Expect(Token::FOR, CHECK_OK);
695   Expect(Token::LPAREN, CHECK_OK);
696   if (peek() != Token::SEMICOLON) {
697     if (peek() == Token::VAR || peek() == Token::CONST ||
698         (peek() == Token::LET && strict_mode() == STRICT)) {
699       bool is_let = peek() == Token::LET;
700       int decl_count;
701       VariableDeclarationProperties decl_props = kHasNoInitializers;
702       ParseVariableDeclarations(
703           kForStatement, &decl_props, &decl_count, CHECK_OK);
704       bool has_initializers = decl_props == kHasInitializers;
705       bool accept_IN = decl_count == 1 && !(is_let && has_initializers);
706       bool accept_OF = !has_initializers;
707       if (accept_IN && CheckInOrOf(accept_OF)) {
708         ParseExpression(true, CHECK_OK);
709         Expect(Token::RPAREN, CHECK_OK);
710 
711         ParseStatement(CHECK_OK);
712         return Statement::Default();
713       }
714     } else {
715       Expression lhs = ParseExpression(false, CHECK_OK);
716       if (CheckInOrOf(lhs.IsIdentifier())) {
717         ParseExpression(true, CHECK_OK);
718         Expect(Token::RPAREN, CHECK_OK);
719 
720         ParseStatement(CHECK_OK);
721         return Statement::Default();
722       }
723     }
724   }
725 
726   // Parsed initializer at this point.
727   Expect(Token::SEMICOLON, CHECK_OK);
728 
729   if (peek() != Token::SEMICOLON) {
730     ParseExpression(true, CHECK_OK);
731   }
732   Expect(Token::SEMICOLON, CHECK_OK);
733 
734   if (peek() != Token::RPAREN) {
735     ParseExpression(true, CHECK_OK);
736   }
737   Expect(Token::RPAREN, CHECK_OK);
738 
739   ParseStatement(ok);
740   return Statement::Default();
741 }
742 
743 
ParseThrowStatement(bool * ok)744 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
745   // ThrowStatement ::
746   //   'throw' [no line terminator] Expression ';'
747 
748   Expect(Token::THROW, CHECK_OK);
749   if (scanner()->HasAnyLineTerminatorBeforeNext()) {
750     ReportMessageAt(scanner()->location(), "newline_after_throw");
751     *ok = false;
752     return Statement::Default();
753   }
754   ParseExpression(true, CHECK_OK);
755   ExpectSemicolon(ok);
756   return Statement::Default();
757 }
758 
759 
ParseTryStatement(bool * ok)760 PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
761   // TryStatement ::
762   //   'try' Block Catch
763   //   'try' Block Finally
764   //   'try' Block Catch Finally
765   //
766   // Catch ::
767   //   'catch' '(' Identifier ')' Block
768   //
769   // Finally ::
770   //   'finally' Block
771 
772   Expect(Token::TRY, CHECK_OK);
773 
774   ParseBlock(CHECK_OK);
775 
776   Token::Value tok = peek();
777   if (tok != Token::CATCH && tok != Token::FINALLY) {
778     ReportMessageAt(scanner()->location(), "no_catch_or_finally");
779     *ok = false;
780     return Statement::Default();
781   }
782   if (tok == Token::CATCH) {
783     Consume(Token::CATCH);
784     Expect(Token::LPAREN, CHECK_OK);
785     ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
786     Expect(Token::RPAREN, CHECK_OK);
787     {
788       PreParserScope with_scope(scope_, WITH_SCOPE);
789       BlockState block_state(&scope_, &with_scope);
790       ParseBlock(CHECK_OK);
791     }
792     tok = peek();
793   }
794   if (tok == Token::FINALLY) {
795     Consume(Token::FINALLY);
796     ParseBlock(CHECK_OK);
797   }
798   return Statement::Default();
799 }
800 
801 
ParseDebuggerStatement(bool * ok)802 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
803   // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
804   // contexts this is used as a statement which invokes the debugger as if a
805   // break point is present.
806   // DebuggerStatement ::
807   //   'debugger' ';'
808 
809   Expect(Token::DEBUGGER, CHECK_OK);
810   ExpectSemicolon(ok);
811   return Statement::Default();
812 }
813 
814 
815 #undef CHECK_OK
816 #define CHECK_OK  ok);                     \
817   if (!*ok) return Expression::Default();  \
818   ((void)0
819 #define DUMMY )  // to make indentation work
820 #undef DUMMY
821 
822 
ParseFunctionLiteral(Identifier function_name,Scanner::Location function_name_location,bool name_is_strict_reserved,FunctionKind kind,int function_token_pos,FunctionLiteral::FunctionType function_type,FunctionLiteral::ArityRestriction arity_restriction,bool * ok)823 PreParser::Expression PreParser::ParseFunctionLiteral(
824     Identifier function_name, Scanner::Location function_name_location,
825     bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
826     FunctionLiteral::FunctionType function_type,
827     FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
828   // Function ::
829   //   '(' FormalParameterList? ')' '{' FunctionBody '}'
830 
831   // Parse function body.
832   ScopeType outer_scope_type = scope_->type();
833   PreParserScope function_scope(scope_, FUNCTION_SCOPE);
834   FunctionState function_state(&function_state_, &scope_, &function_scope, NULL,
835                                this->ast_value_factory());
836   function_state.set_is_generator(IsGeneratorFunction(kind));
837   //  FormalParameterList ::
838   //    '(' (Identifier)*[','] ')'
839   Expect(Token::LPAREN, CHECK_OK);
840   int start_position = position();
841   DuplicateFinder duplicate_finder(scanner()->unicode_cache());
842   // We don't yet know if the function will be strict, so we cannot yet produce
843   // errors for parameter names or duplicates. However, we remember the
844   // locations of these errors if they occur and produce the errors later.
845   Scanner::Location eval_args_error_loc = Scanner::Location::invalid();
846   Scanner::Location dupe_error_loc = Scanner::Location::invalid();
847   Scanner::Location reserved_error_loc = Scanner::Location::invalid();
848 
849   bool done = arity_restriction == FunctionLiteral::GETTER_ARITY ||
850       (peek() == Token::RPAREN &&
851        arity_restriction != FunctionLiteral::SETTER_ARITY);
852   while (!done) {
853     bool is_strict_reserved = false;
854     Identifier param_name =
855         ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
856     if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) {
857       eval_args_error_loc = scanner()->location();
858     }
859     if (!reserved_error_loc.IsValid() && is_strict_reserved) {
860       reserved_error_loc = scanner()->location();
861     }
862 
863     int prev_value = scanner()->FindSymbol(&duplicate_finder, 1);
864 
865     if (!dupe_error_loc.IsValid() && prev_value != 0) {
866       dupe_error_loc = scanner()->location();
867     }
868 
869     if (arity_restriction == FunctionLiteral::SETTER_ARITY) break;
870     done = (peek() == Token::RPAREN);
871     if (!done) Expect(Token::COMMA, CHECK_OK);
872   }
873   Expect(Token::RPAREN, CHECK_OK);
874 
875   // See Parser::ParseFunctionLiteral for more information about lazy parsing
876   // and lazy compilation.
877   bool is_lazily_parsed = (outer_scope_type == GLOBAL_SCOPE && allow_lazy() &&
878                            !parenthesized_function_);
879   parenthesized_function_ = false;
880 
881   Expect(Token::LBRACE, CHECK_OK);
882   if (is_lazily_parsed) {
883     ParseLazyFunctionLiteralBody(CHECK_OK);
884   } else {
885     ParseSourceElements(Token::RBRACE, ok);
886   }
887   Expect(Token::RBRACE, CHECK_OK);
888 
889   // Validate strict mode. We can do this only after parsing the function,
890   // since the function can declare itself strict.
891   // Concise methods use StrictFormalParameters.
892   if (strict_mode() == STRICT || IsConciseMethod(kind)) {
893     if (function_name.IsEvalOrArguments()) {
894       ReportMessageAt(function_name_location, "strict_eval_arguments");
895       *ok = false;
896       return Expression::Default();
897     }
898     if (name_is_strict_reserved) {
899       ReportMessageAt(function_name_location, "unexpected_strict_reserved");
900       *ok = false;
901       return Expression::Default();
902     }
903     if (eval_args_error_loc.IsValid()) {
904       ReportMessageAt(eval_args_error_loc, "strict_eval_arguments");
905       *ok = false;
906       return Expression::Default();
907     }
908     if (dupe_error_loc.IsValid()) {
909       ReportMessageAt(dupe_error_loc, "strict_param_dupe");
910       *ok = false;
911       return Expression::Default();
912     }
913     if (reserved_error_loc.IsValid()) {
914       ReportMessageAt(reserved_error_loc, "unexpected_strict_reserved");
915       *ok = false;
916       return Expression::Default();
917     }
918 
919     int end_position = scanner()->location().end_pos;
920     CheckOctalLiteral(start_position, end_position, CHECK_OK);
921   }
922 
923   return Expression::Default();
924 }
925 
926 
ParseLazyFunctionLiteralBody(bool * ok)927 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
928   int body_start = position();
929   ParseSourceElements(Token::RBRACE, ok);
930   if (!*ok) return;
931 
932   // Position right after terminal '}'.
933   DCHECK_EQ(Token::RBRACE, scanner()->peek());
934   int body_end = scanner()->peek_location().end_pos;
935   log_->LogFunction(body_start, body_end,
936                     function_state_->materialized_literal_count(),
937                     function_state_->expected_property_count(),
938                     strict_mode());
939 }
940 
941 
ParseV8Intrinsic(bool * ok)942 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
943   // CallRuntime ::
944   //   '%' Identifier Arguments
945   Expect(Token::MOD, CHECK_OK);
946   if (!allow_natives_syntax()) {
947     *ok = false;
948     return Expression::Default();
949   }
950   // Allow "eval" or "arguments" for backward compatibility.
951   ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
952   ParseArguments(ok);
953 
954   return Expression::Default();
955 }
956 
957 #undef CHECK_OK
958 
959 
960 } }  // v8::internal
961