1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef V8_EXPRESSION_CLASSIFIER_H
6 #define V8_EXPRESSION_CLASSIFIER_H
10 #include "src/messages.h"
11 #include "src/scanner.h"
12 #include "src/token.h"
18 class ExpressionClassifier {
22 : location(Scanner::Location::invalid()),
23 message(MessageTemplate::kNone),
26 Scanner::Location location;
27 MessageTemplate::Template message;
31 enum TargetProduction {
32 ExpressionProduction = 1 << 0,
33 BindingPatternProduction = 1 << 1,
34 AssignmentPatternProduction = 1 << 2,
35 DistinctFormalParametersProduction = 1 << 3,
36 StrictModeFormalParametersProduction = 1 << 4,
37 StrongModeFormalParametersProduction = 1 << 5,
38 ArrowFormalParametersProduction = 1 << 6,
41 (BindingPatternProduction | AssignmentPatternProduction),
42 FormalParametersProductions = (DistinctFormalParametersProduction |
43 StrictModeFormalParametersProduction |
44 StrongModeFormalParametersProduction),
45 StandardProductions = ExpressionProduction | PatternProductions,
46 AllProductions = (StandardProductions | FormalParametersProductions |
47 ArrowFormalParametersProduction)
50 ExpressionClassifier()
51 : invalid_productions_(0), duplicate_finder_(nullptr) {}
53 explicit ExpressionClassifier(DuplicateFinder* duplicate_finder)
54 : invalid_productions_(0), duplicate_finder_(duplicate_finder) {}
56 bool is_valid(unsigned productions) const {
57 return (invalid_productions_ & productions) == 0;
60 DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
62 bool is_valid_expression() const { return is_valid(ExpressionProduction); }
64 bool is_valid_binding_pattern() const {
65 return is_valid(BindingPatternProduction);
68 bool is_valid_assignment_pattern() const {
69 return is_valid(AssignmentPatternProduction);
72 bool is_valid_arrow_formal_parameters() const {
73 return is_valid(ArrowFormalParametersProduction);
76 bool is_valid_formal_parameter_list_without_duplicates() const {
77 return is_valid(DistinctFormalParametersProduction);
80 // Note: callers should also check
81 // is_valid_formal_parameter_list_without_duplicates().
82 bool is_valid_strict_mode_formal_parameters() const {
83 return is_valid(StrictModeFormalParametersProduction);
86 // Note: callers should also check is_valid_strict_mode_formal_parameters()
87 // and is_valid_formal_parameter_list_without_duplicates().
88 bool is_valid_strong_mode_formal_parameters() const {
89 return is_valid(StrongModeFormalParametersProduction);
92 const Error& expression_error() const { return expression_error_; }
94 const Error& binding_pattern_error() const { return binding_pattern_error_; }
96 const Error& assignment_pattern_error() const {
97 return assignment_pattern_error_;
100 const Error& arrow_formal_parameters_error() const {
101 return arrow_formal_parameters_error_;
104 const Error& duplicate_formal_parameter_error() const {
105 return duplicate_formal_parameter_error_;
108 const Error& strict_mode_formal_parameter_error() const {
109 return strict_mode_formal_parameter_error_;
112 const Error& strong_mode_formal_parameter_error() const {
113 return strong_mode_formal_parameter_error_;
116 void RecordExpressionError(const Scanner::Location& loc,
117 MessageTemplate::Template message,
118 const char* arg = nullptr) {
119 if (!is_valid_expression()) return;
120 invalid_productions_ |= ExpressionProduction;
121 expression_error_.location = loc;
122 class ExpressionClassifier {
126 : location(Scanner::Location::invalid()),
127 message(MessageTemplate::kNone),
130 Scanner::Location location;
131 MessageTemplate::Template message;
134 bool HasError() const { return location.IsValid(); }
137 ExpressionClassifier() : duplicate_finder_(nullptr) {}
139 explicit ExpressionClassifier(DuplicateFinder* duplicate_finder)
140 : duplicate_finder_(duplicate_finder) {}
142 DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
144 bool is_valid_expression() const { return !expression_error_.HasError(); }
146 bool is_valid_binding_pattern() const {
147 return !binding_pattern_error_.HasError();
150 bool is_valid_assignment_pattern() const {
151 return !assignment_pattern_error_.HasError();
154 bool is_valid_arrow_formal_parameters() const {
155 return !arrow_formal_parameters_error_.HasError();
158 bool is_valid_formal_parameter_list_without_duplicates() const {
159 return !duplicate_formal_parameter_error_.HasError();
162 // Note: callers should also check
163 // is_valid_formal_parameter_list_without_duplicates().
164 bool is_valid_strict_mode_formal_parameters() const {
165 return !strict_mode_formal_parameter_error_.HasError();
168 // Note: callers should also check
169 // is_valid_strict_mode_formal_parameters()
170 // and is_valid_formal_parameter_list_without_duplicates().
171 bool is_valid_strong_mode_formal_parameters() const {
172 return !strong_mode_formal_parameter_error_.HasError();
175 const Error& expression_error() const { return expression_error_; }
177 const Error& binding_pattern_error() const {
178 return binding_pattern_error_;
181 const Error& assignment_pattern_error() const {
182 return assignment_pattern_error_;
185 const Error& arrow_formal_parameters_error() const {
186 return arrow_formal_parameters_error_;
189 const Error& duplicate_formal_parameter_error() const {
190 return duplicate_formal_parameter_error_;
193 const Error& strict_mode_formal_parameter_error() const {
194 return strict_mode_formal_parameter_error_;
197 const Error& strong_mode_formal_parameter_error() const {
198 return strong_mode_formal_parameter_error_;
201 void RecordExpressionError(const Scanner::Location& loc,
202 MessageTemplate::Template message,
203 const char* arg = nullptr) {
204 if (!is_valid_expression()) return;
205 expression_error_.location = loc;
206 expression_error_.message = message;
207 expression_error_.arg = arg;
210 void RecordBindingPatternError(const Scanner::Location& loc,
211 MessageTemplate::Template message,
212 const char* arg = nullptr) {
213 if (!is_valid_binding_pattern()) return;
214 binding_pattern_error_.location = loc;
215 binding_pattern_error_.message = message;
216 binding_pattern_error_.arg = arg;
219 void RecordAssignmentPatternError(const Scanner::Location& loc,
220 MessageTemplate::Template message,
221 const char* arg = nullptr) {
222 if (!is_valid_assignment_pattern()) return;
223 assignment_pattern_error_.location = loc;
224 assignment_pattern_error_.message = message;
225 assignment_pattern_error_.arg = arg;
228 void RecordArrowFormalParametersError(const Scanner::Location& loc,
229 MessageTemplate::Template message,
230 const char* arg = nullptr) {
231 if (!is_valid_arrow_formal_parameters()) return;
232 arrow_formal_parameters_error_.location = loc;
233 arrow_formal_parameters_error_.message = message;
234 arrow_formal_parameters_error_.arg = arg;
237 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
238 if (!is_valid_formal_parameter_list_without_duplicates()) return;
239 duplicate_formal_parameter_error_.location = loc;
240 duplicate_formal_parameter_error_.message =
241 MessageTemplate::kStrictParamDupe;
242 duplicate_formal_parameter_error_.arg = nullptr;
245 // Record a binding that would be invalid in strict mode. Confusingly
247 // is not the same as StrictFormalParameterList, which simply forbids
248 // duplicate bindings.
249 void RecordStrictModeFormalParameterError(
250 const Scanner::Location& loc, MessageTemplate::Template message,
251 const char* arg = nullptr) {
252 if (!is_valid_strict_mode_formal_parameters()) return;
253 strict_mode_formal_parameter_error_.location = loc;
254 strict_mode_formal_parameter_error_.message = message;
255 strict_mode_formal_parameter_error_.arg = arg;
258 void RecordStrongModeFormalParameterError(
259 const Scanner::Location& loc, MessageTemplate::Template message,
260 const char* arg = nullptr) {
261 if (!is_valid_strong_mode_formal_parameters()) return;
262 strong_mode_formal_parameter_error_.location = loc;
263 strong_mode_formal_parameter_error_.message = message;
264 strong_mode_formal_parameter_error_.arg = arg;
267 enum TargetProduction {
268 ExpressionProduction = 1 << 0,
269 BindingPatternProduction = 1 << 1,
270 AssignmentPatternProduction = 1 << 2,
271 FormalParametersProduction = 1 << 3,
272 ArrowFormalParametersProduction = 1 << 4,
273 StandardProductions = (ExpressionProduction | BindingPatternProduction |
274 AssignmentPatternProduction),
276 BindingPatternProduction | AssignmentPatternProduction,
277 AllProductions = (StandardProductions | FormalParametersProduction |
278 ArrowFormalParametersProduction),
281 void Accumulate(const ExpressionClassifier& inner,
282 unsigned productions = StandardProductions) {
283 if (productions & ExpressionProduction && is_valid_expression()) {
284 expression_error_ = inner.expression_error_;
286 if (productions & BindingPatternProduction &&
287 is_valid_binding_pattern()) {
288 binding_pattern_error_ = inner.binding_pattern_error_;
290 if (productions & AssignmentPatternProduction &&
291 is_valid_assignment_pattern()) {
292 assignment_pattern_error_ = inner.assignment_pattern_error_;
294 if (productions & FormalParametersProduction) {
295 if (is_valid_formal_parameter_list_without_duplicates()) {
296 duplicate_formal_parameter_error_ =
297 inner.duplicate_formal_parameter_error_;
299 if (is_valid_strict_mode_formal_parameters()) {
300 strict_mode_formal_parameter_error_ =
301 inner.strict_mode_formal_parameter_error_;
303 if (is_valid_strong_mode_formal_parameters()) {
304 strong_mode_formal_parameter_error_ =
305 inner.strong_mode_formal_parameter_error_;
308 if (productions & ArrowFormalParametersProduction &&
309 is_valid_arrow_formal_parameters()) {
310 // The result continues to be a valid arrow formal parameters if the
311 // inner expression is a valid binding pattern.
312 arrow_formal_parameters_error_ = inner.binding_pattern_error_;
316 void AccumulateReclassifyingAsPattern(const ExpressionClassifier& inner) {
317 Accumulate(inner, AllProductions & ~PatternProductions);
318 if (!inner.is_valid_expression()) {
319 if (is_valid_binding_pattern()) {
320 binding_pattern_error_ = inner.expression_error();
322 if (is_valid_assignment_pattern()) {
323 assignment_pattern_error_ = inner.expression_error();
329 Error expression_error_;
330 Error binding_pattern_error_;
331 Error assignment_pattern_error_;
332 Error arrow_formal_parameters_error_;
333 Error duplicate_formal_parameter_error_;
334 Error strict_mode_formal_parameter_error_;
335 Error strong_mode_formal_parameter_error_;
336 DuplicateFinder* duplicate_finder_;
338 expression_error_.message = message;
339 expression_error_.arg = arg;
342 void RecordBindingPatternError(const Scanner::Location& loc,
343 MessageTemplate::Template message,
344 const char* arg = nullptr) {
345 if (!is_valid_binding_pattern()) return;
346 invalid_productions_ |= BindingPatternProduction;
347 binding_pattern_error_.location = loc;
348 binding_pattern_error_.message = message;
349 binding_pattern_error_.arg = arg;
352 void RecordAssignmentPatternError(const Scanner::Location& loc,
353 MessageTemplate::Template message,
354 const char* arg = nullptr) {
355 if (!is_valid_assignment_pattern()) return;
356 invalid_productions_ |= AssignmentPatternProduction;
357 assignment_pattern_error_.location = loc;
358 assignment_pattern_error_.message = message;
359 assignment_pattern_error_.arg = arg;
362 void RecordArrowFormalParametersError(const Scanner::Location& loc,
363 MessageTemplate::Template message,
364 const char* arg = nullptr) {
365 if (!is_valid_arrow_formal_parameters()) return;
366 invalid_productions_ |= ArrowFormalParametersProduction;
367 arrow_formal_parameters_error_.location = loc;
368 arrow_formal_parameters_error_.message = message;
369 arrow_formal_parameters_error_.arg = arg;
372 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
373 if (!is_valid_formal_parameter_list_without_duplicates()) return;
374 invalid_productions_ |= DistinctFormalParametersProduction;
375 duplicate_formal_parameter_error_.location = loc;
376 duplicate_formal_parameter_error_.message =
377 MessageTemplate::kStrictParamDupe;
378 duplicate_formal_parameter_error_.arg = nullptr;
381 // Record a binding that would be invalid in strict mode. Confusingly this
382 // is not the same as StrictFormalParameterList, which simply forbids
383 // duplicate bindings.
384 void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
385 MessageTemplate::Template message,
386 const char* arg = nullptr) {
387 if (!is_valid_strict_mode_formal_parameters()) return;
388 invalid_productions_ |= StrictModeFormalParametersProduction;
389 strict_mode_formal_parameter_error_.location = loc;
390 strict_mode_formal_parameter_error_.message = message;
391 strict_mode_formal_parameter_error_.arg = arg;
394 void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
395 MessageTemplate::Template message,
396 const char* arg = nullptr) {
397 if (!is_valid_strong_mode_formal_parameters()) return;
398 invalid_productions_ |= StrongModeFormalParametersProduction;
399 strong_mode_formal_parameter_error_.location = loc;
400 strong_mode_formal_parameter_error_.message = message;
401 strong_mode_formal_parameter_error_.arg = arg;
404 void Accumulate(const ExpressionClassifier& inner,
405 unsigned productions = StandardProductions) {
406 // Propagate errors from inner, but don't overwrite already recorded
408 unsigned non_arrow_inner_invalid_productions =
409 inner.invalid_productions_ & ~ArrowFormalParametersProduction;
410 if (non_arrow_inner_invalid_productions == 0) return;
411 unsigned non_arrow_productions =
412 productions & ~ArrowFormalParametersProduction;
414 non_arrow_productions & non_arrow_inner_invalid_productions;
415 errors &= ~invalid_productions_;
417 invalid_productions_ |= errors;
418 if (errors & ExpressionProduction)
419 expression_error_ = inner.expression_error_;
420 if (errors & BindingPatternProduction)
421 binding_pattern_error_ = inner.binding_pattern_error_;
422 if (errors & AssignmentPatternProduction)
423 assignment_pattern_error_ = inner.assignment_pattern_error_;
424 if (errors & DistinctFormalParametersProduction)
425 duplicate_formal_parameter_error_ =
426 inner.duplicate_formal_parameter_error_;
427 if (errors & StrictModeFormalParametersProduction)
428 strict_mode_formal_parameter_error_ =
429 inner.strict_mode_formal_parameter_error_;
430 if (errors & StrongModeFormalParametersProduction)
431 strong_mode_formal_parameter_error_ =
432 inner.strong_mode_formal_parameter_error_;
435 // As an exception to the above, the result continues to be a valid arrow
436 // formal parameters if the inner expression is a valid binding pattern.
437 if (productions & ArrowFormalParametersProduction &&
438 is_valid_arrow_formal_parameters() &&
439 !inner.is_valid_binding_pattern()) {
440 invalid_productions_ |= ArrowFormalParametersProduction;
441 arrow_formal_parameters_error_ = inner.binding_pattern_error_;
445 void AccumulateReclassifyingAsPattern(const ExpressionClassifier& inner) {
446 Accumulate(inner, AllProductions & ~PatternProductions);
447 if (!inner.is_valid_expression()) {
448 if (is_valid_binding_pattern()) {
449 binding_pattern_error_ = inner.expression_error();
451 if (is_valid_assignment_pattern()) {
452 assignment_pattern_error_ = inner.expression_error();
458 unsigned invalid_productions_;
459 Error expression_error_;
460 Error binding_pattern_error_;
461 Error assignment_pattern_error_;
462 Error arrow_formal_parameters_error_;
463 Error duplicate_formal_parameter_error_;
464 Error strict_mode_formal_parameter_error_;
465 Error strong_mode_formal_parameter_error_;
466 DuplicateFinder* duplicate_finder_;
471 #endif // V8_EXPRESSION_CLASSIFIER_H