blob: 3f70ed82d060965cce15739cb5f3cada9f204354 [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,
Ben Murdochda12d292016-06-02 14:46:10 +010039 ArrowFormalParametersProduction = 1 << 6,
40 LetPatternProduction = 1 << 7,
41 CoverInitializedNameProduction = 1 << 8,
Ben Murdochc5610432016-08-08 18:44:38 +010042 TailCallExpressionProduction = 1 << 9,
43 AsyncArrowFormalParametersProduction = 1 << 10,
44 AsyncBindingPatternProduction = 1 << 11,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045
46 ExpressionProductions =
Ben Murdochc5610432016-08-08 18:44:38 +010047 (ExpressionProduction | FormalParameterInitializerProduction |
48 TailCallExpressionProduction),
49 PatternProductions =
50 (BindingPatternProduction | AssignmentPatternProduction |
51 LetPatternProduction | AsyncBindingPatternProduction),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052 FormalParametersProductions = (DistinctFormalParametersProduction |
Ben Murdochda12d292016-06-02 14:46:10 +010053 StrictModeFormalParametersProduction),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054 StandardProductions = ExpressionProductions | PatternProductions,
55 AllProductions =
56 (StandardProductions | FormalParametersProductions |
Ben Murdochc5610432016-08-08 18:44:38 +010057 ArrowFormalParametersProduction | CoverInitializedNameProduction |
58 AsyncArrowFormalParametersProduction | AsyncBindingPatternProduction)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059 };
60
61 enum FunctionProperties { NonSimpleParameter = 1 << 0 };
62
Ben Murdoch097c5b22016-05-18 11:27:45 +010063 explicit ExpressionClassifier(const Traits* t)
64 : zone_(t->zone()),
65 non_patterns_to_rewrite_(t->GetNonPatternList()),
66 invalid_productions_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 function_properties_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +010068 duplicate_finder_(nullptr) {
69 non_pattern_begin_ = non_patterns_to_rewrite_->length();
70 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071
Ben Murdoch097c5b22016-05-18 11:27:45 +010072 ExpressionClassifier(const Traits* t, DuplicateFinder* duplicate_finder)
73 : zone_(t->zone()),
74 non_patterns_to_rewrite_(t->GetNonPatternList()),
75 invalid_productions_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076 function_properties_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +010077 duplicate_finder_(duplicate_finder) {
78 non_pattern_begin_ = non_patterns_to_rewrite_->length();
79 }
80
81 ~ExpressionClassifier() { Discard(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082
83 bool is_valid(unsigned productions) const {
84 return (invalid_productions_ & productions) == 0;
85 }
86
87 DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
88
89 bool is_valid_expression() const { return is_valid(ExpressionProduction); }
90
91 bool is_valid_formal_parameter_initializer() const {
92 return is_valid(FormalParameterInitializerProduction);
93 }
94
95 bool is_valid_binding_pattern() const {
96 return is_valid(BindingPatternProduction);
97 }
98
99 bool is_valid_assignment_pattern() const {
100 return is_valid(AssignmentPatternProduction);
101 }
102
103 bool is_valid_arrow_formal_parameters() const {
104 return is_valid(ArrowFormalParametersProduction);
105 }
106
107 bool is_valid_formal_parameter_list_without_duplicates() const {
108 return is_valid(DistinctFormalParametersProduction);
109 }
110
111 // Note: callers should also check
112 // is_valid_formal_parameter_list_without_duplicates().
113 bool is_valid_strict_mode_formal_parameters() const {
114 return is_valid(StrictModeFormalParametersProduction);
115 }
116
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117 bool is_valid_let_pattern() const { return is_valid(LetPatternProduction); }
118
Ben Murdochc5610432016-08-08 18:44:38 +0100119 bool is_valid_async_arrow_formal_parameters() const {
120 return is_valid(AsyncArrowFormalParametersProduction);
121 }
122
123 bool is_valid_async_binding_pattern() const {
124 return is_valid(AsyncBindingPatternProduction);
125 }
126
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000127 const Error& expression_error() const { return expression_error_; }
128
129 const Error& formal_parameter_initializer_error() const {
130 return formal_parameter_initializer_error_;
131 }
132
133 const Error& binding_pattern_error() const { return binding_pattern_error_; }
134
135 const Error& assignment_pattern_error() const {
136 return assignment_pattern_error_;
137 }
138
139 const Error& arrow_formal_parameters_error() const {
140 return arrow_formal_parameters_error_;
141 }
142
143 const Error& duplicate_formal_parameter_error() const {
144 return duplicate_formal_parameter_error_;
145 }
146
147 const Error& strict_mode_formal_parameter_error() const {
148 return strict_mode_formal_parameter_error_;
149 }
150
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 const Error& let_pattern_error() const { return let_pattern_error_; }
152
153 bool has_cover_initialized_name() const {
154 return !is_valid(CoverInitializedNameProduction);
155 }
156 const Error& cover_initialized_name_error() const {
157 return cover_initialized_name_error_;
158 }
159
Ben Murdochc5610432016-08-08 18:44:38 +0100160 bool has_tail_call_expression() const {
161 return !is_valid(TailCallExpressionProduction);
162 }
163 const Error& tail_call_expression_error() const {
164 return tail_call_expression_error_;
165 }
166 const Error& async_arrow_formal_parameters_error() const {
167 return async_arrow_formal_parameters_error_;
168 }
169
170 const Error& async_binding_pattern_error() const {
171 return async_binding_pattern_error_;
172 }
173
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 bool is_simple_parameter_list() const {
175 return !(function_properties_ & NonSimpleParameter);
176 }
177
178 void RecordNonSimpleParameter() {
179 function_properties_ |= NonSimpleParameter;
180 }
181
182 void RecordExpressionError(const Scanner::Location& loc,
183 MessageTemplate::Template message,
184 const char* arg = nullptr) {
185 if (!is_valid_expression()) return;
186 invalid_productions_ |= ExpressionProduction;
187 expression_error_.location = loc;
188 expression_error_.message = message;
189 expression_error_.arg = arg;
190 }
191
192 void RecordExpressionError(const Scanner::Location& loc,
193 MessageTemplate::Template message,
194 ParseErrorType type, const char* arg = nullptr) {
195 if (!is_valid_expression()) return;
196 invalid_productions_ |= ExpressionProduction;
197 expression_error_.location = loc;
198 expression_error_.message = message;
199 expression_error_.arg = arg;
200 expression_error_.type = type;
201 }
202
203 void RecordFormalParameterInitializerError(const Scanner::Location& loc,
204 MessageTemplate::Template message,
205 const char* arg = nullptr) {
206 if (!is_valid_formal_parameter_initializer()) return;
207 invalid_productions_ |= FormalParameterInitializerProduction;
208 formal_parameter_initializer_error_.location = loc;
209 formal_parameter_initializer_error_.message = message;
210 formal_parameter_initializer_error_.arg = arg;
211 }
212
213 void RecordBindingPatternError(const Scanner::Location& loc,
214 MessageTemplate::Template message,
215 const char* arg = nullptr) {
216 if (!is_valid_binding_pattern()) return;
217 invalid_productions_ |= BindingPatternProduction;
218 binding_pattern_error_.location = loc;
219 binding_pattern_error_.message = message;
220 binding_pattern_error_.arg = arg;
221 }
222
223 void RecordAssignmentPatternError(const Scanner::Location& loc,
224 MessageTemplate::Template message,
225 const char* arg = nullptr) {
226 if (!is_valid_assignment_pattern()) return;
227 invalid_productions_ |= AssignmentPatternProduction;
228 assignment_pattern_error_.location = loc;
229 assignment_pattern_error_.message = message;
230 assignment_pattern_error_.arg = arg;
231 }
232
233 void RecordPatternError(const Scanner::Location& loc,
234 MessageTemplate::Template message,
235 const char* arg = nullptr) {
236 RecordBindingPatternError(loc, message, arg);
237 RecordAssignmentPatternError(loc, message, arg);
238 }
239
240 void RecordArrowFormalParametersError(const Scanner::Location& loc,
241 MessageTemplate::Template message,
242 const char* arg = nullptr) {
243 if (!is_valid_arrow_formal_parameters()) return;
244 invalid_productions_ |= ArrowFormalParametersProduction;
245 arrow_formal_parameters_error_.location = loc;
246 arrow_formal_parameters_error_.message = message;
247 arrow_formal_parameters_error_.arg = arg;
248 }
249
Ben Murdochc5610432016-08-08 18:44:38 +0100250 void RecordAsyncArrowFormalParametersError(const Scanner::Location& loc,
251 MessageTemplate::Template message,
252 const char* arg = nullptr) {
253 if (!is_valid_async_arrow_formal_parameters()) return;
254 invalid_productions_ |= AsyncArrowFormalParametersProduction;
255 async_arrow_formal_parameters_error_.location = loc;
256 async_arrow_formal_parameters_error_.message = message;
257 async_arrow_formal_parameters_error_.arg = arg;
258 }
259
260 void RecordAsyncBindingPatternError(const Scanner::Location& loc,
261 MessageTemplate::Template message,
262 const char* arg = nullptr) {
263 if (!is_valid_async_binding_pattern()) return;
264 invalid_productions_ |= AsyncBindingPatternProduction;
265 async_binding_pattern_error_.location = loc;
266 async_binding_pattern_error_.message = message;
267 async_binding_pattern_error_.arg = arg;
268 }
269
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000270 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
271 if (!is_valid_formal_parameter_list_without_duplicates()) return;
272 invalid_productions_ |= DistinctFormalParametersProduction;
273 duplicate_formal_parameter_error_.location = loc;
274 duplicate_formal_parameter_error_.message = MessageTemplate::kParamDupe;
275 duplicate_formal_parameter_error_.arg = nullptr;
276 }
277
278 // Record a binding that would be invalid in strict mode. Confusingly this
279 // is not the same as StrictFormalParameterList, which simply forbids
280 // duplicate bindings.
281 void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
282 MessageTemplate::Template message,
283 const char* arg = nullptr) {
284 if (!is_valid_strict_mode_formal_parameters()) return;
285 invalid_productions_ |= StrictModeFormalParametersProduction;
286 strict_mode_formal_parameter_error_.location = loc;
287 strict_mode_formal_parameter_error_.message = message;
288 strict_mode_formal_parameter_error_.arg = arg;
289 }
290
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291 void RecordLetPatternError(const Scanner::Location& loc,
292 MessageTemplate::Template message,
293 const char* arg = nullptr) {
294 if (!is_valid_let_pattern()) return;
295 invalid_productions_ |= LetPatternProduction;
296 let_pattern_error_.location = loc;
297 let_pattern_error_.message = message;
298 let_pattern_error_.arg = arg;
299 }
300
301 void RecordCoverInitializedNameError(const Scanner::Location& loc,
302 MessageTemplate::Template message,
303 const char* arg = nullptr) {
304 if (has_cover_initialized_name()) return;
305 invalid_productions_ |= CoverInitializedNameProduction;
306 cover_initialized_name_error_.location = loc;
307 cover_initialized_name_error_.message = message;
308 cover_initialized_name_error_.arg = arg;
309 }
310
Ben Murdochc5610432016-08-08 18:44:38 +0100311 void RecordTailCallExpressionError(const Scanner::Location& loc,
312 MessageTemplate::Template message,
313 const char* arg = nullptr) {
314 if (has_tail_call_expression()) return;
315 invalid_productions_ |= TailCallExpressionProduction;
316 tail_call_expression_error_.location = loc;
317 tail_call_expression_error_.message = message;
318 tail_call_expression_error_.arg = arg;
319 }
320
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321 void ForgiveCoverInitializedNameError() {
322 invalid_productions_ &= ~CoverInitializedNameProduction;
323 cover_initialized_name_error_ = Error();
324 }
325
326 void ForgiveAssignmentPatternError() {
327 invalid_productions_ &= ~AssignmentPatternProduction;
328 assignment_pattern_error_ = Error();
329 }
330
Ben Murdoch097c5b22016-05-18 11:27:45 +0100331 void Accumulate(ExpressionClassifier* inner,
332 unsigned productions = StandardProductions,
333 bool merge_non_patterns = true) {
334 if (merge_non_patterns) MergeNonPatterns(inner);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000335 // Propagate errors from inner, but don't overwrite already recorded
336 // errors.
337 unsigned non_arrow_inner_invalid_productions =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100338 inner->invalid_productions_ & ~ArrowFormalParametersProduction;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000339 if (non_arrow_inner_invalid_productions == 0) return;
340 unsigned non_arrow_productions =
341 productions & ~ArrowFormalParametersProduction;
342 unsigned errors =
343 non_arrow_productions & non_arrow_inner_invalid_productions;
344 errors &= ~invalid_productions_;
345 if (errors != 0) {
346 invalid_productions_ |= errors;
347 if (errors & ExpressionProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100348 expression_error_ = inner->expression_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000349 if (errors & FormalParameterInitializerProduction)
350 formal_parameter_initializer_error_ =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100351 inner->formal_parameter_initializer_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000352 if (errors & BindingPatternProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100353 binding_pattern_error_ = inner->binding_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000354 if (errors & AssignmentPatternProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100355 assignment_pattern_error_ = inner->assignment_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000356 if (errors & DistinctFormalParametersProduction)
357 duplicate_formal_parameter_error_ =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100358 inner->duplicate_formal_parameter_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 if (errors & StrictModeFormalParametersProduction)
360 strict_mode_formal_parameter_error_ =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100361 inner->strict_mode_formal_parameter_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000362 if (errors & LetPatternProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100363 let_pattern_error_ = inner->let_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 if (errors & CoverInitializedNameProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100365 cover_initialized_name_error_ = inner->cover_initialized_name_error_;
Ben Murdochc5610432016-08-08 18:44:38 +0100366 if (errors & TailCallExpressionProduction)
367 tail_call_expression_error_ = inner->tail_call_expression_error_;
368 if (errors & AsyncArrowFormalParametersProduction)
369 async_arrow_formal_parameters_error_ =
370 inner->async_arrow_formal_parameters_error_;
371 if (errors & AsyncBindingPatternProduction)
372 async_binding_pattern_error_ = inner->async_binding_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373 }
374
375 // As an exception to the above, the result continues to be a valid arrow
376 // formal parameters if the inner expression is a valid binding pattern.
377 if (productions & ArrowFormalParametersProduction &&
378 is_valid_arrow_formal_parameters()) {
379 // Also copy function properties if expecting an arrow function
380 // parameter.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100381 function_properties_ |= inner->function_properties_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382
Ben Murdoch097c5b22016-05-18 11:27:45 +0100383 if (!inner->is_valid_binding_pattern()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000384 invalid_productions_ |= ArrowFormalParametersProduction;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100385 arrow_formal_parameters_error_ = inner->binding_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000386 }
387 }
388 }
389
Ben Murdoch097c5b22016-05-18 11:27:45 +0100390 V8_INLINE int GetNonPatternBegin() const { return non_pattern_begin_; }
391
392 V8_INLINE void Discard() {
393 DCHECK_LE(non_pattern_begin_, non_patterns_to_rewrite_->length());
394 non_patterns_to_rewrite_->Rewind(non_pattern_begin_);
395 }
396
397 V8_INLINE void MergeNonPatterns(ExpressionClassifier* inner) {
398 DCHECK_LE(non_pattern_begin_, inner->non_pattern_begin_);
399 inner->non_pattern_begin_ = inner->non_patterns_to_rewrite_->length();
400 }
401
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402 private:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100403 Zone* zone_;
404 ZoneList<typename Traits::Type::Expression>* non_patterns_to_rewrite_;
405 int non_pattern_begin_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406 unsigned invalid_productions_;
407 unsigned function_properties_;
Ben Murdochc5610432016-08-08 18:44:38 +0100408 // TODO(ishell): consider using Zone[Hash]Map<TargetProduction, Error>
409 // here to consume less stack space during parsing.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000410 Error expression_error_;
411 Error formal_parameter_initializer_error_;
412 Error binding_pattern_error_;
413 Error assignment_pattern_error_;
414 Error arrow_formal_parameters_error_;
415 Error duplicate_formal_parameter_error_;
416 Error strict_mode_formal_parameter_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000417 Error let_pattern_error_;
418 Error cover_initialized_name_error_;
Ben Murdochc5610432016-08-08 18:44:38 +0100419 Error tail_call_expression_error_;
420 Error async_arrow_formal_parameters_error_;
421 Error async_binding_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000422 DuplicateFinder* duplicate_finder_;
423};
424
Ben Murdoch097c5b22016-05-18 11:27:45 +0100425
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000426} // namespace internal
427} // namespace v8
428
429#endif // V8_PARSING_EXPRESSION_CLASSIFIER_H