Revert "Unify paren handling in Parser and PreParser."
authormarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 6 Feb 2014 11:59:16 +0000 (11:59 +0000)
committermarja@chromium.org <marja@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 6 Feb 2014 11:59:16 +0000 (11:59 +0000)
This reverts r19140.

Reason: Octane regression.

BUG=
TBR=verwaest@chromium.org

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

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

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

index 1756257..1a9919b 100644 (file)
@@ -82,16 +82,6 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) {
 }
 
 
-bool Expression::IsIdentifier() {
-  return (AsVariableProxy() != NULL && !AsVariableProxy()->is_this());
-}
-
-
-bool Expression::IsIdentifierNamed(String* name) {
-  return (AsVariableProxy() != NULL && AsVariableProxy()->name()->Equals(name));
-}
-
-
 VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
     : Expression(zone, position),
       name_(var->name()),
index 2b04599..2b33820 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -351,10 +351,6 @@ class Expression : public AstNode {
   // True if we can prove that the expression is the undefined literal.
   bool IsUndefinedLiteral(Isolate* isolate);
 
-  bool IsIdentifier();
-
-  bool IsIdentifierNamed(String* name);
-
   // Expression type bounds
   Bounds bounds() { return bounds_; }
   void set_bounds(Bounds bounds) { bounds_ = bounds; }
index ae2dd5f..211f737 100644 (file)
@@ -964,8 +964,10 @@ Statement* Parser::ParseModuleElement(ZoneStringList* labels,
           !scanner().HasAnyLineTerminatorBeforeNext() &&
           stmt != NULL) {
         ExpressionStatement* estmt = stmt->AsExpressionStatement();
-        if (estmt != NULL && estmt->expression()->IsIdentifierNamed(
-                                 isolate()->heap()->module_string()) &&
+        if (estmt != NULL &&
+            estmt->expression()->AsVariableProxy() != NULL &&
+            estmt->expression()->AsVariableProxy()->name()->Equals(
+                isolate()->heap()->module_string()) &&
             !scanner().literal_contains_escapes()) {
           return ParseModuleDeclaration(NULL, ok);
         }
@@ -2124,11 +2126,9 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
   int pos = peek_position();
   bool starts_with_idenfifier = peek_any_identifier();
   Expression* expr = ParseExpression(true, CHECK_OK);
-  // Even if the expression starts with an identifier, it is not necessarily an
-  // identifier. For example, "foo + bar" starts with an identifier but is not
-  // an identifier.
   if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
-      expr->IsIdentifier()) {
+      expr->AsVariableProxy() != NULL &&
+      !expr->AsVariableProxy()->is_this()) {
     // Expression is a single identifier, and not, e.g., a parenthesized
     // identifier.
     VariableProxy* var = expr->AsVariableProxy();
@@ -2165,7 +2165,9 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
       peek() == Token::FUNCTION &&
       !scanner().HasAnyLineTerminatorBeforeNext() &&
       expr != NULL &&
-      expr->IsIdentifierNamed(isolate()->heap()->native_string()) &&
+      expr->AsVariableProxy() != NULL &&
+      expr->AsVariableProxy()->name()->Equals(
+          isolate()->heap()->native_string()) &&
       !scanner().literal_contains_escapes()) {
     return ParseNativeDeclaration(ok);
   }
@@ -2175,7 +2177,9 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
   if (!FLAG_harmony_modules ||
       peek() != Token::IDENTIFIER ||
       scanner().HasAnyLineTerminatorBeforeNext() ||
-      !expr->IsIdentifierNamed(isolate()->heap()->module_string()) ||
+      expr->AsVariableProxy() == NULL ||
+      !expr->AsVariableProxy()->name()->Equals(
+          isolate()->heap()->module_string()) ||
       scanner().literal_contains_escapes()) {
     ExpectSemicolon(CHECK_OK);
   }
@@ -2942,7 +2946,8 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
   Property* property = expression ? expression->AsProperty() : NULL;
   if (op == Token::ASSIGN &&
       property != NULL &&
-      property->obj()->IsIdentifier()) {
+      property->obj()->AsVariableProxy() != NULL &&
+      property->obj()->AsVariableProxy()->is_this()) {
     current_function_state_->AddProperty();
   }
 
index becf914..4150d33 100644 (file)
@@ -168,18 +168,15 @@ PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
   // SourceElements ::
   //   (Statement)* <end_token>
 
-  bool directive_prologue = true;
+  bool allow_directive_prologue = true;
   while (peek() != end_token) {
-    if (directive_prologue && peek() != Token::STRING) {
-      directive_prologue = false;
-    }
     Statement statement = ParseSourceElement(CHECK_OK);
-    if (directive_prologue) {
+    if (allow_directive_prologue) {
       if (statement.IsUseStrictLiteral()) {
         set_language_mode(allow_harmony_scoping() ?
                           EXTENDED_MODE : STRICT_MODE);
       } else if (!statement.IsStringLiteral()) {
-        directive_prologue = false;
+        allow_directive_prologue = false;
       }
     }
   }
@@ -471,20 +468,16 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
   //   Expression ';'
   //   Identifier ':' Statement
 
-  bool starts_with_identifier = peek_any_identifier();
   Expression expr = ParseExpression(true, CHECK_OK);
-  // Even if the expression starts with an identifier, it is not necessarily an
-  // identifier. For example, "foo + bar" starts with an identifier but is not
-  // an identifier.
-  if (peek() == Token::COLON && starts_with_identifier && expr.IsIdentifier()) {
-    // Expression is a single identifier, and not, e.g., a parenthesized
-    // identifier.
+  if (expr.IsRawIdentifier()) {
     ASSERT(!expr.AsIdentifier().IsFutureReserved());
     ASSERT(is_classic_mode() ||
            (!expr.AsIdentifier().IsFutureStrictReserved() &&
             !expr.AsIdentifier().IsYield()));
-    Consume(Token::COLON);
-    return ParseStatement(ok);
+    if (peek() == Token::COLON) {
+      Consume(Token::COLON);
+      return ParseStatement(ok);
+    }
     // Preparsing is disabled for extensions (because the extension details
     // aren't passed to lazily compiled functions), so we don't
     // accept "native function" in the preparser.
@@ -1177,6 +1170,7 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
       parenthesized_function_ = (peek() == Token::FUNCTION);
       result = ParseExpression(true, CHECK_OK);
       Expect(Token::RPAREN, CHECK_OK);
+      result = result.Parenthesize();
       break;
 
     case Token::MOD:
index 3a68bed..d0c7e3e 100644 (file)
@@ -347,6 +347,8 @@ class PreParser : public ParserBase {
   // if bit 1 is set, it's a string literal.
   // If neither is set, it's no particular type, and both set isn't
   // use yet.
+  // Bit 2 is used to mark the expression as being parenthesized,
+  // so "(foo)" isn't recognized as a pure identifier (and possible label).
   class Expression {
    public:
     static Expression Default() {
@@ -387,8 +389,21 @@ class PreParser : public ParserBase {
           static_cast<PreParser::Identifier::Type>(code_ >> kIdentifierShift));
     }
 
+    bool IsParenthesized() {
+      // If bit 0 or 1 is set, we interpret bit 2 as meaning parenthesized.
+      return (code_ & 7) > 4;
+    }
+
+    bool IsRawIdentifier() {
+      return !IsParenthesized() && IsIdentifier();
+    }
+
     bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
 
+    bool IsRawStringLiteral() {
+      return !IsParenthesized() && IsStringLiteral();
+    }
+
     bool IsUseStrictLiteral() {
       return (code_ & kStringLiteralMask) == kUseStrictString;
     }
@@ -405,10 +420,27 @@ class PreParser : public ParserBase {
       return code_ == kStrictFunctionExpression;
     }
 
+    Expression Parenthesize() {
+      int type = code_ & 3;
+      if (type != 0) {
+        // Identifiers and string literals can be parenthesized.
+        // They no longer work as labels or directive prologues,
+        // but are still recognized in other contexts.
+        return Expression(code_ | kParenthesizedExpressionFlag);
+      }
+      // For other types of expressions, it's not important to remember
+      // the parentheses.
+      return *this;
+    }
+
    private:
     // First two/three bits are used as flags.
     // Bit 0 and 1 represent identifiers or strings literals, and are
     // mutually exclusive, but can both be absent.
+    // If bit 0 or 1 are set, bit 2 marks that the expression has
+    // been wrapped in parentheses (a string literal can no longer
+    // be a directive prologue, and an identifier can no longer be
+    // a label.
     enum  {
       kUnknownExpression = 0,
       // Identifiers
@@ -420,6 +452,9 @@ class PreParser : public ParserBase {
       kUseStrictString = kStringLiteralFlag | 8,
       kStringLiteralMask = kUseStrictString,
 
+      // Only if identifier or string literal.
+      kParenthesizedExpressionFlag = 4,
+
       // Below here applies if neither identifier nor string literal.
       kThisExpression = 4,
       kThisPropertyExpression = 8,
@@ -445,11 +480,13 @@ class PreParser : public ParserBase {
     // Preserves being an unparenthesized string literal, possibly
     // "use strict".
     static Statement ExpressionStatement(Expression expression) {
-      if (expression.IsUseStrictLiteral()) {
-        return Statement(kUseStrictExpressionStatement);
-      }
-      if (expression.IsStringLiteral()) {
-        return Statement(kStringLiteralExpressionStatement);
+      if (!expression.IsParenthesized()) {
+        if (expression.IsUseStrictLiteral()) {
+          return Statement(kUseStrictExpressionStatement);
+        }
+        if (expression.IsStringLiteral()) {
+          return Statement(kStringLiteralExpressionStatement);
+        }
       }
       return Default();
     }
index 9768e30..0106e59 100644 (file)
@@ -1798,36 +1798,3 @@ TEST(NoErrorsIllegalWordsAsLabels) {
 
   RunParserSyncTest(context_data, statement_data, kSuccess);
 }
-
-
-TEST(ErrorsParenthesizedLabels) {
-  // Parenthesized identifiers shouldn't be recognized as labels.
-  const char* context_data[][2] = {
-    { "", ""},
-    { "function test_func() {", "}" },
-    { NULL, NULL }
-  };
-
-  const char* statement_data[] = {
-    "(mylabel): while(true) { break mylabel; }",
-    NULL
-  };
-
-  RunParserSyncTest(context_data, statement_data, kError);
-}
-
-
-TEST(NoErrorsParenthesizedDirectivePrologue) {
-  // Parenthesized directive prologue shouldn't be recognized.
-  const char* context_data[][2] = {
-    { "", ""},
-    { NULL, NULL }
-  };
-
-  const char* statement_data[] = {
-    "(\"use strict\"); var eval;",
-    NULL
-  };
-
-  RunParserSyncTest(context_data, statement_data, kSuccess);
-}