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 ExpressionClassifier()
49 : invalid_productions_(0), duplicate_finder_(nullptr) {}
51 explicit ExpressionClassifier(DuplicateFinder* duplicate_finder)
52 : invalid_productions_(0), duplicate_finder_(duplicate_finder) {}
54 bool is_valid(unsigned productions) const {
55 return (invalid_productions_ & productions) == 0;
58 DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
60 bool is_valid_expression() const { return is_valid(ExpressionProduction); }
62 bool is_valid_binding_pattern() const {
63 return is_valid(BindingPatternProduction);
66 bool is_valid_assignment_pattern() const {
67 return is_valid(AssignmentPatternProduction);
70 bool is_valid_arrow_formal_parameters() const {
71 return is_valid(ArrowFormalParametersProduction);
74 bool is_valid_formal_parameter_list_without_duplicates() const {
75 return is_valid(DistinctFormalParametersProduction);
78 // Note: callers should also check
79 // is_valid_formal_parameter_list_without_duplicates().
80 bool is_valid_strict_mode_formal_parameters() const {
81 return is_valid(StrictModeFormalParametersProduction);
84 // Note: callers should also check is_valid_strict_mode_formal_parameters()
85 // and is_valid_formal_parameter_list_without_duplicates().
86 bool is_valid_strong_mode_formal_parameters() const {
87 return is_valid(StrongModeFormalParametersProduction);
90 const Error& expression_error() const { return expression_error_; }
92 const Error& binding_pattern_error() const { return binding_pattern_error_; }
94 const Error& assignment_pattern_error() const {
95 return assignment_pattern_error_;
98 const Error& arrow_formal_parameters_error() const {
99 return arrow_formal_parameters_error_;
102 const Error& duplicate_formal_parameter_error() const {
103 return duplicate_formal_parameter_error_;
106 const Error& strict_mode_formal_parameter_error() const {
107 return strict_mode_formal_parameter_error_;
110 const Error& strong_mode_formal_parameter_error() const {
111 return strong_mode_formal_parameter_error_;
114 void RecordExpressionError(const Scanner::Location& loc,
115 MessageTemplate::Template message,
116 const char* arg = nullptr) {
117 if (!is_valid_expression()) return;
118 invalid_productions_ |= ExpressionProduction;
119 expression_error_.location = loc;
120 expression_error_.message = message;
121 expression_error_.arg = arg;
124 void RecordBindingPatternError(const Scanner::Location& loc,
125 MessageTemplate::Template message,
126 const char* arg = nullptr) {
127 if (!is_valid_binding_pattern()) return;
128 invalid_productions_ |= BindingPatternProduction;
129 binding_pattern_error_.location = loc;
130 binding_pattern_error_.message = message;
131 binding_pattern_error_.arg = arg;
134 void RecordAssignmentPatternError(const Scanner::Location& loc,
135 MessageTemplate::Template message,
136 const char* arg = nullptr) {
137 if (!is_valid_assignment_pattern()) return;
138 invalid_productions_ |= AssignmentPatternProduction;
139 assignment_pattern_error_.location = loc;
140 assignment_pattern_error_.message = message;
141 assignment_pattern_error_.arg = arg;
144 void RecordArrowFormalParametersError(const Scanner::Location& loc,
145 MessageTemplate::Template message,
146 const char* arg = nullptr) {
147 if (!is_valid_arrow_formal_parameters()) return;
148 invalid_productions_ |= ArrowFormalParametersProduction;
149 arrow_formal_parameters_error_.location = loc;
150 arrow_formal_parameters_error_.message = message;
151 arrow_formal_parameters_error_.arg = arg;
154 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
155 if (!is_valid_formal_parameter_list_without_duplicates()) return;
156 invalid_productions_ |= DistinctFormalParametersProduction;
157 duplicate_formal_parameter_error_.location = loc;
158 duplicate_formal_parameter_error_.message = MessageTemplate::kParamDupe;
159 duplicate_formal_parameter_error_.arg = nullptr;
162 // Record a binding that would be invalid in strict mode. Confusingly this
163 // is not the same as StrictFormalParameterList, which simply forbids
164 // duplicate bindings.
165 void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
166 MessageTemplate::Template message,
167 const char* arg = nullptr) {
168 if (!is_valid_strict_mode_formal_parameters()) return;
169 invalid_productions_ |= StrictModeFormalParametersProduction;
170 strict_mode_formal_parameter_error_.location = loc;
171 strict_mode_formal_parameter_error_.message = message;
172 strict_mode_formal_parameter_error_.arg = arg;
175 void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
176 MessageTemplate::Template message,
177 const char* arg = nullptr) {
178 if (!is_valid_strong_mode_formal_parameters()) return;
179 invalid_productions_ |= StrongModeFormalParametersProduction;
180 strong_mode_formal_parameter_error_.location = loc;
181 strong_mode_formal_parameter_error_.message = message;
182 strong_mode_formal_parameter_error_.arg = arg;
185 void Accumulate(const ExpressionClassifier& inner,
186 unsigned productions = StandardProductions) {
187 // Propagate errors from inner, but don't overwrite already recorded
189 unsigned non_arrow_inner_invalid_productions =
190 inner.invalid_productions_ & ~ArrowFormalParametersProduction;
191 if (non_arrow_inner_invalid_productions == 0) return;
192 unsigned non_arrow_productions =
193 productions & ~ArrowFormalParametersProduction;
195 non_arrow_productions & non_arrow_inner_invalid_productions;
196 errors &= ~invalid_productions_;
198 invalid_productions_ |= errors;
199 if (errors & ExpressionProduction)
200 expression_error_ = inner.expression_error_;
201 if (errors & BindingPatternProduction)
202 binding_pattern_error_ = inner.binding_pattern_error_;
203 if (errors & AssignmentPatternProduction)
204 assignment_pattern_error_ = inner.assignment_pattern_error_;
205 if (errors & DistinctFormalParametersProduction)
206 duplicate_formal_parameter_error_ =
207 inner.duplicate_formal_parameter_error_;
208 if (errors & StrictModeFormalParametersProduction)
209 strict_mode_formal_parameter_error_ =
210 inner.strict_mode_formal_parameter_error_;
211 if (errors & StrongModeFormalParametersProduction)
212 strong_mode_formal_parameter_error_ =
213 inner.strong_mode_formal_parameter_error_;
216 // As an exception to the above, the result continues to be a valid arrow
217 // formal parameters if the inner expression is a valid binding pattern.
218 if (productions & ArrowFormalParametersProduction &&
219 is_valid_arrow_formal_parameters() &&
220 !inner.is_valid_binding_pattern()) {
221 invalid_productions_ |= ArrowFormalParametersProduction;
222 arrow_formal_parameters_error_ = inner.binding_pattern_error_;
227 unsigned invalid_productions_;
228 Error expression_error_;
229 Error binding_pattern_error_;
230 Error assignment_pattern_error_;
231 Error arrow_formal_parameters_error_;
232 Error duplicate_formal_parameter_error_;
233 Error strict_mode_formal_parameter_error_;
234 Error strong_mode_formal_parameter_error_;
235 DuplicateFinder* duplicate_finder_;
240 #endif // V8_EXPRESSION_CLASSIFIER_H