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