Commit 42ea494c authored by marja@chromium.org's avatar marja@chromium.org

Redo r19140 with better efficiency.

Still relevant parts of the original commit message:

Unify paren handling in Parser and PreParser.

It is only needed in (Pre)Parser::ParseExpressionOrLabelledStatement for not
recognizing parenthesized identifiers as labels and in
(Pre)Parser::ParseSourceElements for not recognizing a parenthesized string as
directive prologue.

Parser Expressions don't keep track of whether they're parenthesized, so
PreParser Expressions shouldn't either.

BUG=3126
LOG=N
R=ulan@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19153 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 43c0a419
...@@ -168,15 +168,18 @@ PreParser::SourceElements PreParser::ParseSourceElements(int end_token, ...@@ -168,15 +168,18 @@ PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
// SourceElements :: // SourceElements ::
// (Statement)* <end_token> // (Statement)* <end_token>
bool allow_directive_prologue = true; bool 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 (allow_directive_prologue) { if (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()) {
allow_directive_prologue = false; directive_prologue = false;
} }
} }
} }
...@@ -468,16 +471,20 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { ...@@ -468,16 +471,20 @@ 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);
if (expr.IsRawIdentifier()) { // 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 (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) {
// 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()));
if (peek() == Token::COLON) { Consume(Token::COLON);
Consume(Token::COLON); return ParseStatement(ok);
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.
...@@ -1170,7 +1177,6 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) { ...@@ -1170,7 +1177,6 @@ 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,8 +347,6 @@ class PreParser : public ParserBase { ...@@ -347,8 +347,6 @@ 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() {
...@@ -389,21 +387,8 @@ class PreParser : public ParserBase { ...@@ -389,21 +387,8 @@ 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;
} }
...@@ -420,27 +405,10 @@ class PreParser : public ParserBase { ...@@ -420,27 +405,10 @@ 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
...@@ -452,9 +420,6 @@ class PreParser : public ParserBase { ...@@ -452,9 +420,6 @@ 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,
...@@ -480,13 +445,11 @@ class PreParser : public ParserBase { ...@@ -480,13 +445,11 @@ 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.IsParenthesized()) { if (expression.IsUseStrictLiteral()) {
if (expression.IsUseStrictLiteral()) { return Statement(kUseStrictExpressionStatement);
return Statement(kUseStrictExpressionStatement); }
} if (expression.IsStringLiteral()) {
if (expression.IsStringLiteral()) { return Statement(kStringLiteralExpressionStatement);
return Statement(kStringLiteralExpressionStatement);
}
} }
return Default(); return Default();
} }
......
...@@ -1798,3 +1798,36 @@ TEST(NoErrorsIllegalWordsAsLabels) { ...@@ -1798,3 +1798,36 @@ 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