Move ParseRegexpLiteral to ParserBase.
authormarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 11 Feb 2014 11:51:01 +0000 (11:51 +0000)
committermarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 11 Feb 2014 11:51:01 +0000 (11:51 +0000)
R=ulan@chromium.org
BUG=v8:3126
LOG=N

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

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

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

index 0f842ad..24eaef0 100644 (file)
@@ -551,6 +551,11 @@ bool ParserTraits::IsEvalOrArguments(Handle<String> identifier) const {
 }
 
 
+int ParserTraits::NextMaterializedLiteralIndex() {
+  return parser_->current_function_state_->NextMaterializedLiteralIndex();
+}
+
+
 void ParserTraits::ReportMessageAt(Scanner::Location source_location,
                                    const char* message,
                                    Vector<const char*> args) {
@@ -601,6 +606,27 @@ Handle<String> ParserTraits::GetSymbol() {
   return parser_->LookupSymbol(symbol_id);
 }
 
+
+Handle<String> ParserTraits::NextLiteralString(PretenureFlag tenured) {
+  Scanner& scanner = parser_->scanner();
+  if (scanner.is_next_literal_ascii()) {
+    return parser_->isolate_->factory()->NewStringFromAscii(
+        scanner.next_literal_ascii_string(), tenured);
+  } else {
+    return parser_->isolate_->factory()->NewStringFromTwoByte(
+        scanner.next_literal_utf16_string(), tenured);
+  }
+}
+
+
+Expression* ParserTraits::NewRegExpLiteral(Handle<String> js_pattern,
+                                           Handle<String> js_flags,
+                                           int literal_index,
+                                           int pos) {
+  return parser_->factory()->NewRegExpLiteral(
+      js_pattern, js_flags, literal_index, pos);
+}
+
 Parser::Parser(CompilationInfo* info)
     : ParserBase<ParserTraits>(&scanner_,
                                info->isolate()->stack_guard()->real_climit(),
@@ -3834,26 +3860,6 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
 }
 
 
-Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
-  int pos = peek_position();
-  if (!scanner().ScanRegExpPattern(seen_equal)) {
-    Next();
-    ReportMessage("unterminated_regexp", Vector<const char*>::empty());
-    *ok = false;
-    return NULL;
-  }
-
-  int literal_index = current_function_state_->NextMaterializedLiteralIndex();
-
-  Handle<String> js_pattern = NextLiteralString(TENURED);
-  scanner().ScanRegExpFlags();
-  Handle<String> js_flags = NextLiteralString(TENURED);
-  Next();
-
-  return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
-}
-
-
 ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
   // Arguments ::
   //   '(' (AssignmentExpression)*[','] ')'
