Index: src/preparser.h |
diff --git a/src/preparser.h b/src/preparser.h |
index b89263229fe372368d3dcd9f20e7313f3fab9aa5..e1d2d1acee7f9bafa4012b10f6a0a0961b90d603 100644 |
--- a/src/preparser.h |
+++ b/src/preparser.h |
@@ -557,40 +557,61 @@ class ParserBase : public Traits { |
Scanner::Location location; |
MessageTemplate::Template message; |
const char* arg; |
+ }; |
+ |
+ enum TargetProduction { |
+ ExpressionProduction = 1 << 0, |
+ BindingPatternProduction = 1 << 1, |
+ AssignmentPatternProduction = 1 << 2, |
+ DistinctFormalParametersProduction = 1 << 3, |
+ StrictModeFormalParametersProduction = 1 << 4, |
+ StrongModeFormalParametersProduction = 1 << 5, |
+ ArrowFormalParametersProduction = 1 << 6, |
- bool HasError() const { return location.IsValid(); } |
+ PatternProductions = |
+ (BindingPatternProduction | AssignmentPatternProduction), |
+ FormalParametersProductions = (DistinctFormalParametersProduction | |
+ StrictModeFormalParametersProduction | |
+ StrongModeFormalParametersProduction), |
+ StandardProductions = ExpressionProduction | PatternProductions, |
+ AllProductions = (StandardProductions | FormalParametersProductions | |
+ ArrowFormalParametersProduction) |
}; |
- ExpressionClassifier() {} |
+ ExpressionClassifier() : invalid_productions_(0) {} |
+ |
+ bool is_valid(unsigned productions) const { |
+ return (invalid_productions_ & productions) == 0; |
+ } |
- bool is_valid_expression() const { return !expression_error_.HasError(); } |
+ bool is_valid_expression() const { return is_valid(ExpressionProduction); } |
bool is_valid_binding_pattern() const { |
- return !binding_pattern_error_.HasError(); |
+ return is_valid(BindingPatternProduction); |
} |
bool is_valid_assignment_pattern() const { |
- return !assignment_pattern_error_.HasError(); |
+ return is_valid(AssignmentPatternProduction); |
} |
bool is_valid_arrow_formal_parameters() const { |
- return !arrow_formal_parameters_error_.HasError(); |
+ return is_valid(ArrowFormalParametersProduction); |
} |
bool is_valid_formal_parameter_list_without_duplicates() const { |
- return !duplicate_formal_parameter_error_.HasError(); |
+ return is_valid(DistinctFormalParametersProduction); |
} |
// Note: callers should also check |
// is_valid_formal_parameter_list_without_duplicates(). |
bool is_valid_strict_mode_formal_parameters() const { |
- return !strict_mode_formal_parameter_error_.HasError(); |
+ return is_valid(StrictModeFormalParametersProduction); |
} |
// Note: callers should also check is_valid_strict_mode_formal_parameters() |
// and is_valid_formal_parameter_list_without_duplicates(). |
bool is_valid_strong_mode_formal_parameters() const { |
- return !strong_mode_formal_parameter_error_.HasError(); |
+ return is_valid(StrongModeFormalParametersProduction); |
} |
const Error& expression_error() const { return expression_error_; } |
@@ -623,6 +644,7 @@ class ParserBase : public Traits { |
MessageTemplate::Template message, |
const char* arg = nullptr) { |
if (!is_valid_expression()) return; |
+ invalid_productions_ |= ExpressionProduction; |
expression_error_.location = loc; |
expression_error_.message = message; |
expression_error_.arg = arg; |
@@ -632,6 +654,7 @@ class ParserBase : public Traits { |
MessageTemplate::Template message, |
const char* arg = nullptr) { |
if (!is_valid_binding_pattern()) return; |
+ invalid_productions_ |= BindingPatternProduction; |
binding_pattern_error_.location = loc; |
binding_pattern_error_.message = message; |
binding_pattern_error_.arg = arg; |
@@ -641,6 +664,7 @@ class ParserBase : public Traits { |
MessageTemplate::Template message, |
const char* arg = nullptr) { |
if (!is_valid_assignment_pattern()) return; |
+ invalid_productions_ |= AssignmentPatternProduction; |
assignment_pattern_error_.location = loc; |
assignment_pattern_error_.message = message; |
assignment_pattern_error_.arg = arg; |
@@ -650,6 +674,7 @@ class ParserBase : public Traits { |
MessageTemplate::Template message, |
const char* arg = nullptr) { |
if (!is_valid_arrow_formal_parameters()) return; |
+ invalid_productions_ |= ArrowFormalParametersProduction; |
arrow_formal_parameters_error_.location = loc; |
arrow_formal_parameters_error_.message = message; |
arrow_formal_parameters_error_.arg = arg; |
@@ -657,6 +682,7 @@ class ParserBase : public Traits { |
void RecordDuplicateFormalParameterError(const Scanner::Location& loc) { |
if (!is_valid_formal_parameter_list_without_duplicates()) return; |
+ invalid_productions_ |= DistinctFormalParametersProduction; |
duplicate_formal_parameter_error_.location = loc; |
duplicate_formal_parameter_error_.message = |
MessageTemplate::kStrictParamDupe; |
@@ -670,6 +696,7 @@ class ParserBase : public Traits { |
MessageTemplate::Template message, |
const char* arg = nullptr) { |
if (!is_valid_strict_mode_formal_parameters()) return; |
+ invalid_productions_ |= StrictModeFormalParametersProduction; |
strict_mode_formal_parameter_error_.location = loc; |
strict_mode_formal_parameter_error_.message = message; |
strict_mode_formal_parameter_error_.arg = arg; |
@@ -679,56 +706,49 @@ class ParserBase : public Traits { |
MessageTemplate::Template message, |
const char* arg = nullptr) { |
if (!is_valid_strong_mode_formal_parameters()) return; |
+ invalid_productions_ |= StrongModeFormalParametersProduction; |
strong_mode_formal_parameter_error_.location = loc; |
strong_mode_formal_parameter_error_.message = message; |
strong_mode_formal_parameter_error_.arg = arg; |
} |
- enum TargetProduction { |
- ExpressionProduction = 1 << 0, |
- BindingPatternProduction = 1 << 1, |
- AssignmentPatternProduction = 1 << 2, |
- FormalParametersProduction = 1 << 3, |
- ArrowFormalParametersProduction = 1 << 4, |
- StandardProductions = (ExpressionProduction | BindingPatternProduction | |
- AssignmentPatternProduction), |
- PatternProductions = |
- BindingPatternProduction | AssignmentPatternProduction, |
- AllProductions = (StandardProductions | FormalParametersProduction | |
- ArrowFormalParametersProduction), |
- }; |
- |
void Accumulate(const ExpressionClassifier& inner, |
unsigned productions = StandardProductions) { |
- if (productions & ExpressionProduction && is_valid_expression()) { |
- expression_error_ = inner.expression_error_; |
- } |
- if (productions & BindingPatternProduction && |
- is_valid_binding_pattern()) { |
- binding_pattern_error_ = inner.binding_pattern_error_; |
- } |
- if (productions & AssignmentPatternProduction && |
- is_valid_assignment_pattern()) { |
- assignment_pattern_error_ = inner.assignment_pattern_error_; |
- } |
- if (productions & FormalParametersProduction) { |
- if (is_valid_formal_parameter_list_without_duplicates()) { |
+ // Propagate errors from inner, but don't overwrite already recorded |
+ // errors. |
+ unsigned non_arrow_inner_invalid_productions = |
+ inner.invalid_productions_ & ~ArrowFormalParametersProduction; |
+ if (non_arrow_inner_invalid_productions == 0) return; |
+ unsigned non_arrow_productions = |
+ productions & ~ArrowFormalParametersProduction; |
+ unsigned errors = |
+ non_arrow_productions & non_arrow_inner_invalid_productions; |
+ errors &= ~invalid_productions_; |
+ if (errors != 0) { |
+ invalid_productions_ |= errors; |
+ if (errors & ExpressionProduction) |
+ expression_error_ = inner.expression_error_; |
+ if (errors & BindingPatternProduction) |
+ binding_pattern_error_ = inner.binding_pattern_error_; |
+ if (errors & AssignmentPatternProduction) |
+ assignment_pattern_error_ = inner.assignment_pattern_error_; |
+ if (errors & DistinctFormalParametersProduction) |
duplicate_formal_parameter_error_ = |
inner.duplicate_formal_parameter_error_; |
- } |
- if (is_valid_strict_mode_formal_parameters()) { |
+ if (errors & StrictModeFormalParametersProduction) |
strict_mode_formal_parameter_error_ = |
inner.strict_mode_formal_parameter_error_; |
- } |
- if (is_valid_strong_mode_formal_parameters()) { |
+ if (errors & StrongModeFormalParametersProduction) |
strong_mode_formal_parameter_error_ = |
inner.strong_mode_formal_parameter_error_; |
- } |
} |
+ |
+ // As an exception to the above, the result continues to be a valid arrow |
+ // formal parameters if the inner expression is a valid binding pattern. |
if (productions & ArrowFormalParametersProduction && |
- is_valid_arrow_formal_parameters()) { |
- // The result continues to be a valid arrow formal parameters if the |
- // inner expression is a valid binding pattern. |
+ is_valid_arrow_formal_parameters() && |
+ !inner.is_valid_binding_pattern()) { |
+ invalid_productions_ |= ArrowFormalParametersProduction; |
arrow_formal_parameters_error_ = inner.binding_pattern_error_; |
} |
} |
@@ -746,6 +766,7 @@ class ParserBase : public Traits { |
} |
private: |
+ unsigned invalid_productions_; |
Error expression_error_; |
Error binding_pattern_error_; |
Error assignment_pattern_error_; |
@@ -2945,7 +2966,7 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, |
// "expression" was not itself an arrow function parameter list, but it might |
// form part of one. Propagate speculative formal parameter error locations. |
classifier->Accumulate(arrow_formals_classifier, |
- ExpressionClassifier::FormalParametersProduction); |
+ ExpressionClassifier::FormalParametersProductions); |
if (!Token::IsAssignmentOp(peek())) { |
if (fni_ != NULL) fni_->Leave(); |