v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
preparser.cc
Go to the documentation of this file.
1 // Copyright 2011 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 #include <math.h>
29 
30 #include "../include/v8stdint.h"
31 
32 #include "allocation.h"
33 #include "checks.h"
34 #include "conversions.h"
35 #include "conversions-inl.h"
36 #include "globals.h"
37 #include "hashmap.h"
38 #include "list.h"
39 #include "preparse-data-format.h"
40 #include "preparse-data.h"
41 #include "preparser.h"
42 #include "unicode.h"
43 #include "utils.h"
44 
45 namespace v8 {
46 
47 #ifdef _MSC_VER
48 // Usually defined in math.h, but not in MSVC.
49 // Abstracted to work
50 int isfinite(double value);
51 #endif
52 
53 namespace preparser {
54 
57  log_ = log;
58  // Lazy functions always have trivial outer scopes (no with/catch scopes).
59  Scope top_scope(&scope_, kTopLevelScope);
60  set_language_mode(mode);
61  Scope function_scope(&scope_, kFunctionScope);
62  ASSERT_EQ(i::Token::LBRACE, scanner_->current_token());
63  bool ok = true;
64  int start_position = scanner_->peek_location().beg_pos;
65  ParseLazyFunctionLiteralBody(&ok);
66  if (stack_overflow_) return kPreParseStackOverflow;
67  if (!ok) {
68  ReportUnexpectedToken(scanner_->current_token());
69  } else {
70  ASSERT_EQ(i::Token::RBRACE, scanner_->peek());
71  if (!is_classic_mode()) {
72  int end_pos = scanner_->location().end_pos;
73  CheckOctalLiteral(start_position, end_pos, &ok);
74  if (ok) {
75  CheckDelayedStrictModeViolation(start_position, end_pos, &ok);
76  }
77  }
78  }
79  return kPreParseSuccess;
80 }
81 
82 
83 // Preparsing checks a JavaScript program and emits preparse-data that helps
84 // a later parsing to be faster.
85 // See preparser-data.h for the data.
86 
87 // The PreParser checks that the syntax follows the grammar for JavaScript,
88 // and collects some information about the program along the way.
89 // The grammar check is only performed in order to understand the program
90 // sufficiently to deduce some information about it, that can be used
91 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
92 // rather it is to speed up properly written and correct programs.
93 // That means that contextual checks (like a label being declared where
94 // it is used) are generally omitted.
95 
96 void PreParser::ReportUnexpectedToken(i::Token::Value token) {
97  // We don't report stack overflows here, to avoid increasing the
98  // stack depth even further. Instead we report it after parsing is
99  // over, in ParseProgram.
100  if (token == i::Token::ILLEGAL && stack_overflow_) {
101  return;
102  }
103  i::Scanner::Location source_location = scanner_->location();
104 
105  // Four of the tokens are treated specially
106  switch (token) {
107  case i::Token::EOS:
108  return ReportMessageAt(source_location, "unexpected_eos", NULL);
109  case i::Token::NUMBER:
110  return ReportMessageAt(source_location, "unexpected_token_number", NULL);
111  case i::Token::STRING:
112  return ReportMessageAt(source_location, "unexpected_token_string", NULL);
113  case i::Token::IDENTIFIER:
114  return ReportMessageAt(source_location,
115  "unexpected_token_identifier", NULL);
116  case i::Token::FUTURE_RESERVED_WORD:
117  return ReportMessageAt(source_location, "unexpected_reserved", NULL);
118  case i::Token::FUTURE_STRICT_RESERVED_WORD:
119  return ReportMessageAt(source_location,
120  "unexpected_strict_reserved", NULL);
121  default:
122  const char* name = i::Token::String(token);
123  ReportMessageAt(source_location, "unexpected_token", name);
124  }
125 }
126 
127 
128 // Checks whether octal literal last seen is between beg_pos and end_pos.
129 // If so, reports an error.
130 void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
131  i::Scanner::Location octal = scanner_->octal_position();
132  if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
133  ReportMessageAt(octal, "strict_octal_literal", NULL);
134  scanner_->clear_octal_position();
135  *ok = false;
136  }
137 }
138 
139 
140 #define CHECK_OK ok); \
141  if (!*ok) return kUnknownSourceElements; \
142  ((void)0
143 #define DUMMY ) // to make indentation work
144 #undef DUMMY
145 
146 
147 PreParser::Statement PreParser::ParseSourceElement(bool* ok) {
148  // (Ecma 262 5th Edition, clause 14):
149  // SourceElement:
150  // Statement
151  // FunctionDeclaration
152  //
153  // In harmony mode we allow additionally the following productions
154  // SourceElement:
155  // LetDeclaration
156  // ConstDeclaration
157 
158  switch (peek()) {
159  case i::Token::FUNCTION:
160  return ParseFunctionDeclaration(ok);
161  case i::Token::LET:
162  case i::Token::CONST:
163  return ParseVariableStatement(kSourceElement, ok);
164  default:
165  return ParseStatement(ok);
166  }
167 }
168 
169 
170 PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
171  bool* ok) {
172  // SourceElements ::
173  // (Statement)* <end_token>
174 
175  bool allow_directive_prologue = true;
176  while (peek() != end_token) {
177  Statement statement = ParseSourceElement(CHECK_OK);
178  if (allow_directive_prologue) {
179  if (statement.IsUseStrictLiteral()) {
180  set_language_mode(harmony_scoping_ ?
182  } else if (!statement.IsStringLiteral()) {
183  allow_directive_prologue = false;
184  }
185  }
186  }
187  return kUnknownSourceElements;
188 }
189 
190 
191 #undef CHECK_OK
192 #define CHECK_OK ok); \
193  if (!*ok) return Statement::Default(); \
194  ((void)0
195 #define DUMMY ) // to make indentation work
196 #undef DUMMY
197 
198 
199 PreParser::Statement PreParser::ParseStatement(bool* ok) {
200  // Statement ::
201  // Block
202  // VariableStatement
203  // EmptyStatement
204  // ExpressionStatement
205  // IfStatement
206  // IterationStatement
207  // ContinueStatement
208  // BreakStatement
209  // ReturnStatement
210  // WithStatement
211  // LabelledStatement
212  // SwitchStatement
213  // ThrowStatement
214  // TryStatement
215  // DebuggerStatement
216 
217  // Note: Since labels can only be used by 'break' and 'continue'
218  // statements, which themselves are only valid within blocks,
219  // iterations or 'switch' statements (i.e., BreakableStatements),
220  // labels can be simply ignored in all other cases; except for
221  // trivial labeled break statements 'label: break label' which is
222  // parsed into an empty statement.
223 
224  // Keep the source position of the statement
225  switch (peek()) {
226  case i::Token::LBRACE:
227  return ParseBlock(ok);
228 
229  case i::Token::CONST:
230  case i::Token::LET:
231  case i::Token::VAR:
232  return ParseVariableStatement(kStatement, ok);
233 
234  case i::Token::SEMICOLON:
235  Next();
236  return Statement::Default();
237 
238  case i::Token::IF:
239  return ParseIfStatement(ok);
240 
241  case i::Token::DO:
242  return ParseDoWhileStatement(ok);
243 
244  case i::Token::WHILE:
245  return ParseWhileStatement(ok);
246 
247  case i::Token::FOR:
248  return ParseForStatement(ok);
249 
250  case i::Token::CONTINUE:
251  return ParseContinueStatement(ok);
252 
253  case i::Token::BREAK:
254  return ParseBreakStatement(ok);
255 
256  case i::Token::RETURN:
257  return ParseReturnStatement(ok);
258 
259  case i::Token::WITH:
260  return ParseWithStatement(ok);
261 
262  case i::Token::SWITCH:
263  return ParseSwitchStatement(ok);
264 
265  case i::Token::THROW:
266  return ParseThrowStatement(ok);
267 
268  case i::Token::TRY:
269  return ParseTryStatement(ok);
270 
271  case i::Token::FUNCTION: {
272  i::Scanner::Location start_location = scanner_->peek_location();
273  Statement statement = ParseFunctionDeclaration(CHECK_OK);
274  i::Scanner::Location end_location = scanner_->location();
275  if (!is_classic_mode()) {
276  ReportMessageAt(start_location.beg_pos, end_location.end_pos,
277  "strict_function", NULL);
278  *ok = false;
279  return Statement::Default();
280  } else {
281  return statement;
282  }
283  }
284 
285  case i::Token::DEBUGGER:
286  return ParseDebuggerStatement(ok);
287 
288  default:
289  return ParseExpressionOrLabelledStatement(ok);
290  }
291 }
292 
293 
294 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
295  // FunctionDeclaration ::
296  // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
297  Expect(i::Token::FUNCTION, CHECK_OK);
298 
299  Identifier identifier = ParseIdentifier(CHECK_OK);
300  i::Scanner::Location location = scanner_->location();
301 
302  Expression function_value = ParseFunctionLiteral(CHECK_OK);
303 
304  if (function_value.IsStrictFunction() &&
305  !identifier.IsValidStrictVariable()) {
306  // Strict mode violation, using either reserved word or eval/arguments
307  // as name of strict function.
308  const char* type = "strict_function_name";
309  if (identifier.IsFutureStrictReserved()) {
310  type = "strict_reserved_word";
311  }
312  ReportMessageAt(location, type, NULL);
313  *ok = false;
314  }
315  return Statement::FunctionDeclaration();
316 }
317 
318 
319 PreParser::Statement PreParser::ParseBlock(bool* ok) {
320  // Block ::
321  // '{' Statement* '}'
322 
323  // Note that a Block does not introduce a new execution scope!
324  // (ECMA-262, 3rd, 12.2)
325  //
326  Expect(i::Token::LBRACE, CHECK_OK);
327  while (peek() != i::Token::RBRACE) {
328  if (is_extended_mode()) {
329  ParseSourceElement(CHECK_OK);
330  } else {
331  ParseStatement(CHECK_OK);
332  }
333  }
334  Expect(i::Token::RBRACE, ok);
335  return Statement::Default();
336 }
337 
338 
339 PreParser::Statement PreParser::ParseVariableStatement(
340  VariableDeclarationContext var_context,
341  bool* ok) {
342  // VariableStatement ::
343  // VariableDeclarations ';'
344 
345  Statement result = ParseVariableDeclarations(var_context,
346  NULL,
347  NULL,
348  CHECK_OK);
349  ExpectSemicolon(CHECK_OK);
350  return result;
351 }
352 
353 
354 // If the variable declaration declares exactly one non-const
355 // variable, then *var is set to that variable. In all other cases,
356 // *var is untouched; in particular, it is the caller's responsibility
357 // to initialize it properly. This mechanism is also used for the parsing
358 // of 'for-in' loops.
359 PreParser::Statement PreParser::ParseVariableDeclarations(
360  VariableDeclarationContext var_context,
361  VariableDeclarationProperties* decl_props,
362  int* num_decl,
363  bool* ok) {
364  // VariableDeclarations ::
365  // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
366  //
367  // The ES6 Draft Rev3 specifies the following grammar for const declarations
368  //
369  // ConstDeclaration ::
370  // const ConstBinding (',' ConstBinding)* ';'
371  // ConstBinding ::
372  // Identifier '=' AssignmentExpression
373  //
374  // TODO(ES6):
375  // ConstBinding ::
376  // BindingPattern '=' AssignmentExpression
377  bool require_initializer = false;
378  if (peek() == i::Token::VAR) {
379  Consume(i::Token::VAR);
380  } else if (peek() == i::Token::CONST) {
381  // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
382  //
383  // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
384  //
385  // * It is a Syntax Error if the code that matches this production is not
386  // contained in extended code.
387  //
388  // However disallowing const in classic mode will break compatibility with
389  // existing pages. Therefore we keep allowing const with the old
390  // non-harmony semantics in classic mode.
391  Consume(i::Token::CONST);
392  switch (language_mode()) {
393  case i::CLASSIC_MODE:
394  break;
395  case i::STRICT_MODE: {
396  i::Scanner::Location location = scanner_->peek_location();
397  ReportMessageAt(location, "strict_const", NULL);
398  *ok = false;
399  return Statement::Default();
400  }
401  case i::EXTENDED_MODE:
402  if (var_context != kSourceElement &&
403  var_context != kForStatement) {
404  i::Scanner::Location location = scanner_->peek_location();
405  ReportMessageAt(location.beg_pos, location.end_pos,
406  "unprotected_const", NULL);
407  *ok = false;
408  return Statement::Default();
409  }
410  require_initializer = true;
411  break;
412  }
413  } else if (peek() == i::Token::LET) {
414  // ES6 Draft Rev4 section 12.2.1:
415  //
416  // LetDeclaration : let LetBindingList ;
417  //
418  // * It is a Syntax Error if the code that matches this production is not
419  // contained in extended code.
420  if (!is_extended_mode()) {
421  i::Scanner::Location location = scanner_->peek_location();
422  ReportMessageAt(location.beg_pos, location.end_pos,
423  "illegal_let", NULL);
424  *ok = false;
425  return Statement::Default();
426  }
427  Consume(i::Token::LET);
428  if (var_context != kSourceElement &&
429  var_context != kForStatement) {
430  i::Scanner::Location location = scanner_->peek_location();
431  ReportMessageAt(location.beg_pos, location.end_pos,
432  "unprotected_let", NULL);
433  *ok = false;
434  return Statement::Default();
435  }
436  } else {
437  *ok = false;
438  return Statement::Default();
439  }
440 
441  // The scope of a var/const declared variable anywhere inside a function
442  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
443  // of a let declared variable is the scope of the immediately enclosing
444  // block.
445  int nvars = 0; // the number of variables declared
446  do {
447  // Parse variable name.
448  if (nvars > 0) Consume(i::Token::COMMA);
449  Identifier identifier = ParseIdentifier(CHECK_OK);
450  if (!is_classic_mode() && !identifier.IsValidStrictVariable()) {
451  StrictModeIdentifierViolation(scanner_->location(),
452  "strict_var_name",
453  identifier,
454  ok);
455  return Statement::Default();
456  }
457  nvars++;
458  if (peek() == i::Token::ASSIGN || require_initializer) {
459  Expect(i::Token::ASSIGN, CHECK_OK);
460  ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
461  if (decl_props != NULL) *decl_props = kHasInitializers;
462  }
463  } while (peek() == i::Token::COMMA);
464 
465  if (num_decl != NULL) *num_decl = nvars;
466  return Statement::Default();
467 }
468 
469 
470 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
471  // ExpressionStatement | LabelledStatement ::
472  // Expression ';'
473  // Identifier ':' Statement
474 
475  Expression expr = ParseExpression(true, CHECK_OK);
476  if (expr.IsRawIdentifier()) {
477  ASSERT(!expr.AsIdentifier().IsFutureReserved());
478  ASSERT(is_classic_mode() || !expr.AsIdentifier().IsFutureStrictReserved());
479  if (peek() == i::Token::COLON) {
480  Consume(i::Token::COLON);
481  return ParseStatement(ok);
482  }
483  // Preparsing is disabled for extensions (because the extension details
484  // aren't passed to lazily compiled functions), so we don't
485  // accept "native function" in the preparser.
486  }
487  // Parsed expression statement.
488  ExpectSemicolon(CHECK_OK);
489  return Statement::ExpressionStatement(expr);
490 }
491 
492 
493 PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
494  // IfStatement ::
495  // 'if' '(' Expression ')' Statement ('else' Statement)?
496 
497  Expect(i::Token::IF, CHECK_OK);
498  Expect(i::Token::LPAREN, CHECK_OK);
499  ParseExpression(true, CHECK_OK);
500  Expect(i::Token::RPAREN, CHECK_OK);
501  ParseStatement(CHECK_OK);
502  if (peek() == i::Token::ELSE) {
503  Next();
504  ParseStatement(CHECK_OK);
505  }
506  return Statement::Default();
507 }
508 
509 
510 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
511  // ContinueStatement ::
512  // 'continue' [no line terminator] Identifier? ';'
513 
514  Expect(i::Token::CONTINUE, CHECK_OK);
515  i::Token::Value tok = peek();
516  if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
517  tok != i::Token::SEMICOLON &&
518  tok != i::Token::RBRACE &&
519  tok != i::Token::EOS) {
520  ParseIdentifier(CHECK_OK);
521  }
522  ExpectSemicolon(CHECK_OK);
523  return Statement::Default();
524 }
525 
526 
527 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
528  // BreakStatement ::
529  // 'break' [no line terminator] Identifier? ';'
530 
531  Expect(i::Token::BREAK, CHECK_OK);
532  i::Token::Value tok = peek();
533  if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
534  tok != i::Token::SEMICOLON &&
535  tok != i::Token::RBRACE &&
536  tok != i::Token::EOS) {
537  ParseIdentifier(CHECK_OK);
538  }
539  ExpectSemicolon(CHECK_OK);
540  return Statement::Default();
541 }
542 
543 
544 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
545  // ReturnStatement ::
546  // 'return' [no line terminator] Expression? ';'
547 
548  // Consume the return token. It is necessary to do the before
549  // reporting any errors on it, because of the way errors are
550  // reported (underlining).
551  Expect(i::Token::RETURN, CHECK_OK);
552 
553  // An ECMAScript program is considered syntactically incorrect if it
554  // contains a return statement that is not within the body of a
555  // function. See ECMA-262, section 12.9, page 67.
556  // This is not handled during preparsing.
557 
558  i::Token::Value tok = peek();
559  if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
560  tok != i::Token::SEMICOLON &&
561  tok != i::Token::RBRACE &&
562  tok != i::Token::EOS) {
563  ParseExpression(true, CHECK_OK);
564  }
565  ExpectSemicolon(CHECK_OK);
566  return Statement::Default();
567 }
568 
569 
570 PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
571  // WithStatement ::
572  // 'with' '(' Expression ')' Statement
573  Expect(i::Token::WITH, CHECK_OK);
574  if (!is_classic_mode()) {
575  i::Scanner::Location location = scanner_->location();
576  ReportMessageAt(location, "strict_mode_with", NULL);
577  *ok = false;
578  return Statement::Default();
579  }
580  Expect(i::Token::LPAREN, CHECK_OK);
581  ParseExpression(true, CHECK_OK);
582  Expect(i::Token::RPAREN, CHECK_OK);
583 
584  Scope::InsideWith iw(scope_);
585  ParseStatement(CHECK_OK);
586  return Statement::Default();
587 }
588 
589 
590 PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
591  // SwitchStatement ::
592  // 'switch' '(' Expression ')' '{' CaseClause* '}'
593 
594  Expect(i::Token::SWITCH, CHECK_OK);
595  Expect(i::Token::LPAREN, CHECK_OK);
596  ParseExpression(true, CHECK_OK);
597  Expect(i::Token::RPAREN, CHECK_OK);
598 
599  Expect(i::Token::LBRACE, CHECK_OK);
600  i::Token::Value token = peek();
601  while (token != i::Token::RBRACE) {
602  if (token == i::Token::CASE) {
603  Expect(i::Token::CASE, CHECK_OK);
604  ParseExpression(true, CHECK_OK);
605  } else {
606  Expect(i::Token::DEFAULT, CHECK_OK);
607  }
608  Expect(i::Token::COLON, CHECK_OK);
609  token = peek();
610  while (token != i::Token::CASE &&
611  token != i::Token::DEFAULT &&
612  token != i::Token::RBRACE) {
613  ParseStatement(CHECK_OK);
614  token = peek();
615  }
616  }
617  Expect(i::Token::RBRACE, ok);
618  return Statement::Default();
619 }
620 
621 
622 PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
623  // DoStatement ::
624  // 'do' Statement 'while' '(' Expression ')' ';'
625 
626  Expect(i::Token::DO, CHECK_OK);
627  ParseStatement(CHECK_OK);
628  Expect(i::Token::WHILE, CHECK_OK);
629  Expect(i::Token::LPAREN, CHECK_OK);
630  ParseExpression(true, CHECK_OK);
631  Expect(i::Token::RPAREN, ok);
632  if (peek() == i::Token::SEMICOLON) Consume(i::Token::SEMICOLON);
633  return Statement::Default();
634 }
635 
636 
637 PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
638  // WhileStatement ::
639  // 'while' '(' Expression ')' Statement
640 
641  Expect(i::Token::WHILE, CHECK_OK);
642  Expect(i::Token::LPAREN, CHECK_OK);
643  ParseExpression(true, CHECK_OK);
644  Expect(i::Token::RPAREN, CHECK_OK);
645  ParseStatement(ok);
646  return Statement::Default();
647 }
648 
649 
650 PreParser::Statement PreParser::ParseForStatement(bool* ok) {
651  // ForStatement ::
652  // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
653 
654  Expect(i::Token::FOR, CHECK_OK);
655  Expect(i::Token::LPAREN, CHECK_OK);
656  if (peek() != i::Token::SEMICOLON) {
657  if (peek() == i::Token::VAR || peek() == i::Token::CONST ||
658  peek() == i::Token::LET) {
659  bool is_let = peek() == i::Token::LET;
660  int decl_count;
661  VariableDeclarationProperties decl_props = kHasNoInitializers;
662  ParseVariableDeclarations(
663  kForStatement, &decl_props, &decl_count, CHECK_OK);
664  bool accept_IN = decl_count == 1 &&
665  !(is_let && decl_props == kHasInitializers);
666  if (peek() == i::Token::IN && accept_IN) {
667  Expect(i::Token::IN, CHECK_OK);
668  ParseExpression(true, CHECK_OK);
669  Expect(i::Token::RPAREN, CHECK_OK);
670 
671  ParseStatement(CHECK_OK);
672  return Statement::Default();
673  }
674  } else {
675  ParseExpression(false, CHECK_OK);
676  if (peek() == i::Token::IN) {
677  Expect(i::Token::IN, CHECK_OK);
678  ParseExpression(true, CHECK_OK);
679  Expect(i::Token::RPAREN, CHECK_OK);
680 
681  ParseStatement(CHECK_OK);
682  return Statement::Default();
683  }
684  }
685  }
686 
687  // Parsed initializer at this point.
688  Expect(i::Token::SEMICOLON, CHECK_OK);
689 
690  if (peek() != i::Token::SEMICOLON) {
691  ParseExpression(true, CHECK_OK);
692  }
693  Expect(i::Token::SEMICOLON, CHECK_OK);
694 
695  if (peek() != i::Token::RPAREN) {
696  ParseExpression(true, CHECK_OK);
697  }
698  Expect(i::Token::RPAREN, CHECK_OK);
699 
700  ParseStatement(ok);
701  return Statement::Default();
702 }
703 
704 
705 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
706  // ThrowStatement ::
707  // 'throw' [no line terminator] Expression ';'
708 
709  Expect(i::Token::THROW, CHECK_OK);
710  if (scanner_->HasAnyLineTerminatorBeforeNext()) {
711  i::Scanner::Location pos = scanner_->location();
712  ReportMessageAt(pos, "newline_after_throw", NULL);
713  *ok = false;
714  return Statement::Default();
715  }
716  ParseExpression(true, CHECK_OK);
717  ExpectSemicolon(ok);
718  return Statement::Default();
719 }
720 
721 
722 PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
723  // TryStatement ::
724  // 'try' Block Catch
725  // 'try' Block Finally
726  // 'try' Block Catch Finally
727  //
728  // Catch ::
729  // 'catch' '(' Identifier ')' Block
730  //
731  // Finally ::
732  // 'finally' Block
733 
734  // In preparsing, allow any number of catch/finally blocks, including zero
735  // of both.
736 
737  Expect(i::Token::TRY, CHECK_OK);
738 
739  ParseBlock(CHECK_OK);
740 
741  bool catch_or_finally_seen = false;
742  if (peek() == i::Token::CATCH) {
743  Consume(i::Token::CATCH);
744  Expect(i::Token::LPAREN, CHECK_OK);
745  Identifier id = ParseIdentifier(CHECK_OK);
746  if (!is_classic_mode() && !id.IsValidStrictVariable()) {
747  StrictModeIdentifierViolation(scanner_->location(),
748  "strict_catch_variable",
749  id,
750  ok);
751  return Statement::Default();
752  }
753  Expect(i::Token::RPAREN, CHECK_OK);
754  { Scope::InsideWith iw(scope_);
755  ParseBlock(CHECK_OK);
756  }
757  catch_or_finally_seen = true;
758  }
759  if (peek() == i::Token::FINALLY) {
760  Consume(i::Token::FINALLY);
761  ParseBlock(CHECK_OK);
762  catch_or_finally_seen = true;
763  }
764  if (!catch_or_finally_seen) {
765  *ok = false;
766  }
767  return Statement::Default();
768 }
769 
770 
771 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
772  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
773  // contexts this is used as a statement which invokes the debugger as if a
774  // break point is present.
775  // DebuggerStatement ::
776  // 'debugger' ';'
777 
778  Expect(i::Token::DEBUGGER, CHECK_OK);
779  ExpectSemicolon(ok);
780  return Statement::Default();
781 }
782 
783 
784 #undef CHECK_OK
785 #define CHECK_OK ok); \
786  if (!*ok) return Expression::Default(); \
787  ((void)0
788 #define DUMMY ) // to make indentation work
789 #undef DUMMY
790 
791 
792 // Precedence = 1
793 PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) {
794  // Expression ::
795  // AssignmentExpression
796  // Expression ',' AssignmentExpression
797 
798  Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
799  while (peek() == i::Token::COMMA) {
800  Expect(i::Token::COMMA, CHECK_OK);
801  ParseAssignmentExpression(accept_IN, CHECK_OK);
802  result = Expression::Default();
803  }
804  return result;
805 }
806 
807 
808 // Precedence = 2
809 PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
810  bool* ok) {
811  // AssignmentExpression ::
812  // ConditionalExpression
813  // LeftHandSideExpression AssignmentOperator AssignmentExpression
814 
815  i::Scanner::Location before = scanner_->peek_location();
816  Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
817 
818  if (!i::Token::IsAssignmentOp(peek())) {
819  // Parsed conditional expression only (no assignment).
820  return expression;
821  }
822 
823  if (!is_classic_mode() &&
824  expression.IsIdentifier() &&
825  expression.AsIdentifier().IsEvalOrArguments()) {
826  i::Scanner::Location after = scanner_->location();
827  ReportMessageAt(before.beg_pos, after.end_pos,
828  "strict_lhs_assignment", NULL);
829  *ok = false;
830  return Expression::Default();
831  }
832 
833  i::Token::Value op = Next(); // Get assignment operator.
834  ParseAssignmentExpression(accept_IN, CHECK_OK);
835 
836  if ((op == i::Token::ASSIGN) && expression.IsThisProperty()) {
837  scope_->AddProperty();
838  }
839 
840  return Expression::Default();
841 }
842 
843 
844 // Precedence = 3
845 PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
846  bool* ok) {
847  // ConditionalExpression ::
848  // LogicalOrExpression
849  // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
850 
851  // We start using the binary expression parser for prec >= 4 only!
852  Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
853  if (peek() != i::Token::CONDITIONAL) return expression;
854  Consume(i::Token::CONDITIONAL);
855  // In parsing the first assignment expression in conditional
856  // expressions we always accept the 'in' keyword; see ECMA-262,
857  // section 11.12, page 58.
858  ParseAssignmentExpression(true, CHECK_OK);
859  Expect(i::Token::COLON, CHECK_OK);
860  ParseAssignmentExpression(accept_IN, CHECK_OK);
861  return Expression::Default();
862 }
863 
864 
865 int PreParser::Precedence(i::Token::Value tok, bool accept_IN) {
866  if (tok == i::Token::IN && !accept_IN)
867  return 0; // 0 precedence will terminate binary expression parsing
868 
869  return i::Token::Precedence(tok);
870 }
871 
872 
873 // Precedence >= 4
874 PreParser::Expression PreParser::ParseBinaryExpression(int prec,
875  bool accept_IN,
876  bool* ok) {
877  Expression result = ParseUnaryExpression(CHECK_OK);
878  for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
879  // prec1 >= 4
880  while (Precedence(peek(), accept_IN) == prec1) {
881  Next();
882  ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
883  result = Expression::Default();
884  }
885  }
886  return result;
887 }
888 
889 
890 PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
891  // UnaryExpression ::
892  // PostfixExpression
893  // 'delete' UnaryExpression
894  // 'void' UnaryExpression
895  // 'typeof' UnaryExpression
896  // '++' UnaryExpression
897  // '--' UnaryExpression
898  // '+' UnaryExpression
899  // '-' UnaryExpression
900  // '~' UnaryExpression
901  // '!' UnaryExpression
902 
903  i::Token::Value op = peek();
904  if (i::Token::IsUnaryOp(op)) {
905  op = Next();
906  ParseUnaryExpression(ok);
907  return Expression::Default();
908  } else if (i::Token::IsCountOp(op)) {
909  op = Next();
910  i::Scanner::Location before = scanner_->peek_location();
911  Expression expression = ParseUnaryExpression(CHECK_OK);
912  if (!is_classic_mode() &&
913  expression.IsIdentifier() &&
914  expression.AsIdentifier().IsEvalOrArguments()) {
915  i::Scanner::Location after = scanner_->location();
916  ReportMessageAt(before.beg_pos, after.end_pos,
917  "strict_lhs_prefix", NULL);
918  *ok = false;
919  }
920  return Expression::Default();
921  } else {
922  return ParsePostfixExpression(ok);
923  }
924 }
925 
926 
927 PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
928  // PostfixExpression ::
929  // LeftHandSideExpression ('++' | '--')?
930 
931  i::Scanner::Location before = scanner_->peek_location();
932  Expression expression = ParseLeftHandSideExpression(CHECK_OK);
933  if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
934  i::Token::IsCountOp(peek())) {
935  if (!is_classic_mode() &&
936  expression.IsIdentifier() &&
937  expression.AsIdentifier().IsEvalOrArguments()) {
938  i::Scanner::Location after = scanner_->location();
939  ReportMessageAt(before.beg_pos, after.end_pos,
940  "strict_lhs_postfix", NULL);
941  *ok = false;
942  return Expression::Default();
943  }
944  Next();
945  return Expression::Default();
946  }
947  return expression;
948 }
949 
950 
951 PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) {
952  // LeftHandSideExpression ::
953  // (NewExpression | MemberExpression) ...
954 
955  Expression result = Expression::Default();
956  if (peek() == i::Token::NEW) {
957  result = ParseNewExpression(CHECK_OK);
958  } else {
959  result = ParseMemberExpression(CHECK_OK);
960  }
961 
962  while (true) {
963  switch (peek()) {
964  case i::Token::LBRACK: {
965  Consume(i::Token::LBRACK);
966  ParseExpression(true, CHECK_OK);
967  Expect(i::Token::RBRACK, CHECK_OK);
968  if (result.IsThis()) {
969  result = Expression::ThisProperty();
970  } else {
971  result = Expression::Default();
972  }
973  break;
974  }
975 
976  case i::Token::LPAREN: {
977  ParseArguments(CHECK_OK);
978  result = Expression::Default();
979  break;
980  }
981 
982  case i::Token::PERIOD: {
983  Consume(i::Token::PERIOD);
984  ParseIdentifierName(CHECK_OK);
985  if (result.IsThis()) {
986  result = Expression::ThisProperty();
987  } else {
988  result = Expression::Default();
989  }
990  break;
991  }
992 
993  default:
994  return result;
995  }
996  }
997 }
998 
999 
1000 PreParser::Expression PreParser::ParseNewExpression(bool* ok) {
1001  // NewExpression ::
1002  // ('new')+ MemberExpression
1003 
1004  // The grammar for new expressions is pretty warped. The keyword
1005  // 'new' can either be a part of the new expression (where it isn't
1006  // followed by an argument list) or a part of the member expression,
1007  // where it must be followed by an argument list. To accommodate
1008  // this, we parse the 'new' keywords greedily and keep track of how
1009  // many we have parsed. This information is then passed on to the
1010  // member expression parser, which is only allowed to match argument
1011  // lists as long as it has 'new' prefixes left
1012  unsigned new_count = 0;
1013  do {
1014  Consume(i::Token::NEW);
1015  new_count++;
1016  } while (peek() == i::Token::NEW);
1017 
1018  return ParseMemberWithNewPrefixesExpression(new_count, ok);
1019 }
1020 
1021 
1022 PreParser::Expression PreParser::ParseMemberExpression(bool* ok) {
1023  return ParseMemberWithNewPrefixesExpression(0, ok);
1024 }
1025 
1026 
1027 PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
1028  unsigned new_count, bool* ok) {
1029  // MemberExpression ::
1030  // (PrimaryExpression | FunctionLiteral)
1031  // ('[' Expression ']' | '.' Identifier | Arguments)*
1032 
1033  // Parse the initial primary or function expression.
1034  Expression result = Expression::Default();
1035  if (peek() == i::Token::FUNCTION) {
1036  Consume(i::Token::FUNCTION);
1037  Identifier identifier = Identifier::Default();
1038  if (peek_any_identifier()) {
1039  identifier = ParseIdentifier(CHECK_OK);
1040  }
1041  result = ParseFunctionLiteral(CHECK_OK);
1042  if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
1043  StrictModeIdentifierViolation(scanner_->location(),
1044  "strict_function_name",
1045  identifier,
1046  ok);
1047  return Expression::Default();
1048  }
1049  } else {
1050  result = ParsePrimaryExpression(CHECK_OK);
1051  }
1052 
1053  while (true) {
1054  switch (peek()) {
1055  case i::Token::LBRACK: {
1056  Consume(i::Token::LBRACK);
1057  ParseExpression(true, CHECK_OK);
1058  Expect(i::Token::RBRACK, CHECK_OK);
1059  if (result.IsThis()) {
1060  result = Expression::ThisProperty();
1061  } else {
1062  result = Expression::Default();
1063  }
1064  break;
1065  }
1066  case i::Token::PERIOD: {
1067  Consume(i::Token::PERIOD);
1068  ParseIdentifierName(CHECK_OK);
1069  if (result.IsThis()) {
1070  result = Expression::ThisProperty();
1071  } else {
1072  result = Expression::Default();
1073  }
1074  break;
1075  }
1076  case i::Token::LPAREN: {
1077  if (new_count == 0) return result;
1078  // Consume one of the new prefixes (already parsed).
1079  ParseArguments(CHECK_OK);
1080  new_count--;
1081  result = Expression::Default();
1082  break;
1083  }
1084  default:
1085  return result;
1086  }
1087  }
1088 }
1089 
1090 
1091 PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
1092  // PrimaryExpression ::
1093  // 'this'
1094  // 'null'
1095  // 'true'
1096  // 'false'
1097  // Identifier
1098  // Number
1099  // String
1100  // ArrayLiteral
1101  // ObjectLiteral
1102  // RegExpLiteral
1103  // '(' Expression ')'
1104 
1105  Expression result = Expression::Default();
1106  switch (peek()) {
1107  case i::Token::THIS: {
1108  Next();
1109  result = Expression::This();
1110  break;
1111  }
1112 
1113  case i::Token::FUTURE_RESERVED_WORD: {
1114  Next();
1115  i::Scanner::Location location = scanner_->location();
1116  ReportMessageAt(location.beg_pos, location.end_pos,
1117  "reserved_word", NULL);
1118  *ok = false;
1119  return Expression::Default();
1120  }
1121 
1122  case i::Token::FUTURE_STRICT_RESERVED_WORD:
1123  if (!is_classic_mode()) {
1124  Next();
1125  i::Scanner::Location location = scanner_->location();
1126  ReportMessageAt(location, "strict_reserved_word", NULL);
1127  *ok = false;
1128  return Expression::Default();
1129  }
1130  // FALLTHROUGH
1131  case i::Token::IDENTIFIER: {
1132  Identifier id = ParseIdentifier(CHECK_OK);
1133  result = Expression::FromIdentifier(id);
1134  break;
1135  }
1136 
1137  case i::Token::NULL_LITERAL:
1138  case i::Token::TRUE_LITERAL:
1139  case i::Token::FALSE_LITERAL:
1140  case i::Token::NUMBER: {
1141  Next();
1142  break;
1143  }
1144  case i::Token::STRING: {
1145  Next();
1146  result = GetStringSymbol();
1147  break;
1148  }
1149 
1150  case i::Token::ASSIGN_DIV:
1151  result = ParseRegExpLiteral(true, CHECK_OK);
1152  break;
1153 
1154  case i::Token::DIV:
1155  result = ParseRegExpLiteral(false, CHECK_OK);
1156  break;
1157 
1158  case i::Token::LBRACK:
1159  result = ParseArrayLiteral(CHECK_OK);
1160  break;
1161 
1162  case i::Token::LBRACE:
1163  result = ParseObjectLiteral(CHECK_OK);
1164  break;
1165 
1166  case i::Token::LPAREN:
1167  Consume(i::Token::LPAREN);
1168  parenthesized_function_ = (peek() == i::Token::FUNCTION);
1169  result = ParseExpression(true, CHECK_OK);
1170  Expect(i::Token::RPAREN, CHECK_OK);
1171  result = result.Parenthesize();
1172  break;
1173 
1174  case i::Token::MOD:
1175  result = ParseV8Intrinsic(CHECK_OK);
1176  break;
1177 
1178  default: {
1179  Next();
1180  *ok = false;
1181  return Expression::Default();
1182  }
1183  }
1184 
1185  return result;
1186 }
1187 
1188 
1189 PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
1190  // ArrayLiteral ::
1191  // '[' Expression? (',' Expression?)* ']'
1192  Expect(i::Token::LBRACK, CHECK_OK);
1193  while (peek() != i::Token::RBRACK) {
1194  if (peek() != i::Token::COMMA) {
1195  ParseAssignmentExpression(true, CHECK_OK);
1196  }
1197  if (peek() != i::Token::RBRACK) {
1198  Expect(i::Token::COMMA, CHECK_OK);
1199  }
1200  }
1201  Expect(i::Token::RBRACK, CHECK_OK);
1202 
1203  scope_->NextMaterializedLiteralIndex();
1204  return Expression::Default();
1205 }
1206 
1207 void PreParser::CheckDuplicate(DuplicateFinder* finder,
1208  i::Token::Value property,
1209  int type,
1210  bool* ok) {
1211  int old_type;
1212  if (property == i::Token::NUMBER) {
1213  old_type = finder->AddNumber(scanner_->literal_ascii_string(), type);
1214  } else if (scanner_->is_literal_ascii()) {
1215  old_type = finder->AddAsciiSymbol(scanner_->literal_ascii_string(),
1216  type);
1217  } else {
1218  old_type = finder->AddUtf16Symbol(scanner_->literal_utf16_string(), type);
1219  }
1220  if (HasConflict(old_type, type)) {
1221  if (IsDataDataConflict(old_type, type)) {
1222  // Both are data properties.
1223  if (is_classic_mode()) return;
1224  ReportMessageAt(scanner_->location(),
1225  "strict_duplicate_property", NULL);
1226  } else if (IsDataAccessorConflict(old_type, type)) {
1227  // Both a data and an accessor property with the same name.
1228  ReportMessageAt(scanner_->location(),
1229  "accessor_data_property", NULL);
1230  } else {
1231  ASSERT(IsAccessorAccessorConflict(old_type, type));
1232  // Both accessors of the same type.
1233  ReportMessageAt(scanner_->location(),
1234  "accessor_get_set", NULL);
1235  }
1236  *ok = false;
1237  }
1238 }
1239 
1240 
1241 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
1242  // ObjectLiteral ::
1243  // '{' (
1244  // ((IdentifierName | String | Number) ':' AssignmentExpression)
1245  // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1246  // )*[','] '}'
1247 
1248  Expect(i::Token::LBRACE, CHECK_OK);
1249  DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1250  while (peek() != i::Token::RBRACE) {
1251  i::Token::Value next = peek();
1252  switch (next) {
1253  case i::Token::IDENTIFIER:
1254  case i::Token::FUTURE_RESERVED_WORD:
1255  case i::Token::FUTURE_STRICT_RESERVED_WORD: {
1256  bool is_getter = false;
1257  bool is_setter = false;
1258  ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
1259  if ((is_getter || is_setter) && peek() != i::Token::COLON) {
1260  i::Token::Value name = Next();
1261  bool is_keyword = i::Token::IsKeyword(name);
1262  if (name != i::Token::IDENTIFIER &&
1263  name != i::Token::FUTURE_RESERVED_WORD &&
1264  name != i::Token::FUTURE_STRICT_RESERVED_WORD &&
1265  name != i::Token::NUMBER &&
1266  name != i::Token::STRING &&
1267  !is_keyword) {
1268  *ok = false;
1269  return Expression::Default();
1270  }
1271  if (!is_keyword) {
1272  LogSymbol();
1273  }
1274  PropertyType type = is_getter ? kGetterProperty : kSetterProperty;
1275  CheckDuplicate(&duplicate_finder, name, type, CHECK_OK);
1276  ParseFunctionLiteral(CHECK_OK);
1277  if (peek() != i::Token::RBRACE) {
1278  Expect(i::Token::COMMA, CHECK_OK);
1279  }
1280  continue; // restart the while
1281  }
1282  CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1283  break;
1284  }
1285  case i::Token::STRING:
1286  Consume(next);
1287  CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1288  GetStringSymbol();
1289  break;
1290  case i::Token::NUMBER:
1291  Consume(next);
1292  CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1293  break;
1294  default:
1295  if (i::Token::IsKeyword(next)) {
1296  Consume(next);
1297  CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1298  } else {
1299  // Unexpected token.
1300  *ok = false;
1301  return Expression::Default();
1302  }
1303  }
1304 
1305  Expect(i::Token::COLON, CHECK_OK);
1306  ParseAssignmentExpression(true, CHECK_OK);
1307 
1308  // TODO(1240767): Consider allowing trailing comma.
1309  if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
1310  }
1311  Expect(i::Token::RBRACE, CHECK_OK);
1312 
1313  scope_->NextMaterializedLiteralIndex();
1314  return Expression::Default();
1315 }
1316 
1317 
1318 PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
1319  bool* ok) {
1320  if (!scanner_->ScanRegExpPattern(seen_equal)) {
1321  Next();
1322  ReportMessageAt(scanner_->location(), "unterminated_regexp", NULL);
1323  *ok = false;
1324  return Expression::Default();
1325  }
1326 
1327  scope_->NextMaterializedLiteralIndex();
1328 
1329  if (!scanner_->ScanRegExpFlags()) {
1330  Next();
1331  ReportMessageAt(scanner_->location(), "invalid_regexp_flags", NULL);
1332  *ok = false;
1333  return Expression::Default();
1334  }
1335  Next();
1336  return Expression::Default();
1337 }
1338 
1339 
1340 PreParser::Arguments PreParser::ParseArguments(bool* ok) {
1341  // Arguments ::
1342  // '(' (AssignmentExpression)*[','] ')'
1343 
1344  Expect(i::Token::LPAREN, ok);
1345  if (!*ok) return -1;
1346  bool done = (peek() == i::Token::RPAREN);
1347  int argc = 0;
1348  while (!done) {
1349  ParseAssignmentExpression(true, ok);
1350  if (!*ok) return -1;
1351  argc++;
1352  done = (peek() == i::Token::RPAREN);
1353  if (!done) {
1354  Expect(i::Token::COMMA, ok);
1355  if (!*ok) return -1;
1356  }
1357  }
1358  Expect(i::Token::RPAREN, ok);
1359  return argc;
1360 }
1361 
1362 
1363 PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
1364  // Function ::
1365  // '(' FormalParameterList? ')' '{' FunctionBody '}'
1366 
1367  // Parse function body.
1368  ScopeType outer_scope_type = scope_->type();
1369  bool inside_with = scope_->IsInsideWith();
1370  Scope function_scope(&scope_, kFunctionScope);
1371  // FormalParameterList ::
1372  // '(' (Identifier)*[','] ')'
1373  Expect(i::Token::LPAREN, CHECK_OK);
1374  int start_position = scanner_->location().beg_pos;
1375  bool done = (peek() == i::Token::RPAREN);
1376  DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1377  while (!done) {
1378  Identifier id = ParseIdentifier(CHECK_OK);
1379  if (!id.IsValidStrictVariable()) {
1380  StrictModeIdentifierViolation(scanner_->location(),
1381  "strict_param_name",
1382  id,
1383  CHECK_OK);
1384  }
1385  int prev_value;
1386  if (scanner_->is_literal_ascii()) {
1387  prev_value =
1388  duplicate_finder.AddAsciiSymbol(scanner_->literal_ascii_string(), 1);
1389  } else {
1390  prev_value =
1391  duplicate_finder.AddUtf16Symbol(scanner_->literal_utf16_string(), 1);
1392  }
1393 
1394  if (prev_value != 0) {
1395  SetStrictModeViolation(scanner_->location(),
1396  "strict_param_dupe",
1397  CHECK_OK);
1398  }
1399  done = (peek() == i::Token::RPAREN);
1400  if (!done) {
1401  Expect(i::Token::COMMA, CHECK_OK);
1402  }
1403  }
1404  Expect(i::Token::RPAREN, CHECK_OK);
1405 
1406  // Determine if the function will be lazily compiled.
1407  // Currently only happens to top-level functions.
1408  // Optimistically assume that all top-level functions are lazily compiled.
1409  bool is_lazily_compiled = (outer_scope_type == kTopLevelScope &&
1410  !inside_with && allow_lazy_ &&
1411  !parenthesized_function_);
1412  parenthesized_function_ = false;
1413 
1414  Expect(i::Token::LBRACE, CHECK_OK);
1415  if (is_lazily_compiled) {
1416  ParseLazyFunctionLiteralBody(CHECK_OK);
1417  } else {
1418  ParseSourceElements(i::Token::RBRACE, ok);
1419  }
1420  Expect(i::Token::RBRACE, CHECK_OK);
1421 
1422  if (!is_classic_mode()) {
1423  int end_position = scanner_->location().end_pos;
1424  CheckOctalLiteral(start_position, end_position, CHECK_OK);
1425  CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK);
1426  return Expression::StrictFunction();
1427  }
1428 
1429  return Expression::Default();
1430 }
1431 
1432 
1433 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
1434  int body_start = scanner_->location().beg_pos;
1435  log_->PauseRecording();
1436  ParseSourceElements(i::Token::RBRACE, ok);
1437  log_->ResumeRecording();
1438  if (!*ok) return;
1439 
1440  // Position right after terminal '}'.
1441  ASSERT_EQ(i::Token::RBRACE, scanner_->peek());
1442  int body_end = scanner_->peek_location().end_pos;
1443  log_->LogFunction(body_start, body_end,
1444  scope_->materialized_literal_count(),
1445  scope_->expected_properties(),
1446  language_mode());
1447 }
1448 
1449 
1450 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
1451  // CallRuntime ::
1452  // '%' Identifier Arguments
1453  Expect(i::Token::MOD, CHECK_OK);
1454  if (!allow_natives_syntax_) {
1455  *ok = false;
1456  return Expression::Default();
1457  }
1458  ParseIdentifier(CHECK_OK);
1459  ParseArguments(ok);
1460 
1461  return Expression::Default();
1462 }
1463 
1464 #undef CHECK_OK
1465 
1466 
1467 void PreParser::ExpectSemicolon(bool* ok) {
1468  // Check for automatic semicolon insertion according to
1469  // the rules given in ECMA-262, section 7.9, page 21.
1470  i::Token::Value tok = peek();
1471  if (tok == i::Token::SEMICOLON) {
1472  Next();
1473  return;
1474  }
1475  if (scanner_->HasAnyLineTerminatorBeforeNext() ||
1476  tok == i::Token::RBRACE ||
1477  tok == i::Token::EOS) {
1478  return;
1479  }
1480  Expect(i::Token::SEMICOLON, ok);
1481 }
1482 
1483 
1484 void PreParser::LogSymbol() {
1485  int identifier_pos = scanner_->location().beg_pos;
1486  if (scanner_->is_literal_ascii()) {
1487  log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
1488  } else {
1489  log_->LogUtf16Symbol(identifier_pos, scanner_->literal_utf16_string());
1490  }
1491 }
1492 
1493 
1494 PreParser::Expression PreParser::GetStringSymbol() {
1495  const int kUseStrictLength = 10;
1496  const char* kUseStrictChars = "use strict";
1497  LogSymbol();
1498  if (scanner_->is_literal_ascii() &&
1499  scanner_->literal_length() == kUseStrictLength &&
1500  !scanner_->literal_contains_escapes() &&
1501  !strncmp(scanner_->literal_ascii_string().start(), kUseStrictChars,
1502  kUseStrictLength)) {
1503  return Expression::UseStrictStringLiteral();
1504  }
1505  return Expression::StringLiteral();
1506 }
1507 
1508 
1509 PreParser::Identifier PreParser::GetIdentifierSymbol() {
1510  LogSymbol();
1511  if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) {
1512  return Identifier::FutureReserved();
1513  } else if (scanner_->current_token() ==
1514  i::Token::FUTURE_STRICT_RESERVED_WORD) {
1515  return Identifier::FutureStrictReserved();
1516  }
1517  if (scanner_->is_literal_ascii()) {
1518  // Detect strict-mode poison words.
1519  if (scanner_->literal_length() == 4 &&
1520  !strncmp(scanner_->literal_ascii_string().start(), "eval", 4)) {
1521  return Identifier::Eval();
1522  }
1523  if (scanner_->literal_length() == 9 &&
1524  !strncmp(scanner_->literal_ascii_string().start(), "arguments", 9)) {
1525  return Identifier::Arguments();
1526  }
1527  }
1528  return Identifier::Default();
1529 }
1530 
1531 
1532 PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
1533  i::Token::Value next = Next();
1534  switch (next) {
1535  case i::Token::FUTURE_RESERVED_WORD: {
1536  i::Scanner::Location location = scanner_->location();
1537  ReportMessageAt(location.beg_pos, location.end_pos,
1538  "reserved_word", NULL);
1539  *ok = false;
1540  return GetIdentifierSymbol();
1541  }
1542  case i::Token::FUTURE_STRICT_RESERVED_WORD:
1543  if (!is_classic_mode()) {
1544  i::Scanner::Location location = scanner_->location();
1545  ReportMessageAt(location.beg_pos, location.end_pos,
1546  "strict_reserved_word", NULL);
1547  *ok = false;
1548  }
1549  // FALLTHROUGH
1550  case i::Token::IDENTIFIER:
1551  return GetIdentifierSymbol();
1552  default:
1553  *ok = false;
1554  return Identifier::Default();
1555  }
1556 }
1557 
1558 
1559 void PreParser::SetStrictModeViolation(i::Scanner::Location location,
1560  const char* type,
1561  bool* ok) {
1562  if (!is_classic_mode()) {
1563  ReportMessageAt(location, type, NULL);
1564  *ok = false;
1565  return;
1566  }
1567  // Delay report in case this later turns out to be strict code
1568  // (i.e., for function names and parameters prior to a "use strict"
1569  // directive).
1570  // It's safe to overwrite an existing violation.
1571  // It's either from a function that turned out to be non-strict,
1572  // or it's in the current function (and we just need to report
1573  // one error), or it's in a unclosed nesting function that wasn't
1574  // strict (otherwise we would already be in strict mode).
1575  strict_mode_violation_location_ = location;
1576  strict_mode_violation_type_ = type;
1577 }
1578 
1579 
1580 void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
1581  int end_pos,
1582  bool* ok) {
1583  i::Scanner::Location location = strict_mode_violation_location_;
1584  if (location.IsValid() &&
1585  location.beg_pos > beg_pos && location.end_pos < end_pos) {
1586  ReportMessageAt(location, strict_mode_violation_type_, NULL);
1587  *ok = false;
1588  }
1589 }
1590 
1591 
1592 void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
1593  const char* eval_args_type,
1594  Identifier identifier,
1595  bool* ok) {
1596  const char* type = eval_args_type;
1597  if (identifier.IsFutureReserved()) {
1598  type = "reserved_word";
1599  } else if (identifier.IsFutureStrictReserved()) {
1600  type = "strict_reserved_word";
1601  }
1602  if (!is_classic_mode()) {
1603  ReportMessageAt(location, type, NULL);
1604  *ok = false;
1605  return;
1606  }
1607  strict_mode_violation_location_ = location;
1608  strict_mode_violation_type_ = type;
1609 }
1610 
1611 
1612 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
1613  i::Token::Value next = Next();
1614  if (i::Token::IsKeyword(next)) {
1615  int pos = scanner_->location().beg_pos;
1616  const char* keyword = i::Token::String(next);
1617  log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword,
1618  i::StrLength(keyword)));
1619  return Identifier::Default();
1620  }
1621  if (next == i::Token::IDENTIFIER ||
1622  next == i::Token::FUTURE_RESERVED_WORD ||
1623  next == i::Token::FUTURE_STRICT_RESERVED_WORD) {
1624  return GetIdentifierSymbol();
1625  }
1626  *ok = false;
1627  return Identifier::Default();
1628 }
1629 
1630 #undef CHECK_OK
1631 
1632 
1633 // This function reads an identifier and determines whether or not it
1634 // is 'get' or 'set'.
1635 PreParser::Identifier PreParser::ParseIdentifierNameOrGetOrSet(bool* is_get,
1636  bool* is_set,
1637  bool* ok) {
1638  Identifier result = ParseIdentifierName(ok);
1639  if (!*ok) return Identifier::Default();
1640  if (scanner_->is_literal_ascii() &&
1641  scanner_->literal_length() == 3) {
1642  const char* token = scanner_->literal_ascii_string().start();
1643  *is_get = strncmp(token, "get", 3) == 0;
1644  *is_set = !*is_get && strncmp(token, "set", 3) == 0;
1645  }
1646  return result;
1647 }
1648 
1649 bool PreParser::peek_any_identifier() {
1650  i::Token::Value next = peek();
1651  return next == i::Token::IDENTIFIER ||
1652  next == i::Token::FUTURE_RESERVED_WORD ||
1653  next == i::Token::FUTURE_STRICT_RESERVED_WORD;
1654 }
1655 
1656 
1658  return AddSymbol(i::Vector<const byte>::cast(key), true, value);
1659 }
1660 
1662  return AddSymbol(i::Vector<const byte>::cast(key), false, value);
1663 }
1664 
1665 int DuplicateFinder::AddSymbol(i::Vector<const byte> key,
1666  bool is_ascii,
1667  int value) {
1668  uint32_t hash = Hash(key, is_ascii);
1669  byte* encoding = BackupKey(key, is_ascii);
1670  i::HashMap::Entry* entry = map_.Lookup(encoding, hash, true);
1671  int old_value = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1672  entry->value =
1673  reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value));
1674  return old_value;
1675 }
1676 
1677 
1679  ASSERT(key.length() > 0);
1680  // Quick check for already being in canonical form.
1681  if (IsNumberCanonical(key)) {
1682  return AddAsciiSymbol(key, value);
1683  }
1684 
1686  double double_value = StringToDouble(unicode_constants_, key, flags, 0.0);
1687  int length;
1688  const char* string;
1689  if (!isfinite(double_value)) {
1690  string = "Infinity";
1691  length = 8; // strlen("Infinity");
1692  } else {
1693  string = DoubleToCString(double_value,
1694  i::Vector<char>(number_buffer_, kBufferSize));
1695  length = i::StrLength(string);
1696  }
1697  return AddSymbol(i::Vector<const byte>(reinterpret_cast<const byte*>(string),
1698  length), true, value);
1699 }
1700 
1701 
1702 bool DuplicateFinder::IsNumberCanonical(i::Vector<const char> number) {
1703  // Test for a safe approximation of number literals that are already
1704  // in canonical form: max 15 digits, no leading zeroes, except an
1705  // integer part that is a single zero, and no trailing zeros below
1706  // the decimal point.
1707  int pos = 0;
1708  int length = number.length();
1709  if (number.length() > 15) return false;
1710  if (number[pos] == '0') {
1711  pos++;
1712  } else {
1713  while (pos < length &&
1714  static_cast<unsigned>(number[pos] - '0') <= ('9' - '0')) pos++;
1715  }
1716  if (length == pos) return true;
1717  if (number[pos] != '.') return false;
1718  pos++;
1719  bool invalid_last_digit = true;
1720  while (pos < length) {
1721  byte digit = number[pos] - '0';
1722  if (digit > '9' - '0') return false;
1723  invalid_last_digit = (digit == 0);
1724  pos++;
1725  }
1726  return !invalid_last_digit;
1727 }
1728 
1729 
1730 uint32_t DuplicateFinder::Hash(i::Vector<const byte> key, bool is_ascii) {
1731  // Primitive hash function, almost identical to the one used
1732  // for strings (except that it's seeded by the length and ASCII-ness).
1733  int length = key.length();
1734  uint32_t hash = (length << 1) | (is_ascii ? 1 : 0) ;
1735  for (int i = 0; i < length; i++) {
1736  uint32_t c = key[i];
1737  hash = (hash + c) * 1025;
1738  hash ^= (hash >> 6);
1739  }
1740  return hash;
1741 }
1742 
1743 
1744 bool DuplicateFinder::Match(void* first, void* second) {
1745  // Decode lengths.
1746  // Length + ASCII-bit is encoded as base 128, most significant heptet first,
1747  // with a 8th bit being non-zero while there are more heptets.
1748  // The value encodes the number of bytes following, and whether the original
1749  // was ASCII.
1750  byte* s1 = reinterpret_cast<byte*>(first);
1751  byte* s2 = reinterpret_cast<byte*>(second);
1752  uint32_t length_ascii_field = 0;
1753  byte c1;
1754  do {
1755  c1 = *s1;
1756  if (c1 != *s2) return false;
1757  length_ascii_field = (length_ascii_field << 7) | (c1 & 0x7f);
1758  s1++;
1759  s2++;
1760  } while ((c1 & 0x80) != 0);
1761  int length = static_cast<int>(length_ascii_field >> 1);
1762  return memcmp(s1, s2, length) == 0;
1763 }
1764 
1765 
1766 byte* DuplicateFinder::BackupKey(i::Vector<const byte> bytes,
1767  bool is_ascii) {
1768  uint32_t ascii_length = (bytes.length() << 1) | (is_ascii ? 1 : 0);
1769  backing_store_.StartSequence();
1770  // Emit ascii_length as base-128 encoded number, with the 7th bit set
1771  // on the byte of every heptet except the last, least significant, one.
1772  if (ascii_length >= (1 << 7)) {
1773  if (ascii_length >= (1 << 14)) {
1774  if (ascii_length >= (1 << 21)) {
1775  if (ascii_length >= (1 << 28)) {
1776  backing_store_.Add(static_cast<byte>((ascii_length >> 28) | 0x80));
1777  }
1778  backing_store_.Add(static_cast<byte>((ascii_length >> 21) | 0x80u));
1779  }
1780  backing_store_.Add(static_cast<byte>((ascii_length >> 14) | 0x80u));
1781  }
1782  backing_store_.Add(static_cast<byte>((ascii_length >> 7) | 0x80u));
1783  }
1784  backing_store_.Add(static_cast<byte>(ascii_length & 0x7f));
1785 
1786  backing_store_.AddBlock(bytes);
1787  return backing_store_.EndSequence().start();
1788 }
1789 } } // v8::preparser
const SwVfpRegister s2
static int Precedence(Value tok)
Definition: token.h:282
static bool IsUnaryOp(Value op)
Definition: token.h:260
int literal_length() const
Definition: scanner.h:349
void Add(T value)
Definition: utils.h:566
#define ASSERT(condition)
Definition: checks.h:270
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage including flags
bool HasAnyLineTerminatorBeforeNext() const
Definition: scanner.h:423
int AddNumber(i::Vector< const char > key, int value)
Definition: preparser.cc:1678
virtual void LogFunction(int start, int end, int literals, int properties, LanguageMode language_mode)=0
double StringToDouble(UnicodeCache *unicode_cache, const char *str, int flags, double empty_string_val)
Definition: conversions.cc:41
#define IN
uint8_t byte
Definition: preparser.h:43
Vector< T > AddBlock(int size, T initial_value)
Definition: utils.h:579
T * start() const
Definition: utils.h:390
bool literal_contains_escapes() const
Definition: scanner.h:354
virtual void LogAsciiSymbol(int start, Vector< const char > literal)
Definition: preparse-data.h:55
static const char * String(Value tok)
Definition: token.h:275
const char * DoubleToCString(double v, Vector< char > buffer)
Definition: conversions.cc:68
static bool IsAssignmentOp(Value tok)
Definition: token.h:206
virtual void ResumeRecording()=0
Entry * Lookup(void *key, uint32_t hash, bool insert, AllocationPolicy allocator=AllocationPolicy())
Definition: hashmap.h:131
int length() const
Definition: utils.h:384
#define CHECK_OK
Definition: preparser.cc:785
bool is_literal_ascii()
Definition: scanner.h:345
int AddUtf16Symbol(i::Vector< const uint16_t > key, int value)
Definition: preparser.cc:1661
static bool IsKeyword(Value tok)
Definition: token.h:202
int AddAsciiSymbol(i::Vector< const char > key, int value)
Definition: preparser.cc:1657
int StrLength(const char *string)
Definition: utils.h:234
PreParseResult PreParseLazyFunction(i::LanguageMode mode, i::ParserRecorder *log)
Definition: preparser.cc:55
const SwVfpRegister s1
Location location() const
Definition: scanner.h:330
Vector< T > EndSequence()
Definition: utils.h:715
virtual void PauseRecording()=0
virtual void LogUtf16Symbol(int start, Vector< const uc16 > literal)
Definition: preparse-data.h:56
void clear_octal_position()
Definition: scanner.h:399
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
Vector< const char > literal_ascii_string()
Definition: scanner.h:337
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Token::Value peek() const
Definition: scanner.h:367
Location octal_position() const
Definition: scanner.h:398
Token::Value current_token()
Definition: scanner.h:327
Vector< const uc16 > literal_utf16_string()
Definition: scanner.h:341
bool ScanRegExpPattern(bool seen_equal)
Definition: scanner.cc:993
static bool IsCountOp(Value op)
Definition: token.h:264
UnicodeCache * unicode_cache()
Definition: scanner.h:390
int isfinite(double x)
Location peek_location() const
Definition: scanner.h:369