5 #ifndef V8_PARSING_EXPRESSION_CLASSIFIER_H_ 6 #define V8_PARSING_EXPRESSION_CLASSIFIER_H_ 10 #include "src/message-template.h" 11 #include "src/parsing/scanner.h" 19 #define ERROR_CODES(T) \ 20 T(ExpressionProduction, 0) \ 21 T(FormalParameterInitializerProduction, 1) \ 22 T(PatternProduction, 2) \ 23 T(BindingPatternProduction, 3) \ 24 T(StrictModeFormalParametersProduction, 4) \ 25 T(LetPatternProduction, 5) \ 26 T(AsyncArrowFormalParametersProduction, 6) 71 template <
typename Types>
74 template <
typename Types,
typename ErrorTracker>
77 enum ErrorKind :
unsigned {
78 #define DEFINE_ERROR_KIND(NAME, CODE) k##NAME = CODE, 79 ERROR_CODES(DEFINE_ERROR_KIND)
80 #undef DEFINE_ERROR_KIND 86 : location(Scanner::Location::invalid()),
87 message_(static_cast<int>(MessageTemplate::kNone)),
91 ErrorKind k,
const char* a =
nullptr)
92 : location(loc), message_(static_cast<int>(msg)), kind(k), arg(a) {}
97 MessageTemplate message()
const {
98 STATIC_ASSERT(static_cast<int>(MessageTemplate::kLastMessage) <
100 return static_cast<MessageTemplate
>(message_);
108 enum TargetProduction :
unsigned {
109 #define DEFINE_PRODUCTION(NAME, CODE) NAME = 1 << CODE, 110 ERROR_CODES(DEFINE_PRODUCTION)
111 #undef DEFINE_PRODUCTION 113 #define DEFINE_ALL_PRODUCTIONS(NAME, CODE) NAME | 114 AllProductions = ERROR_CODES(DEFINE_ALL_PRODUCTIONS) 0
115 #undef DEFINE_ALL_PRODUCTIONS 121 invalid_productions_(0),
122 is_non_simple_parameter_list_(0) {}
124 virtual ~ExpressionClassifierBase() =
default;
126 V8_INLINE
bool is_valid(
unsigned productions)
const {
127 return (invalid_productions_ & productions) == 0;
130 V8_INLINE
bool is_valid_expression()
const {
131 return is_valid(ExpressionProduction);
134 V8_INLINE
bool is_valid_formal_parameter_initializer()
const {
135 return is_valid(FormalParameterInitializerProduction);
138 V8_INLINE
bool is_valid_pattern()
const {
139 return is_valid(PatternProduction);
142 V8_INLINE
bool is_valid_binding_pattern()
const {
143 return is_valid(BindingPatternProduction);
148 V8_INLINE
bool is_valid_strict_mode_formal_parameters()
const {
149 return is_valid(StrictModeFormalParametersProduction);
152 V8_INLINE
bool is_valid_let_pattern()
const {
153 return is_valid(LetPatternProduction);
156 bool is_valid_async_arrow_formal_parameters()
const {
157 return is_valid(AsyncArrowFormalParametersProduction);
160 V8_INLINE
bool is_simple_parameter_list()
const {
161 return !is_non_simple_parameter_list_;
164 V8_INLINE
void RecordNonSimpleParameter() {
165 is_non_simple_parameter_list_ = 1;
168 V8_INLINE
void Accumulate(ExpressionClassifier<Types>*
const inner,
169 unsigned productions) {
171 static_cast<ErrorTracker*
>(
this)->CheckErrorPositions(inner);
175 unsigned filter = productions & ~this->invalid_productions_;
176 unsigned errors = inner->invalid_productions_ & filter;
177 static_cast<ErrorTracker*
>(
this)->AccumulateErrorImpl(inner, productions,
179 this->invalid_productions_ |= errors;
183 typename Types::Base* base_;
184 unsigned invalid_productions_ : kUnusedError;
185 STATIC_ASSERT(kUnusedError <= 15);
186 unsigned is_non_simple_parameter_list_ : 1;
189 template <
typename Types>
192 ExpressionClassifierErrorTracker<Types>> {
196 using typename BaseClassType::Error;
197 using typename BaseClassType::ErrorKind;
198 using TP =
typename BaseClassType::TargetProduction;
202 reported_errors_(base->impl()->GetReportedErrorList()) {
203 reported_errors_begin_ = reported_errors_end_ = reported_errors_->length();
207 if (reported_errors_end_ == reported_errors_->length()) {
208 reported_errors_->Rewind(reported_errors_begin_);
209 reported_errors_end_ = reported_errors_begin_;
211 DCHECK_EQ(reported_errors_begin_, reported_errors_end_);
215 V8_INLINE
const Error& reported_error(ErrorKind kind)
const {
216 if (!this->is_valid(1 << kind)) {
217 for (
int i = reported_errors_begin_;
i < reported_errors_end_;
i++) {
218 if (reported_errors_->at(
i).kind == kind)
219 return reported_errors_->at(
i);
235 V8_INLINE
void Add(TP production,
const Error& e) {
236 if (!this->is_valid(production))
return;
237 this->invalid_productions_ |= production;
238 DCHECK_EQ(reported_errors_end_, reported_errors_->length());
239 reported_errors_->Add(e, this->base_->impl()->zone());
240 reported_errors_end_++;
248 V8_INLINE
void Copy(
int i) {
249 DCHECK_LT(
i, reported_errors_->length());
250 if (reported_errors_end_ !=
i)
251 reported_errors_->at(reported_errors_end_) = reported_errors_->at(
i);
252 reported_errors_end_++;
258 DCHECK_EQ(inner->reported_errors_, this->reported_errors_);
259 DCHECK_EQ(inner->reported_errors_begin_, this->reported_errors_end_);
260 DCHECK_EQ(inner->reported_errors_end_, this->reported_errors_->length());
265 this->reported_errors_->Rewind(this->reported_errors_end_);
266 inner->reported_errors_begin_ = inner->reported_errors_end_ =
267 this->reported_errors_end_;
271 unsigned productions,
unsigned errors) {
274 for (
int i = inner->reported_errors_begin_; errors != 0;
i++) {
275 int mask = 1 << this->reported_errors_->at(
i).kind;
276 if ((errors & mask) != 0) {
294 uint16_t reported_errors_begin_;
295 uint16_t reported_errors_end_;
300 template <
typename Types>
303 Types, ExpressionClassifierEmptyErrorTracker<Types>> {
308 using typename BaseClassType::Error;
309 using typename BaseClassType::ErrorKind;
310 using TP =
typename BaseClassType::TargetProduction;
316 V8_INLINE
const Error& reported_error(ErrorKind kind)
const {
321 V8_INLINE
void Add(TP production,
const Error& e) {
322 this->invalid_productions_ |= production;
331 unsigned productions,
unsigned errors) {}
336 template <
typename Types>
338 :
public std::conditional<
339 Types::ExpressionClassifierReportErrors,
340 ExpressionClassifierErrorTracker<Types>,
341 ExpressionClassifierEmptyErrorTracker<Types>>
::type {
342 static constexpr
bool ReportErrors = Types::ExpressionClassifierReportErrors;
345 using BaseClassType =
typename std::conditional<
346 Types::ExpressionClassifierReportErrors,
350 using typename BaseClassType::Error;
351 using typename BaseClassType::ErrorKind;
352 using TP =
typename BaseClassType::TargetProduction;
356 Types::ExpressionClassifierReportErrors,
359 previous_(base->classifier_) {
360 base->classifier_ =
this;
363 V8_INLINE ~ExpressionClassifier()
override {
364 if (this->base_->classifier_ ==
this) this->base_->classifier_ = previous_;
367 V8_INLINE
const Error& expression_error()
const {
368 return this->reported_error(ErrorKind::kExpressionProduction);
371 V8_INLINE
const Error& formal_parameter_initializer_error()
const {
372 return this->reported_error(
373 ErrorKind::kFormalParameterInitializerProduction);
376 V8_INLINE
const Error& pattern_error()
const {
377 return this->reported_error(ErrorKind::kPatternProduction);
380 V8_INLINE
const Error& binding_pattern_error()
const {
381 return this->reported_error(ErrorKind::kBindingPatternProduction);
384 V8_INLINE
const Error& strict_mode_formal_parameter_error()
const {
385 return this->reported_error(
386 ErrorKind::kStrictModeFormalParametersProduction);
389 V8_INLINE
const Error& let_pattern_error()
const {
390 return this->reported_error(ErrorKind::kLetPatternProduction);
393 V8_INLINE
const Error& async_arrow_formal_parameters_error()
const {
394 return this->reported_error(
395 ErrorKind::kAsyncArrowFormalParametersProduction);
398 V8_INLINE
bool does_error_reporting() {
return ReportErrors; }
400 void RecordExpressionError(
const Scanner::Location& loc,
401 MessageTemplate message,
402 const char* arg =
nullptr) {
403 this->Add(TP::ExpressionProduction,
404 Error(loc, message, ErrorKind::kExpressionProduction, arg));
407 void RecordFormalParameterInitializerError(
const Scanner::Location& loc,
408 MessageTemplate message,
409 const char* arg =
nullptr) {
410 this->Add(TP::FormalParameterInitializerProduction,
412 ErrorKind::kFormalParameterInitializerProduction, arg));
415 void RecordPatternError(
const Scanner::Location& loc, MessageTemplate message,
416 const char* arg =
nullptr) {
417 this->Add(TP::PatternProduction,
418 Error(loc, message, ErrorKind::kPatternProduction, arg));
421 void RecordBindingPatternError(
const Scanner::Location& loc,
422 MessageTemplate message,
423 const char* arg =
nullptr) {
424 this->Add(TP::BindingPatternProduction,
425 Error(loc, message, ErrorKind::kBindingPatternProduction, arg));
428 void RecordAsyncArrowFormalParametersError(
const Scanner::Location& loc,
429 MessageTemplate message,
430 const char* arg =
nullptr) {
431 this->Add(TP::AsyncArrowFormalParametersProduction,
433 ErrorKind::kAsyncArrowFormalParametersProduction, arg));
439 void RecordStrictModeFormalParameterError(
const Scanner::Location& loc,
440 MessageTemplate message,
441 const char* arg =
nullptr) {
442 this->Add(TP::StrictModeFormalParametersProduction,
444 ErrorKind::kStrictModeFormalParametersProduction, arg));
447 void RecordLetPatternError(
const Scanner::Location& loc,
448 MessageTemplate message,
449 const char* arg =
nullptr) {
450 this->Add(TP::LetPatternProduction,
451 Error(loc, message, ErrorKind::kLetPatternProduction, arg));
454 ExpressionClassifier* previous()
const {
return previous_; }
457 ExpressionClassifier* previous_;
459 DISALLOW_COPY_AND_ASSIGN(ExpressionClassifier);
467 #endif // V8_PARSING_EXPRESSION_CLASSIFIER_H_