| Index: src/expression-classifier.h
|
| diff --git a/src/expression-classifier.h b/src/expression-classifier.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..af761fb2bf66d74d0ab4ab031af8e8e32a7f8d37
|
| --- /dev/null
|
| +++ b/src/expression-classifier.h
|
| @@ -0,0 +1,471 @@
|
| +// Copyright 2015 the V8 project authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef V8_EXPRESSION_CLASSIFIER_H
|
| +#define V8_EXPRESSION_CLASSIFIER_H
|
| +
|
| +#include "src/v8.h"
|
| +
|
| +#include "src/messages.h"
|
| +#include "src/scanner.h"
|
| +#include "src/token.h"
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +
|
| +
|
| +class ExpressionClassifier {
|
| + public:
|
| + struct Error {
|
| + Error()
|
| + : location(Scanner::Location::invalid()),
|
| + message(MessageTemplate::kNone),
|
| + arg(nullptr) {}
|
| +
|
| + 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,
|
| +
|
| + PatternProductions =
|
| + (BindingPatternProduction | AssignmentPatternProduction),
|
| + FormalParametersProductions = (DistinctFormalParametersProduction |
|
| + StrictModeFormalParametersProduction |
|
| + StrongModeFormalParametersProduction),
|
| + StandardProductions = ExpressionProduction | PatternProductions,
|
| + AllProductions = (StandardProductions | FormalParametersProductions |
|
| + ArrowFormalParametersProduction)
|
| + };
|
| +
|
| + ExpressionClassifier()
|
| + : invalid_productions_(0), duplicate_finder_(nullptr) {}
|
| +
|
| + explicit ExpressionClassifier(DuplicateFinder* duplicate_finder)
|
| + : invalid_productions_(0), duplicate_finder_(duplicate_finder) {}
|
| +
|
| + bool is_valid(unsigned productions) const {
|
| + return (invalid_productions_ & productions) == 0;
|
| + }
|
| +
|
| + DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
|
| +
|
| + bool is_valid_expression() const { return is_valid(ExpressionProduction); }
|
| +
|
| + bool is_valid_binding_pattern() const {
|
| + return is_valid(BindingPatternProduction);
|
| + }
|
| +
|
| + bool is_valid_assignment_pattern() const {
|
| + return is_valid(AssignmentPatternProduction);
|
| + }
|
| +
|
| + bool is_valid_arrow_formal_parameters() const {
|
| + return is_valid(ArrowFormalParametersProduction);
|
| + }
|
| +
|
| + bool is_valid_formal_parameter_list_without_duplicates() const {
|
| + 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 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 is_valid(StrongModeFormalParametersProduction);
|
| + }
|
| +
|
| + const Error& expression_error() const { return expression_error_; }
|
| +
|
| + const Error& binding_pattern_error() const { return binding_pattern_error_; }
|
| +
|
| + const Error& assignment_pattern_error() const {
|
| + return assignment_pattern_error_;
|
| + }
|
| +
|
| + const Error& arrow_formal_parameters_error() const {
|
| + return arrow_formal_parameters_error_;
|
| + }
|
| +
|
| + const Error& duplicate_formal_parameter_error() const {
|
| + return duplicate_formal_parameter_error_;
|
| + }
|
| +
|
| + const Error& strict_mode_formal_parameter_error() const {
|
| + return strict_mode_formal_parameter_error_;
|
| + }
|
| +
|
| + const Error& strong_mode_formal_parameter_error() const {
|
| + return strong_mode_formal_parameter_error_;
|
| + }
|
| +
|
| + void RecordExpressionError(const Scanner::Location& loc,
|
| + MessageTemplate::Template message,
|
| + const char* arg = nullptr) {
|
| + if (!is_valid_expression()) return;
|
| + invalid_productions_ |= ExpressionProduction;
|
| + expression_error_.location = loc;
|
| + class ExpressionClassifier {
|
| + public:
|
| + struct Error {
|
| + Error()
|
| + : location(Scanner::Location::invalid()),
|
| + message(MessageTemplate::kNone),
|
| + arg(nullptr) {}
|
| +
|
| + Scanner::Location location;
|
| + MessageTemplate::Template message;
|
| + const char* arg;
|
| +
|
| + bool HasError() const { return location.IsValid(); }
|
| + };
|
| +
|
| + ExpressionClassifier() : duplicate_finder_(nullptr) {}
|
| +
|
| + explicit ExpressionClassifier(DuplicateFinder* duplicate_finder)
|
| + : duplicate_finder_(duplicate_finder) {}
|
| +
|
| + DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
|
| +
|
| + bool is_valid_expression() const { return !expression_error_.HasError(); }
|
| +
|
| + bool is_valid_binding_pattern() const {
|
| + return !binding_pattern_error_.HasError();
|
| + }
|
| +
|
| + bool is_valid_assignment_pattern() const {
|
| + return !assignment_pattern_error_.HasError();
|
| + }
|
| +
|
| + bool is_valid_arrow_formal_parameters() const {
|
| + return !arrow_formal_parameters_error_.HasError();
|
| + }
|
| +
|
| + bool is_valid_formal_parameter_list_without_duplicates() const {
|
| + return !duplicate_formal_parameter_error_.HasError();
|
| + }
|
| +
|
| + // 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();
|
| + }
|
| +
|
| + // 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();
|
| + }
|
| +
|
| + const Error& expression_error() const { return expression_error_; }
|
| +
|
| + const Error& binding_pattern_error() const {
|
| + return binding_pattern_error_;
|
| + }
|
| +
|
| + const Error& assignment_pattern_error() const {
|
| + return assignment_pattern_error_;
|
| + }
|
| +
|
| + const Error& arrow_formal_parameters_error() const {
|
| + return arrow_formal_parameters_error_;
|
| + }
|
| +
|
| + const Error& duplicate_formal_parameter_error() const {
|
| + return duplicate_formal_parameter_error_;
|
| + }
|
| +
|
| + const Error& strict_mode_formal_parameter_error() const {
|
| + return strict_mode_formal_parameter_error_;
|
| + }
|
| +
|
| + const Error& strong_mode_formal_parameter_error() const {
|
| + return strong_mode_formal_parameter_error_;
|
| + }
|
| +
|
| + void RecordExpressionError(const Scanner::Location& loc,
|
| + MessageTemplate::Template message,
|
| + const char* arg = nullptr) {
|
| + if (!is_valid_expression()) return;
|
| + expression_error_.location = loc;
|
| + expression_error_.message = message;
|
| + expression_error_.arg = arg;
|
| + }
|
| +
|
| + void RecordBindingPatternError(const Scanner::Location& loc,
|
| + MessageTemplate::Template message,
|
| + const char* arg = nullptr) {
|
| + if (!is_valid_binding_pattern()) return;
|
| + binding_pattern_error_.location = loc;
|
| + binding_pattern_error_.message = message;
|
| + binding_pattern_error_.arg = arg;
|
| + }
|
| +
|
| + void RecordAssignmentPatternError(const Scanner::Location& loc,
|
| + MessageTemplate::Template message,
|
| + const char* arg = nullptr) {
|
| + if (!is_valid_assignment_pattern()) return;
|
| + assignment_pattern_error_.location = loc;
|
| + assignment_pattern_error_.message = message;
|
| + assignment_pattern_error_.arg = arg;
|
| + }
|
| +
|
| + void RecordArrowFormalParametersError(const Scanner::Location& loc,
|
| + MessageTemplate::Template message,
|
| + const char* arg = nullptr) {
|
| + if (!is_valid_arrow_formal_parameters()) return;
|
| + arrow_formal_parameters_error_.location = loc;
|
| + arrow_formal_parameters_error_.message = message;
|
| + arrow_formal_parameters_error_.arg = arg;
|
| + }
|
| +
|
| + void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
|
| + if (!is_valid_formal_parameter_list_without_duplicates()) return;
|
| + duplicate_formal_parameter_error_.location = loc;
|
| + duplicate_formal_parameter_error_.message =
|
| + MessageTemplate::kStrictParamDupe;
|
| + duplicate_formal_parameter_error_.arg = nullptr;
|
| + }
|
| +
|
| + // Record a binding that would be invalid in strict mode. Confusingly
|
| + // this
|
| + // is not the same as StrictFormalParameterList, which simply forbids
|
| + // duplicate bindings.
|
| + void RecordStrictModeFormalParameterError(
|
| + const Scanner::Location& loc, MessageTemplate::Template message,
|
| + const char* arg = nullptr) {
|
| + if (!is_valid_strict_mode_formal_parameters()) return;
|
| + strict_mode_formal_parameter_error_.location = loc;
|
| + strict_mode_formal_parameter_error_.message = message;
|
| + strict_mode_formal_parameter_error_.arg = arg;
|
| + }
|
| +
|
| + void RecordStrongModeFormalParameterError(
|
| + const Scanner::Location& loc, MessageTemplate::Template message,
|
| + const char* arg = nullptr) {
|
| + if (!is_valid_strong_mode_formal_parameters()) return;
|
| + 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()) {
|
| + duplicate_formal_parameter_error_ =
|
| + inner.duplicate_formal_parameter_error_;
|
| + }
|
| + if (is_valid_strict_mode_formal_parameters()) {
|
| + strict_mode_formal_parameter_error_ =
|
| + inner.strict_mode_formal_parameter_error_;
|
| + }
|
| + if (is_valid_strong_mode_formal_parameters()) {
|
| + strong_mode_formal_parameter_error_ =
|
| + inner.strong_mode_formal_parameter_error_;
|
| + }
|
| + }
|
| + 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.
|
| + arrow_formal_parameters_error_ = inner.binding_pattern_error_;
|
| + }
|
| + }
|
| +
|
| + void AccumulateReclassifyingAsPattern(const ExpressionClassifier& inner) {
|
| + Accumulate(inner, AllProductions & ~PatternProductions);
|
| + if (!inner.is_valid_expression()) {
|
| + if (is_valid_binding_pattern()) {
|
| + binding_pattern_error_ = inner.expression_error();
|
| + }
|
| + if (is_valid_assignment_pattern()) {
|
| + assignment_pattern_error_ = inner.expression_error();
|
| + }
|
| + }
|
| + }
|
| +
|
| + private:
|
| + Error expression_error_;
|
| + Error binding_pattern_error_;
|
| + Error assignment_pattern_error_;
|
| + Error arrow_formal_parameters_error_;
|
| + Error duplicate_formal_parameter_error_;
|
| + Error strict_mode_formal_parameter_error_;
|
| + Error strong_mode_formal_parameter_error_;
|
| + DuplicateFinder* duplicate_finder_;
|
| + };
|
| + expression_error_.message = message;
|
| + expression_error_.arg = arg;
|
| + }
|
| +
|
| + void RecordBindingPatternError(const Scanner::Location& loc,
|
| + 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;
|
| + }
|
| +
|
| + void RecordAssignmentPatternError(const Scanner::Location& loc,
|
| + 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;
|
| + }
|
| +
|
| + void RecordArrowFormalParametersError(const Scanner::Location& loc,
|
| + 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;
|
| + }
|
| +
|
| + 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;
|
| + duplicate_formal_parameter_error_.arg = nullptr;
|
| + }
|
| +
|
| + // Record a binding that would be invalid in strict mode. Confusingly this
|
| + // is not the same as StrictFormalParameterList, which simply forbids
|
| + // duplicate bindings.
|
| + void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
|
| + 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;
|
| + }
|
| +
|
| + void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
|
| + 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;
|
| + }
|
| +
|
| + void Accumulate(const ExpressionClassifier& inner,
|
| + unsigned productions = StandardProductions) {
|
| + // 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 (errors & StrictModeFormalParametersProduction)
|
| + strict_mode_formal_parameter_error_ =
|
| + inner.strict_mode_formal_parameter_error_;
|
| + 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() &&
|
| + !inner.is_valid_binding_pattern()) {
|
| + invalid_productions_ |= ArrowFormalParametersProduction;
|
| + arrow_formal_parameters_error_ = inner.binding_pattern_error_;
|
| + }
|
| + }
|
| +
|
| + void AccumulateReclassifyingAsPattern(const ExpressionClassifier& inner) {
|
| + Accumulate(inner, AllProductions & ~PatternProductions);
|
| + if (!inner.is_valid_expression()) {
|
| + if (is_valid_binding_pattern()) {
|
| + binding_pattern_error_ = inner.expression_error();
|
| + }
|
| + if (is_valid_assignment_pattern()) {
|
| + assignment_pattern_error_ = inner.expression_error();
|
| + }
|
| + }
|
| + }
|
| +
|
| + private:
|
| + unsigned invalid_productions_;
|
| + Error expression_error_;
|
| + Error binding_pattern_error_;
|
| + Error assignment_pattern_error_;
|
| + Error arrow_formal_parameters_error_;
|
| + Error duplicate_formal_parameter_error_;
|
| + Error strict_mode_formal_parameter_error_;
|
| + Error strong_mode_formal_parameter_error_;
|
| + DuplicateFinder* duplicate_finder_;
|
| +};
|
| +}
|
| +} // v8::internal
|
| +
|
| +#endif // V8_EXPRESSION_CLASSIFIER_H
|
|
|