blob: 96ccf871f4c36399c1228f408d60aca2881e042d [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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.
4
5#ifndef V8_PARSING_EXPRESSION_CLASSIFIER_H
6#define V8_PARSING_EXPRESSION_CLASSIFIER_H
7
8#include "src/messages.h"
9#include "src/parsing/scanner.h"
10#include "src/parsing/token.h"
11
12namespace v8 {
13namespace internal {
14
15
16class ExpressionClassifier {
17 public:
18 struct Error {
19 Error()
20 : location(Scanner::Location::invalid()),
21 message(MessageTemplate::kNone),
22 type(kSyntaxError),
23 arg(nullptr) {}
24
25 Scanner::Location location;
26 MessageTemplate::Template message : 30;
27 ParseErrorType type : 2;
28 const char* arg;
29 };
30
31 enum TargetProduction {
32 ExpressionProduction = 1 << 0,
33 FormalParameterInitializerProduction = 1 << 1,
34 BindingPatternProduction = 1 << 2,
35 AssignmentPatternProduction = 1 << 3,
36 DistinctFormalParametersProduction = 1 << 4,
37 StrictModeFormalParametersProduction = 1 << 5,
38 StrongModeFormalParametersProduction = 1 << 6,
39 ArrowFormalParametersProduction = 1 << 7,
40 LetPatternProduction = 1 << 8,
41 CoverInitializedNameProduction = 1 << 9,
42
43 ExpressionProductions =
44 (ExpressionProduction | FormalParameterInitializerProduction),
45 PatternProductions = (BindingPatternProduction |
46 AssignmentPatternProduction | LetPatternProduction),
47 FormalParametersProductions = (DistinctFormalParametersProduction |
48 StrictModeFormalParametersProduction |
49 StrongModeFormalParametersProduction),
50 StandardProductions = ExpressionProductions | PatternProductions,
51 AllProductions =
52 (StandardProductions | FormalParametersProductions |
53 ArrowFormalParametersProduction | CoverInitializedNameProduction)
54 };
55
56 enum FunctionProperties { NonSimpleParameter = 1 << 0 };
57
58 ExpressionClassifier()
59 : invalid_productions_(0),
60 function_properties_(0),
61 duplicate_finder_(nullptr) {}
62
63 explicit ExpressionClassifier(DuplicateFinder* duplicate_finder)
64 : invalid_productions_(0),
65 function_properties_(0),
66 duplicate_finder_(duplicate_finder) {}
67
68 bool is_valid(unsigned productions) const {
69 return (invalid_productions_ & productions) == 0;
70 }
71
72 DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
73
74 bool is_valid_expression() const { return is_valid(ExpressionProduction); }
75
76 bool is_valid_formal_parameter_initializer() const {
77 return is_valid(FormalParameterInitializerProduction);
78 }
79
80 bool is_valid_binding_pattern() const {
81 return is_valid(BindingPatternProduction);
82 }
83
84 bool is_valid_assignment_pattern() const {
85 return is_valid(AssignmentPatternProduction);
86 }
87
88 bool is_valid_arrow_formal_parameters() const {
89 return is_valid(ArrowFormalParametersProduction);
90 }
91
92 bool is_valid_formal_parameter_list_without_duplicates() const {
93 return is_valid(DistinctFormalParametersProduction);
94 }
95
96 // Note: callers should also check
97 // is_valid_formal_parameter_list_without_duplicates().
98 bool is_valid_strict_mode_formal_parameters() const {
99 return is_valid(StrictModeFormalParametersProduction);
100 }
101
102 // Note: callers should also check is_valid_strict_mode_formal_parameters()
103 // and is_valid_formal_parameter_list_without_duplicates().
104 bool is_valid_strong_mode_formal_parameters() const {
105 return is_valid(StrongModeFormalParametersProduction);
106 }
107
108 bool is_valid_let_pattern() const { return is_valid(LetPatternProduction); }
109
110 const Error& expression_error() const { return expression_error_; }
111
112 const Error& formal_parameter_initializer_error() const {
113 return formal_parameter_initializer_error_;
114 }
115
116 const Error& binding_pattern_error() const { return binding_pattern_error_; }
117
118 const Error& assignment_pattern_error() const {
119 return assignment_pattern_error_;
120 }
121
122 const Error& arrow_formal_parameters_error() const {
123 return arrow_formal_parameters_error_;
124 }
125
126 const Error& duplicate_formal_parameter_error() const {
127 return duplicate_formal_parameter_error_;
128 }
129
130 const Error& strict_mode_formal_parameter_error() const {
131 return strict_mode_formal_parameter_error_;
132 }
133
134 const Error& strong_mode_formal_parameter_error() const {
135 return strong_mode_formal_parameter_error_;
136 }
137
138 const Error& let_pattern_error() const { return let_pattern_error_; }
139
140 bool has_cover_initialized_name() const {
141 return !is_valid(CoverInitializedNameProduction);
142 }
143 const Error& cover_initialized_name_error() const {
144 return cover_initialized_name_error_;
145 }
146
147 bool is_simple_parameter_list() const {
148 return !(function_properties_ & NonSimpleParameter);
149 }
150
151 void RecordNonSimpleParameter() {
152 function_properties_ |= NonSimpleParameter;
153 }
154
155 void RecordExpressionError(const Scanner::Location& loc,
156 MessageTemplate::Template message,
157 const char* arg = nullptr) {
158 if (!is_valid_expression()) return;
159 invalid_productions_ |= ExpressionProduction;
160 expression_error_.location = loc;
161 expression_error_.message = message;
162 expression_error_.arg = arg;
163 }
164
165 void RecordExpressionError(const Scanner::Location& loc,
166 MessageTemplate::Template message,
167 ParseErrorType type, const char* arg = nullptr) {
168 if (!is_valid_expression()) return;
169 invalid_productions_ |= ExpressionProduction;
170 expression_error_.location = loc;
171 expression_error_.message = message;
172 expression_error_.arg = arg;
173 expression_error_.type = type;
174 }
175
176 void RecordFormalParameterInitializerError(const Scanner::Location& loc,
177 MessageTemplate::Template message,
178 const char* arg = nullptr) {
179 if (!is_valid_formal_parameter_initializer()) return;
180 invalid_productions_ |= FormalParameterInitializerProduction;
181 formal_parameter_initializer_error_.location = loc;
182 formal_parameter_initializer_error_.message = message;
183 formal_parameter_initializer_error_.arg = arg;
184 }
185
186 void RecordBindingPatternError(const Scanner::Location& loc,
187 MessageTemplate::Template message,
188 const char* arg = nullptr) {
189 if (!is_valid_binding_pattern()) return;
190 invalid_productions_ |= BindingPatternProduction;
191 binding_pattern_error_.location = loc;
192 binding_pattern_error_.message = message;
193 binding_pattern_error_.arg = arg;
194 }
195
196 void RecordAssignmentPatternError(const Scanner::Location& loc,
197 MessageTemplate::Template message,
198 const char* arg = nullptr) {
199 if (!is_valid_assignment_pattern()) return;
200 invalid_productions_ |= AssignmentPatternProduction;
201 assignment_pattern_error_.location = loc;
202 assignment_pattern_error_.message = message;
203 assignment_pattern_error_.arg = arg;
204 }
205
206 void RecordPatternError(const Scanner::Location& loc,
207 MessageTemplate::Template message,
208 const char* arg = nullptr) {
209 RecordBindingPatternError(loc, message, arg);
210 RecordAssignmentPatternError(loc, message, arg);
211 }
212
213 void RecordArrowFormalParametersError(const Scanner::Location& loc,
214 MessageTemplate::Template message,
215 const char* arg = nullptr) {
216 if (!is_valid_arrow_formal_parameters()) return;
217 invalid_productions_ |= ArrowFormalParametersProduction;
218 arrow_formal_parameters_error_.location = loc;
219 arrow_formal_parameters_error_.message = message;
220 arrow_formal_parameters_error_.arg = arg;
221 }
222
223 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
224 if (!is_valid_formal_parameter_list_without_duplicates()) return;
225 invalid_productions_ |= DistinctFormalParametersProduction;
226 duplicate_formal_parameter_error_.location = loc;
227 duplicate_formal_parameter_error_.message = MessageTemplate::kParamDupe;
228 duplicate_formal_parameter_error_.arg = nullptr;
229 }
230
231 // Record a binding that would be invalid in strict mode. Confusingly this
232 // is not the same as StrictFormalParameterList, which simply forbids
233 // duplicate bindings.
234 void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
235 MessageTemplate::Template message,
236 const char* arg = nullptr) {
237 if (!is_valid_strict_mode_formal_parameters()) return;
238 invalid_productions_ |= StrictModeFormalParametersProduction;
239 strict_mode_formal_parameter_error_.location = loc;
240 strict_mode_formal_parameter_error_.message = message;
241 strict_mode_formal_parameter_error_.arg = arg;
242 }
243
244 void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
245 MessageTemplate::Template message,
246 const char* arg = nullptr) {
247 if (!is_valid_strong_mode_formal_parameters()) return;
248 invalid_productions_ |= StrongModeFormalParametersProduction;
249 strong_mode_formal_parameter_error_.location = loc;
250 strong_mode_formal_parameter_error_.message = message;
251 strong_mode_formal_parameter_error_.arg = arg;
252 }
253
254 void RecordLetPatternError(const Scanner::Location& loc,
255 MessageTemplate::Template message,
256 const char* arg = nullptr) {
257 if (!is_valid_let_pattern()) return;
258 invalid_productions_ |= LetPatternProduction;
259 let_pattern_error_.location = loc;
260 let_pattern_error_.message = message;
261 let_pattern_error_.arg = arg;
262 }
263
264 void RecordCoverInitializedNameError(const Scanner::Location& loc,
265 MessageTemplate::Template message,
266 const char* arg = nullptr) {
267 if (has_cover_initialized_name()) return;
268 invalid_productions_ |= CoverInitializedNameProduction;
269 cover_initialized_name_error_.location = loc;
270 cover_initialized_name_error_.message = message;
271 cover_initialized_name_error_.arg = arg;
272 }
273
274 void ForgiveCoverInitializedNameError() {
275 invalid_productions_ &= ~CoverInitializedNameProduction;
276 cover_initialized_name_error_ = Error();
277 }
278
279 void ForgiveAssignmentPatternError() {
280 invalid_productions_ &= ~AssignmentPatternProduction;
281 assignment_pattern_error_ = Error();
282 }
283
284 void Accumulate(const ExpressionClassifier& inner,
285 unsigned productions = StandardProductions) {
286 // Propagate errors from inner, but don't overwrite already recorded
287 // errors.
288 unsigned non_arrow_inner_invalid_productions =
289 inner.invalid_productions_ & ~ArrowFormalParametersProduction;
290 if (non_arrow_inner_invalid_productions == 0) return;
291 unsigned non_arrow_productions =
292 productions & ~ArrowFormalParametersProduction;
293 unsigned errors =
294 non_arrow_productions & non_arrow_inner_invalid_productions;
295 errors &= ~invalid_productions_;
296 if (errors != 0) {
297 invalid_productions_ |= errors;
298 if (errors & ExpressionProduction)
299 expression_error_ = inner.expression_error_;
300 if (errors & FormalParameterInitializerProduction)
301 formal_parameter_initializer_error_ =
302 inner.formal_parameter_initializer_error_;
303 if (errors & BindingPatternProduction)
304 binding_pattern_error_ = inner.binding_pattern_error_;
305 if (errors & AssignmentPatternProduction)
306 assignment_pattern_error_ = inner.assignment_pattern_error_;
307 if (errors & DistinctFormalParametersProduction)
308 duplicate_formal_parameter_error_ =
309 inner.duplicate_formal_parameter_error_;
310 if (errors & StrictModeFormalParametersProduction)
311 strict_mode_formal_parameter_error_ =
312 inner.strict_mode_formal_parameter_error_;
313 if (errors & StrongModeFormalParametersProduction)
314 strong_mode_formal_parameter_error_ =
315 inner.strong_mode_formal_parameter_error_;
316 if (errors & LetPatternProduction)
317 let_pattern_error_ = inner.let_pattern_error_;
318 if (errors & CoverInitializedNameProduction)
319 cover_initialized_name_error_ = inner.cover_initialized_name_error_;
320 }
321
322 // As an exception to the above, the result continues to be a valid arrow
323 // formal parameters if the inner expression is a valid binding pattern.
324 if (productions & ArrowFormalParametersProduction &&
325 is_valid_arrow_formal_parameters()) {
326 // Also copy function properties if expecting an arrow function
327 // parameter.
328 function_properties_ |= inner.function_properties_;
329
330 if (!inner.is_valid_binding_pattern()) {
331 invalid_productions_ |= ArrowFormalParametersProduction;
332 arrow_formal_parameters_error_ = inner.binding_pattern_error_;
333 }
334 }
335 }
336
337 private:
338 unsigned invalid_productions_;
339 unsigned function_properties_;
340 Error expression_error_;
341 Error formal_parameter_initializer_error_;
342 Error binding_pattern_error_;
343 Error assignment_pattern_error_;
344 Error arrow_formal_parameters_error_;
345 Error duplicate_formal_parameter_error_;
346 Error strict_mode_formal_parameter_error_;
347 Error strong_mode_formal_parameter_error_;
348 Error let_pattern_error_;
349 Error cover_initialized_name_error_;
350 DuplicateFinder* duplicate_finder_;
351};
352
353} // namespace internal
354} // namespace v8
355
356#endif // V8_PARSING_EXPRESSION_CLASSIFIER_H