Commit e6bc60c9 authored by marja@chromium.org's avatar marja@chromium.org

Revert "Unify paren handling in Parser and PreParser."

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
parent 88b45eef
...@@ -82,16 +82,6 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) { ...@@ -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) VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
: Expression(zone, position), : Expression(zone, position),
name_(var->name()), name_(var->name()),
......
...@@ -351,10 +351,6 @@ class Expression : public AstNode { ...@@ -351,10 +351,6 @@ class Expression : public AstNode {
// True if we can prove that the expression is the undefined literal. // True if we can prove that the expression is the undefined literal.
bool IsUndefinedLiteral(Isolate* isolate); bool IsUndefinedLiteral(Isolate* isolate);
bool IsIdentifier();
bool IsIdentifierNamed(String* name);
// Expression type bounds // Expression type bounds
Bounds bounds() { return bounds_; } Bounds bounds() { return bounds_; }
void set_bounds(Bounds bounds) { bounds_ = bounds; } void set_bounds(Bounds bounds) { bounds_ = bounds; }
......
...@@ -964,8 +964,10 @@ Statement* Parser::ParseModuleElement(ZoneStringList* labels, ...@@ -964,8 +964,10 @@ Statement* Parser::ParseModuleElement(ZoneStringList* labels,
!scanner().HasAnyLineTerminatorBeforeNext() && !scanner().HasAnyLineTerminatorBeforeNext() &&
stmt != NULL) { stmt != NULL) {
ExpressionStatement* estmt = stmt->AsExpressionStatement(); ExpressionStatement* estmt = stmt->AsExpressionStatement();
if (estmt != NULL && estmt->expression()->IsIdentifierNamed( if (estmt != NULL &&
isolate()->heap()->module_string()) && estmt->expression()->AsVariableProxy() != NULL &&
estmt->expression()->AsVariableProxy()->name()->Equals(
isolate()->heap()->module_string()) &&
!scanner().literal_contains_escapes()) { !scanner().literal_contains_escapes()) {
return ParseModuleDeclaration(NULL, ok); return ParseModuleDeclaration(NULL, ok);
} }
...@@ -2124,11 +2126,9 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, ...@@ -2124,11 +2126,9 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
int pos = peek_position(); int pos = peek_position();
bool starts_with_idenfifier = peek_any_identifier(); bool starts_with_idenfifier = peek_any_identifier();
Expression* expr = ParseExpression(true, CHECK_OK); 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 && 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 // Expression is a single identifier, and not, e.g., a parenthesized
// identifier. // identifier.
VariableProxy* var = expr->AsVariableProxy(); VariableProxy* var = expr->AsVariableProxy();
...@@ -2165,7 +2165,9 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, ...@@ -2165,7 +2165,9 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
peek() == Token::FUNCTION && peek() == Token::FUNCTION &&
!scanner().HasAnyLineTerminatorBeforeNext() && !scanner().HasAnyLineTerminatorBeforeNext() &&
expr != NULL && expr != NULL &&
expr->IsIdentifierNamed(isolate()->heap()->native_string()) && expr->AsVariableProxy() != NULL &&
expr->AsVariableProxy()->name()->Equals(
isolate()->heap()->native_string()) &&
!scanner().literal_contains_escapes()) { !scanner().literal_contains_escapes()) {
return ParseNativeDeclaration(ok); return ParseNativeDeclaration(ok);
} }
...@@ -2175,7 +2177,9 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels, ...@@ -2175,7 +2177,9 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
if (!FLAG_harmony_modules || if (!FLAG_harmony_modules ||
peek() != Token::IDENTIFIER || peek() != Token::IDENTIFIER ||
scanner().HasAnyLineTerminatorBeforeNext() || scanner().HasAnyLineTerminatorBeforeNext() ||
!expr->IsIdentifierNamed(isolate()->heap()->module_string()) || expr->AsVariableProxy() == NULL ||
!expr->AsVariableProxy()->name()->Equals(
isolate()->heap()->module_string()) ||
scanner().literal_contains_escapes()) { scanner().literal_contains_escapes()) {
ExpectSemicolon(CHECK_OK); ExpectSemicolon(CHECK_OK);
} }
...@@ -2942,7 +2946,8 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) { ...@@ -2942,7 +2946,8 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
Property* property = expression ? expression->AsProperty() : NULL; Property* property = expression ? expression->AsProperty() : NULL;
if (op == Token::ASSIGN && if (op == Token::ASSIGN &&
property != NULL && property != NULL &&
property->obj()->IsIdentifier()) { property->obj()->AsVariableProxy() != NULL &&
property->obj()->AsVariableProxy()->is_this()) {
current_function_state_->AddProperty(); current_function_state_->AddProperty();
} }
......
...@@ -168,18 +168,15 @@ PreParser::SourceElements PreParser::ParseSourceElements(int end_token, ...@@ -168,18 +168,15 @@ PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
// SourceElements :: // SourceElements ::
// (Statement)* <end_token> // (Statement)* <end_token>
bool directive_prologue = true; bool allow_directive_prologue = true;
while (peek() != end_token) { while (peek() != end_token) {
if (directive_prologue && peek() != Token::STRING) {
directive_prologue = false;
}
Statement statement = ParseSourceElement(CHECK_OK); Statement statement = ParseSourceElement(CHECK_OK);
if (directive_prologue) { if (allow_directive_prologue) {
if (statement.IsUseStrictLiteral()) { if (statement.IsUseStrictLiteral()) {
set_language_mode(allow_harmony_scoping() ? set_language_mode(allow_harmony_scoping() ?
EXTENDED_MODE : STRICT_MODE); EXTENDED_MODE : STRICT_MODE);
} else if (!statement.IsStringLiteral()) { } else if (!statement.IsStringLiteral()) {
directive_prologue = false; allow_directive_prologue = false;
} }
} }
} }
...@@ -471,20 +468,16 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { ...@@ -471,20 +468,16 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
// Expression ';' // Expression ';'
// Identifier ':' Statement // Identifier ':' Statement
bool starts_with_identifier = peek_any_identifier();
Expression expr = ParseExpression(true, CHECK_OK); Expression expr = ParseExpression(true, CHECK_OK);
// Even if the expression starts with an identifier, it is not necessarily an if (expr.IsRawIdentifier()) {
// 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.
ASSERT(!expr.AsIdentifier().IsFutureReserved()); ASSERT(!expr.AsIdentifier().IsFutureReserved());
ASSERT(is_classic_mode() || ASSERT(is_classic_mode() ||
(!expr.AsIdentifier().IsFutureStrictReserved() && (!expr.AsIdentifier().IsFutureStrictReserved() &&
!expr.AsIdentifier().IsYield())); !expr.AsIdentifier().IsYield()));
Consume(Token::COLON); if (peek() == Token::COLON) {
return ParseStatement(ok); Consume(Token::COLON);
return ParseStatement(ok);
}
// Preparsing is disabled for extensions (because the extension details // Preparsing is disabled for extensions (because the extension details
// aren't passed to lazily compiled functions), so we don't // aren't passed to lazily compiled functions), so we don't
// accept "native function" in the preparser. // accept "native function" in the preparser.
...@@ -1177,6 +1170,7 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) { ...@@ -1177,6 +1170,7 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
parenthesized_function_ = (peek() == Token::FUNCTION); parenthesized_function_ = (peek() == Token::FUNCTION);
result = ParseExpression(true, CHECK_OK); result = ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK); Expect(Token::RPAREN, CHECK_OK);
result = result.Parenthesize();
break; break;
case Token::MOD: case Token::MOD:
......
...@@ -347,6 +347,8 @@ class PreParser : public ParserBase { ...@@ -347,6 +347,8 @@ class PreParser : public ParserBase {
// if bit 1 is set, it's a string literal. // if bit 1 is set, it's a string literal.
// If neither is set, it's no particular type, and both set isn't // If neither is set, it's no particular type, and both set isn't
// use yet. // 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 { class Expression {
public: public:
static Expression Default() { static Expression Default() {
...@@ -387,8 +389,21 @@ class PreParser : public ParserBase { ...@@ -387,8 +389,21 @@ class PreParser : public ParserBase {
static_cast<PreParser::Identifier::Type>(code_ >> kIdentifierShift)); 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 IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
bool IsRawStringLiteral() {
return !IsParenthesized() && IsStringLiteral();
}
bool IsUseStrictLiteral() { bool IsUseStrictLiteral() {
return (code_ & kStringLiteralMask) == kUseStrictString; return (code_ & kStringLiteralMask) == kUseStrictString;
} }
...@@ -405,10 +420,27 @@ class PreParser : public ParserBase { ...@@ -405,10 +420,27 @@ class PreParser : public ParserBase {
return code_ == kStrictFunctionExpression; 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: private:
// First two/three bits are used as flags. // First two/three bits are used as flags.
// Bit 0 and 1 represent identifiers or strings literals, and are // Bit 0 and 1 represent identifiers or strings literals, and are
// mutually exclusive, but can both be absent. // 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 { enum {
kUnknownExpression = 0, kUnknownExpression = 0,
// Identifiers // Identifiers
...@@ -420,6 +452,9 @@ class PreParser : public ParserBase { ...@@ -420,6 +452,9 @@ class PreParser : public ParserBase {
kUseStrictString = kStringLiteralFlag | 8, kUseStrictString = kStringLiteralFlag | 8,
kStringLiteralMask = kUseStrictString, kStringLiteralMask = kUseStrictString,
// Only if identifier or string literal.
kParenthesizedExpressionFlag = 4,
// Below here applies if neither identifier nor string literal. // Below here applies if neither identifier nor string literal.
kThisExpression = 4, kThisExpression = 4,
kThisPropertyExpression = 8, kThisPropertyExpression = 8,
...@@ -445,11 +480,13 @@ class PreParser : public ParserBase { ...@@ -445,11 +480,13 @@ class PreParser : public ParserBase {
// Preserves being an unparenthesized string literal, possibly // Preserves being an unparenthesized string literal, possibly
// "use strict". // "use strict".
static Statement ExpressionStatement(Expression expression) { static Statement ExpressionStatement(Expression expression) {
if (expression.IsUseStrictLiteral()) { if (!expression.IsParenthesized()) {
return Statement(kUseStrictExpressionStatement); if (expression.IsUseStrictLiteral()) {
} return Statement(kUseStrictExpressionStatement);
if (expression.IsStringLiteral()) { }
return Statement(kStringLiteralExpressionStatement); if (expression.IsStringLiteral()) {
return Statement(kStringLiteralExpressionStatement);
}
} }
return Default(); return Default();
} }
......
...@@ -1798,36 +1798,3 @@ TEST(NoErrorsIllegalWordsAsLabels) { ...@@ -1798,36 +1798,3 @@ TEST(NoErrorsIllegalWordsAsLabels) {
RunParserSyncTest(context_data, statement_data, kSuccess); 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment