(Pre)Parser: Move ParsePrimaryExpression to ParserBase.
authormarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 14 Feb 2014 11:24:26 +0000 (11:24 +0000)
committermarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 14 Feb 2014 11:24:26 +0000 (11:24 +0000)
Notes:
- To be able to move the recursive descent functions to ParserBase one at a
time, we temporarily need routing functions from traits to Parser/PreParser,
since the recursive descent functions form a cyclic structure.
- PreParser used to always allow intrinsic syntax. After this CL, it depends on
allow_natives_syntax() which was already in ParserBase.
- This CL also decouples (Pre)ParserTraits better from (Pre)Parser, passing more
information as parameters, so that the Traits don't need to get it from
(Pre)Parser.
R=ulan@chromium.org
BUG=v8:3126
LOG=N

Review URL: https://codereview.chromium.org/163333003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19374 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/parser.cc
src/parser.h
src/preparser.cc
src/preparser.h
test/cctest/test-parsing.cc

index fb1585e..0da774b 100644 (file)
@@ -535,7 +535,7 @@ void ParserTraits::ReportMessageAt(Scanner::Location source_location,
 }
 
 
-Handle<String> ParserTraits::GetSymbol() {
+Handle<String> ParserTraits::GetSymbol(Scanner* scanner) {
   int symbol_id = -1;
   if (parser_->pre_parse_data() != NULL) {
     symbol_id = parser_->pre_parse_data()->GetSymbolIdentifier();
@@ -544,21 +544,99 @@ Handle<String> ParserTraits::GetSymbol() {
 }
 
 
-Handle<String> ParserTraits::NextLiteralString(PretenureFlag tenured) {
-  Scanner& scanner = parser_->scanner();
-  if (scanner.is_next_literal_ascii()) {
+Handle<String> ParserTraits::NextLiteralString(Scanner* scanner,
+                                               PretenureFlag tenured) {
+  if (scanner->is_next_literal_ascii()) {
     return parser_->isolate_->factory()->NewStringFromAscii(
-        scanner.next_literal_ascii_string(), tenured);
+        scanner->next_literal_ascii_string(), tenured);
   } else {
     return parser_->isolate_->factory()->NewStringFromTwoByte(
-        scanner.next_literal_utf16_string(), tenured);
+        scanner->next_literal_utf16_string(), tenured);
   }
 }
 
 
+Expression* ParserTraits::ThisExpression(
+    Scope* scope,
+    AstNodeFactory<AstConstructionVisitor>* factory) {
+  return factory->NewVariableProxy(scope->receiver());
+}
+
+
+Expression* ParserTraits::ExpressionFromLiteral(
+    Token::Value token, int pos,
+    Scanner* scanner,
+    AstNodeFactory<AstConstructionVisitor>* factory) {
+  Factory* isolate_factory = parser_->isolate()->factory();
+  switch (token) {
+    case Token::NULL_LITERAL:
+      return factory->NewLiteral(isolate_factory->null_value(), pos);
+    case Token::TRUE_LITERAL:
+      return factory->NewLiteral(isolate_factory->true_value(), pos);
+    case Token::FALSE_LITERAL:
+      return factory->NewLiteral(isolate_factory->false_value(), pos);
+    case Token::NUMBER: {
+      ASSERT(scanner->is_literal_ascii());
+      double value = StringToDouble(parser_->isolate()->unicode_cache(),
+                                    scanner->literal_ascii_string(),
+                                    ALLOW_HEX | ALLOW_OCTAL |
+                                        ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
+      return factory->NewNumberLiteral(value, pos);
+    }
+    default:
+      ASSERT(false);
+  }
+  return NULL;
+}
+
+
+Expression* ParserTraits::ExpressionFromIdentifier(
+    Handle<String> name, int pos, Scope* scope,
+    AstNodeFactory<AstConstructionVisitor>* factory) {
+  if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
+  // The name may refer to a module instance object, so its type is unknown.
+#ifdef DEBUG
+  if (FLAG_print_interface_details)
+    PrintF("# Variable %s ", name->ToAsciiArray());
+#endif
+  Interface* interface = Interface::NewUnknown(parser_->zone());
+  return scope->NewUnresolved(factory, name, interface, pos);
+}
+
+
+Expression* ParserTraits::ExpressionFromString(
+    int pos, Scanner* scanner,
+    AstNodeFactory<AstConstructionVisitor>* factory) {
+  Handle<String> symbol = GetSymbol(scanner);
+  if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
+  return factory->NewLiteral(symbol, pos);
+}
+
+
+Expression* ParserTraits::ParseArrayLiteral(bool* ok) {
+  return parser_->ParseArrayLiteral(ok);
+}
+
+
+Expression* ParserTraits::ParseObjectLiteral(bool* ok) {
+  return parser_->ParseObjectLiteral(ok);
+}
+
+
+Expression* ParserTraits::ParseExpression(bool accept_IN, bool* ok) {
+  return parser_->ParseExpression(accept_IN, ok);
+}
+
+
+Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
+  return parser_->ParseV8Intrinsic(ok);
+}
+
+
 Parser::Parser(CompilationInfo* info)
     : ParserBase<ParserTraits>(&scanner_,
                                info->isolate()->stack_guard()->real_climit(),
+                               info->extension(),
                                this),
       isolate_(info->isolate()),
       symbol_cache_(0, info->zone()),
@@ -567,7 +645,6 @@ Parser::Parser(CompilationInfo* info)
       reusable_preparser_(NULL),
       original_scope_(NULL),
       target_stack_(NULL),
-      extension_(info->extension()),
       pre_parse_data_(NULL),
       fni_(NULL),
       zone_(info->zone()),
@@ -3430,124 +3507,6 @@ void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
 }
 
 
-Expression* Parser::ParsePrimaryExpression(bool* ok) {
-  // PrimaryExpression ::
-  //   'this'
-  //   'null'
-  //   'true'
-  //   'false'
-  //   Identifier
-  //   Number
-  //   String
-  //   ArrayLiteral
-  //   ObjectLiteral
-  //   RegExpLiteral
-  //   '(' Expression ')'
-
-  int pos = peek_position();
-  Expression* result = NULL;
-  switch (peek()) {
-    case Token::THIS: {
-      Consume(Token::THIS);
-      result = factory()->NewVariableProxy(scope_->receiver());
-      break;
-    }
-
-    case Token::NULL_LITERAL:
-      Consume(Token::NULL_LITERAL);
-      result = factory()->NewLiteral(isolate()->factory()->null_value(), pos);
-      break;
-
-    case Token::TRUE_LITERAL:
-      Consume(Token::TRUE_LITERAL);
-      result = factory()->NewLiteral(isolate()->factory()->true_value(), pos);
-      break;
-
-    case Token::FALSE_LITERAL:
-      Consume(Token::FALSE_LITERAL);
-      result = factory()->NewLiteral(isolate()->factory()->false_value(), pos);
-      break;
-
-    case Token::IDENTIFIER:
-    case Token::YIELD:
-    case Token::FUTURE_STRICT_RESERVED_WORD: {
-      // Using eval or arguments in this context is OK even in strict mode.
-      Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
-      if (fni_ != NULL) fni_->PushVariableName(name);
-      // The name may refer to a module instance object, so its type is unknown.
-#ifdef DEBUG
-      if (FLAG_print_interface_details)
-        PrintF("# Variable %s ", name->ToAsciiArray());
-#endif
-      Interface* interface = Interface::NewUnknown(zone());
-      result = scope_->NewUnresolved(factory(), name, interface, pos);
-      break;
-    }
-
-    case Token::NUMBER: {
-      Consume(Token::NUMBER);
-      ASSERT(scanner().is_literal_ascii());
-      double value = StringToDouble(isolate()->unicode_cache(),
-                                    scanner().literal_ascii_string(),
-                                    ALLOW_HEX | ALLOW_OCTAL |
-                                        ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
-      result = factory()->NewNumberLiteral(value, pos);
-      break;
-    }
-
-    case Token::STRING: {
-      Consume(Token::STRING);
-      Handle<String> symbol = GetSymbol();
-      result = factory()->NewLiteral(symbol, pos);
-      if (fni_ != NULL) fni_->PushLiteralName(symbol);
-      break;
-    }
-
-    case Token::ASSIGN_DIV:
-      result = ParseRegExpLiteral(true, CHECK_OK);
-      break;
-
-    case Token::DIV:
-      result = ParseRegExpLiteral(false, CHECK_OK);
-      break;
-
-    case Token::LBRACK:
-      result = ParseArrayLiteral(CHECK_OK);
-      break;
-
-    case Token::LBRACE:
-      result = ParseObjectLiteral(CHECK_OK);
-      break;
-
-    case Token::LPAREN:
-      Consume(Token::LPAREN);
-      // Heuristically try to detect immediately called functions before
-      // seeing the call parentheses.
-      parenthesized_function_ = (peek() == Token::FUNCTION);
-      result = ParseExpression(true, CHECK_OK);
-      Expect(Token::RPAREN, CHECK_OK);
-      break;
-
-    case Token::MOD:
-      if (allow_natives_syntax() || extension_ != NULL) {
-        result = ParseV8Intrinsic(CHECK_OK);
-        break;
-      }
-      // If we're not allowing special syntax we fall-through to the
-      // default case.
-
-    default: {
-      Token::Value tok = Next();
-      ReportUnexpectedToken(tok);
-      *ok = false;
-      return NULL;
-    }
-  }
-
-  return result;
-}
-
-
 Expression* Parser::ParseArrayLiteral(bool* ok) {
   // ArrayLiteral ::
   //   '[' Expression? (',' Expression?)* ']'
index ddd015c..a3523ea 100644 (file)
@@ -463,8 +463,26 @@ class ParserTraits {
   }
 
   // Producing data during the recursive descent.
-  Handle<String> GetSymbol();
-  Handle<String> NextLiteralString(PretenureFlag tenured);
+  Handle<String> GetSymbol(Scanner* scanner = NULL);
+  Handle<String> NextLiteralString(Scanner* scanner,
+                                   PretenureFlag tenured);
+  Expression* ThisExpression(Scope* scope,
+                             AstNodeFactory<AstConstructionVisitor>* factory);
+  Expression* ExpressionFromLiteral(
+      Token::Value token, int pos, Scanner* scanner,
+      AstNodeFactory<AstConstructionVisitor>* factory);
+  Expression* ExpressionFromIdentifier(
+      Handle<String> name, int pos, Scope* scope,
+      AstNodeFactory<AstConstructionVisitor>* factory);
+  Expression* ExpressionFromString(
+      int pos, Scanner* scanner,
+      AstNodeFactory<AstConstructionVisitor>* factory);
+
+  // Temporary glue; these functions will move to ParserBase.
+  Expression* ParseArrayLiteral(bool* ok);
+  Expression* ParseObjectLiteral(bool* ok);
+  Expression* ParseExpression(bool accept_IN, bool* ok);
+  Expression* ParseV8Intrinsic(bool* ok);
 
  private:
   Parser* parser_;
@@ -626,7 +644,6 @@ class Parser : public ParserBase<ParserTraits> {
   Expression* ParseNewPrefix(PositionStack* stack, bool* ok);
   Expression* ParseMemberWithNewPrefixesExpression(PositionStack* stack,
                                                    bool* ok);
-  Expression* ParsePrimaryExpression(bool* ok);
   Expression* ParseArrayLiteral(bool* ok);
   Expression* ParseObjectLiteral(bool* ok);
 
@@ -735,7 +752,6 @@ class Parser : public ParserBase<ParserTraits> {
   PreParser* reusable_preparser_;
   Scope* original_scope_;  // for ES5 function declarations in sloppy eval
   Target* target_stack_;  // for break, continue statements
-  v8::Extension* extension_;
   ScriptDataImpl* pre_parse_data_;
   FuncNameInferrer* fni_;
 
index ad0e05e..6759550 100644 (file)
@@ -81,8 +81,7 @@ void PreParserTraits::ReportMessageAt(int start_pos,
 }
 
 
-PreParserIdentifier PreParserTraits::GetSymbol() {
-  Scanner* scanner = pre_parser_->scanner();
+PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
   pre_parser_->LogSymbol();
   if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) {
     return PreParserIdentifier::FutureReserved();
@@ -107,6 +106,42 @@ PreParserIdentifier PreParserTraits::GetSymbol() {
 }
 
 
+PreParserExpression PreParserTraits::ExpressionFromString(
+    int pos, Scanner* scanner, PreParserFactory* factory) {
+  const int kUseStrictLength = 10;
+  const char* kUseStrictChars = "use strict";
+  pre_parser_->LogSymbol();
+  if (scanner->is_literal_ascii() &&
+      scanner->literal_length() == kUseStrictLength &&
+      !scanner->literal_contains_escapes() &&
+      !strncmp(scanner->literal_ascii_string().start(), kUseStrictChars,
+               kUseStrictLength)) {
+    return PreParserExpression::UseStrictStringLiteral();
+  }
+  return PreParserExpression::StringLiteral();
+}
+
+
+PreParserExpression PreParserTraits::ParseArrayLiteral(bool* ok) {
+  return pre_parser_->ParseArrayLiteral(ok);
+}
+
+
+PreParserExpression PreParserTraits::ParseObjectLiteral(bool* ok) {
+  return pre_parser_->ParseObjectLiteral(ok);
+}
+
+
+PreParserExpression PreParserTraits::ParseExpression(bool accept_IN, bool* ok) {
+  return pre_parser_->ParseExpression(accept_IN, ok);
+}
+
+
+PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
+  return pre_parser_->ParseV8Intrinsic(ok);
+}
+
+
 PreParser::PreParseResult PreParser::PreParseLazyFunction(
     LanguageMode mode, bool is_generator, ParserRecorder* log) {
   log_ = log;
@@ -1111,90 +1146,6 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
 }
 
 
-PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
-  // PrimaryExpression ::
-  //   'this'
-  //   'null'
-  //   'true'
-  //   'false'
-  //   Identifier
-  //   Number
-  //   String
-  //   ArrayLiteral
-  //   ObjectLiteral
-  //   RegExpLiteral
-  //   '(' Expression ')'
-
-  Expression result = Expression::Default();
-  switch (peek()) {
-    case Token::THIS: {
-      Next();
-      result = Expression::This();
-      break;
-    }
-
-    case Token::FUTURE_RESERVED_WORD:
-    case Token::FUTURE_STRICT_RESERVED_WORD:
-    case Token::YIELD:
-    case Token::IDENTIFIER: {
-      // Using eval or arguments in this context is OK even in strict mode.
-      Identifier id = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
-      result = Expression::FromIdentifier(id);
-      break;
-    }
-
-    case Token::NULL_LITERAL:
-    case Token::TRUE_LITERAL:
-    case Token::FALSE_LITERAL:
-    case Token::NUMBER: {
-      Next();
-      break;
-    }
-    case Token::STRING: {
-      Next();
-      result = GetStringSymbol();
-      break;
-    }
-
-    case Token::ASSIGN_DIV:
-      result = ParseRegExpLiteral(true, CHECK_OK);
-      break;
-
-    case Token::DIV:
-      result = ParseRegExpLiteral(false, CHECK_OK);
-      break;
-
-    case Token::LBRACK:
-      result = ParseArrayLiteral(CHECK_OK);
-      break;
-
-    case Token::LBRACE:
-      result = ParseObjectLiteral(CHECK_OK);
-      break;
-
-    case Token::LPAREN:
-      Consume(Token::LPAREN);
-      parenthesized_function_ = (peek() == Token::FUNCTION);
-      result = ParseExpression(true, CHECK_OK);
-      Expect(Token::RPAREN, CHECK_OK);
-      break;
-
-    case Token::MOD:
-      result = ParseV8Intrinsic(CHECK_OK);
-      break;
-
-    default: {
-      Token::Value next = Next();
-      ReportUnexpectedToken(next);
-      *ok = false;
-      return Expression::Default();
-    }
-  }
-
-  return result;
-}
-
-
 PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) {
   // ArrayLiteral ::
   //   '[' Expression? (',' Expression?)* ']'
@@ -1266,7 +1217,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
       case Token::STRING:
         Consume(next);
         checker.CheckProperty(next, kValueProperty, CHECK_OK);
-        GetStringSymbol();
+        LogSymbol();
         break;
       case Token::NUMBER:
         Consume(next);
@@ -1475,19 +1426,4 @@ void PreParser::LogSymbol() {
 }
 
 
-PreParser::Expression PreParser::GetStringSymbol() {
-  const int kUseStrictLength = 10;
-  const char* kUseStrictChars = "use strict";
-  LogSymbol();
-  if (scanner()->is_literal_ascii() &&
-      scanner()->literal_length() == kUseStrictLength &&
-      !scanner()->literal_contains_escapes() &&
-      !strncmp(scanner()->literal_ascii_string().start(), kUseStrictChars,
-               kUseStrictLength)) {
-    return Expression::UseStrictStringLiteral();
-  }
-  return Expression::StringLiteral();
-}
-
-
 } }  // v8::internal
index 5dd41da..cbc92da 100644 (file)
@@ -32,6 +32,7 @@
 #include "scopes.h"
 #include "token.h"
 #include "scanner.h"
+#include "v8.h"
 
 namespace v8 {
 namespace internal {
@@ -41,11 +42,13 @@ template <typename Traits>
 class ParserBase : public Traits {
  public:
   ParserBase(Scanner* scanner, uintptr_t stack_limit,
+             v8::Extension* extension,
              typename Traits::Type::Parser this_object)
       : Traits(this_object),
         parenthesized_function_(false),
         scope_(NULL),
         function_state_(NULL),
+        extension_(extension),
         scanner_(scanner),
         stack_limit_(stack_limit),
         stack_overflow_(false),
@@ -329,7 +332,9 @@ class ParserBase : public Traits {
                                                                 bool* ok);
 
   typename Traits::Type::Expression ParseRegExpLiteral(bool seen_equal,
-                                                        bool* ok);
+                                                       bool* ok);
+
+  typename Traits::Type::Expression ParsePrimaryExpression(bool* ok);
 
   // Used to detect duplicates in object literals. Each of the values
   // kGetterProperty, kSetterProperty and kValueProperty represents
@@ -393,6 +398,7 @@ class ParserBase : public Traits {
 
   typename Traits::Type::Scope* scope_;  // Scope stack.
   FunctionState* function_state_;  // Function state stack.
+  v8::Extension* extension_;
 
  private:
   Scanner* scanner_;
@@ -641,11 +647,39 @@ class PreParserTraits {
   }
 
   // Producing data during the recursive descent.
-  PreParserIdentifier GetSymbol();
-  static PreParserIdentifier NextLiteralString(PretenureFlag tenured) {
+  PreParserIdentifier GetSymbol(Scanner* scanner);
+  static PreParserIdentifier NextLiteralString(Scanner* scanner,
+                                               PretenureFlag tenured) {
     return PreParserIdentifier::Default();
   }
 
+  static PreParserExpression ThisExpression(PreParserScope* scope,
+                                            PreParserFactory* factory) {
+    return PreParserExpression::This();
+  }
+
+  static PreParserExpression ExpressionFromLiteral(
+      Token::Value token, int pos, Scanner* scanner,
+      PreParserFactory* factory) {
+    return PreParserExpression::Default();
+  }
+
+  static PreParserExpression ExpressionFromIdentifier(
+      PreParserIdentifier name, int pos, PreParserScope* scope,
+      PreParserFactory* factory) {
+    return PreParserExpression::FromIdentifier(name);
+  }
+
+  PreParserExpression ExpressionFromString(int pos,
+                                           Scanner* scanner,
+                                           PreParserFactory* factory = NULL);
+
+  // Temporary glue; these functions will move to ParserBase.
+  PreParserExpression ParseArrayLiteral(bool* ok);
+  PreParserExpression ParseObjectLiteral(bool* ok);
+  PreParserExpression ParseExpression(bool accept_IN, bool* ok);
+  PreParserExpression ParseV8Intrinsic(bool* ok);
+
  private:
   PreParser* pre_parser_;
 };
@@ -676,7 +710,7 @@ class PreParser : public ParserBase<PreParserTraits> {
   PreParser(Scanner* scanner,
             ParserRecorder* log,
             uintptr_t stack_limit)
-      : ParserBase<PreParserTraits>(scanner, stack_limit, this),
+      : ParserBase<PreParserTraits>(scanner, stack_limit, NULL, this),
         log_(log) {}
 
   // Pre-parse the program from the character stream; returns true on
@@ -823,7 +857,6 @@ class PreParser : public ParserBase<PreParserTraits> {
   Expression ParseNewExpression(bool* ok);
   Expression ParseMemberExpression(bool* ok);
   Expression ParseMemberWithNewPrefixesExpression(unsigned new_count, bool* ok);
-  Expression ParsePrimaryExpression(bool* ok);
   Expression ParseArrayLiteral(bool* ok);
   Expression ParseObjectLiteral(bool* ok);
   Expression ParseV8Intrinsic(bool* ok);
@@ -922,7 +955,7 @@ typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifier(
     bool* ok) {
   Token::Value next = Next();
   if (next == Token::IDENTIFIER) {
-    typename Traits::Type::Identifier name = this->GetSymbol();
+    typename Traits::Type::Identifier name = this->GetSymbol(scanner());
     if (allow_eval_or_arguments == kDontAllowEvalOrArguments &&
         !is_classic_mode() && this->IsEvalOrArguments(name)) {
       ReportMessageAt(scanner()->location(), "strict_eval_arguments");
@@ -931,7 +964,7 @@ typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifier(
     return name;
   } else if (is_classic_mode() && (next == Token::FUTURE_STRICT_RESERVED_WORD ||
                                    (next == Token::YIELD && !is_generator()))) {
-    return this->GetSymbol();
+    return this->GetSymbol(scanner());
   } else {
     this->ReportUnexpectedToken(next);
     *ok = false;
@@ -955,7 +988,7 @@ typename Traits::Type::Identifier ParserBase<
     *ok = false;
     return Traits::EmptyIdentifier();
   }
-  return this->GetSymbol();
+  return this->GetSymbol(scanner());
 }
 
 
@@ -969,7 +1002,7 @@ typename Traits::Type::Identifier ParserBase<Traits>::ParseIdentifierName(
     *ok = false;
     return Traits::EmptyIdentifier();
   }
-  return this->GetSymbol();
+  return this->GetSymbol(scanner());
 }
 
 
@@ -1004,7 +1037,7 @@ ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) {
   int literal_index = function_state_->NextMaterializedLiteralIndex();
 
   typename Traits::Type::Identifier js_pattern =
-      this->NextLiteralString(TENURED);
+      this->NextLiteralString(scanner(), TENURED);
   if (!scanner()->ScanRegExpFlags()) {
     Next();
     ReportMessageAt(scanner()->location(), "invalid_regexp_flags");
@@ -1012,12 +1045,115 @@ ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) {
     return Traits::EmptyExpression();
   }
   typename Traits::Type::Identifier js_flags =
-      this->NextLiteralString(TENURED);
+      this->NextLiteralString(scanner(), TENURED);
   Next();
   return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
 }
 
 
+#define CHECK_OK  ok); \
+  if (!*ok) return this->EmptyExpression(); \
+  ((void)0
+#define DUMMY )  // to make indentation work
+#undef DUMMY
+
+template <class Traits>
+typename Traits::Type::Expression ParserBase<Traits>::ParsePrimaryExpression(
+    bool* ok) {
+  // PrimaryExpression ::
+  //   'this'
+  //   'null'
+  //   'true'
+  //   'false'
+  //   Identifier
+  //   Number
+  //   String
+  //   ArrayLiteral
+  //   ObjectLiteral
+  //   RegExpLiteral
+  //   '(' Expression ')'
+
+  int pos = peek_position();
+  typename Traits::Type::Expression result = this->EmptyExpression();
+  Token::Value token = peek();
+  switch (token) {
+    case Token::THIS: {
+      Consume(Token::THIS);
+      result = this->ThisExpression(scope_, factory());
+      break;
+    }
+
+    case Token::NULL_LITERAL:
+    case Token::TRUE_LITERAL:
+    case Token::FALSE_LITERAL:
+    case Token::NUMBER:
+      Next();
+      result = this->ExpressionFromLiteral(token, pos, scanner(), factory());
+      break;
+
+    case Token::IDENTIFIER:
+    case Token::YIELD:
+    case Token::FUTURE_STRICT_RESERVED_WORD: {
+      // Using eval or arguments in this context is OK even in strict mode.
+      typename Traits::Type::Identifier name =
+          ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
+      result =
+          this->ExpressionFromIdentifier(name, pos, scope_, factory());
+      break;
+    }
+
+    case Token::STRING: {
+      Consume(Token::STRING);
+      result = this->ExpressionFromString(pos, scanner(), factory());
+      break;
+    }
+
+    case Token::ASSIGN_DIV:
+      result = this->ParseRegExpLiteral(true, CHECK_OK);
+      break;
+
+    case Token::DIV:
+      result = this->ParseRegExpLiteral(false, CHECK_OK);
+      break;
+
+    case Token::LBRACK:
+      result = this->ParseArrayLiteral(CHECK_OK);
+      break;
+
+    case Token::LBRACE:
+      result = this->ParseObjectLiteral(CHECK_OK);
+      break;
+
+    case Token::LPAREN:
+      Consume(Token::LPAREN);
+      // Heuristically try to detect immediately called functions before
+      // seeing the call parentheses.
+      parenthesized_function_ = (peek() == Token::FUNCTION);
+      result = this->ParseExpression(true, CHECK_OK);
+      Expect(Token::RPAREN, CHECK_OK);
+      break;
+
+    case Token::MOD:
+      if (allow_natives_syntax() || extension_ != NULL) {
+        result = this->ParseV8Intrinsic(CHECK_OK);
+        break;
+      }
+      // If we're not allowing special syntax we fall-through to the
+      // default case.
+
+    default: {
+      Next();
+      ReportUnexpectedToken(token);
+      *ok = false;
+    }
+  }
+
+  return result;
+}
+
+#undef CHECK_OK
+
+
 template <typename Traits>
 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
     Token::Value property,
index 3d8fc39..5de0eba 100644 (file)
@@ -1391,7 +1391,7 @@ void RunParserSyncTest(const char* context_data[][2],
 
   static const ParserFlag flags[] = {
     kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators,
-    kAllowForOf
+    kAllowForOf, kAllowNativesSyntax
   };
   for (int i = 0; context_data[i][0] != NULL; ++i) {
     for (int j = 0; statement_data[j] != NULL; ++j) {
@@ -2046,3 +2046,20 @@ TEST(NoErrorsRegexpLiteral) {
 
   RunParserSyncTest(context_data, statement_data, kSuccess);
 }
+
+
+TEST(Intrinsics) {
+  const char* context_data[][2] = {
+    {"", ""},
+    { NULL, NULL }
+  };
+
+  const char* statement_data[] = {
+    "%someintrinsic(arg)",
+    NULL
+  };
+
+  // Parsing will fail or succeed depending on whether we allow natives syntax
+  // or not.
+  RunParserSyncTest(context_data, statement_data, kSuccessOrError);
+}