blob: fa1a2f97a486895482bcc6e88b851f8331347131 [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
Ben Murdoch097c5b22016-05-18 11:27:45 +010016template <typename Traits>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017class ExpressionClassifier {
18 public:
19 struct Error {
20 Error()
21 : location(Scanner::Location::invalid()),
22 message(MessageTemplate::kNone),
23 type(kSyntaxError),
24 arg(nullptr) {}
25
26 Scanner::Location location;
27 MessageTemplate::Template message : 30;
28 ParseErrorType type : 2;
29 const char* arg;
30 };
31
32 enum TargetProduction {
33 ExpressionProduction = 1 << 0,
34 FormalParameterInitializerProduction = 1 << 1,
35 BindingPatternProduction = 1 << 2,
36 AssignmentPatternProduction = 1 << 3,
37 DistinctFormalParametersProduction = 1 << 4,
38 StrictModeFormalParametersProduction = 1 << 5,
39 StrongModeFormalParametersProduction = 1 << 6,
40 ArrowFormalParametersProduction = 1 << 7,
41 LetPatternProduction = 1 << 8,
42 CoverInitializedNameProduction = 1 << 9,
43
44 ExpressionProductions =
45 (ExpressionProduction | FormalParameterInitializerProduction),
46 PatternProductions = (BindingPatternProduction |
47 AssignmentPatternProduction | LetPatternProduction),
48 FormalParametersProductions = (DistinctFormalParametersProduction |
49 StrictModeFormalParametersProduction |
50 StrongModeFormalParametersProduction),
51 StandardProductions = ExpressionProductions | PatternProductions,
52 AllProductions =
53 (StandardProductions | FormalParametersProductions |
54 ArrowFormalParametersProduction | CoverInitializedNameProduction)
55 };
56
57 enum FunctionProperties { NonSimpleParameter = 1 << 0 };
58
Ben Murdoch097c5b22016-05-18 11:27:45 +010059 explicit ExpressionClassifier(const Traits* t)
60 : zone_(t->zone()),
61 non_patterns_to_rewrite_(t->GetNonPatternList()),
62 invalid_productions_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063 function_properties_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +010064 duplicate_finder_(nullptr) {
65 non_pattern_begin_ = non_patterns_to_rewrite_->length();
66 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067
Ben Murdoch097c5b22016-05-18 11:27:45 +010068 ExpressionClassifier(const Traits* t, DuplicateFinder* duplicate_finder)
69 : zone_(t->zone()),
70 non_patterns_to_rewrite_(t->GetNonPatternList()),
71 invalid_productions_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 function_properties_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +010073 duplicate_finder_(duplicate_finder) {
74 non_pattern_begin_ = non_patterns_to_rewrite_->length();
75 }
76
77 ~ExpressionClassifier() { Discard(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078
79 bool is_valid(unsigned productions) const {
80 return (invalid_productions_ & productions) == 0;
81 }
82
83 DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
84
85 bool is_valid_expression() const { return is_valid(ExpressionProduction); }
86
87 bool is_valid_formal_parameter_initializer() const {
88 return is_valid(FormalParameterInitializerProduction);
89 }
90
91 bool is_valid_binding_pattern() const {
92 return is_valid(BindingPatternProduction);
93 }
94
95 bool is_valid_assignment_pattern() const {
96 return is_valid(AssignmentPatternProduction);
97 }
98
99 bool is_valid_arrow_formal_parameters() const {
100 return is_valid(ArrowFormalParametersProduction);
101 }
102
103 bool is_valid_formal_parameter_list_without_duplicates() const {
104 return is_valid(DistinctFormalParametersProduction);
105 }
106
107 // Note: callers should also check
108 // is_valid_formal_parameter_list_without_duplicates().
109 bool is_valid_strict_mode_formal_parameters() const {
110 return is_valid(StrictModeFormalParametersProduction);
111 }
112
113 // Note: callers should also check is_valid_strict_mode_formal_parameters()
114 // and is_valid_formal_parameter_list_without_duplicates().
115 bool is_valid_strong_mode_formal_parameters() const {
116 return is_valid(StrongModeFormalParametersProduction);
117 }
118
119 bool is_valid_let_pattern() const { return is_valid(LetPatternProduction); }
120
121 const Error& expression_error() const { return expression_error_; }
122
123 const Error& formal_parameter_initializer_error() const {
124 return formal_parameter_initializer_error_;
125 }
126
127 const Error& binding_pattern_error() const { return binding_pattern_error_; }
128
129 const Error& assignment_pattern_error() const {
130 return assignment_pattern_error_;
131 }
132
133 const Error& arrow_formal_parameters_error() const {
134 return arrow_formal_parameters_error_;
135 }
136
137 const Error& duplicate_formal_parameter_error() const {
138 return duplicate_formal_parameter_error_;
139 }
140
141 const Error& strict_mode_formal_parameter_error() const {
142 return strict_mode_formal_parameter_error_;
143 }
144
145 const Error& strong_mode_formal_parameter_error() const {
146 return strong_mode_formal_parameter_error_;
147 }
148
149 const Error& let_pattern_error() const { return let_pattern_error_; }
150
151 bool has_cover_initialized_name() const {
152 return !is_valid(CoverInitializedNameProduction);
153 }
154 const Error& cover_initialized_name_error() const {
155 return cover_initialized_name_error_;
156 }
157
158 bool is_simple_parameter_list() const {
159 return !(function_properties_ & NonSimpleParameter);
160 }
161
162 void RecordNonSimpleParameter() {
163 function_properties_ |= NonSimpleParameter;
164 }
165
166 void RecordExpressionError(const Scanner::Location& loc,
167 MessageTemplate::Template message,
168 const char* arg = nullptr) {
169 if (!is_valid_expression()) return;
170 invalid_productions_ |= ExpressionProduction;
171 expression_error_.location = loc;
172 expression_error_.message = message;
173 expression_error_.arg = arg;
174 }
175
176 void RecordExpressionError(const Scanner::Location& loc,
177 MessageTemplate::Template message,
178 ParseErrorType type, const char* arg = nullptr) {
179 if (!is_valid_expression()) return;
180 invalid_productions_ |= ExpressionProduction;
181 expression_error_.location = loc;
182 expression_error_.message = message;
183 expression_error_.arg = arg;
184 expression_error_.type = type;
185 }
186
187 void RecordFormalParameterInitializerError(const Scanner::Location& loc,
188 MessageTemplate::Template message,
189 const char* arg = nullptr) {
190 if (!is_valid_formal_parameter_initializer()) return;
191 invalid_productions_ |= FormalParameterInitializerProduction;
192 formal_parameter_initializer_error_.location = loc;
193 formal_parameter_initializer_error_.message = message;
194 formal_parameter_initializer_error_.arg = arg;
195 }
196
197 void RecordBindingPatternError(const Scanner::Location& loc,
198 MessageTemplate::Template message,
199 const char* arg = nullptr) {
200 if (!is_valid_binding_pattern()) return;
201 invalid_productions_ |= BindingPatternProduction;
202 binding_pattern_error_.location = loc;
203 binding_pattern_error_.message = message;
204 binding_pattern_error_.arg = arg;
205 }
206
207 void RecordAssignmentPatternError(const Scanner::Location& loc,
208 MessageTemplate::Template message,
209 const char* arg = nullptr) {
210 if (!is_valid_assignment_pattern()) return;
211 invalid_productions_ |= AssignmentPatternProduction;
212 assignment_pattern_error_.location = loc;
213 assignment_pattern_error_.message = message;
214 assignment_pattern_error_.arg = arg;
215 }
216
217 void RecordPatternError(const Scanner::Location& loc,
218 MessageTemplate::Template message,
219 const char* arg = nullptr) {
220 RecordBindingPatternError(loc, message, arg);
221 RecordAssignmentPatternError(loc, message, arg);
222 }
223
224 void RecordArrowFormalParametersError(const Scanner::Location& loc,
225 MessageTemplate::Template message,
226 const char* arg = nullptr) {
227 if (!is_valid_arrow_formal_parameters()) return;
228 invalid_productions_ |= ArrowFormalParametersProduction;
229 arrow_formal_parameters_error_.location = loc;
230 arrow_formal_parameters_error_.message = message;
231 arrow_formal_parameters_error_.arg = arg;
232 }
233
234 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
235 if (!is_valid_formal_parameter_list_without_duplicates()) return;
236 invalid_productions_ |= DistinctFormalParametersProduction;
237 duplicate_formal_parameter_error_.location = loc;
238 duplicate_formal_parameter_error_.message = MessageTemplate::kParamDupe;
239 duplicate_formal_parameter_error_.arg = nullptr;
240 }
241
242 // Record a binding that would be invalid in strict mode. Confusingly this
243 // is not the same as StrictFormalParameterList, which simply forbids
244 // duplicate bindings.
245 void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
246 MessageTemplate::Template message,
247 const char* arg = nullptr) {
248 if (!is_valid_strict_mode_formal_parameters()) return;
249 invalid_productions_ |= StrictModeFormalParametersProduction;
250 strict_mode_formal_parameter_error_.location = loc;
251 strict_mode_formal_parameter_error_.message = message;
252 strict_mode_formal_parameter_error_.arg = arg;
253 }
254
255 void RecordStrongModeFormalParameterError(const Scanner::Location& loc,
256 MessageTemplate::Template message,
257 const char* arg = nullptr) {
258 if (!is_valid_strong_mode_formal_parameters()) return;
259 invalid_productions_ |= StrongModeFormalParametersProduction;
260 strong_mode_formal_parameter_error_.location = loc;
261 strong_mode_formal_parameter_error_.message = message;
262 strong_mode_formal_parameter_error_.arg = arg;
263 }
264
265 void RecordLetPatternError(const Scanner::Location& loc,
266 MessageTemplate::Template message,
267 const char* arg = nullptr) {
268 if (!is_valid_let_pattern()) return;
269 invalid_productions_ |= LetPatternProduction;
270 let_pattern_error_.location = loc;
271 let_pattern_error_.message = message;
272 let_pattern_error_.arg = arg;
273 }
274
275 void RecordCoverInitializedNameError(const Scanner::Location& loc,
276 MessageTemplate::Template message,
277 const char* arg = nullptr) {
278 if (has_cover_initialized_name()) return;
279 invalid_productions_ |= CoverInitializedNameProduction;
280 cover_initialized_name_error_.location = loc;
281 cover_initialized_name_error_.message = message;
282 cover_initialized_name_error_.arg = arg;
283 }
284
285 void ForgiveCoverInitializedNameError() {
286 invalid_productions_ &= ~CoverInitializedNameProduction;
287 cover_initialized_name_error_ = Error();
288 }
289
290 void ForgiveAssignmentPatternError() {
291 invalid_productions_ &= ~AssignmentPatternProduction;
292 assignment_pattern_error_ = Error();
293 }
294
Ben Murdoch097c5b22016-05-18 11:27:45 +0100295 void Accumulate(ExpressionClassifier* inner,
296 unsigned productions = StandardProductions,
297 bool merge_non_patterns = true) {
298 if (merge_non_patterns) MergeNonPatterns(inner);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000299 // Propagate errors from inner, but don't overwrite already recorded
300 // errors.
301 unsigned non_arrow_inner_invalid_productions =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100302 inner->invalid_productions_ & ~ArrowFormalParametersProduction;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000303 if (non_arrow_inner_invalid_productions == 0) return;
304 unsigned non_arrow_productions =
305 productions & ~ArrowFormalParametersProduction;
306 unsigned errors =
307 non_arrow_productions & non_arrow_inner_invalid_productions;
308 errors &= ~invalid_productions_;
309 if (errors != 0) {
310 invalid_productions_ |= errors;
311 if (errors & ExpressionProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100312 expression_error_ = inner->expression_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 if (errors & FormalParameterInitializerProduction)
314 formal_parameter_initializer_error_ =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100315 inner->formal_parameter_initializer_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000316 if (errors & BindingPatternProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100317 binding_pattern_error_ = inner->binding_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000318 if (errors & AssignmentPatternProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100319 assignment_pattern_error_ = inner->assignment_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320 if (errors & DistinctFormalParametersProduction)
321 duplicate_formal_parameter_error_ =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100322 inner->duplicate_formal_parameter_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000323 if (errors & StrictModeFormalParametersProduction)
324 strict_mode_formal_parameter_error_ =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100325 inner->strict_mode_formal_parameter_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000326 if (errors & StrongModeFormalParametersProduction)
327 strong_mode_formal_parameter_error_ =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100328 inner->strong_mode_formal_parameter_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329 if (errors & LetPatternProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100330 let_pattern_error_ = inner->let_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331 if (errors & CoverInitializedNameProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100332 cover_initialized_name_error_ = inner->cover_initialized_name_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000333 }
334
335 // As an exception to the above, the result continues to be a valid arrow
336 // formal parameters if the inner expression is a valid binding pattern.
337 if (productions & ArrowFormalParametersProduction &&
338 is_valid_arrow_formal_parameters()) {
339 // Also copy function properties if expecting an arrow function
340 // parameter.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100341 function_properties_ |= inner->function_properties_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000342
Ben Murdoch097c5b22016-05-18 11:27:45 +0100343 if (!inner->is_valid_binding_pattern()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000344 invalid_productions_ |= ArrowFormalParametersProduction;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100345 arrow_formal_parameters_error_ = inner->binding_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000346 }
347 }
348 }
349
Ben Murdoch097c5b22016-05-18 11:27:45 +0100350 V8_INLINE int GetNonPatternBegin() const { return non_pattern_begin_; }
351
352 V8_INLINE void Discard() {
353 DCHECK_LE(non_pattern_begin_, non_patterns_to_rewrite_->length());
354 non_patterns_to_rewrite_->Rewind(non_pattern_begin_);
355 }
356
357 V8_INLINE void MergeNonPatterns(ExpressionClassifier* inner) {
358 DCHECK_LE(non_pattern_begin_, inner->non_pattern_begin_);
359 inner->non_pattern_begin_ = inner->non_patterns_to_rewrite_->length();
360 }
361
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000362 private:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100363 Zone* zone_;
364 ZoneList<typename Traits::Type::Expression>* non_patterns_to_rewrite_;
365 int non_pattern_begin_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 unsigned invalid_productions_;
367 unsigned function_properties_;
368 Error expression_error_;
369 Error formal_parameter_initializer_error_;
370 Error binding_pattern_error_;
371 Error assignment_pattern_error_;
372 Error arrow_formal_parameters_error_;
373 Error duplicate_formal_parameter_error_;
374 Error strict_mode_formal_parameter_error_;
375 Error strong_mode_formal_parameter_error_;
376 Error let_pattern_error_;
377 Error cover_initialized_name_error_;
378 DuplicateFinder* duplicate_finder_;
379};
380
Ben Murdoch097c5b22016-05-18 11:27:45 +0100381
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382} // namespace internal
383} // namespace v8
384
385#endif // V8_PARSING_EXPRESSION_CLASSIFIER_H