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 expression_error_.message = message;
123 expression_error_.arg = arg;
126 void RecordBindingPatternError(const Scanner::Location& loc,
127 MessageTemplate::Template message,
128 const char* arg = nullptr) {
129 if (!is_valid_binding_pattern()) return;
130 invalid_productions_ |= BindingPatternProduction;
131 binding_pattern_error_.location = loc;
132 binding_pattern_error_.message = message;
133 binding_pattern_error_.arg = arg;
136 void RecordAssignmentPatternError(const Scanner::Location& loc,
137 MessageTemplate::Template message,
138 const char* arg = nullptr) {
139 if (!is_valid_assignment_pattern()) return;
140 invalid_productions_ |= AssignmentPatternProduction;
141 assignment_pattern_error_.location = loc;
142 assignment_pattern_error_.message = message;
143 assignment_pattern_error_.arg = arg;
146 void RecordArrowFormalParametersError(const Scanner::Location& loc,
147 MessageTemplate::Template message,
148 const char* arg = nullptr) {
149 if (!is_valid_arrow_formal_parameters()) return;
150 invalid_productions_ |= ArrowFormalParametersProduction;
151 arrow_formal_parameters_error_.location = loc;
152 arrow_formal_parameters_error_.message = message;
153 arrow_formal_parameters_error_.arg = arg;
156 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
157 if (!is_valid_formal_parameter_list_without_duplicates()) return;
158 invalid_productions_ |= DistinctFormalParametersProduction;
159 duplicate_formal_parameter_error_.location = loc;
160 duplicate_formal_parameter_error_.message =
161 MessageTemplate::kStrictParamDupe;
162 duplicate_formal_parameter_error_.arg = nullptr;
165 // Record a binding that would be invalid in strict mode. Confusingly this
166 // is not the same as StrictFormalParameterList, which simply forbids
167 // duplicate bindings.
168 void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
169 MessageTemplate::Template message,
170 const char* arg = nullptr) {
171 if (!is_valid_strict_mode_formal_parameters()) return;
172 invalid_productions_ |= StrictModeFormalParametersProduction;
173 strict_mode_formal_parameter_error_.location = loc;
174 strict_mode_formal_parameter_error_.message = message;
175 strict_mode_formal_parameter_error_.arg = arg;
178 void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
179 MessageTemplate::Template message,
180 const char* arg = nullptr) {
181 if (!is_valid_strong_mode_formal_parameters()) return;
182 invalid_productions_ |= StrongModeFormalParametersProduction;
183 strong_mode_formal_parameter_error_.location = loc;
184 strong_mode_formal_parameter_error_.message = message;
185 strong_mode_formal_parameter_error_.arg = arg;
188 void Accumulate(const ExpressionClassifier& inner,
189 unsigned productions = StandardProductions) {
190 // Propagate errors from inner, but don't overwrite already recorded
192 unsigned non_arrow_inner_invalid_productions =
193 inner.invalid_productions_ & ~ArrowFormalParametersProduction;
194 if (non_arrow_inner_invalid_productions == 0) return;
195 unsigned non_arrow_productions =
196 productions & ~ArrowFormalParametersProduction;
198 non_arrow_productions & non_arrow_inner_invalid_productions;
199 errors &= ~invalid_productions_;
201 invalid_productions_ |= errors;
202 if (errors & ExpressionProduction)
203 expression_error_ = inner.expression_error_;
204 if (errors & BindingPatternProduction)
205 binding_pattern_error_ = inner.binding_pattern_error_;
206 if (errors & AssignmentPatternProduction)
207 assignment_pattern_error_ = inner.assignment_pattern_error_;
208 if (errors & DistinctFormalParametersProduction)
209 duplicate_formal_parameter_error_ =
210 inner.duplicate_formal_parameter_error_;
211 if (errors & StrictModeFormalParametersProduction)
212 strict_mode_formal_parameter_error_ =
213 inner.strict_mode_formal_parameter_error_;
214 if (errors & StrongModeFormalParametersProduction)
215 strong_mode_formal_parameter_error_ =
216 inner.strong_mode_formal_parameter_error_;
219 // As an exception to the above, the result continues to be a valid arrow
220 // formal parameters if the inner expression is a valid binding pattern.
221 if (productions & ArrowFormalParametersProduction &&
222 is_valid_arrow_formal_parameters() &&
223 !inner.is_valid_binding_pattern()) {
224 invalid_productions_ |= ArrowFormalParametersProduction;
225 arrow_formal_parameters_error_ = inner.binding_pattern_error_;
229 void AccumulateReclassifyingAsPattern(const ExpressionClassifier& inner) {
230 Accumulate(inner, AllProductions & ~PatternProductions);
231 if (!inner.is_valid_expression()) {
232 if (is_valid_binding_pattern()) {
233 binding_pattern_error_ = inner.expression_error();
235 if (is_valid_assignment_pattern()) {
236 assignment_pattern_error_ = inner.expression_error();
242 unsigned invalid_productions_;
243 Error expression_error_;
244 Error binding_pattern_error_;
245 Error assignment_pattern_error_;
246 Error arrow_formal_parameters_error_;
247 Error duplicate_formal_parameter_error_;
248 Error strict_mode_formal_parameter_error_;
249 Error strong_mode_formal_parameter_error_;
250 DuplicateFinder* duplicate_finder_;
255 #endif // V8_EXPRESSION_CLASSIFIER_H