Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1071)

Unified Diff: src/preparser.h

Issue 1066933005: Use ExpressionClassifier for bindings. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: CR feedback Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser.cc ('k') | src/preparser.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/preparser.h
diff --git a/src/preparser.h b/src/preparser.h
index 36320513adb872f5ef4f51d450551af9ab1499d8..e6b884616272060a4638ca08eb28382f94b5bdf3 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -581,66 +581,121 @@ class ParserBase : public Traits {
void ReportUnexpectedToken(Token::Value token);
void ReportUnexpectedTokenAt(Scanner::Location location, Token::Value token);
- // Recursive descent functions:
-
- // Parses an identifier that is valid for the current scope, in particular it
- // fails on strict mode future reserved keywords in a strict scope. If
- // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
- // "arguments" as identifier even in strict mode (this is needed in cases like
- // "var foo = eval;").
- IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok);
- // Parses an identifier or a strict mode future reserved word, and indicate
- // whether it is strict mode future reserved.
- IdentifierT ParseIdentifierOrStrictReservedWord(
- bool* is_strict_reserved,
- bool* ok);
- IdentifierT ParseIdentifierName(bool* ok);
- // Parses an identifier and determines whether or not it is 'get' or 'set'.
- IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get,
- bool* is_set,
- bool* ok);
-
-
class ExpressionClassifier {
public:
ExpressionClassifier()
: expression_error_(Scanner::Location::invalid()),
+ expression_error_message_(nullptr),
binding_pattern_error_(Scanner::Location::invalid()),
- assignment_pattern_error_(Scanner::Location::invalid()) {}
+ binding_pattern_error_message_(nullptr),
+ assignment_pattern_error_(Scanner::Location::invalid()),
+ assignment_pattern_error_message_(nullptr) {}
+
+ bool is_valid_expression() const { return !expression_error_.IsValid(); }
- bool is_valid_expression() const {
- return expression_error_ == Scanner::Location::invalid();
+ Scanner::Location expression_error_loc() const { return expression_error_; }
+ const char* expression_error_message() const {
+ return expression_error_message_;
}
bool is_valid_binding_pattern() const {
- return binding_pattern_error_ == Scanner::Location::invalid();
+ return !binding_pattern_error_.IsValid();
+ }
+ Scanner::Location binding_pattern_error_loc() const {
+ return binding_pattern_error_;
+ }
+ const char* binding_pattern_error_message() const {
+ return binding_pattern_error_message_;
}
- bool is_valid_assignmnent_pattern() const {
- return assignment_pattern_error_ == Scanner::Location::invalid();
+ bool is_valid_assignment_pattern() const {
+ return !assignment_pattern_error_.IsValid();
+ }
+ Scanner::Location assignment_pattern_error_loc() const {
+ return assignment_pattern_error_;
+ }
+ const char* assignment_pattern_error_message() const {
+ return assignment_pattern_error_message_;
}
- void RecordExpressionError(const Scanner::Location& loc) {
+ void RecordExpressionError(const Scanner::Location& loc,
+ const char* message) {
if (!is_valid_expression()) return;
expression_error_ = loc;
+ expression_error_message_ = message;
}
- void RecordBindingPatternError(const Scanner::Location& loc) {
+ void RecordBindingPatternError(const Scanner::Location& loc,
+ const char* message) {
if (!is_valid_binding_pattern()) return;
binding_pattern_error_ = loc;
+ binding_pattern_error_message_ = message;
}
- void RecordAssignmentPatternError(const Scanner::Location& loc) {
- if (!is_valid_assignmnent_pattern()) return;
+ void RecordAssignmentPatternError(const Scanner::Location& loc,
+ const char* message) {
+ if (!is_valid_assignment_pattern()) return;
assignment_pattern_error_ = loc;
+ assignment_pattern_error_message_ = message;
}
private:
Scanner::Location expression_error_;
+ const char* expression_error_message_;
Scanner::Location binding_pattern_error_;
+ const char* binding_pattern_error_message_;
Scanner::Location assignment_pattern_error_;
+ const char* assignment_pattern_error_message_;
};
+ void ValidateExpression(const ExpressionClassifier* classifier, bool* ok) {
+ if (!classifier->is_valid_expression()) {
+ ReportMessageAt(classifier->expression_error_loc(),
+ classifier->expression_error_message());
+ *ok = false;
+ }
+ }
+
+ void ValidateBindingPattern(const ExpressionClassifier* classifier,
+ bool* ok) {
+ if (!classifier->is_valid_binding_pattern()) {
+ Traits::ReportMessageAt(classifier->binding_pattern_error_loc(),
+ classifier->binding_pattern_error_message());
+ *ok = false;
+ }
+ }
+
+
+ void ValidateAssignmentPattern(const ExpressionClassifier* classifier,
+ bool* ok) {
+ if (!classifier->is_valid_assignment_pattern()) {
+ Traits::ReportMessageAt(classifier->assignment_pattern_error_loc(),
+ classifier->assignment_pattern_error_message());
+ *ok = false;
+ }
+ }
+
+
+ // Recursive descent functions:
+
+ // Parses an identifier that is valid for the current scope, in particular it
+ // fails on strict mode future reserved keywords in a strict scope. If
+ // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or
+ // "arguments" as identifier even in strict mode (this is needed in cases like
+ // "var foo = eval;").
+ IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok);
+ IdentifierT ParseAndClassifyIdentifier(ExpressionClassifier* classifier,
+ bool* ok);
+ // Parses an identifier or a strict mode future reserved word, and indicate
+ // whether it is strict mode future reserved.
+ IdentifierT ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
+ bool* ok);
+ IdentifierT ParseIdentifierName(bool* ok);
+ // Parses an identifier and determines whether or not it is 'get' or 'set'.
+ IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, bool* is_set,
+ bool* ok);
+
+
ExpressionT ParseRegExpLiteral(bool seen_equal,
ExpressionClassifier* classifier, bool* ok);
@@ -1960,23 +2015,45 @@ void ParserBase<Traits>::ReportUnexpectedTokenAt(
template <class Traits>
typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier(
AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) {
+ ExpressionClassifier classifier;
+ auto result = ParseAndClassifyIdentifier(&classifier, ok);
arv (Not doing code reviews) 2015/04/23 20:20:30 Can't you use CHECK_OK_CUSTOM here? auto result =
Dmitry Lomov (no reviews) 2015/04/24 10:03:55 No because I need Traits::EmptyIdentifier()
+ if (!*ok) return Traits::EmptyIdentifier();
+
+ if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) {
+ ValidateAssignmentPattern(&classifier, ok);
+ if (!*ok) return Traits::EmptyIdentifier();
+ ValidateBindingPattern(&classifier, ok);
+ if (!*ok) return Traits::EmptyIdentifier();
+ } else {
+ ValidateExpression(&classifier, ok);
+ if (!*ok) return Traits::EmptyIdentifier();
+ }
+
+ return result;
+}
+
+
+template <class Traits>
+typename ParserBase<Traits>::IdentifierT
+ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier,
+ bool* ok) {
Token::Value next = Next();
if (next == Token::IDENTIFIER) {
IdentifierT name = this->GetSymbol(scanner());
- if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) {
- if (is_strict(language_mode()) && this->IsEvalOrArguments(name)) {
- ReportMessage("strict_eval_arguments");
- *ok = false;
- }
- if (is_strong(language_mode()) && this->IsUndefined(name)) {
- ReportMessage("strong_undefined");
- *ok = false;
- }
- } else {
- if (is_strong(language_mode()) && this->IsArguments(name)) {
- ReportMessage("strong_arguments");
- *ok = false;
- }
+ if (is_strict(language_mode()) && this->IsEvalOrArguments(name)) {
+ classifier->RecordBindingPatternError(scanner()->location(),
+ "strict_eval_arguments");
+ }
+ if (is_strong(language_mode()) && this->IsUndefined(name)) {
+ // TODO(dslomov): allow 'undefined' in nested patterns.
+ classifier->RecordBindingPatternError(scanner()->location(),
+ "strong_undefined");
+ classifier->RecordAssignmentPatternError(scanner()->location(),
+ "strong_undefined");
+ }
+ if (is_strong(language_mode()) && this->IsArguments(name)) {
+ classifier->RecordExpressionError(scanner()->location(),
+ "strong_arguments");
}
if (this->IsArguments(name)) scope_->RecordArgumentsUsage();
return name;
@@ -1992,6 +2069,7 @@ typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier(
}
}
+
template <class Traits>
typename ParserBase<Traits>::IdentifierT ParserBase<
Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
@@ -2141,7 +2219,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
case Token::YIELD:
case Token::FUTURE_STRICT_RESERVED_WORD: {
// Using eval or arguments in this context is OK even in strict mode.
- IdentifierT name = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
+ IdentifierT name = ParseAndClassifyIdentifier(classifier, CHECK_OK);
result = this->ExpressionFromIdentifier(name, beg_pos, end_pos, scope_,
factory());
break;
@@ -2241,7 +2319,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
bool accept_IN, bool* ok) {
ExpressionClassifier classifier;
ExpressionT result = ParseExpression(accept_IN, &classifier, CHECK_OK);
- // TODO(dslomov): report error if not a valid expression.
+ ValidateExpression(&classifier, CHECK_OK);
return result;
}
« no previous file with comments | « src/parser.cc ('k') | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698