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 BindingPatternProduction = 1 << 1,
32 AssignmentPatternProduction = 1 << 2,
33 DistinctFormalParametersProduction = 1 << 3,
34 StrictModeFormalParametersProduction = 1 << 4,
35 StrongModeFormalParametersProduction = 1 << 5,
36 ArrowFormalParametersProduction = 1 << 6,
39 (BindingPatternProduction | AssignmentPatternProduction),
40 FormalParametersProductions = (DistinctFormalParametersProduction |
41 StrictModeFormalParametersProduction |
42 StrongModeFormalParametersProduction),
43 StandardProductions = ExpressionProduction | PatternProductions,
44 AllProductions = (StandardProductions | FormalParametersProductions |
45 ArrowFormalParametersProduction)
48 enum FunctionProperties { NonSimpleParameter = 1 << 0 };
50 ExpressionClassifier()
51 : invalid_productions_(0),
52 function_properties_(0),
53 duplicate_finder_(nullptr) {}
55 explicit ExpressionClassifier(DuplicateFinder* duplicate_finder)
56 : invalid_productions_(0),
57 function_properties_(0),
58 duplicate_finder_(duplicate_finder) {}
60 bool is_valid(unsigned productions) const {
61 return (invalid_productions_ & productions) == 0;
64 DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
66 bool is_valid_expression() const { return is_valid(ExpressionProduction); }
68 bool is_valid_binding_pattern() const {
69 return is_valid(BindingPatternProduction);
72 bool is_valid_assignment_pattern() const {
73 return is_valid(AssignmentPatternProduction);
76 bool is_valid_arrow_formal_parameters() const {
77 return is_valid(ArrowFormalParametersProduction);
80 bool is_valid_formal_parameter_list_without_duplicates() const {
81 return is_valid(DistinctFormalParametersProduction);
84 // Note: callers should also check
85 // is_valid_formal_parameter_list_without_duplicates().
86 bool is_valid_strict_mode_formal_parameters() const {
87 return is_valid(StrictModeFormalParametersProduction);
90 // Note: callers should also check is_valid_strict_mode_formal_parameters()
91 // and is_valid_formal_parameter_list_without_duplicates().
92 bool is_valid_strong_mode_formal_parameters() const {
93 return is_valid(StrongModeFormalParametersProduction);
96 const Error& expression_error() const { return expression_error_; }
98 const Error& binding_pattern_error() const { return binding_pattern_error_; }
100 const Error& assignment_pattern_error() const {
101 return assignment_pattern_error_;
104 const Error& arrow_formal_parameters_error() const {
105 return arrow_formal_parameters_error_;
108 const Error& duplicate_formal_parameter_error() const {
109 return duplicate_formal_parameter_error_;
112 const Error& strict_mode_formal_parameter_error() const {
113 return strict_mode_formal_parameter_error_;
116 const Error& strong_mode_formal_parameter_error() const {
117 return strong_mode_formal_parameter_error_;
120 bool is_simple_parameter_list() const {
121 return !(function_properties_ & NonSimpleParameter);
124 void RecordNonSimpleParameter() {
125 function_properties_ |= NonSimpleParameter;
128 void RecordExpressionError(const Scanner::Location& loc,
129 MessageTemplate::Template message,
130 const char* arg = nullptr) {
131 if (!is_valid_expression()) return;
132 invalid_productions_ |= ExpressionProduction;
133 expression_error_.location = loc;
134 expression_error_.message = message;
135 expression_error_.arg = arg;
138 void RecordBindingPatternError(const Scanner::Location& loc,
139 MessageTemplate::Template message,
140 const char* arg = nullptr) {
141 if (!is_valid_binding_pattern()) return;
142 invalid_productions_ |= BindingPatternProduction;
143 binding_pattern_error_.location = loc;
144 binding_pattern_error_.message = message;
145 binding_pattern_error_.arg = arg;
148 void RecordAssignmentPatternError(const Scanner::Location& loc,
149 MessageTemplate::Template message,
150 const char* arg = nullptr) {
151 if (!is_valid_assignment_pattern()) return;
152 invalid_productions_ |= AssignmentPatternProduction;
153 assignment_pattern_error_.location = loc;
154 assignment_pattern_error_.message = message;
155 assignment_pattern_error_.arg = arg;
158 void RecordArrowFormalParametersError(const Scanner::Location& loc,
159 MessageTemplate::Template message,
160 const char* arg = nullptr) {
161 if (!is_valid_arrow_formal_parameters()) return;
162 invalid_productions_ |= ArrowFormalParametersProduction;
163 arrow_formal_parameters_error_.location = loc;
164 arrow_formal_parameters_error_.message = message;
165 arrow_formal_parameters_error_.arg = arg;
168 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
169 if (!is_valid_formal_parameter_list_without_duplicates()) return;
170 invalid_productions_ |= DistinctFormalParametersProduction;
171 duplicate_formal_parameter_error_.location = loc;
172 duplicate_formal_parameter_error_.message = MessageTemplate::kParamDupe;
173 duplicate_formal_parameter_error_.arg = nullptr;
176 // Record a binding that would be invalid in strict mode. Confusingly this
177 // is not the same as StrictFormalParameterList, which simply forbids
178 // duplicate bindings.
179 void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
180 MessageTemplate::Template message,
181 const char* arg = nullptr) {
182 if (!is_valid_strict_mode_formal_parameters()) return;
183 invalid_productions_ |= StrictModeFormalParametersProduction;
184 strict_mode_formal_parameter_error_.location = loc;
185 strict_mode_formal_parameter_error_.message = message;
186 strict_mode_formal_parameter_error_.arg = arg;
189 void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
190 MessageTemplate::Template message,
191 const char* arg = nullptr) {
192 if (!is_valid_strong_mode_formal_parameters()) return;
193 invalid_productions_ |= StrongModeFormalParametersProduction;
194 strong_mode_formal_parameter_error_.location = loc;
195 strong_mode_formal_parameter_error_.message = message;
196 strong_mode_formal_parameter_error_.arg = arg;
199 void Accumulate(const ExpressionClassifier& inner,
200 unsigned productions = StandardProductions) {
201 // Propagate errors from inner, but don't overwrite already recorded
203 unsigned non_arrow_inner_invalid_productions =
204 inner.invalid_productions_ & ~ArrowFormalParametersProduction;
205 if (non_arrow_inner_invalid_productions == 0) return;
206 unsigned non_arrow_productions =
207 productions & ~ArrowFormalParametersProduction;
209 non_arrow_productions & non_arrow_inner_invalid_productions;
210 errors &= ~invalid_productions_;
212 invalid_productions_ |= errors;
213 if (errors & ExpressionProduction)
214 expression_error_ = inner.expression_error_;
215 if (errors & BindingPatternProduction)
216 binding_pattern_error_ = inner.binding_pattern_error_;
217 if (errors & AssignmentPatternProduction)
218 assignment_pattern_error_ = inner.assignment_pattern_error_;
219 if (errors & DistinctFormalParametersProduction)
220 duplicate_formal_parameter_error_ =
221 inner.duplicate_formal_parameter_error_;
222 if (errors & StrictModeFormalParametersProduction)
223 strict_mode_formal_parameter_error_ =
224 inner.strict_mode_formal_parameter_error_;
225 if (errors & StrongModeFormalParametersProduction)
226 strong_mode_formal_parameter_error_ =
227 inner.strong_mode_formal_parameter_error_;
230 // As an exception to the above, the result continues to be a valid arrow
231 // formal parameters if the inner expression is a valid binding pattern.
232 if (productions & ArrowFormalParametersProduction &&
233 is_valid_arrow_formal_parameters()) {
234 // Also copy function properties if expecting an arrow function
236 function_properties_ |= inner.function_properties_;
238 if (!inner.is_valid_binding_pattern()) {
239 invalid_productions_ |= ArrowFormalParametersProduction;
240 arrow_formal_parameters_error_ = inner.binding_pattern_error_;
246 unsigned invalid_productions_;
247 unsigned function_properties_;
248 Error expression_error_;
249 Error binding_pattern_error_;
250 Error assignment_pattern_error_;
251 Error arrow_formal_parameters_error_;
252 Error duplicate_formal_parameter_error_;
253 Error strict_mode_formal_parameter_error_;
254 Error strong_mode_formal_parameter_error_;
255 DuplicateFinder* duplicate_finder_;
260 #endif // V8_EXPRESSION_CLASSIFIER_H