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