preparser.cc revision b8e0da25ee8efac3bb05cd6b2730aafbd96119f4
1
2// Copyright 2010 the V8 project authors. All rights reserved.
3// Redistribution and use in source and binary forms, with or without
4// modification, are permitted provided that the following conditions are
5// met:
6//
7//     * Redistributions of source code must retain the above copyright
8//       notice, this list of conditions and the following disclaimer.
9//     * Redistributions in binary form must reproduce the above
10//       copyright notice, this list of conditions and the following
11//       disclaimer in the documentation and/or other materials provided
12//       with the distribution.
13//     * Neither the name of Google Inc. nor the names of its
14//       contributors may be used to endorse or promote products derived
15//       from this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29#include "../include/v8stdint.h"
30#include "unicode.h"
31#include "globals.h"
32#include "checks.h"
33#include "allocation.h"
34#include "utils.h"
35#include "list.h"
36#include "scanner-base.h"
37#include "preparse-data.h"
38#include "preparser.h"
39
40namespace v8 {
41namespace preparser {
42
43// Preparsing checks a JavaScript program and emits preparse-data that helps
44// a later parsing to be faster.
45// See preparser-data.h for the data.
46
47// The PreParser checks that the syntax follows the grammar for JavaScript,
48// and collects some information about the program along the way.
49// The grammar check is only performed in order to understand the program
50// sufficiently to deduce some information about it, that can be used
51// to speed up later parsing. Finding errors is not the goal of pre-parsing,
52// rather it is to speed up properly written and correct programs.
53// That means that contextual checks (like a label being declared where
54// it is used) are generally omitted.
55
56namespace i = ::v8::internal;
57
58#define CHECK_OK  ok);  \
59  if (!*ok) return -1;  \
60  ((void)0
61#define DUMMY )  // to make indentation work
62#undef DUMMY
63
64
65void PreParser::ReportUnexpectedToken(i::Token::Value token) {
66  // We don't report stack overflows here, to avoid increasing the
67  // stack depth even further.  Instead we report it after parsing is
68  // over, in ParseProgram.
69  if (token == i::Token::ILLEGAL && stack_overflow_) {
70    return;
71  }
72  i::JavaScriptScanner::Location source_location = scanner_->location();
73
74  // Four of the tokens are treated specially
75  switch (token) {
76  case i::Token::EOS:
77    return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
78                           "unexpected_eos", NULL);
79  case i::Token::NUMBER:
80    return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
81                           "unexpected_token_number", NULL);
82  case i::Token::STRING:
83    return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
84                           "unexpected_token_string", NULL);
85  case i::Token::IDENTIFIER:
86    return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
87                           "unexpected_token_identifier", NULL);
88  default:
89    const char* name = i::Token::String(token);
90    ReportMessageAt(source_location.beg_pos, source_location.end_pos,
91                    "unexpected_token", name);
92  }
93}
94
95
96PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
97                                                         bool* ok) {
98  // SourceElements ::
99  //   (Statement)* <end_token>
100
101  while (peek() != end_token) {
102    ParseStatement(CHECK_OK);
103  }
104  return kUnknownSourceElements;
105}
106
107
108PreParser::Statement PreParser::ParseStatement(bool* ok) {
109  // Statement ::
110  //   Block
111  //   VariableStatement
112  //   EmptyStatement
113  //   ExpressionStatement
114  //   IfStatement
115  //   IterationStatement
116  //   ContinueStatement
117  //   BreakStatement
118  //   ReturnStatement
119  //   WithStatement
120  //   LabelledStatement
121  //   SwitchStatement
122  //   ThrowStatement
123  //   TryStatement
124  //   DebuggerStatement
125
126  // Note: Since labels can only be used by 'break' and 'continue'
127  // statements, which themselves are only valid within blocks,
128  // iterations or 'switch' statements (i.e., BreakableStatements),
129  // labels can be simply ignored in all other cases; except for
130  // trivial labeled break statements 'label: break label' which is
131  // parsed into an empty statement.
132
133  // Keep the source position of the statement
134  switch (peek()) {
135    case i::Token::LBRACE:
136      return ParseBlock(ok);
137
138    case i::Token::CONST:
139    case i::Token::VAR:
140      return ParseVariableStatement(ok);
141
142    case i::Token::SEMICOLON:
143      Next();
144      return kUnknownStatement;
145
146    case i::Token::IF:
147      return  ParseIfStatement(ok);
148
149    case i::Token::DO:
150      return ParseDoWhileStatement(ok);
151
152    case i::Token::WHILE:
153      return ParseWhileStatement(ok);
154
155    case i::Token::FOR:
156      return ParseForStatement(ok);
157
158    case i::Token::CONTINUE:
159      return ParseContinueStatement(ok);
160
161    case i::Token::BREAK:
162      return ParseBreakStatement(ok);
163
164    case i::Token::RETURN:
165      return ParseReturnStatement(ok);
166
167    case i::Token::WITH:
168      return ParseWithStatement(ok);
169
170    case i::Token::SWITCH:
171      return ParseSwitchStatement(ok);
172
173    case i::Token::THROW:
174      return ParseThrowStatement(ok);
175
176    case i::Token::TRY:
177      return ParseTryStatement(ok);
178
179    case i::Token::FUNCTION:
180      return ParseFunctionDeclaration(ok);
181
182    case i::Token::NATIVE:
183      return ParseNativeDeclaration(ok);
184
185    case i::Token::DEBUGGER:
186      return ParseDebuggerStatement(ok);
187
188    default:
189      return ParseExpressionOrLabelledStatement(ok);
190  }
191}
192
193
194PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
195  // FunctionDeclaration ::
196  //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
197  Expect(i::Token::FUNCTION, CHECK_OK);
198  ParseIdentifier(CHECK_OK);
199  ParseFunctionLiteral(CHECK_OK);
200  return kUnknownStatement;
201}
202
203
204// Language extension which is only enabled for source files loaded
205// through the API's extension mechanism.  A native function
206// declaration is resolved by looking up the function through a
207// callback provided by the extension.
208PreParser::Statement PreParser::ParseNativeDeclaration(bool* ok) {
209  Expect(i::Token::NATIVE, CHECK_OK);
210  Expect(i::Token::FUNCTION, CHECK_OK);
211  ParseIdentifier(CHECK_OK);
212  Expect(i::Token::LPAREN, CHECK_OK);
213  bool done = (peek() == i::Token::RPAREN);
214  while (!done) {
215    ParseIdentifier(CHECK_OK);
216    done = (peek() == i::Token::RPAREN);
217    if (!done) {
218      Expect(i::Token::COMMA, CHECK_OK);
219    }
220  }
221  Expect(i::Token::RPAREN, CHECK_OK);
222  Expect(i::Token::SEMICOLON, CHECK_OK);
223  return kUnknownStatement;
224}
225
226
227PreParser::Statement PreParser::ParseBlock(bool* ok) {
228  // Block ::
229  //   '{' Statement* '}'
230
231  // Note that a Block does not introduce a new execution scope!
232  // (ECMA-262, 3rd, 12.2)
233  //
234  Expect(i::Token::LBRACE, CHECK_OK);
235  while (peek() != i::Token::RBRACE) {
236    ParseStatement(CHECK_OK);
237  }
238  Expect(i::Token::RBRACE, CHECK_OK);
239  return kUnknownStatement;
240}
241
242
243PreParser::Statement PreParser::ParseVariableStatement(bool* ok) {
244  // VariableStatement ::
245  //   VariableDeclarations ';'
246
247  Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK);
248  ExpectSemicolon(CHECK_OK);
249  return result;
250}
251
252
253// If the variable declaration declares exactly one non-const
254// variable, then *var is set to that variable. In all other cases,
255// *var is untouched; in particular, it is the caller's responsibility
256// to initialize it properly. This mechanism is also used for the parsing
257// of 'for-in' loops.
258PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN,
259                                                          int* num_decl,
260                                                          bool* ok) {
261  // VariableDeclarations ::
262  //   ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
263
264  if (peek() == i::Token::VAR) {
265    Consume(i::Token::VAR);
266  } else if (peek() == i::Token::CONST) {
267    Consume(i::Token::CONST);
268  } else {
269    *ok = false;
270    return 0;
271  }
272
273  // The scope of a variable/const declared anywhere inside a function
274  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). .
275  int nvars = 0;  // the number of variables declared
276  do {
277    // Parse variable name.
278    if (nvars > 0) Consume(i::Token::COMMA);
279    ParseIdentifier(CHECK_OK);
280    nvars++;
281    if (peek() == i::Token::ASSIGN) {
282      Expect(i::Token::ASSIGN, CHECK_OK);
283      ParseAssignmentExpression(accept_IN, CHECK_OK);
284    }
285  } while (peek() == i::Token::COMMA);
286
287  if (num_decl != NULL) *num_decl = nvars;
288  return kUnknownStatement;
289}
290
291
292PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(
293    bool* ok) {
294  // ExpressionStatement | LabelledStatement ::
295  //   Expression ';'
296  //   Identifier ':' Statement
297
298  Expression expr = ParseExpression(true, CHECK_OK);
299  if (peek() == i::Token::COLON && expr == kIdentifierExpression) {
300    Consume(i::Token::COLON);
301    return ParseStatement(ok);
302  }
303  // Parsed expression statement.
304  ExpectSemicolon(CHECK_OK);
305  return kUnknownStatement;
306}
307
308
309PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
310  // IfStatement ::
311  //   'if' '(' Expression ')' Statement ('else' Statement)?
312
313  Expect(i::Token::IF, CHECK_OK);
314  Expect(i::Token::LPAREN, CHECK_OK);
315  ParseExpression(true, CHECK_OK);
316  Expect(i::Token::RPAREN, CHECK_OK);
317  ParseStatement(CHECK_OK);
318  if (peek() == i::Token::ELSE) {
319    Next();
320    ParseStatement(CHECK_OK);
321  }
322  return kUnknownStatement;
323}
324
325
326PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
327  // ContinueStatement ::
328  //   'continue' [no line terminator] Identifier? ';'
329
330  Expect(i::Token::CONTINUE, CHECK_OK);
331  i::Token::Value tok = peek();
332  if (!scanner_->has_line_terminator_before_next() &&
333      tok != i::Token::SEMICOLON &&
334      tok != i::Token::RBRACE &&
335      tok != i::Token::EOS) {
336    ParseIdentifier(CHECK_OK);
337  }
338  ExpectSemicolon(CHECK_OK);
339  return kUnknownStatement;
340}
341
342
343PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
344  // BreakStatement ::
345  //   'break' [no line terminator] Identifier? ';'
346
347  Expect(i::Token::BREAK, CHECK_OK);
348  i::Token::Value tok = peek();
349  if (!scanner_->has_line_terminator_before_next() &&
350      tok != i::Token::SEMICOLON &&
351      tok != i::Token::RBRACE &&
352      tok != i::Token::EOS) {
353    ParseIdentifier(CHECK_OK);
354  }
355  ExpectSemicolon(CHECK_OK);
356  return kUnknownStatement;
357}
358
359
360PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
361  // ReturnStatement ::
362  //   'return' [no line terminator] Expression? ';'
363
364  // Consume the return token. It is necessary to do the before
365  // reporting any errors on it, because of the way errors are
366  // reported (underlining).
367  Expect(i::Token::RETURN, CHECK_OK);
368
369  // An ECMAScript program is considered syntactically incorrect if it
370  // contains a return statement that is not within the body of a
371  // function. See ECMA-262, section 12.9, page 67.
372  // This is not handled during preparsing.
373
374  i::Token::Value tok = peek();
375  if (!scanner_->has_line_terminator_before_next() &&
376      tok != i::Token::SEMICOLON &&
377      tok != i::Token::RBRACE &&
378      tok != i::Token::EOS) {
379    ParseExpression(true, CHECK_OK);
380  }
381  ExpectSemicolon(CHECK_OK);
382  return kUnknownStatement;
383}
384
385
386PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
387  // WithStatement ::
388  //   'with' '(' Expression ')' Statement
389  Expect(i::Token::WITH, CHECK_OK);
390  Expect(i::Token::LPAREN, CHECK_OK);
391  ParseExpression(true, CHECK_OK);
392  Expect(i::Token::RPAREN, CHECK_OK);
393
394  scope_->EnterWith();
395  ParseStatement(CHECK_OK);
396  scope_->LeaveWith();
397  return kUnknownStatement;
398}
399
400
401PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
402  // SwitchStatement ::
403  //   'switch' '(' Expression ')' '{' CaseClause* '}'
404
405  Expect(i::Token::SWITCH, CHECK_OK);
406  Expect(i::Token::LPAREN, CHECK_OK);
407  ParseExpression(true, CHECK_OK);
408  Expect(i::Token::RPAREN, CHECK_OK);
409
410  Expect(i::Token::LBRACE, CHECK_OK);
411  i::Token::Value token = peek();
412  while (token != i::Token::RBRACE) {
413    if (token == i::Token::CASE) {
414      Expect(i::Token::CASE, CHECK_OK);
415      ParseExpression(true, CHECK_OK);
416      Expect(i::Token::COLON, CHECK_OK);
417    } else if (token == i::Token::DEFAULT) {
418      Expect(i::Token::DEFAULT, CHECK_OK);
419      Expect(i::Token::COLON, CHECK_OK);
420    } else {
421      ParseStatement(CHECK_OK);
422    }
423    token = peek();
424  }
425  Expect(i::Token::RBRACE, CHECK_OK);
426
427  return kUnknownStatement;
428}
429
430
431PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
432  // DoStatement ::
433  //   'do' Statement 'while' '(' Expression ')' ';'
434
435  Expect(i::Token::DO, CHECK_OK);
436  ParseStatement(CHECK_OK);
437  Expect(i::Token::WHILE, CHECK_OK);
438  Expect(i::Token::LPAREN, CHECK_OK);
439  ParseExpression(true, CHECK_OK);
440  Expect(i::Token::RPAREN, CHECK_OK);
441  return kUnknownStatement;
442}
443
444
445PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
446  // WhileStatement ::
447  //   'while' '(' Expression ')' Statement
448
449  Expect(i::Token::WHILE, CHECK_OK);
450  Expect(i::Token::LPAREN, CHECK_OK);
451  ParseExpression(true, CHECK_OK);
452  Expect(i::Token::RPAREN, CHECK_OK);
453  ParseStatement(CHECK_OK);
454  return kUnknownStatement;
455}
456
457
458PreParser::Statement PreParser::ParseForStatement(bool* ok) {
459  // ForStatement ::
460  //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
461
462  Expect(i::Token::FOR, CHECK_OK);
463  Expect(i::Token::LPAREN, CHECK_OK);
464  if (peek() != i::Token::SEMICOLON) {
465    if (peek() == i::Token::VAR || peek() == i::Token::CONST) {
466      int decl_count;
467      ParseVariableDeclarations(false, &decl_count, CHECK_OK);
468      if (peek() == i::Token::IN && decl_count == 1) {
469        Expect(i::Token::IN, CHECK_OK);
470        ParseExpression(true, CHECK_OK);
471        Expect(i::Token::RPAREN, CHECK_OK);
472
473        ParseStatement(CHECK_OK);
474        return kUnknownStatement;
475      }
476    } else {
477      ParseExpression(false, CHECK_OK);
478      if (peek() == i::Token::IN) {
479        Expect(i::Token::IN, CHECK_OK);
480        ParseExpression(true, CHECK_OK);
481        Expect(i::Token::RPAREN, CHECK_OK);
482
483        ParseStatement(CHECK_OK);
484        return kUnknownStatement;
485      }
486    }
487  }
488
489  // Parsed initializer at this point.
490  Expect(i::Token::SEMICOLON, CHECK_OK);
491
492  if (peek() != i::Token::SEMICOLON) {
493    ParseExpression(true, CHECK_OK);
494  }
495  Expect(i::Token::SEMICOLON, CHECK_OK);
496
497  if (peek() != i::Token::RPAREN) {
498    ParseExpression(true, CHECK_OK);
499  }
500  Expect(i::Token::RPAREN, CHECK_OK);
501
502  ParseStatement(CHECK_OK);
503  return kUnknownStatement;
504}
505
506
507PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
508  // ThrowStatement ::
509  //   'throw' [no line terminator] Expression ';'
510
511  Expect(i::Token::THROW, CHECK_OK);
512  if (scanner_->has_line_terminator_before_next()) {
513    i::JavaScriptScanner::Location pos = scanner_->location();
514    ReportMessageAt(pos.beg_pos, pos.end_pos,
515                    "newline_after_throw", NULL);
516    *ok = false;
517    return kUnknownStatement;
518  }
519  ParseExpression(true, CHECK_OK);
520  ExpectSemicolon(CHECK_OK);
521
522  return kUnknownStatement;
523}
524
525
526PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
527  // TryStatement ::
528  //   'try' Block Catch
529  //   'try' Block Finally
530  //   'try' Block Catch Finally
531  //
532  // Catch ::
533  //   'catch' '(' Identifier ')' Block
534  //
535  // Finally ::
536  //   'finally' Block
537
538  // In preparsing, allow any number of catch/finally blocks, including zero
539  // of both.
540
541  Expect(i::Token::TRY, CHECK_OK);
542
543  ParseBlock(CHECK_OK);
544
545  bool catch_or_finally_seen = false;
546  if (peek() == i::Token::CATCH) {
547    Consume(i::Token::CATCH);
548    Expect(i::Token::LPAREN, CHECK_OK);
549    ParseIdentifier(CHECK_OK);
550    Expect(i::Token::RPAREN, CHECK_OK);
551    scope_->EnterWith();
552    ParseBlock(ok);
553    scope_->LeaveWith();
554    if (!*ok) return kUnknownStatement;
555    catch_or_finally_seen = true;
556  }
557  if (peek() == i::Token::FINALLY) {
558    Consume(i::Token::FINALLY);
559    ParseBlock(CHECK_OK);
560    catch_or_finally_seen = true;
561  }
562  if (!catch_or_finally_seen) {
563    *ok = false;
564  }
565  return kUnknownStatement;
566}
567
568
569PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
570  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
571  // contexts this is used as a statement which invokes the debugger as if a
572  // break point is present.
573  // DebuggerStatement ::
574  //   'debugger' ';'
575
576  Expect(i::Token::DEBUGGER, CHECK_OK);
577  ExpectSemicolon(CHECK_OK);
578  return kUnknownStatement;
579}
580
581
582// Precedence = 1
583PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) {
584  // Expression ::
585  //   AssignmentExpression
586  //   Expression ',' AssignmentExpression
587
588  Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
589  while (peek() == i::Token::COMMA) {
590    Expect(i::Token::COMMA, CHECK_OK);
591    ParseAssignmentExpression(accept_IN, CHECK_OK);
592    result = kUnknownExpression;
593  }
594  return result;
595}
596
597
598// Precedence = 2
599PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
600                                                           bool* ok) {
601  // AssignmentExpression ::
602  //   ConditionalExpression
603  //   LeftHandSideExpression AssignmentOperator AssignmentExpression
604
605  Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
606
607  if (!i::Token::IsAssignmentOp(peek())) {
608    // Parsed conditional expression only (no assignment).
609    return expression;
610  }
611
612  i::Token::Value op = Next();  // Get assignment operator.
613  ParseAssignmentExpression(accept_IN, CHECK_OK);
614
615  if ((op == i::Token::ASSIGN) && (expression == kThisPropertyExpression)) {
616    scope_->AddProperty();
617  }
618
619  return kUnknownExpression;
620}
621
622
623// Precedence = 3
624PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN,
625                                                            bool* ok) {
626  // ConditionalExpression ::
627  //   LogicalOrExpression
628  //   LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
629
630  // We start using the binary expression parser for prec >= 4 only!
631  Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
632  if (peek() != i::Token::CONDITIONAL) return expression;
633  Consume(i::Token::CONDITIONAL);
634  // In parsing the first assignment expression in conditional
635  // expressions we always accept the 'in' keyword; see ECMA-262,
636  // section 11.12, page 58.
637  ParseAssignmentExpression(true, CHECK_OK);
638  Expect(i::Token::COLON, CHECK_OK);
639  ParseAssignmentExpression(accept_IN, CHECK_OK);
640  return kUnknownExpression;
641}
642
643
644int PreParser::Precedence(i::Token::Value tok, bool accept_IN) {
645  if (tok == i::Token::IN && !accept_IN)
646    return 0;  // 0 precedence will terminate binary expression parsing
647
648  return i::Token::Precedence(tok);
649}
650
651
652// Precedence >= 4
653PreParser::Expression PreParser::ParseBinaryExpression(int prec,
654                                                       bool accept_IN,
655                                                       bool* ok) {
656  Expression result = ParseUnaryExpression(CHECK_OK);
657  for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
658    // prec1 >= 4
659    while (Precedence(peek(), accept_IN) == prec1) {
660      Next();
661      ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
662      result = kUnknownExpression;
663    }
664  }
665  return result;
666}
667
668
669PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
670  // UnaryExpression ::
671  //   PostfixExpression
672  //   'delete' UnaryExpression
673  //   'void' UnaryExpression
674  //   'typeof' UnaryExpression
675  //   '++' UnaryExpression
676  //   '--' UnaryExpression
677  //   '+' UnaryExpression
678  //   '-' UnaryExpression
679  //   '~' UnaryExpression
680  //   '!' UnaryExpression
681
682  i::Token::Value op = peek();
683  if (i::Token::IsUnaryOp(op) || i::Token::IsCountOp(op)) {
684    op = Next();
685    ParseUnaryExpression(ok);
686    return kUnknownExpression;
687  } else {
688    return ParsePostfixExpression(ok);
689  }
690}
691
692
693PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
694  // PostfixExpression ::
695  //   LeftHandSideExpression ('++' | '--')?
696
697  Expression expression = ParseLeftHandSideExpression(CHECK_OK);
698  if (!scanner_->has_line_terminator_before_next() &&
699      i::Token::IsCountOp(peek())) {
700    Next();
701    return kUnknownExpression;
702  }
703  return expression;
704}
705
706
707PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) {
708  // LeftHandSideExpression ::
709  //   (NewExpression | MemberExpression) ...
710
711  Expression result;
712  if (peek() == i::Token::NEW) {
713    result = ParseNewExpression(CHECK_OK);
714  } else {
715    result = ParseMemberExpression(CHECK_OK);
716  }
717
718  while (true) {
719    switch (peek()) {
720      case i::Token::LBRACK: {
721        Consume(i::Token::LBRACK);
722        ParseExpression(true, CHECK_OK);
723        Expect(i::Token::RBRACK, CHECK_OK);
724        if (result == kThisExpression) {
725          result = kThisPropertyExpression;
726        } else {
727          result = kUnknownExpression;
728        }
729        break;
730      }
731
732      case i::Token::LPAREN: {
733        ParseArguments(CHECK_OK);
734        result = kUnknownExpression;
735        break;
736      }
737
738      case i::Token::PERIOD: {
739        Consume(i::Token::PERIOD);
740        ParseIdentifierName(CHECK_OK);
741        if (result == kThisExpression) {
742          result = kThisPropertyExpression;
743        } else {
744          result = kUnknownExpression;
745        }
746        break;
747      }
748
749      default:
750        return result;
751    }
752  }
753}
754
755
756PreParser::Expression PreParser::ParseNewExpression(bool* ok) {
757  // NewExpression ::
758  //   ('new')+ MemberExpression
759
760  // The grammar for new expressions is pretty warped. The keyword
761  // 'new' can either be a part of the new expression (where it isn't
762  // followed by an argument list) or a part of the member expression,
763  // where it must be followed by an argument list. To accommodate
764  // this, we parse the 'new' keywords greedily and keep track of how
765  // many we have parsed. This information is then passed on to the
766  // member expression parser, which is only allowed to match argument
767  // lists as long as it has 'new' prefixes left
768  unsigned new_count = 0;
769  do {
770    Consume(i::Token::NEW);
771    new_count++;
772  } while (peek() == i::Token::NEW);
773
774  return ParseMemberWithNewPrefixesExpression(new_count, ok);
775}
776
777
778PreParser::Expression PreParser::ParseMemberExpression(bool* ok) {
779  return ParseMemberWithNewPrefixesExpression(0, ok);
780}
781
782
783PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
784    unsigned new_count, bool* ok) {
785  // MemberExpression ::
786  //   (PrimaryExpression | FunctionLiteral)
787  //     ('[' Expression ']' | '.' Identifier | Arguments)*
788
789  // Parse the initial primary or function expression.
790  Expression result = kUnknownExpression;
791  if (peek() == i::Token::FUNCTION) {
792    Consume(i::Token::FUNCTION);
793    if (peek() == i::Token::IDENTIFIER) {
794      ParseIdentifier(CHECK_OK);
795    }
796    result = ParseFunctionLiteral(CHECK_OK);
797  } else {
798    result = ParsePrimaryExpression(CHECK_OK);
799  }
800
801  while (true) {
802    switch (peek()) {
803      case i::Token::LBRACK: {
804        Consume(i::Token::LBRACK);
805        ParseExpression(true, CHECK_OK);
806        Expect(i::Token::RBRACK, CHECK_OK);
807        if (result == kThisExpression) {
808          result = kThisPropertyExpression;
809        } else {
810          result = kUnknownExpression;
811        }
812        break;
813      }
814      case i::Token::PERIOD: {
815        Consume(i::Token::PERIOD);
816        ParseIdentifierName(CHECK_OK);
817        if (result == kThisExpression) {
818          result = kThisPropertyExpression;
819        } else {
820          result = kUnknownExpression;
821        }
822        break;
823      }
824      case i::Token::LPAREN: {
825        if (new_count == 0) return result;
826        // Consume one of the new prefixes (already parsed).
827        ParseArguments(CHECK_OK);
828        new_count--;
829        result = kUnknownExpression;
830        break;
831      }
832      default:
833        return result;
834    }
835  }
836}
837
838
839PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
840  // PrimaryExpression ::
841  //   'this'
842  //   'null'
843  //   'true'
844  //   'false'
845  //   Identifier
846  //   Number
847  //   String
848  //   ArrayLiteral
849  //   ObjectLiteral
850  //   RegExpLiteral
851  //   '(' Expression ')'
852
853  Expression result = kUnknownExpression;
854  switch (peek()) {
855    case i::Token::THIS: {
856      Next();
857      result = kThisExpression;
858      break;
859    }
860
861    case i::Token::IDENTIFIER: {
862      ParseIdentifier(CHECK_OK);
863      result = kIdentifierExpression;
864      break;
865    }
866
867    case i::Token::NULL_LITERAL:
868    case i::Token::TRUE_LITERAL:
869    case i::Token::FALSE_LITERAL:
870    case i::Token::NUMBER: {
871      Next();
872      break;
873    }
874    case i::Token::STRING: {
875      Next();
876      result = GetStringSymbol();
877      break;
878    }
879
880    case i::Token::ASSIGN_DIV:
881      result = ParseRegExpLiteral(true, CHECK_OK);
882      break;
883
884    case i::Token::DIV:
885      result = ParseRegExpLiteral(false, CHECK_OK);
886      break;
887
888    case i::Token::LBRACK:
889      result = ParseArrayLiteral(CHECK_OK);
890      break;
891
892    case i::Token::LBRACE:
893      result = ParseObjectLiteral(CHECK_OK);
894      break;
895
896    case i::Token::LPAREN:
897      Consume(i::Token::LPAREN);
898      parenthesized_function_ = (peek() == i::Token::FUNCTION);
899      result = ParseExpression(true, CHECK_OK);
900      Expect(i::Token::RPAREN, CHECK_OK);
901      if (result == kIdentifierExpression) result = kUnknownExpression;
902      break;
903
904    case i::Token::MOD:
905      result = ParseV8Intrinsic(CHECK_OK);
906      break;
907
908    default: {
909      Next();
910      *ok = false;
911      return kUnknownExpression;
912    }
913  }
914
915  return result;
916}
917
918
919PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
920  // ArrayLiteral ::
921  //   '[' Expression? (',' Expression?)* ']'
922  Expect(i::Token::LBRACK, CHECK_OK);
923  while (peek() != i::Token::RBRACK) {
924    if (peek() != i::Token::COMMA) {
925      ParseAssignmentExpression(true, CHECK_OK);
926    }
927    if (peek() != i::Token::RBRACK) {
928      Expect(i::Token::COMMA, CHECK_OK);
929    }
930  }
931  Expect(i::Token::RBRACK, CHECK_OK);
932
933  scope_->NextMaterializedLiteralIndex();
934  return kUnknownExpression;
935}
936
937
938PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
939  // ObjectLiteral ::
940  //   '{' (
941  //       ((IdentifierName | String | Number) ':' AssignmentExpression)
942  //     | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
943  //    )*[','] '}'
944
945  Expect(i::Token::LBRACE, CHECK_OK);
946  while (peek() != i::Token::RBRACE) {
947    i::Token::Value next = peek();
948    switch (next) {
949      case i::Token::IDENTIFIER: {
950        bool is_getter = false;
951        bool is_setter = false;
952        ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
953        if ((is_getter || is_setter) && peek() != i::Token::COLON) {
954            i::Token::Value name = Next();
955            bool is_keyword = i::Token::IsKeyword(name);
956            if (name != i::Token::IDENTIFIER &&
957                name != i::Token::NUMBER &&
958                name != i::Token::STRING &&
959                !is_keyword) {
960              *ok = false;
961              return kUnknownExpression;
962            }
963            if (!is_keyword) {
964              LogSymbol();
965            }
966            ParseFunctionLiteral(CHECK_OK);
967            if (peek() != i::Token::RBRACE) {
968              Expect(i::Token::COMMA, CHECK_OK);
969            }
970            continue;  // restart the while
971        }
972        break;
973      }
974      case i::Token::STRING:
975        Consume(next);
976        GetStringSymbol();
977        break;
978      case i::Token::NUMBER:
979        Consume(next);
980        break;
981      default:
982        if (i::Token::IsKeyword(next)) {
983          Consume(next);
984        } else {
985          // Unexpected token.
986          *ok = false;
987          return kUnknownExpression;
988        }
989    }
990
991    Expect(i::Token::COLON, CHECK_OK);
992    ParseAssignmentExpression(true, CHECK_OK);
993
994    // TODO(1240767): Consider allowing trailing comma.
995    if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
996  }
997  Expect(i::Token::RBRACE, CHECK_OK);
998
999  scope_->NextMaterializedLiteralIndex();
1000  return kUnknownExpression;
1001}
1002
1003
1004PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
1005                                                    bool* ok) {
1006  if (!scanner_->ScanRegExpPattern(seen_equal)) {
1007    Next();
1008    i::JavaScriptScanner::Location location = scanner_->location();
1009    ReportMessageAt(location.beg_pos, location.end_pos,
1010                    "unterminated_regexp", NULL);
1011    *ok = false;
1012    return kUnknownExpression;
1013  }
1014
1015  scope_->NextMaterializedLiteralIndex();
1016
1017  if (!scanner_->ScanRegExpFlags()) {
1018    Next();
1019    i::JavaScriptScanner::Location location = scanner_->location();
1020    ReportMessageAt(location.beg_pos, location.end_pos,
1021                    "invalid_regexp_flags", NULL);
1022    *ok = false;
1023    return kUnknownExpression;
1024  }
1025  Next();
1026  return kUnknownExpression;
1027}
1028
1029
1030PreParser::Arguments PreParser::ParseArguments(bool* ok) {
1031  // Arguments ::
1032  //   '(' (AssignmentExpression)*[','] ')'
1033
1034  Expect(i::Token::LPAREN, CHECK_OK);
1035  bool done = (peek() == i::Token::RPAREN);
1036  int argc = 0;
1037  while (!done) {
1038    ParseAssignmentExpression(true, CHECK_OK);
1039    argc++;
1040    done = (peek() == i::Token::RPAREN);
1041    if (!done) Expect(i::Token::COMMA, CHECK_OK);
1042  }
1043  Expect(i::Token::RPAREN, CHECK_OK);
1044  return argc;
1045}
1046
1047
1048PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
1049  // Function ::
1050  //   '(' FormalParameterList? ')' '{' FunctionBody '}'
1051
1052  // Parse function body.
1053  ScopeType outer_scope_type = scope_->type();
1054  bool inside_with = scope_->IsInsideWith();
1055  Scope function_scope(&scope_, kFunctionScope);
1056
1057  //  FormalParameterList ::
1058  //    '(' (Identifier)*[','] ')'
1059  Expect(i::Token::LPAREN, CHECK_OK);
1060  bool done = (peek() == i::Token::RPAREN);
1061  while (!done) {
1062    ParseIdentifier(CHECK_OK);
1063    done = (peek() == i::Token::RPAREN);
1064    if (!done) {
1065      Expect(i::Token::COMMA, CHECK_OK);
1066    }
1067  }
1068  Expect(i::Token::RPAREN, CHECK_OK);
1069
1070  Expect(i::Token::LBRACE, CHECK_OK);
1071  int function_block_pos = scanner_->location().beg_pos;
1072
1073  // Determine if the function will be lazily compiled.
1074  // Currently only happens to top-level functions.
1075  // Optimistically assume that all top-level functions are lazily compiled.
1076  bool is_lazily_compiled = (outer_scope_type == kTopLevelScope &&
1077                             !inside_with && allow_lazy_ &&
1078                             !parenthesized_function_);
1079  parenthesized_function_ = false;
1080
1081  if (is_lazily_compiled) {
1082    log_->PauseRecording();
1083    ParseSourceElements(i::Token::RBRACE, ok);
1084    log_->ResumeRecording();
1085    if (!*ok) return kUnknownExpression;
1086
1087    Expect(i::Token::RBRACE, CHECK_OK);
1088
1089    // Position right after terminal '}'.
1090    int end_pos = scanner_->location().end_pos;
1091    log_->LogFunction(function_block_pos, end_pos,
1092                      function_scope.materialized_literal_count(),
1093                      function_scope.expected_properties());
1094  } else {
1095    ParseSourceElements(i::Token::RBRACE, CHECK_OK);
1096    Expect(i::Token::RBRACE, CHECK_OK);
1097  }
1098  return kUnknownExpression;
1099}
1100
1101
1102PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
1103  // CallRuntime ::
1104  //   '%' Identifier Arguments
1105
1106  Expect(i::Token::MOD, CHECK_OK);
1107  ParseIdentifier(CHECK_OK);
1108  ParseArguments(CHECK_OK);
1109
1110  return kUnknownExpression;
1111}
1112
1113
1114void PreParser::ExpectSemicolon(bool* ok) {
1115  // Check for automatic semicolon insertion according to
1116  // the rules given in ECMA-262, section 7.9, page 21.
1117  i::Token::Value tok = peek();
1118  if (tok == i::Token::SEMICOLON) {
1119    Next();
1120    return;
1121  }
1122  if (scanner_->has_line_terminator_before_next() ||
1123      tok == i::Token::RBRACE ||
1124      tok == i::Token::EOS) {
1125    return;
1126  }
1127  Expect(i::Token::SEMICOLON, ok);
1128}
1129
1130
1131void PreParser::LogSymbol() {
1132  int identifier_pos = scanner_->location().beg_pos;
1133  if (scanner_->is_literal_ascii()) {
1134    log_->LogAsciiSymbol(identifier_pos, scanner_->literal_ascii_string());
1135  } else {
1136    log_->LogUC16Symbol(identifier_pos, scanner_->literal_uc16_string());
1137  }
1138}
1139
1140
1141PreParser::Identifier PreParser::GetIdentifierSymbol() {
1142  LogSymbol();
1143  return kUnknownIdentifier;
1144}
1145
1146
1147PreParser::Expression PreParser::GetStringSymbol() {
1148  LogSymbol();
1149  return kUnknownExpression;
1150}
1151
1152
1153PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
1154  Expect(i::Token::IDENTIFIER, ok);
1155  if (!*ok) return kUnknownIdentifier;
1156  return GetIdentifierSymbol();
1157}
1158
1159
1160PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
1161  i::Token::Value next = Next();
1162  if (i::Token::IsKeyword(next)) {
1163    int pos = scanner_->location().beg_pos;
1164    const char* keyword = i::Token::String(next);
1165    log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword,
1166                                                    i::StrLength(keyword)));
1167    return kUnknownExpression;
1168  }
1169  if (next == i::Token::IDENTIFIER) {
1170    return GetIdentifierSymbol();
1171  }
1172  *ok = false;
1173  return kUnknownIdentifier;
1174}
1175
1176
1177// This function reads an identifier and determines whether or not it
1178// is 'get' or 'set'.  The reason for not using ParseIdentifier and
1179// checking on the output is that this involves heap allocation which
1180// we can't do during preparsing.
1181PreParser::Identifier PreParser::ParseIdentifierOrGetOrSet(bool* is_get,
1182                                                           bool* is_set,
1183                                                           bool* ok) {
1184  Expect(i::Token::IDENTIFIER, CHECK_OK);
1185  if (scanner_->is_literal_ascii() && scanner_->literal_length() == 3) {
1186    const char* token = scanner_->literal_ascii_string().start();
1187    *is_get = strncmp(token, "get", 3) == 0;
1188    *is_set = !*is_get && strncmp(token, "set", 3) == 0;
1189  }
1190  return GetIdentifierSymbol();
1191}
1192
1193#undef CHECK_OK
1194} }  // v8::preparser
1195