index 64513d3..c2dd77f 100644 (file)
@@ -412,6 +412,7 @@ class ParserTraits {
   typedef Parser* ParserType;
   // Return types for traversing functions.
   typedef Handle<String> IdentifierType;
+  typedef Expression* ExpressionType;
 
   explicit ParserTraits(Parser* parser) : parser_(parser) {}
 
@@ -419,6 +420,7 @@ class ParserTraits {
   bool is_classic_mode() const;
   bool is_generator() const;
   bool IsEvalOrArguments(Handle<String> identifier) const;
+  int NextMaterializedLiteralIndex();
 
   // Reporting errors.
   void ReportMessageAt(Scanner::Location source_location,
@@ -429,12 +431,21 @@ class ParserTraits {
                        const char* message,
                        Vector<Handle<String> > args);
 
-  // Identifiers:
+  // "null" return type creators.
   static IdentifierType EmptyIdentifier() {
     return Handle<String>();
   }
+  static ExpressionType EmptyExpression() {
+    return NULL;
+  }
 
+  // Producing data during the recursive descent.
   IdentifierType GetSymbol();
+  IdentifierType NextLiteralString(PretenureFlag tenured);
+  ExpressionType NewRegExpLiteral(IdentifierType js_pattern,
+                                  IdentifierType js_flags,
+                                  int literal_index,
+                                  int pos);
 
  private:
   Parser* parser_;
@@ -657,7 +668,6 @@ class Parser : public ParserBase<ParserTraits> {
   Expression* ParsePrimaryExpression(bool* ok);
   Expression* ParseArrayLiteral(bool* ok);
   Expression* ParseObjectLiteral(bool* ok);
-  Expression* ParseRegExpLiteral(bool seen_equal, bool* ok);
 
   // Initialize the components of a for-in / for-of statement.
   void InitializeForEachStatement(ForEachStatement* stmt,
@@ -690,16 +700,6 @@ class Parser : public ParserBase<ParserTraits> {
     }
   }
 
-  Handle<String> NextLiteralString(PretenureFlag tenured) {
-    if (scanner().is_next_literal_ascii()) {
-      return isolate_->factory()->NewStringFromAscii(
-          scanner().next_literal_ascii_string(), tenured);
-    } else {
-      return isolate_->factory()->NewStringFromTwoByte(
-          scanner().next_literal_utf16_string(), tenured);
-    }
-  }
-
   // Get odd-ball literals.
   Literal* GetLiteralUndefined(int position);
   Literal* GetLiteralTheHole(int position);
index c01acdd..3c18490 100644 (file)
@@ -65,6 +65,11 @@ bool PreParserTraits::is_generator() const {
 }
 
 
+int PreParserTraits::NextMaterializedLiteralIndex() {
+  return pre_parser_->scope_->NextMaterializedLiteralIndex();
+}
+
+
 void PreParserTraits::ReportMessageAt(Scanner::Location location,
                                       const char* message,
                                       Vector<const char*> args) {
@@ -1301,28 +1306,6 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
 }
 
 
-PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
-                                                    bool* ok) {
-  if (!scanner()->ScanRegExpPattern(seen_equal)) {
-    Next();
-    ReportMessageAt(scanner()->location(), "unterminated_regexp");
-    *ok = false;
-    return Expression::Default();
-  }
-
-  scope_->NextMaterializedLiteralIndex();
-
-  if (!scanner()->ScanRegExpFlags()) {
-    Next();
-    ReportMessageAt(scanner()->location(), "invalid_regexp_flags");
-    *ok = false;
-    return Expression::Default();
-  }
-  Next();
-  return Expression::Default();
-}
-
-
 PreParser::Arguments PreParser::ParseArguments(bool* ok) {
   // Arguments ::
   //   '(' (AssignmentExpression)*[','] ')'
index b6a9e84..b3f67c9 100644 (file)
@@ -225,6 +225,8 @@ class ParserBase : public Traits {
                                                                 bool* is_set,
                                                                 bool* ok);
 
+  typename Traits::ExpressionType ParseRegExpLiteral(bool seen_equal, bool* ok);
+
   // Used to detect duplicates in object literals. Each of the values
   // kGetterProperty, kSetterProperty and kValueProperty represents
   // a type of object literal property. When parsing a property, its
@@ -427,6 +429,7 @@ class PreParserTraits {
   typedef PreParser* ParserType;
   // Return types for traversing functions.
   typedef PreParserIdentifier IdentifierType;
+  typedef PreParserExpression ExpressionType;
 
   explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
 
@@ -436,6 +439,7 @@ class PreParserTraits {
   static bool IsEvalOrArguments(IdentifierType identifier) {
     return identifier.IsEvalOrArguments();
   }
+  int NextMaterializedLiteralIndex();
 
   // Reporting errors.
   void ReportMessageAt(Scanner::Location location,
@@ -449,12 +453,25 @@ class PreParserTraits {
                        const char* type,
                        const char* name_opt);
 
-  // Identifiers:
+  // "null" return type creators.
   static IdentifierType EmptyIdentifier() {
     return PreParserIdentifier::Default();
   }
+  static ExpressionType EmptyExpression() {
+    return PreParserExpression::Default();
+  }
 
+  // Producing data during the recursive descent.
   IdentifierType GetSymbol();
+  static IdentifierType NextLiteralString(PretenureFlag tenured) {
+    return PreParserIdentifier::Default();
+  }
+  ExpressionType NewRegExpLiteral(IdentifierType js_pattern,
+                                  IdentifierType js_flags,
+                                  int literal_index,
+                                  int pos) {
+    return PreParserExpression::Default();
+  }
 
  private:
   PreParser* pre_parser_;
@@ -616,7 +633,7 @@ class PreParser : public ParserBase<PreParserTraits> {
       *variable = this;
     }
     ~Scope() { *variable_ = prev_; }
-    void NextMaterializedLiteralIndex() { materialized_literal_count_++; }
+    int NextMaterializedLiteralIndex() { return materialized_literal_count_++; }
     void AddProperty() { expected_properties_++; }
     ScopeType type() { return type_; }
     int expected_properties() { return expected_properties_; }
@@ -701,7 +718,6 @@ class PreParser : public ParserBase<PreParserTraits> {
   Expression ParsePrimaryExpression(bool* ok);
   Expression ParseArrayLiteral(bool* ok);
   Expression ParseObjectLiteral(bool* ok);
-  Expression ParseRegExpLiteral(bool seen_equal, bool* ok);
   Expression ParseV8Intrinsic(bool* ok);
 
   Arguments ParseArguments(bool* ok);
@@ -848,6 +864,32 @@ ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get,
 }
 
 
+template <class Traits>
+typename Traits::ExpressionType
+ParserBase<Traits>::ParseRegExpLiteral(bool seen_equal, bool* ok) {
+  int pos = peek_position();
+  if (!scanner()->ScanRegExpPattern(seen_equal)) {
+    Next();
+    ReportMessage("unterminated_regexp", Vector<const char*>::empty());
+    *ok = false;
+    return Traits::EmptyExpression();
+  }
+
+  int literal_index = this->NextMaterializedLiteralIndex();
+
+  typename Traits::IdentifierType js_pattern = this->NextLiteralString(TENURED);
+  if (!scanner()->ScanRegExpFlags()) {
+    Next();
+    ReportMessageAt(scanner()->location(), "invalid_regexp_flags");
+    *ok = false;
+    return Traits::EmptyExpression();
+  }
+  typename Traits::IdentifierType js_flags = this->NextLiteralString(TENURED);
+  Next();
+  return this->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
+}
+
+
 template <typename Traits>
 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
     Token::Value property,
index f3f238c..3d8fc39 100644 (file)
@@ -2014,3 +2014,35 @@ TEST(NoErrorsTryCatchFinally) {
 
   RunParserSyncTest(context_data, statement_data, kSuccess);
 }
+
+
+TEST(ErrorsRegexpLiteral) {
+  const char* context_data[][2] = {
+    {"var r = ", ""},
+    { NULL, NULL }
+  };
+
+  const char* statement_data[] = {
+    "/unterminated",
+    NULL
+  };
+
+  RunParserSyncTest(context_data, statement_data, kError);
+}
+
+
+TEST(NoErrorsRegexpLiteral) {
+  const char* context_data[][2] = {
+    {"var r = ", ""},
+    { NULL, NULL }
+  };
+
+  const char* statement_data[] = {
+    "/foo/",
+    "/foo/g",
+    "/foo/whatever",  // This is an error but not detected by the parser.
+    NULL
+  };
+
+  RunParserSyncTest(context_data, statement_data, kSuccess);
+}