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
8 #include "src/messages.h"
9 #include "src/scanner.h"
10 #include "src/token.h"
16 class ExpressionClassifier {
20 : location(Scanner::Location::invalid()),
21 message(MessageTemplate::kNone),
24 Scanner::Location location;
25 MessageTemplate::Template message;
29 enum TargetProduction {
30 ExpressionProduction = 1 << 0,
31 FormalParameterInitializerProduction = 1 << 1,
32 BindingPatternProduction = 1 << 2,
33 AssignmentPatternProduction = 1 << 3,
34 DistinctFormalParametersProduction = 1 << 4,
35 StrictModeFormalParametersProduction = 1 << 5,
36 StrongModeFormalParametersProduction = 1 << 6,
37 ArrowFormalParametersProduction = 1 << 7,
39 ExpressionProductions =
40 (ExpressionProduction | FormalParameterInitializerProduction),
42 (BindingPatternProduction | AssignmentPatternProduction),
43 FormalParametersProductions = (DistinctFormalParametersProduction |
44 StrictModeFormalParametersProduction |
45 StrongModeFormalParametersProduction),
46 StandardProductions = ExpressionProductions | PatternProductions,
47 AllProductions = (StandardProductions | FormalParametersProductions |
48 ArrowFormalParametersProduction)
51 enum FunctionProperties { NonSimpleParameter = 1 << 0 };
53 ExpressionClassifier()
54 : invalid_productions_(0),
55 function_properties_(0),
56 duplicate_finder_(nullptr) {}
58 explicit ExpressionClassifier(DuplicateFinder* duplicate_finder)
59 : invalid_productions_(0),
60 function_properties_(0),
61 duplicate_finder_(duplicate_finder) {}
63 bool is_valid(unsigned productions) const {
64 return (invalid_productions_ & productions) == 0;
67 DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
69 bool is_valid_expression() const { return is_valid(ExpressionProduction); }
71 bool is_valid_formal_parameter_initializer() const {
72 return is_valid(FormalParameterInitializerProduction);
75 bool is_valid_binding_pattern() const {
76 return is_valid(BindingPatternProduction);
79 bool is_valid_assignment_pattern() const {
80 return is_valid(AssignmentPatternProduction);
83 bool is_valid_arrow_formal_parameters() const {
84 return is_valid(ArrowFormalParametersProduction);
87 bool is_valid_formal_parameter_list_without_duplicates() const {
88 return is_valid(DistinctFormalParametersProduction);
91 // Note: callers should also check
92 // is_valid_formal_parameter_list_without_duplicates().
93 bool is_valid_strict_mode_formal_parameters() const {
94 return is_valid(StrictModeFormalParametersProduction);
97 // Note: callers should also check is_valid_strict_mode_formal_parameters()
98 // and is_valid_formal_parameter_list_without_duplicates().
99 bool is_valid_strong_mode_formal_parameters() const {
100 return is_valid(StrongModeFormalParametersProduction);
103 const Error& expression_error() const { return expression_error_; }
105 const Error& formal_parameter_initializer_error() const {
106 return formal_parameter_initializer_error_;
109 const Error& binding_pattern_error() const { return binding_pattern_error_; }
111 const Error& assignment_pattern_error() const {
112 return assignment_pattern_error_;
115 const Error& arrow_formal_parameters_error() const {
116 return arrow_formal_parameters_error_;
119 const Error& duplicate_formal_parameter_error() const {
120 return duplicate_formal_parameter_error_;
123 const Error& strict_mode_formal_parameter_error() const {
124 return strict_mode_formal_parameter_error_;
127 const Error& strong_mode_formal_parameter_error() const {
128 return strong_mode_formal_parameter_error_;
131 bool is_simple_parameter_list() const {
132 return !(function_properties_ & NonSimpleParameter);
135 void RecordNonSimpleParameter() {
136 function_properties_ |= NonSimpleParameter;
139 void RecordExpressionError(const Scanner::Location& loc,
140 MessageTemplate::Template message,
141 const char* arg = nullptr) {
142 if (!is_valid_expression()) return;
143 invalid_productions_ |= ExpressionProduction;
144 expression_error_.location = loc;
145 expression_error_.message = message;
146 expression_error_.arg = arg;
149 void RecordFormalParameterInitializerError(const Scanner::Location& loc,
150 MessageTemplate::Template message,
151 const char* arg = nullptr) {
152 if (!is_valid_formal_parameter_initializer()) return;
153 invalid_productions_ |= FormalParameterInitializerProduction;
154 formal_parameter_initializer_error_.location = loc;
155 formal_parameter_initializer_error_.message = message;
156 formal_parameter_initializer_error_.arg = arg;
159 void RecordBindingPatternError(const Scanner::Location& loc,
160 MessageTemplate::Template message,
161 const char* arg = nullptr) {
162 if (!is_valid_binding_pattern()) return;
163 invalid_productions_ |= BindingPatternProduction;
164 binding_pattern_error_.location = loc;
165 binding_pattern_error_.message = message;
166 binding_pattern_error_.arg = arg;
169 void RecordAssignmentPatternError(const Scanner::Location& loc,
170 MessageTemplate::Template message,
171 const char* arg = nullptr) {
172 if (!is_valid_assignment_pattern()) return;
173 invalid_productions_ |= AssignmentPatternProduction;
174 assignment_pattern_error_.location = loc;
175 assignment_pattern_error_.message = message;
176 assignment_pattern_error_.arg = arg;
179 void RecordArrowFormalParametersError(const Scanner::Location& loc,
180 MessageTemplate::Template message,
181 const char* arg = nullptr) {
182 if (!is_valid_arrow_formal_parameters()) return;
183 invalid_productions_ |= ArrowFormalParametersProduction;
184 arrow_formal_parameters_error_.location = loc;
185 arrow_formal_parameters_error_.message = message;
186 arrow_formal_parameters_error_.arg = arg;
189 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
190 if (!is_valid_formal_parameter_list_without_duplicates()) return;
191 invalid_productions_ |= DistinctFormalParametersProduction;
192 duplicate_formal_parameter_error_.location = loc;
193 duplicate_formal_parameter_error_.message = MessageTemplate::kParamDupe;
194 duplicate_formal_parameter_error_.arg = nullptr;
197 // Record a binding that would be invalid in strict mode. Confusingly this
198 // is not the same as StrictFormalParameterList, which simply forbids
199 // duplicate bindings.
200 void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
201 MessageTemplate::Template message,
202 const char* arg = nullptr) {
203 if (!is_valid_strict_mode_formal_parameters()) return;
204 invalid_productions_ |= StrictModeFormalParametersProduction;
205 strict_mode_formal_parameter_error_.location = loc;
206 strict_mode_formal_parameter_error_.message = message;
207 strict_mode_formal_parameter_error_.arg = arg;
210 void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
211 MessageTemplate::Template message,
212 const char* arg = nullptr) {
213 if (!is_valid_strong_mode_formal_parameters()) return;
214 invalid_productions_ |= StrongModeFormalParametersProduction;
215 strong_mode_formal_parameter_error_.location = loc;
216 strong_mode_formal_parameter_error_.message = message;
217 strong_mode_formal_parameter_error_.arg = arg;
220 void Accumulate(const ExpressionClassifier& inner,
221 unsigned productions = StandardProductions) {
222 // Propagate errors from inner, but don't overwrite already recorded
224 unsigned non_arrow_inner_invalid_productions =
225 inner.invalid_productions_ & ~ArrowFormalParametersProduction;
226 if (non_arrow_inner_invalid_productions == 0) return;
227 unsigned non_arrow_productions =
228 productions & ~ArrowFormalParametersProduction;
230 non_arrow_productions & non_arrow_inner_invalid_productions;
231 errors &= ~invalid_productions_;
233 invalid_productions_ |= errors;
234 if (errors & ExpressionProduction)
235 expression_error_ = inner.expression_error_;
236 if (errors & FormalParameterInitializerProduction)
237 formal_parameter_initializer_error_ =
238 inner.formal_parameter_initializer_error_;
239 if (errors & BindingPatternProduction)
240 binding_pattern_error_ = inner.binding_pattern_error_;
241 if (errors & AssignmentPatternProduction)
242 assignment_pattern_error_ = inner.assignment_pattern_error_;
243 if (errors & DistinctFormalParametersProduction)
244 duplicate_formal_parameter_error_ =
245 inner.duplicate_formal_parameter_error_;
246 if (errors & StrictModeFormalParametersProduction)
247 strict_mode_formal_parameter_error_ =
248 inner.strict_mode_formal_parameter_error_;
249 if (errors & StrongModeFormalParametersProduction)
250 strong_mode_formal_parameter_error_ =
251 inner.strong_mode_formal_parameter_error_;
254 // As an exception to the above, the result continues to be a valid arrow
255 // formal parameters if the inner expression is a valid binding pattern.
256 if (productions & ArrowFormalParametersProduction &&
257 is_valid_arrow_formal_parameters()) {
258 // Also copy function properties if expecting an arrow function
260 function_properties_ |= inner.function_properties_;
262 if (!inner.is_valid_binding_pattern()) {
263 invalid_productions_ |= ArrowFormalParametersProduction;
264 arrow_formal_parameters_error_ = inner.binding_pattern_error_;
270 unsigned invalid_productions_;
271 unsigned function_properties_;
272 Error expression_error_;
273 Error formal_parameter_initializer_error_;
274 Error binding_pattern_error_;
275 Error assignment_pattern_error_;
276 Error arrow_formal_parameters_error_;
277 Error duplicate_formal_parameter_error_;
278 Error strict_mode_formal_parameter_error_;
279 Error strong_mode_formal_parameter_error_;
280 DuplicateFinder* duplicate_finder_;
285 #endif // V8_EXPRESSION_CLASSIFIER_H