summaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing/expression-classifier.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/parsing/expression-classifier.h')
-rw-r--r--deps/v8/src/parsing/expression-classifier.h528
1 files changed, 337 insertions, 191 deletions
diff --git a/deps/v8/src/parsing/expression-classifier.h b/deps/v8/src/parsing/expression-classifier.h
index 7833dbc8d3..2eed75b939 100644
--- a/deps/v8/src/parsing/expression-classifier.h
+++ b/deps/v8/src/parsing/expression-classifier.h
@@ -5,9 +5,10 @@
#ifndef V8_PARSING_EXPRESSION_CLASSIFIER_H_
#define V8_PARSING_EXPRESSION_CLASSIFIER_H_
+#include <type_traits>
+
#include "src/messages.h"
#include "src/parsing/scanner.h"
-#include "src/zone/zone-containers.h"
namespace v8 {
namespace internal {
@@ -47,14 +48,38 @@ class DuplicateFinder;
// by calling the method Discard. Both actions result in removing the
// classifier from the parser's stack.
+// Expression classifier is split into four parts. The base implementing the
+// general expression classifier logic. Two parts that implement the error
+// tracking interface, where one is the actual implementation and the other is
+// an empty class providing only the interface without logic. The expression
+// classifier class then combines the other parts and provides the full
+// expression classifier interface by inheriting conditionally, controlled by
+// Types::ExpressionClassifierReportErrors, either from the ErrorTracker or the
+// EmptyErrorTracker.
+//
+// Base
+// / \
+// / \
+// / \
+// / \
+// ErrorTracker EmptyErrorTracker
+// \ /
+// \ /
+// \ /
+// \ /
+// ExpressionClassifier
+
template <typename Types>
-class ExpressionClassifier {
+class ExpressionClassifier;
+
+template <typename Types, typename ErrorTracker>
+class ExpressionClassifierBase {
public:
enum ErrorKind : unsigned {
#define DEFINE_ERROR_KIND(NAME, CODE) k##NAME = CODE,
ERROR_CODES(DEFINE_ERROR_KIND)
#undef DEFINE_ERROR_KIND
- kUnusedError = 15 // Larger than error codes; should fit in 4 bits
+ kUnusedError = 15 // Larger than error codes; should fit in 4 bits
};
struct Error {
@@ -86,23 +111,14 @@ class ExpressionClassifier {
};
// clang-format on
- explicit ExpressionClassifier(typename Types::Base* base,
- DuplicateFinder* duplicate_finder = nullptr)
+ explicit ExpressionClassifierBase(typename Types::Base* base,
+ DuplicateFinder* duplicate_finder = nullptr)
: base_(base),
- previous_(base->classifier_),
- zone_(base->impl()->zone()),
- reported_errors_(base->impl()->GetReportedErrorList()),
duplicate_finder_(duplicate_finder),
invalid_productions_(0),
- is_non_simple_parameter_list_(0) {
- base->classifier_ = this;
- reported_errors_begin_ = reported_errors_end_ = reported_errors_->size();
- }
+ is_non_simple_parameter_list_(0) {}
- V8_INLINE ~ExpressionClassifier() {
- Discard();
- if (base_->classifier_ == this) base_->classifier_ = previous_;
- }
+ virtual ~ExpressionClassifierBase() = default;
V8_INLINE bool is_valid(unsigned productions) const {
return (invalid_productions_ & productions) == 0;
@@ -150,80 +166,338 @@ class ExpressionClassifier {
return is_valid(AsyncArrowFormalParametersProduction);
}
+ V8_INLINE bool is_simple_parameter_list() const {
+ return !is_non_simple_parameter_list_;
+ }
+
+ V8_INLINE void RecordNonSimpleParameter() {
+ is_non_simple_parameter_list_ = 1;
+ }
+
+ V8_INLINE void Accumulate(ExpressionClassifier<Types>* const inner,
+ unsigned productions) {
+#ifdef DEBUG
+ static_cast<ErrorTracker*>(this)->CheckErrorPositions(inner);
+#endif
+ // 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) {
+ unsigned errors = non_arrow_inner_invalid_productions & productions &
+ ~this->invalid_productions_;
+ // The result will continue to be a valid arrow formal parameters if the
+ // inner expression is a valid binding pattern.
+ bool copy_BP_to_AFP = false;
+ if (productions & ArrowFormalParametersProduction &&
+ this->is_valid_arrow_formal_parameters()) {
+ // Also whether we've seen any non-simple parameters
+ // if expecting an arrow function parameter.
+ this->is_non_simple_parameter_list_ |=
+ inner->is_non_simple_parameter_list_;
+ if (!inner->is_valid_binding_pattern()) {
+ copy_BP_to_AFP = true;
+ this->invalid_productions_ |= ArrowFormalParametersProduction;
+ }
+ }
+ if (errors != 0 || copy_BP_to_AFP) {
+ this->invalid_productions_ |= errors;
+ static_cast<ErrorTracker*>(this)->AccumulateErrorImpl(
+ inner, productions, errors, copy_BP_to_AFP);
+ }
+ }
+ static_cast<ErrorTracker*>(this)->RewindErrors(inner);
+ }
+
+ protected:
+ typename Types::Base* base_;
+ DuplicateFinder* duplicate_finder_;
+ unsigned invalid_productions_ : kUnusedError;
+ STATIC_ASSERT(kUnusedError <= 15);
+ unsigned is_non_simple_parameter_list_ : 1;
+};
+
+template <typename Types>
+class ExpressionClassifierErrorTracker
+ : public ExpressionClassifierBase<Types,
+ ExpressionClassifierErrorTracker<Types>> {
+ public:
+ using BaseClassType =
+ ExpressionClassifierBase<Types, ExpressionClassifierErrorTracker<Types>>;
+ using typename BaseClassType::Error;
+ using typename BaseClassType::ErrorKind;
+ using TP = typename BaseClassType::TargetProduction;
+
+ ExpressionClassifierErrorTracker(typename Types::Base* base,
+ DuplicateFinder* duplicate_finder)
+ : BaseClassType(base, duplicate_finder),
+ reported_errors_(base->impl()->GetReportedErrorList()) {
+ reported_errors_begin_ = reported_errors_end_ = reported_errors_->length();
+ }
+
+ ~ExpressionClassifierErrorTracker() override { Discard(); }
+
+ V8_INLINE void Discard() {
+ if (reported_errors_end_ == reported_errors_->length()) {
+ reported_errors_->Rewind(reported_errors_begin_);
+ reported_errors_end_ = reported_errors_begin_;
+ }
+ DCHECK_EQ(reported_errors_begin_, reported_errors_end_);
+ }
+
+ protected:
+ V8_INLINE const Error& reported_error(ErrorKind kind) const {
+ if (this->invalid_productions_ & (1 << kind)) {
+ for (int i = reported_errors_begin_; i < reported_errors_end_; i++) {
+ if (reported_errors_->at(i).kind == kind)
+ return reported_errors_->at(i);
+ }
+ UNREACHABLE();
+ }
+ // We should only be looking for an error when we know that one has
+ // been reported. But we're not... So this is to make sure we have
+ // the same behaviour.
+ UNREACHABLE();
+
+ // Make MSVC happy by returning an error from this inaccessible path.
+ static Error none;
+ return none;
+ }
+
+ // Adds e to the end of the list of reported errors for this classifier.
+ // It is expected that this classifier is the last one in the stack.
+ V8_INLINE void Add(const Error& e) {
+ DCHECK_EQ(reported_errors_end_, reported_errors_->length());
+ reported_errors_->Add(e, this->base_->impl()->zone());
+ reported_errors_end_++;
+ }
+
+ // Copies the error at position i of the list of reported errors, so that
+ // it becomes the last error reported for this classifier. Position i
+ // could be either after the existing errors of this classifier (i.e.,
+ // in an inner classifier) or it could be an existing error (in case a
+ // copy is needed).
+ V8_INLINE void Copy(int i) {
+ DCHECK_LT(i, reported_errors_->length());
+ if (reported_errors_end_ != i)
+ reported_errors_->at(reported_errors_end_) = reported_errors_->at(i);
+ reported_errors_end_++;
+ }
+
+ private:
+#ifdef DEBUG
+ V8_INLINE void CheckErrorPositions(ExpressionClassifier<Types>* const inner) {
+ DCHECK_EQ(inner->reported_errors_, this->reported_errors_);
+ DCHECK_EQ(inner->reported_errors_begin_, this->reported_errors_end_);
+ DCHECK_EQ(inner->reported_errors_end_, this->reported_errors_->length());
+ }
+#endif
+
+ V8_INLINE void RewindErrors(ExpressionClassifier<Types>* const inner) {
+ this->reported_errors_->Rewind(this->reported_errors_end_);
+ inner->reported_errors_begin_ = inner->reported_errors_end_ =
+ this->reported_errors_end_;
+ }
+
+ void AccumulateErrorImpl(ExpressionClassifier<Types>* const inner,
+ unsigned productions, unsigned errors,
+ bool copy_BP_to_AFP) {
+ // Traverse the list of errors reported by the inner classifier
+ // to copy what's necessary.
+ int binding_pattern_index = inner->reported_errors_end_;
+ for (int i = inner->reported_errors_begin_; i < inner->reported_errors_end_;
+ i++) {
+ int k = this->reported_errors_->at(i).kind;
+ if (errors & (1 << k)) this->Copy(i);
+ // Check if it's a BP error that has to be copied to an AFP error.
+ if (k == ErrorKind::kBindingPatternProduction && copy_BP_to_AFP) {
+ if (this->reported_errors_end_ <= i) {
+ // If the BP error itself has not already been copied,
+ // copy it now and change it to an AFP error.
+ this->Copy(i);
+ this->reported_errors_->at(this->reported_errors_end_ - 1).kind =
+ ErrorKind::kArrowFormalParametersProduction;
+ } else {
+ // Otherwise, if the BP error was already copied, keep its
+ // position and wait until the end of the traversal.
+ DCHECK_EQ(this->reported_errors_end_, i + 1);
+ binding_pattern_index = i;
+ }
+ }
+ }
+ // Do we still have to copy the BP error to an AFP error?
+ if (binding_pattern_index < inner->reported_errors_end_) {
+ // If there's still unused space in the list of the inner
+ // classifier, copy it there, otherwise add it to the end
+ // of the list.
+ if (this->reported_errors_end_ < inner->reported_errors_end_)
+ this->Copy(binding_pattern_index);
+ else
+ Add(this->reported_errors_->at(binding_pattern_index));
+ this->reported_errors_->at(this->reported_errors_end_ - 1).kind =
+ ErrorKind::kArrowFormalParametersProduction;
+ }
+ }
+
+ private:
+ ZoneList<Error>* reported_errors_;
+ // The uint16_t for reported_errors_begin_ and reported_errors_end_ will
+ // not be enough in the case of a long series of expressions using nested
+ // classifiers, e.g., a long sequence of assignments, as in:
+ // literals with spreads, as in:
+ // var N=65536; eval("var x;" + "x=".repeat(N) + "42");
+ // This should not be a problem, as such things currently fail with a
+ // stack overflow while parsing.
+ uint16_t reported_errors_begin_;
+ uint16_t reported_errors_end_;
+
+ friend BaseClassType;
+};
+
+template <typename Types>
+class ExpressionClassifierEmptyErrorTracker
+ : public ExpressionClassifierBase<
+ Types, ExpressionClassifierEmptyErrorTracker<Types>> {
+ public:
+ using BaseClassType =
+ ExpressionClassifierBase<Types,
+ ExpressionClassifierEmptyErrorTracker<Types>>;
+ using typename BaseClassType::Error;
+ using typename BaseClassType::ErrorKind;
+ using TP = typename BaseClassType::TargetProduction;
+
+ ExpressionClassifierEmptyErrorTracker(typename Types::Base* base,
+ DuplicateFinder* duplicate_finder)
+ : BaseClassType(base, duplicate_finder) {}
+
+ V8_INLINE void Discard() {}
+
+ protected:
+ V8_INLINE const Error& reported_error(ErrorKind kind) const {
+ static Error none;
+ return none;
+ }
+
+ V8_INLINE void Add(const Error& e) {}
+
+ private:
+#ifdef DEBUG
+ V8_INLINE void CheckErrorPositions(ExpressionClassifier<Types>* const inner) {
+ }
+#endif
+ V8_INLINE void RewindErrors(ExpressionClassifier<Types>* const inner) {}
+ V8_INLINE void AccumulateErrorImpl(ExpressionClassifier<Types>* const inner,
+ unsigned productions, unsigned errors,
+ bool copy_BP_to_AFP) {}
+
+ friend BaseClassType;
+};
+
+template <typename Types>
+class ExpressionClassifier
+ : public std::conditional<
+ Types::ExpressionClassifierReportErrors,
+ ExpressionClassifierErrorTracker<Types>,
+ ExpressionClassifierEmptyErrorTracker<Types>>::type {
+ static constexpr bool ReportErrors = Types::ExpressionClassifierReportErrors;
+
+ public:
+ using BaseClassType = typename std::conditional<
+ Types::ExpressionClassifierReportErrors,
+ typename ExpressionClassifierErrorTracker<Types>::BaseClassType,
+ typename ExpressionClassifierEmptyErrorTracker<Types>::BaseClassType>::
+ type;
+ using typename BaseClassType::Error;
+ using typename BaseClassType::ErrorKind;
+ using TP = typename BaseClassType::TargetProduction;
+
+ explicit ExpressionClassifier(typename Types::Base* base,
+ DuplicateFinder* duplicate_finder = nullptr)
+ : std::conditional<Types::ExpressionClassifierReportErrors,
+ ExpressionClassifierErrorTracker<Types>,
+ ExpressionClassifierEmptyErrorTracker<Types>>::
+ type(base, duplicate_finder),
+ previous_(base->classifier_) {
+ base->classifier_ = this;
+ }
+
+ V8_INLINE ~ExpressionClassifier() override {
+ if (this->base_->classifier_ == this) this->base_->classifier_ = previous_;
+ }
+
V8_INLINE const Error& expression_error() const {
- return reported_error(kExpressionProduction);
+ return this->reported_error(ErrorKind::kExpressionProduction);
}
V8_INLINE const Error& formal_parameter_initializer_error() const {
- return reported_error(kFormalParameterInitializerProduction);
+ return this->reported_error(
+ ErrorKind::kFormalParameterInitializerProduction);
}
V8_INLINE const Error& binding_pattern_error() const {
- return reported_error(kBindingPatternProduction);
+ return this->reported_error(ErrorKind::kBindingPatternProduction);
}
V8_INLINE const Error& assignment_pattern_error() const {
- return reported_error(kAssignmentPatternProduction);
+ return this->reported_error(ErrorKind::kAssignmentPatternProduction);
}
V8_INLINE const Error& arrow_formal_parameters_error() const {
- return reported_error(kArrowFormalParametersProduction);
+ return this->reported_error(ErrorKind::kArrowFormalParametersProduction);
}
V8_INLINE const Error& duplicate_formal_parameter_error() const {
- return reported_error(kDistinctFormalParametersProduction);
+ return this->reported_error(ErrorKind::kDistinctFormalParametersProduction);
}
V8_INLINE const Error& strict_mode_formal_parameter_error() const {
- return reported_error(kStrictModeFormalParametersProduction);
+ return this->reported_error(
+ ErrorKind::kStrictModeFormalParametersProduction);
}
V8_INLINE const Error& let_pattern_error() const {
- return reported_error(kLetPatternProduction);
+ return this->reported_error(ErrorKind::kLetPatternProduction);
}
V8_INLINE const Error& async_arrow_formal_parameters_error() const {
- return reported_error(kAsyncArrowFormalParametersProduction);
- }
-
- V8_INLINE bool is_simple_parameter_list() const {
- return !is_non_simple_parameter_list_;
+ return this->reported_error(
+ ErrorKind::kAsyncArrowFormalParametersProduction);
}
- V8_INLINE void RecordNonSimpleParameter() {
- is_non_simple_parameter_list_ = 1;
- }
+ V8_INLINE bool does_error_reporting() { return ReportErrors; }
void RecordExpressionError(const Scanner::Location& loc,
MessageTemplate::Template message,
const char* arg = nullptr) {
- if (!is_valid_expression()) return;
- invalid_productions_ |= ExpressionProduction;
- Add(Error(loc, message, kExpressionProduction, arg));
+ if (!this->is_valid_expression()) return;
+ this->invalid_productions_ |= TP::ExpressionProduction;
+ this->Add(Error(loc, message, ErrorKind::kExpressionProduction, arg));
}
void RecordFormalParameterInitializerError(const Scanner::Location& loc,
MessageTemplate::Template message,
const char* arg = nullptr) {
- if (!is_valid_formal_parameter_initializer()) return;
- invalid_productions_ |= FormalParameterInitializerProduction;
- Add(Error(loc, message, kFormalParameterInitializerProduction, arg));
+ if (!this->is_valid_formal_parameter_initializer()) return;
+ this->invalid_productions_ |= TP::FormalParameterInitializerProduction;
+ this->Add(Error(loc, message,
+ ErrorKind::kFormalParameterInitializerProduction, arg));
}
void RecordBindingPatternError(const Scanner::Location& loc,
MessageTemplate::Template message,
const char* arg = nullptr) {
- if (!is_valid_binding_pattern()) return;
- invalid_productions_ |= BindingPatternProduction;
- Add(Error(loc, message, kBindingPatternProduction, arg));
+ if (!this->is_valid_binding_pattern()) return;
+ this->invalid_productions_ |= TP::BindingPatternProduction;
+ this->Add(Error(loc, message, ErrorKind::kBindingPatternProduction, arg));
}
void RecordAssignmentPatternError(const Scanner::Location& loc,
MessageTemplate::Template message,
const char* arg = nullptr) {
- if (!is_valid_assignment_pattern()) return;
- invalid_productions_ |= AssignmentPatternProduction;
- Add(Error(loc, message, kAssignmentPatternProduction, arg));
+ if (!this->is_valid_assignment_pattern()) return;
+ this->invalid_productions_ |= TP::AssignmentPatternProduction;
+ this->Add(
+ Error(loc, message, ErrorKind::kAssignmentPatternProduction, arg));
}
void RecordPatternError(const Scanner::Location& loc,
@@ -236,24 +510,26 @@ class ExpressionClassifier {
void RecordArrowFormalParametersError(const Scanner::Location& loc,
MessageTemplate::Template message,
const char* arg = nullptr) {
- if (!is_valid_arrow_formal_parameters()) return;
- invalid_productions_ |= ArrowFormalParametersProduction;
- Add(Error(loc, message, kArrowFormalParametersProduction, arg));
+ if (!this->is_valid_arrow_formal_parameters()) return;
+ this->invalid_productions_ |= TP::ArrowFormalParametersProduction;
+ this->Add(
+ Error(loc, message, ErrorKind::kArrowFormalParametersProduction, arg));
}
void RecordAsyncArrowFormalParametersError(const Scanner::Location& loc,
MessageTemplate::Template message,
const char* arg = nullptr) {
- if (!is_valid_async_arrow_formal_parameters()) return;
- invalid_productions_ |= AsyncArrowFormalParametersProduction;
- Add(Error(loc, message, kAsyncArrowFormalParametersProduction, arg));
+ if (!this->is_valid_async_arrow_formal_parameters()) return;
+ this->invalid_productions_ |= TP::AsyncArrowFormalParametersProduction;
+ this->Add(Error(loc, message,
+ ErrorKind::kAsyncArrowFormalParametersProduction, arg));
}
void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
- if (!is_valid_formal_parameter_list_without_duplicates()) return;
- invalid_productions_ |= DistinctFormalParametersProduction;
- Add(Error(loc, MessageTemplate::kParamDupe,
- kDistinctFormalParametersProduction));
+ if (!this->is_valid_formal_parameter_list_without_duplicates()) return;
+ this->invalid_productions_ |= TP::DistinctFormalParametersProduction;
+ this->Add(Error(loc, MessageTemplate::kParamDupe,
+ ErrorKind::kDistinctFormalParametersProduction));
}
// Record a binding that would be invalid in strict mode. Confusingly this
@@ -262,160 +538,30 @@ class ExpressionClassifier {
void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
MessageTemplate::Template message,
const char* arg = nullptr) {
- if (!is_valid_strict_mode_formal_parameters()) return;
- invalid_productions_ |= StrictModeFormalParametersProduction;
- Add(Error(loc, message, kStrictModeFormalParametersProduction, arg));
+ if (!this->is_valid_strict_mode_formal_parameters()) return;
+ this->invalid_productions_ |= TP::StrictModeFormalParametersProduction;
+ this->Add(Error(loc, message,
+ ErrorKind::kStrictModeFormalParametersProduction, arg));
}
void RecordLetPatternError(const Scanner::Location& loc,
MessageTemplate::Template message,
const char* arg = nullptr) {
- if (!is_valid_let_pattern()) return;
- invalid_productions_ |= LetPatternProduction;
- Add(Error(loc, message, kLetPatternProduction, arg));
- }
-
- void Accumulate(ExpressionClassifier* inner, unsigned productions) {
- DCHECK_EQ(inner->reported_errors_, reported_errors_);
- DCHECK_EQ(inner->reported_errors_begin_, reported_errors_end_);
- DCHECK_EQ(inner->reported_errors_end_, reported_errors_->size());
- // 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) {
- unsigned errors = non_arrow_inner_invalid_productions & productions &
- ~invalid_productions_;
- // The result will continue to be a valid arrow formal parameters if the
- // inner expression is a valid binding pattern.
- bool copy_BP_to_AFP = false;
- if (productions & ArrowFormalParametersProduction &&
- is_valid_arrow_formal_parameters()) {
- // Also whether we've seen any non-simple parameters
- // if expecting an arrow function parameter.
- is_non_simple_parameter_list_ |= inner->is_non_simple_parameter_list_;
- if (!inner->is_valid_binding_pattern()) {
- copy_BP_to_AFP = true;
- invalid_productions_ |= ArrowFormalParametersProduction;
- }
- }
- // Traverse the list of errors reported by the inner classifier
- // to copy what's necessary.
- if (errors != 0 || copy_BP_to_AFP) {
- invalid_productions_ |= errors;
- int binding_pattern_index = inner->reported_errors_end_;
- for (int i = inner->reported_errors_begin_;
- i < inner->reported_errors_end_; i++) {
- int k = reported_errors_->at(i).kind;
- if (errors & (1 << k)) Copy(i);
- // Check if it's a BP error that has to be copied to an AFP error.
- if (k == kBindingPatternProduction && copy_BP_to_AFP) {
- if (reported_errors_end_ <= i) {
- // If the BP error itself has not already been copied,
- // copy it now and change it to an AFP error.
- Copy(i);
- reported_errors_->at(reported_errors_end_-1).kind =
- kArrowFormalParametersProduction;
- } else {
- // Otherwise, if the BP error was already copied, keep its
- // position and wait until the end of the traversal.
- DCHECK_EQ(reported_errors_end_, i+1);
- binding_pattern_index = i;
- }
- }
- }
- // Do we still have to copy the BP error to an AFP error?
- if (binding_pattern_index < inner->reported_errors_end_) {
- // If there's still unused space in the list of the inner
- // classifier, copy it there, otherwise add it to the end
- // of the list.
- if (reported_errors_end_ < inner->reported_errors_end_)
- Copy(binding_pattern_index);
- else
- Add(reported_errors_->at(binding_pattern_index));
- reported_errors_->at(reported_errors_end_-1).kind =
- kArrowFormalParametersProduction;
- }
- }
- }
- reported_errors_->resize(reported_errors_end_);
- inner->reported_errors_begin_ = inner->reported_errors_end_ =
- reported_errors_end_;
- }
-
- V8_INLINE void Discard() {
- if (reported_errors_end_ == reported_errors_->size()) {
- reported_errors_->resize(reported_errors_begin_);
- reported_errors_end_ = reported_errors_begin_;
- }
- DCHECK_EQ(reported_errors_begin_, reported_errors_end_);
+ if (!this->is_valid_let_pattern()) return;
+ this->invalid_productions_ |= TP::LetPatternProduction;
+ this->Add(Error(loc, message, ErrorKind::kLetPatternProduction, arg));
}
ExpressionClassifier* previous() const { return previous_; }
private:
- V8_INLINE const Error& reported_error(ErrorKind kind) const {
- if (invalid_productions_ & (1 << kind)) {
- for (int i = reported_errors_begin_; i < reported_errors_end_; i++) {
- if (reported_errors_->at(i).kind == kind)
- return reported_errors_->at(i);
- }
- UNREACHABLE();
- }
- // We should only be looking for an error when we know that one has
- // been reported. But we're not... So this is to make sure we have
- // the same behaviour.
- UNREACHABLE();
-
- // Make MSVC happy by returning an error from this inaccessible path.
- static Error none;
- return none;
- }
-
- // Adds e to the end of the list of reported errors for this classifier.
- // It is expected that this classifier is the last one in the stack.
- V8_INLINE void Add(const Error& e) {
- DCHECK_EQ(reported_errors_end_, reported_errors_->size());
- reported_errors_->push_back(e);
- reported_errors_end_++;
- }
-
- // Copies the error at position i of the list of reported errors, so that
- // it becomes the last error reported for this classifier. Position i
- // could be either after the existing errors of this classifier (i.e.,
- // in an inner classifier) or it could be an existing error (in case a
- // copy is needed).
- V8_INLINE void Copy(int i) {
- DCHECK_LT(i, reported_errors_->size());
- if (reported_errors_end_ != i)
- reported_errors_->at(reported_errors_end_) = reported_errors_->at(i);
- reported_errors_end_++;
- }
-
- typename Types::Base* base_;
ExpressionClassifier* previous_;
- Zone* zone_;
- ZoneVector<Error>* reported_errors_;
- DuplicateFinder* duplicate_finder_;
- unsigned invalid_productions_ : 15;
- unsigned is_non_simple_parameter_list_ : 1;
- // The uint16_t for reported_errors_begin_ and reported_errors_end_ will
- // not be enough in the case of a long series of expressions using nested
- // classifiers, e.g., a long sequence of assignments, as in:
- // literals with spreads, as in:
- // var N=65536; eval("var x;" + "x=".repeat(N) + "42");
- // This should not be a problem, as such things currently fail with a
- // stack overflow while parsing.
- uint16_t reported_errors_begin_;
- uint16_t reported_errors_end_;
DISALLOW_COPY_AND_ASSIGN(ExpressionClassifier);
};
-
#undef ERROR_CODES
-
} // namespace internal
} // namespace v8