Index: src/preparser.cc |
diff --git a/src/preparser.cc b/src/preparser.cc |
index 5bd9906f73b2644a366c9ee4adc2a2fd3c266f8e..eaadb58915425f755e1cefc57e7681dd9ade900e 100644 |
--- a/src/preparser.cc |
+++ b/src/preparser.cc |
@@ -56,13 +56,6 @@ namespace preparser { |
namespace i = ::v8::internal; |
-#define CHECK_OK ok); \ |
- if (!*ok) return -1; \ |
- ((void)0 |
-#define DUMMY ) // to make indentation work |
-#undef DUMMY |
- |
- |
void PreParser::ReportUnexpectedToken(i::Token::Value token) { |
// We don't report stack overflows here, to avoid increasing the |
// stack depth even further. Instead we report it after parsing is |
@@ -107,6 +100,13 @@ void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { |
} |
+#define CHECK_OK ok); \ |
+ if (!*ok) return kUnknownSourceElements; \ |
+ ((void)0 |
+#define DUMMY ) // to make indentation work |
+#undef DUMMY |
+ |
+ |
PreParser::SourceElements PreParser::ParseSourceElements(int end_token, |
bool* ok) { |
// SourceElements :: |
@@ -116,9 +116,9 @@ PreParser::SourceElements PreParser::ParseSourceElements(int end_token, |
while (peek() != end_token) { |
Statement statement = ParseStatement(CHECK_OK); |
if (allow_directive_prologue) { |
- if (statement == kUseStrictExpressionStatement) { |
+ if (statement.IsUseStrictLiteral()) { |
set_strict_mode(); |
- } else if (statement != kStringLiteralExpressionStatement) { |
+ } else if (!statement.IsStringLiteral()) { |
allow_directive_prologue = false; |
} |
} |
@@ -127,6 +127,14 @@ PreParser::SourceElements PreParser::ParseSourceElements(int end_token, |
} |
+#undef CHECK_OK |
+#define CHECK_OK ok); \ |
+ if (!*ok) return Statement::Default(); \ |
+ ((void)0 |
+#define DUMMY ) // to make indentation work |
+#undef DUMMY |
+ |
+ |
PreParser::Statement PreParser::ParseStatement(bool* ok) { |
// Statement :: |
// Block |
@@ -163,10 +171,10 @@ PreParser::Statement PreParser::ParseStatement(bool* ok) { |
case i::Token::SEMICOLON: |
Next(); |
- return kUnknownStatement; |
+ return Statement::Default(); |
case i::Token::IF: |
- return ParseIfStatement(ok); |
+ return ParseIfStatement(ok); |
case i::Token::DO: |
return ParseDoWhileStatement(ok); |
@@ -217,9 +225,24 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { |
// FunctionDeclaration :: |
// 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
Expect(i::Token::FUNCTION, CHECK_OK); |
- ParseIdentifier(CHECK_OK); |
- ParseFunctionLiteral(CHECK_OK); |
- return kUnknownStatement; |
+ |
+ Identifier identifier = ParseIdentifier(CHECK_OK); |
+ i::Scanner::Location location = scanner_->location(); |
+ |
+ Expression function_value = ParseFunctionLiteral(CHECK_OK); |
+ |
+ if (function_value.IsStrictFunction() && |
+ !identifier.IsValidStrictVariable()) { |
+ // Strict mode violation, using either reserved word or eval/arguments |
+ // as name of strict function. |
+ const char* type = "strict_function_name"; |
+ if (identifier.IsFutureReserved()) { |
+ type = "strict_reserved_word"; |
+ } |
+ ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); |
+ *ok = false; |
+ } |
+ return Statement::Default(); |
} |
@@ -242,7 +265,7 @@ PreParser::Statement PreParser::ParseNativeDeclaration(bool* ok) { |
} |
Expect(i::Token::RPAREN, CHECK_OK); |
Expect(i::Token::SEMICOLON, CHECK_OK); |
- return kUnknownStatement; |
+ return Statement::Default(); |
} |
@@ -257,8 +280,8 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) { |
while (peek() != i::Token::RBRACE) { |
ParseStatement(CHECK_OK); |
} |
- Expect(i::Token::RBRACE, CHECK_OK); |
- return kUnknownStatement; |
+ Expect(i::Token::RBRACE, ok); |
+ return Statement::Default(); |
} |
@@ -289,7 +312,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN, |
Consume(i::Token::CONST); |
} else { |
*ok = false; |
- return 0; |
+ return Statement::Default(); |
} |
// The scope of a variable/const declared anywhere inside a function |
@@ -298,7 +321,14 @@ PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN, |
do { |
// Parse variable name. |
if (nvars > 0) Consume(i::Token::COMMA); |
- ParseIdentifier(CHECK_OK); |
+ Identifier identifier = ParseIdentifier(CHECK_OK); |
+ if (strict_mode() && !identifier.IsValidStrictVariable()) { |
+ StrictModeIdentifierViolation(scanner_->location(), |
+ "strict_var_name", |
+ identifier, |
+ ok); |
+ return Statement::Default(); |
+ } |
nvars++; |
if (peek() == i::Token::ASSIGN) { |
Expect(i::Token::ASSIGN, CHECK_OK); |
@@ -307,31 +337,24 @@ PreParser::Statement PreParser::ParseVariableDeclarations(bool accept_IN, |
} while (peek() == i::Token::COMMA); |
if (num_decl != NULL) *num_decl = nvars; |
- return kUnknownStatement; |
+ return Statement::Default(); |
} |
-PreParser::Statement PreParser::ParseExpressionOrLabelledStatement( |
- bool* ok) { |
+PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { |
// ExpressionStatement | LabelledStatement :: |
// Expression ';' |
// Identifier ':' Statement |
Expression expr = ParseExpression(true, CHECK_OK); |
- if (peek() == i::Token::COLON && expr == kIdentifierExpression) { |
+ if (peek() == i::Token::COLON && expr.IsRawIdentifier()) { |
Consume(i::Token::COLON); |
ParseStatement(ok); |
- return kUnknownStatement; |
+ return Statement::Default(); |
} |
// Parsed expression statement. |
ExpectSemicolon(CHECK_OK); |
- if (expr == kStringLiteralExpression) { |
- return kStringLiteralExpressionStatement; |
- } |
- if (expr == kUseStrictString) { |
- return kUseStrictExpressionStatement; |
- } |
- return kUnknownStatement; |
+ return Statement::ExpressionStatement(expr); |
} |
@@ -348,7 +371,7 @@ PreParser::Statement PreParser::ParseIfStatement(bool* ok) { |
Next(); |
ParseStatement(CHECK_OK); |
} |
- return kUnknownStatement; |
+ return Statement::Default(); |
} |
@@ -365,7 +388,7 @@ PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { |
ParseIdentifier(CHECK_OK); |
} |
ExpectSemicolon(CHECK_OK); |
- return kUnknownStatement; |
+ return Statement::Default(); |
} |
@@ -382,7 +405,7 @@ PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { |
ParseIdentifier(CHECK_OK); |
} |
ExpectSemicolon(CHECK_OK); |
- return kUnknownStatement; |
+ return Statement::Default(); |
} |
@@ -408,7 +431,7 @@ PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { |
ParseExpression(true, CHECK_OK); |
} |
ExpectSemicolon(CHECK_OK); |
- return kUnknownStatement; |
+ return Statement::Default(); |
} |
@@ -416,6 +439,13 @@ PreParser::Statement PreParser::ParseWithStatement(bool* ok) { |
// WithStatement :: |
// 'with' '(' Expression ')' Statement |
Expect(i::Token::WITH, CHECK_OK); |
+ if (strict_mode()) { |
+ i::Scanner::Location location = scanner_->location(); |
+ ReportMessageAt(location.beg_pos, location.end_pos, |
+ "strict_mode_with", NULL); |
+ *ok = false; |
+ return Statement::Default(); |
+ } |
Expect(i::Token::LPAREN, CHECK_OK); |
ParseExpression(true, CHECK_OK); |
Expect(i::Token::RPAREN, CHECK_OK); |
@@ -423,7 +453,7 @@ PreParser::Statement PreParser::ParseWithStatement(bool* ok) { |
scope_->EnterWith(); |
ParseStatement(CHECK_OK); |
scope_->LeaveWith(); |
- return kUnknownStatement; |
+ return Statement::Default(); |
} |
@@ -451,9 +481,8 @@ PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) { |
} |
token = peek(); |
} |
- Expect(i::Token::RBRACE, CHECK_OK); |
- |
- return kUnknownStatement; |
+ Expect(i::Token::RBRACE, ok); |
+ return Statement::Default(); |
} |
@@ -466,8 +495,8 @@ PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) { |
Expect(i::Token::WHILE, CHECK_OK); |
Expect(i::Token::LPAREN, CHECK_OK); |
ParseExpression(true, CHECK_OK); |
- Expect(i::Token::RPAREN, CHECK_OK); |
- return kUnknownStatement; |
+ Expect(i::Token::RPAREN, ok); |
+ return Statement::Default(); |
} |
@@ -479,8 +508,8 @@ PreParser::Statement PreParser::ParseWhileStatement(bool* ok) { |
Expect(i::Token::LPAREN, CHECK_OK); |
ParseExpression(true, CHECK_OK); |
Expect(i::Token::RPAREN, CHECK_OK); |
- ParseStatement(CHECK_OK); |
- return kUnknownStatement; |
+ ParseStatement(ok); |
+ return Statement::Default(); |
} |
@@ -500,7 +529,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) { |
Expect(i::Token::RPAREN, CHECK_OK); |
ParseStatement(CHECK_OK); |
- return kUnknownStatement; |
+ return Statement::Default(); |
} |
} else { |
ParseExpression(false, CHECK_OK); |
@@ -510,7 +539,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) { |
Expect(i::Token::RPAREN, CHECK_OK); |
ParseStatement(CHECK_OK); |
- return kUnknownStatement; |
+ return Statement::Default(); |
} |
} |
} |
@@ -528,8 +557,8 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) { |
} |
Expect(i::Token::RPAREN, CHECK_OK); |
- ParseStatement(CHECK_OK); |
- return kUnknownStatement; |
+ ParseStatement(ok); |
+ return Statement::Default(); |
} |
@@ -543,12 +572,11 @@ PreParser::Statement PreParser::ParseThrowStatement(bool* ok) { |
ReportMessageAt(pos.beg_pos, pos.end_pos, |
"newline_after_throw", NULL); |
*ok = false; |
- return kUnknownStatement; |
+ return Statement::Default(); |
} |
ParseExpression(true, CHECK_OK); |
- ExpectSemicolon(CHECK_OK); |
- |
- return kUnknownStatement; |
+ ExpectSemicolon(ok); |
+ return Statement::Default(); |
} |
@@ -575,12 +603,19 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) { |
if (peek() == i::Token::CATCH) { |
Consume(i::Token::CATCH); |
Expect(i::Token::LPAREN, CHECK_OK); |
- ParseIdentifier(CHECK_OK); |
+ Identifier id = ParseIdentifier(CHECK_OK); |
+ if (strict_mode() && !id.IsValidStrictVariable()) { |
+ StrictModeIdentifierViolation(scanner_->location(), |
+ "strict_catch_variable", |
+ id, |
+ ok); |
+ return Statement::Default(); |
+ } |
Expect(i::Token::RPAREN, CHECK_OK); |
scope_->EnterWith(); |
ParseBlock(ok); |
scope_->LeaveWith(); |
- if (!*ok) return kUnknownStatement; |
+ if (!*ok) Statement::Default(); |
catch_or_finally_seen = true; |
} |
if (peek() == i::Token::FINALLY) { |
@@ -591,7 +626,7 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) { |
if (!catch_or_finally_seen) { |
*ok = false; |
} |
- return kUnknownStatement; |
+ return Statement::Default(); |
} |
@@ -603,11 +638,19 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { |
// 'debugger' ';' |
Expect(i::Token::DEBUGGER, CHECK_OK); |
- ExpectSemicolon(CHECK_OK); |
- return kUnknownStatement; |
+ ExpectSemicolon(ok); |
+ return Statement::Default(); |
} |
+#undef CHECK_OK |
+#define CHECK_OK ok); \ |
+ if (!*ok) return Expression::Default(); \ |
+ ((void)0 |
+#define DUMMY ) // to make indentation work |
+#undef DUMMY |
+ |
+ |
// Precedence = 1 |
PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) { |
// Expression :: |
@@ -618,7 +661,7 @@ PreParser::Expression PreParser::ParseExpression(bool accept_IN, bool* ok) { |
while (peek() == i::Token::COMMA) { |
Expect(i::Token::COMMA, CHECK_OK); |
ParseAssignmentExpression(accept_IN, CHECK_OK); |
- result = kUnknownExpression; |
+ result = Expression::Default(); |
} |
return result; |
} |
@@ -631,6 +674,7 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN, |
// ConditionalExpression |
// LeftHandSideExpression AssignmentOperator AssignmentExpression |
+ i::Scanner::Location before = scanner_->peek_location(); |
Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK); |
if (!i::Token::IsAssignmentOp(peek())) { |
@@ -638,14 +682,23 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN, |
return expression; |
} |
+ if (strict_mode() && expression.IsIdentifier() && |
+ expression.AsIdentifier().IsEvalOrArguments()) { |
+ i::Scanner::Location after = scanner_->location(); |
+ ReportMessageAt(before.beg_pos, after.end_pos, |
+ "strict_lhs_assignment", NULL); |
+ *ok = false; |
+ return Expression::Default(); |
+ } |
+ |
i::Token::Value op = Next(); // Get assignment operator. |
ParseAssignmentExpression(accept_IN, CHECK_OK); |
- if ((op == i::Token::ASSIGN) && (expression == kThisPropertyExpression)) { |
+ if ((op == i::Token::ASSIGN) && expression.IsThisProperty()) { |
scope_->AddProperty(); |
} |
- return kUnknownExpression; |
+ return Expression::Default(); |
} |
@@ -666,7 +719,7 @@ PreParser::Expression PreParser::ParseConditionalExpression(bool accept_IN, |
ParseAssignmentExpression(true, CHECK_OK); |
Expect(i::Token::COLON, CHECK_OK); |
ParseAssignmentExpression(accept_IN, CHECK_OK); |
- return kUnknownExpression; |
+ return Expression::Default(); |
} |
@@ -688,7 +741,7 @@ PreParser::Expression PreParser::ParseBinaryExpression(int prec, |
while (Precedence(peek(), accept_IN) == prec1) { |
Next(); |
ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK); |
- result = kUnknownExpression; |
+ result = Expression::Default(); |
} |
} |
return result; |
@@ -709,10 +762,22 @@ PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) { |
// '!' UnaryExpression |
i::Token::Value op = peek(); |
- if (i::Token::IsUnaryOp(op) || i::Token::IsCountOp(op)) { |
+ if (i::Token::IsUnaryOp(op)) { |
op = Next(); |
ParseUnaryExpression(ok); |
- return kUnknownExpression; |
+ return Expression::Default(); |
+ } else if (i::Token::IsCountOp(op)) { |
+ op = Next(); |
+ i::Scanner::Location before = scanner_->peek_location(); |
+ Expression expression = ParseUnaryExpression(CHECK_OK); |
+ if (strict_mode() && expression.IsIdentifier() && |
+ expression.AsIdentifier().IsEvalOrArguments()) { |
+ i::Scanner::Location after = scanner_->location(); |
+ ReportMessageAt(before.beg_pos, after.end_pos, |
+ "strict_lhs_prefix", NULL); |
+ *ok = false; |
+ } |
+ return Expression::Default(); |
} else { |
return ParsePostfixExpression(ok); |
} |
@@ -723,11 +788,20 @@ PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) { |
// PostfixExpression :: |
// LeftHandSideExpression ('++' | '--')? |
+ i::Scanner::Location before = scanner_->peek_location(); |
Expression expression = ParseLeftHandSideExpression(CHECK_OK); |
if (!scanner_->has_line_terminator_before_next() && |
i::Token::IsCountOp(peek())) { |
+ if (strict_mode() && expression.IsIdentifier() && |
+ expression.AsIdentifier().IsEvalOrArguments()) { |
+ i::Scanner::Location after = scanner_->location(); |
+ ReportMessageAt(before.beg_pos, after.end_pos, |
+ "strict_lhs_postfix", NULL); |
+ *ok = false; |
+ return Expression::Default(); |
+ } |
Next(); |
- return kUnknownExpression; |
+ return Expression::Default(); |
} |
return expression; |
} |
@@ -737,7 +811,7 @@ PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) { |
// LeftHandSideExpression :: |
// (NewExpression | MemberExpression) ... |
- Expression result; |
+ Expression result = Expression::Default(); |
if (peek() == i::Token::NEW) { |
result = ParseNewExpression(CHECK_OK); |
} else { |
@@ -750,27 +824,27 @@ PreParser::Expression PreParser::ParseLeftHandSideExpression(bool* ok) { |
Consume(i::Token::LBRACK); |
ParseExpression(true, CHECK_OK); |
Expect(i::Token::RBRACK, CHECK_OK); |
- if (result == kThisExpression) { |
- result = kThisPropertyExpression; |
+ if (result.IsThis()) { |
+ result = Expression::ThisProperty(); |
} else { |
- result = kUnknownExpression; |
+ result = Expression::Default(); |
} |
break; |
} |
case i::Token::LPAREN: { |
ParseArguments(CHECK_OK); |
- result = kUnknownExpression; |
+ result = Expression::Default(); |
break; |
} |
case i::Token::PERIOD: { |
Consume(i::Token::PERIOD); |
ParseIdentifierName(CHECK_OK); |
- if (result == kThisExpression) { |
- result = kThisPropertyExpression; |
+ if (result.IsThis()) { |
+ result = Expression::ThisProperty(); |
} else { |
- result = kUnknownExpression; |
+ result = Expression::Default(); |
} |
break; |
} |
@@ -816,13 +890,21 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( |
// ('[' Expression ']' | '.' Identifier | Arguments)* |
// Parse the initial primary or function expression. |
- Expression result = kUnknownExpression; |
+ Expression result = Expression::Default(); |
if (peek() == i::Token::FUNCTION) { |
Consume(i::Token::FUNCTION); |
+ Identifier identifier = Identifier::Default(); |
if (peek_any_identifier()) { |
- ParseIdentifier(CHECK_OK); |
+ identifier = ParseIdentifier(CHECK_OK); |
} |
result = ParseFunctionLiteral(CHECK_OK); |
+ if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) { |
+ StrictModeIdentifierViolation(scanner_->location(), |
+ "strict_function_name", |
+ identifier, |
+ ok); |
+ return Expression::Default(); |
+ } |
} else { |
result = ParsePrimaryExpression(CHECK_OK); |
} |
@@ -833,20 +915,20 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( |
Consume(i::Token::LBRACK); |
ParseExpression(true, CHECK_OK); |
Expect(i::Token::RBRACK, CHECK_OK); |
- if (result == kThisExpression) { |
- result = kThisPropertyExpression; |
+ if (result.IsThis()) { |
+ result = Expression::ThisProperty(); |
} else { |
- result = kUnknownExpression; |
+ result = Expression::Default(); |
} |
break; |
} |
case i::Token::PERIOD: { |
Consume(i::Token::PERIOD); |
ParseIdentifierName(CHECK_OK); |
- if (result == kThisExpression) { |
- result = kThisPropertyExpression; |
+ if (result.IsThis()) { |
+ result = Expression::ThisProperty(); |
} else { |
- result = kUnknownExpression; |
+ result = Expression::Default(); |
} |
break; |
} |
@@ -855,7 +937,7 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( |
// Consume one of the new prefixes (already parsed). |
ParseArguments(CHECK_OK); |
new_count--; |
- result = kUnknownExpression; |
+ result = Expression::Default(); |
break; |
} |
default: |
@@ -879,18 +961,27 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) { |
// RegExpLiteral |
// '(' Expression ')' |
- Expression result = kUnknownExpression; |
+ Expression result = Expression::Default(); |
switch (peek()) { |
case i::Token::THIS: { |
Next(); |
- result = kThisExpression; |
+ result = Expression::This(); |
break; |
} |
- case i::Token::IDENTIFIER: |
- case i::Token::FUTURE_RESERVED_WORD: { |
- ParseIdentifier(CHECK_OK); |
- result = kIdentifierExpression; |
+ case i::Token::FUTURE_RESERVED_WORD: |
+ if (strict_mode()) { |
+ Next(); |
+ i::Scanner::Location location = scanner_->location(); |
+ ReportMessageAt(location.beg_pos, location.end_pos, |
+ "strict_reserved_word", NULL); |
+ *ok = false; |
+ return Expression::Default(); |
+ } |
+ // FALLTHROUGH |
+ case i::Token::IDENTIFIER: { |
+ Identifier id = ParseIdentifier(CHECK_OK); |
+ result = Expression::Identifier(id); |
break; |
} |
@@ -928,7 +1019,7 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) { |
parenthesized_function_ = (peek() == i::Token::FUNCTION); |
result = ParseExpression(true, CHECK_OK); |
Expect(i::Token::RPAREN, CHECK_OK); |
- if (result == kIdentifierExpression) result = kUnknownExpression; |
+ result = result.Parenthesize(); |
break; |
case i::Token::MOD: |
@@ -938,7 +1029,7 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) { |
default: { |
Next(); |
*ok = false; |
- return kUnknownExpression; |
+ return Expression::Default(); |
} |
} |
@@ -961,7 +1052,7 @@ PreParser::Expression PreParser::ParseArrayLiteral(bool* ok) { |
Expect(i::Token::RBRACK, CHECK_OK); |
scope_->NextMaterializedLiteralIndex(); |
- return kUnknownExpression; |
+ return Expression::Default(); |
} |
@@ -990,7 +1081,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { |
name != i::Token::STRING && |
!is_keyword) { |
*ok = false; |
- return kUnknownExpression; |
+ return Expression::Default(); |
} |
if (!is_keyword) { |
LogSymbol(); |
@@ -1016,7 +1107,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { |
} else { |
// Unexpected token. |
*ok = false; |
- return kUnknownExpression; |
+ return Expression::Default(); |
} |
} |
@@ -1029,7 +1120,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { |
Expect(i::Token::RBRACE, CHECK_OK); |
scope_->NextMaterializedLiteralIndex(); |
- return kUnknownExpression; |
+ return Expression::Default(); |
} |
@@ -1041,7 +1132,7 @@ PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal, |
ReportMessageAt(location.beg_pos, location.end_pos, |
"unterminated_regexp", NULL); |
*ok = false; |
- return kUnknownExpression; |
+ return Expression::Default(); |
} |
scope_->NextMaterializedLiteralIndex(); |
@@ -1052,10 +1143,10 @@ PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal, |
ReportMessageAt(location.beg_pos, location.end_pos, |
"invalid_regexp_flags", NULL); |
*ok = false; |
- return kUnknownExpression; |
+ return Expression::Default(); |
} |
Next(); |
- return kUnknownExpression; |
+ return Expression::Default(); |
} |
@@ -1063,16 +1154,21 @@ PreParser::Arguments PreParser::ParseArguments(bool* ok) { |
// Arguments :: |
// '(' (AssignmentExpression)*[','] ')' |
- Expect(i::Token::LPAREN, CHECK_OK); |
+ Expect(i::Token::LPAREN, ok); |
+ if (!*ok) return -1; |
bool done = (peek() == i::Token::RPAREN); |
int argc = 0; |
while (!done) { |
- ParseAssignmentExpression(true, CHECK_OK); |
+ ParseAssignmentExpression(true, ok); |
+ if (!*ok) return -1; |
argc++; |
done = (peek() == i::Token::RPAREN); |
- if (!done) Expect(i::Token::COMMA, CHECK_OK); |
+ if (!done) { |
+ Expect(i::Token::COMMA, ok); |
+ if (!*ok) return -1; |
+ } |
} |
- Expect(i::Token::RPAREN, CHECK_OK); |
+ Expect(i::Token::RPAREN, ok); |
return argc; |
} |
@@ -1091,7 +1187,13 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) { |
int start_position = scanner_->location().beg_pos; |
bool done = (peek() == i::Token::RPAREN); |
while (!done) { |
- ParseIdentifier(CHECK_OK); |
+ Identifier id = ParseIdentifier(CHECK_OK); |
+ if (!id.IsValidStrictVariable()) { |
+ StrictModeIdentifierViolation(scanner_->location(), |
+ "strict_param_name", |
+ id, |
+ CHECK_OK); |
+ } |
done = (peek() == i::Token::RPAREN); |
if (!done) { |
Expect(i::Token::COMMA, CHECK_OK); |
@@ -1114,7 +1216,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) { |
log_->PauseRecording(); |
ParseSourceElements(i::Token::RBRACE, ok); |
log_->ResumeRecording(); |
- if (!*ok) return kUnknownExpression; |
+ if (!*ok) Expression::Default(); |
Expect(i::Token::RBRACE, CHECK_OK); |
@@ -1128,12 +1230,14 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) { |
Expect(i::Token::RBRACE, CHECK_OK); |
} |
- if (scope_->is_strict()) { |
+ if (strict_mode()) { |
int end_position = scanner_->location().end_pos; |
CheckOctalLiteral(start_position, end_position, CHECK_OK); |
+ CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK); |
+ return Expression::StrictFunction(); |
} |
- return kUnknownExpression; |
+ return Expression::Default(); |
} |
@@ -1143,11 +1247,13 @@ PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { |
Expect(i::Token::MOD, CHECK_OK); |
ParseIdentifier(CHECK_OK); |
- ParseArguments(CHECK_OK); |
+ ParseArguments(ok); |
- return kUnknownExpression; |
+ return Expression::Default(); |
} |
+#undef CHECK_OK |
+ |
void PreParser::ExpectSemicolon(bool* ok) { |
// Check for automatic semicolon insertion according to |
@@ -1176,12 +1282,6 @@ void PreParser::LogSymbol() { |
} |
-PreParser::Identifier PreParser::GetIdentifierSymbol() { |
- LogSymbol(); |
- return kUnknownIdentifier; |
-} |
- |
- |
PreParser::Expression PreParser::GetStringSymbol() { |
const int kUseStrictLength = 10; |
const char* kUseStrictChars = "use strict"; |
@@ -1191,21 +1291,89 @@ PreParser::Expression PreParser::GetStringSymbol() { |
!scanner_->literal_contains_escapes() && |
!strncmp(scanner_->literal_ascii_string().start(), kUseStrictChars, |
kUseStrictLength)) { |
- return kUseStrictString; |
+ return Expression::UseStrictStringLiteral(); |
+ } |
+ return Expression::StringLiteral(); |
+} |
+ |
+ |
+PreParser::Identifier PreParser::GetIdentifierSymbol() { |
+ LogSymbol(); |
+ if (scanner_->current_token() == i::Token::FUTURE_RESERVED_WORD) { |
+ return Identifier::FutureReserved(); |
+ } |
+ if (scanner_->is_literal_ascii()) { |
+ // Detect strict-mode poison words. |
+ if (scanner_->literal_length() == 4 && |
+ !strncmp(scanner_->literal_ascii_string().start(), "eval", 4)) { |
+ return Identifier::Eval(); |
+ } |
+ if (scanner_->literal_length() == 9 && |
+ !strncmp(scanner_->literal_ascii_string().start(), "arguments", 9)) { |
+ return Identifier::Arguments(); |
+ } |
} |
- return kStringLiteralExpression; |
+ return Identifier::Default(); |
} |
PreParser::Identifier PreParser::ParseIdentifier(bool* ok) { |
if (!Check(i::Token::FUTURE_RESERVED_WORD)) { |
Expect(i::Token::IDENTIFIER, ok); |
+ if (!*ok) return Identifier::Default(); |
} |
- if (!*ok) return kUnknownIdentifier; |
return GetIdentifierSymbol(); |
} |
+void PreParser::SetStrictModeViolation(i::Scanner::Location location, |
+ const char* type, |
+ bool* ok) { |
+ if (strict_mode()) { |
+ ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); |
+ *ok = false; |
+ return; |
+ } |
+ // Delay report in case this later turns out to be strict code |
+ // (i.e., for function names and parameters prior to a "use strict" |
+ // directive). |
+ strict_mode_violation_location_ = location; |
+ strict_mode_violation_type_ = type; |
+} |
+ |
+ |
+void PreParser::CheckDelayedStrictModeViolation(int beg_pos, |
+ int end_pos, |
+ bool* ok) { |
+ i::Scanner::Location location = strict_mode_violation_location_; |
+ if (location.IsValid() && |
+ location.beg_pos > beg_pos && location.end_pos < end_pos) { |
+ ReportMessageAt(location.beg_pos, location.end_pos, |
+ strict_mode_violation_type_, NULL); |
+ *ok = false; |
+ } |
+ strict_mode_violation_location_ = i::Scanner::Location::invalid(); |
+} |
+ |
+ |
+void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location, |
+ const char* eval_args_type, |
+ Identifier identifier, |
+ bool* ok) { |
+ const char* type = eval_args_type; |
+ if (identifier.IsFutureReserved()) { |
+ type = "strict_reserved_word"; |
+ } |
+ if (strict_mode()) { |
+ ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); |
+ *ok = false; |
+ return; |
+ } |
+ strict_mode_violation_location_ = location; |
+ strict_mode_violation_type_ = type; |
+} |
+ |
+ |
PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { |
i::Token::Value next = Next(); |
if (i::Token::IsKeyword(next)) { |
@@ -1213,24 +1381,28 @@ PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { |
const char* keyword = i::Token::String(next); |
log_->LogAsciiSymbol(pos, i::Vector<const char>(keyword, |
i::StrLength(keyword))); |
- return kUnknownExpression; |
+ return Identifier::Default(); |
} |
if (next == i::Token::IDENTIFIER || |
next == i::Token::FUTURE_RESERVED_WORD) { |
return GetIdentifierSymbol(); |
} |
*ok = false; |
- return kUnknownIdentifier; |
+ return Identifier::Default(); |
} |
+#undef CHECK_OK |
+ |
// This function reads an identifier and determines whether or not it |
// is 'get' or 'set'. |
PreParser::Identifier PreParser::ParseIdentifierOrGetOrSet(bool* is_get, |
bool* is_set, |
bool* ok) { |
- PreParser::Identifier result = ParseIdentifier(CHECK_OK); |
- if (scanner_->is_literal_ascii() && scanner_->literal_length() == 3) { |
+ Identifier result = ParseIdentifier(ok); |
+ if (!*ok) return Identifier::Default(); |
+ if (scanner_->is_literal_ascii() && |
+ scanner_->literal_length() == 3) { |
const char* token = scanner_->literal_ascii_string().start(); |
*is_get = strncmp(token, "get", 3) == 0; |
*is_set = !*is_get && strncmp(token, "set", 3) == 0; |
@@ -1243,6 +1415,4 @@ bool PreParser::peek_any_identifier() { |
return next == i::Token::IDENTIFIER || |
next == i::Token::FUTURE_RESERVED_WORD; |
} |
- |
-#undef CHECK_OK |
} } // v8::preparser |