blob: 71fa3d3e89b16018137605ed014740e5027beca4 [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 Murdoch4a90d5f2016-03-22 12:00:34 +000042
43 ExpressionProductions =
44 (ExpressionProduction | FormalParameterInitializerProduction),
45 PatternProductions = (BindingPatternProduction |
46 AssignmentPatternProduction | LetPatternProduction),
47 FormalParametersProductions = (DistinctFormalParametersProduction |
Ben Murdochda12d292016-06-02 14:46:10 +010048 StrictModeFormalParametersProduction),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 StandardProductions = ExpressionProductions | PatternProductions,
50 AllProductions =
51 (StandardProductions | FormalParametersProductions |
52 ArrowFormalParametersProduction | CoverInitializedNameProduction)
53 };
54
55 enum FunctionProperties { NonSimpleParameter = 1 << 0 };
56
Ben Murdoch097c5b22016-05-18 11:27:45 +010057 explicit ExpressionClassifier(const Traits* t)
58 : zone_(t->zone()),
59 non_patterns_to_rewrite_(t->GetNonPatternList()),
60 invalid_productions_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061 function_properties_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +010062 duplicate_finder_(nullptr) {
63 non_pattern_begin_ = non_patterns_to_rewrite_->length();
64 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065
Ben Murdoch097c5b22016-05-18 11:27:45 +010066 ExpressionClassifier(const Traits* t, DuplicateFinder* duplicate_finder)
67 : zone_(t->zone()),
68 non_patterns_to_rewrite_(t->GetNonPatternList()),
69 invalid_productions_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 function_properties_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +010071 duplicate_finder_(duplicate_finder) {
72 non_pattern_begin_ = non_patterns_to_rewrite_->length();
73 }
74
75 ~ExpressionClassifier() { Discard(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076
77 bool is_valid(unsigned productions) const {
78 return (invalid_productions_ & productions) == 0;
79 }
80
81 DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
82
83 bool is_valid_expression() const { return is_valid(ExpressionProduction); }
84
85 bool is_valid_formal_parameter_initializer() const {
86 return is_valid(FormalParameterInitializerProduction);
87 }
88
89 bool is_valid_binding_pattern() const {
90 return is_valid(BindingPatternProduction);
91 }
92
93 bool is_valid_assignment_pattern() const {
94 return is_valid(AssignmentPatternProduction);
95 }
96
97 bool is_valid_arrow_formal_parameters() const {
98 return is_valid(ArrowFormalParametersProduction);
99 }
100
101 bool is_valid_formal_parameter_list_without_duplicates() const {
102 return is_valid(DistinctFormalParametersProduction);
103 }
104
105 // Note: callers should also check
106 // is_valid_formal_parameter_list_without_duplicates().
107 bool is_valid_strict_mode_formal_parameters() const {
108 return is_valid(StrictModeFormalParametersProduction);
109 }
110
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000111 bool is_valid_let_pattern() const { return is_valid(LetPatternProduction); }
112
113 const Error& expression_error() const { return expression_error_; }
114
115 const Error& formal_parameter_initializer_error() const {
116 return formal_parameter_initializer_error_;
117 }
118
119 const Error& binding_pattern_error() const { return binding_pattern_error_; }
120
121 const Error& assignment_pattern_error() const {
122 return assignment_pattern_error_;
123 }
124
125 const Error& arrow_formal_parameters_error() const {
126 return arrow_formal_parameters_error_;
127 }
128
129 const Error& duplicate_formal_parameter_error() const {
130 return duplicate_formal_parameter_error_;
131 }
132
133 const Error& strict_mode_formal_parameter_error() const {
134 return strict_mode_formal_parameter_error_;
135 }
136
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000137 const Error& let_pattern_error() const { return let_pattern_error_; }
138
139 bool has_cover_initialized_name() const {
140 return !is_valid(CoverInitializedNameProduction);
141 }
142 const Error& cover_initialized_name_error() const {
143 return cover_initialized_name_error_;
144 }
145
146 bool is_simple_parameter_list() const {
147 return !(function_properties_ & NonSimpleParameter);
148 }
149
150 void RecordNonSimpleParameter() {
151 function_properties_ |= NonSimpleParameter;
152 }
153
154 void RecordExpressionError(const Scanner::Location& loc,
155 MessageTemplate::Template message,
156 const char* arg = nullptr) {
157 if (!is_valid_expression()) return;
158 invalid_productions_ |= ExpressionProduction;
159 expression_error_.location = loc;
160 expression_error_.message = message;
161 expression_error_.arg = arg;
162 }
163
164 void RecordExpressionError(const Scanner::Location& loc,
165 MessageTemplate::Template message,
166 ParseErrorType type, const char* arg = nullptr) {
167 if (!is_valid_expression()) return;
168 invalid_productions_ |= ExpressionProduction;
169 expression_error_.location = loc;
170 expression_error_.message = message;
171 expression_error_.arg = arg;
172 expression_error_.type = type;
173 }
174
175 void RecordFormalParameterInitializerError(const Scanner::Location& loc,
176 MessageTemplate::Template message,
177 const char* arg = nullptr) {
178 if (!is_valid_formal_parameter_initializer()) return;
179 invalid_productions_ |= FormalParameterInitializerProduction;
180 formal_parameter_initializer_error_.location = loc;
181 formal_parameter_initializer_error_.message = message;
182 formal_parameter_initializer_error_.arg = arg;
183 }
184
185 void RecordBindingPatternError(const Scanner::Location& loc,
186 MessageTemplate::Template message,
187 const char* arg = nullptr) {
188 if (!is_valid_binding_pattern()) return;
189 invalid_productions_ |= BindingPatternProduction;
190 binding_pattern_error_.location = loc;
191 binding_pattern_error_.message = message;
192 binding_pattern_error_.arg = arg;
193 }
194
195 void RecordAssignmentPatternError(const Scanner::Location& loc,
196 MessageTemplate::Template message,
197 const char* arg = nullptr) {
198 if (!is_valid_assignment_pattern()) return;
199 invalid_productions_ |= AssignmentPatternProduction;
200 assignment_pattern_error_.location = loc;
201 assignment_pattern_error_.message = message;
202 assignment_pattern_error_.arg = arg;
203 }
204
205 void RecordPatternError(const Scanner::Location& loc,
206 MessageTemplate::Template message,
207 const char* arg = nullptr) {
208 RecordBindingPatternError(loc, message, arg);
209 RecordAssignmentPatternError(loc, message, arg);
210 }
211
212 void RecordArrowFormalParametersError(const Scanner::Location& loc,
213 MessageTemplate::Template message,
214 const char* arg = nullptr) {
215 if (!is_valid_arrow_formal_parameters()) return;
216 invalid_productions_ |= ArrowFormalParametersProduction;
217 arrow_formal_parameters_error_.location = loc;
218 arrow_formal_parameters_error_.message = message;
219 arrow_formal_parameters_error_.arg = arg;
220 }
221
222 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
223 if (!is_valid_formal_parameter_list_without_duplicates()) return;
224 invalid_productions_ |= DistinctFormalParametersProduction;
225 duplicate_formal_parameter_error_.location = loc;
226 duplicate_formal_parameter_error_.message = MessageTemplate::kParamDupe;
227 duplicate_formal_parameter_error_.arg = nullptr;
228 }
229
230 // Record a binding that would be invalid in strict mode. Confusingly this
231 // is not the same as StrictFormalParameterList, which simply forbids
232 // duplicate bindings.
233 void RecordStrictModeFormalParameterError(const Scanner::Location& loc,
234 MessageTemplate::Template message,
235 const char* arg = nullptr) {
236 if (!is_valid_strict_mode_formal_parameters()) return;
237 invalid_productions_ |= StrictModeFormalParametersProduction;
238 strict_mode_formal_parameter_error_.location = loc;
239 strict_mode_formal_parameter_error_.message = message;
240 strict_mode_formal_parameter_error_.arg = arg;
241 }
242
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000243 void RecordLetPatternError(const Scanner::Location& loc,
244 MessageTemplate::Template message,
245 const char* arg = nullptr) {
246 if (!is_valid_let_pattern()) return;
247 invalid_productions_ |= LetPatternProduction;
248 let_pattern_error_.location = loc;
249 let_pattern_error_.message = message;
250 let_pattern_error_.arg = arg;
251 }
252
253 void RecordCoverInitializedNameError(const Scanner::Location& loc,
254 MessageTemplate::Template message,
255 const char* arg = nullptr) {
256 if (has_cover_initialized_name()) return;
257 invalid_productions_ |= CoverInitializedNameProduction;
258 cover_initialized_name_error_.location = loc;
259 cover_initialized_name_error_.message = message;
260 cover_initialized_name_error_.arg = arg;
261 }
262
263 void ForgiveCoverInitializedNameError() {
264 invalid_productions_ &= ~CoverInitializedNameProduction;
265 cover_initialized_name_error_ = Error();
266 }
267
268 void ForgiveAssignmentPatternError() {
269 invalid_productions_ &= ~AssignmentPatternProduction;
270 assignment_pattern_error_ = Error();
271 }
272
Ben Murdoch097c5b22016-05-18 11:27:45 +0100273 void Accumulate(ExpressionClassifier* inner,
274 unsigned productions = StandardProductions,
275 bool merge_non_patterns = true) {
276 if (merge_non_patterns) MergeNonPatterns(inner);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277 // Propagate errors from inner, but don't overwrite already recorded
278 // errors.
279 unsigned non_arrow_inner_invalid_productions =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100280 inner->invalid_productions_ & ~ArrowFormalParametersProduction;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 if (non_arrow_inner_invalid_productions == 0) return;
282 unsigned non_arrow_productions =
283 productions & ~ArrowFormalParametersProduction;
284 unsigned errors =
285 non_arrow_productions & non_arrow_inner_invalid_productions;
286 errors &= ~invalid_productions_;
287 if (errors != 0) {
288 invalid_productions_ |= errors;
289 if (errors & ExpressionProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100290 expression_error_ = inner->expression_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291 if (errors & FormalParameterInitializerProduction)
292 formal_parameter_initializer_error_ =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100293 inner->formal_parameter_initializer_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000294 if (errors & BindingPatternProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100295 binding_pattern_error_ = inner->binding_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000296 if (errors & AssignmentPatternProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100297 assignment_pattern_error_ = inner->assignment_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000298 if (errors & DistinctFormalParametersProduction)
299 duplicate_formal_parameter_error_ =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100300 inner->duplicate_formal_parameter_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 if (errors & StrictModeFormalParametersProduction)
302 strict_mode_formal_parameter_error_ =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100303 inner->strict_mode_formal_parameter_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304 if (errors & LetPatternProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100305 let_pattern_error_ = inner->let_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306 if (errors & CoverInitializedNameProduction)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100307 cover_initialized_name_error_ = inner->cover_initialized_name_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000308 }
309
310 // As an exception to the above, the result continues to be a valid arrow
311 // formal parameters if the inner expression is a valid binding pattern.
312 if (productions & ArrowFormalParametersProduction &&
313 is_valid_arrow_formal_parameters()) {
314 // Also copy function properties if expecting an arrow function
315 // parameter.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100316 function_properties_ |= inner->function_properties_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317
Ben Murdoch097c5b22016-05-18 11:27:45 +0100318 if (!inner->is_valid_binding_pattern()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000319 invalid_productions_ |= ArrowFormalParametersProduction;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100320 arrow_formal_parameters_error_ = inner->binding_pattern_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321 }
322 }
323 }
324
Ben Murdoch097c5b22016-05-18 11:27:45 +0100325 V8_INLINE int GetNonPatternBegin() const { return non_pattern_begin_; }
326
327 V8_INLINE void Discard() {
328 DCHECK_LE(non_pattern_begin_, non_patterns_to_rewrite_->length());
329 non_patterns_to_rewrite_->Rewind(non_pattern_begin_);
330 }
331
332 V8_INLINE void MergeNonPatterns(ExpressionClassifier* inner) {
333 DCHECK_LE(non_pattern_begin_, inner->non_pattern_begin_);
334 inner->non_pattern_begin_ = inner->non_patterns_to_rewrite_->length();
335 }
336
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000337 private:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100338 Zone* zone_;
339 ZoneList<typename Traits::Type::Expression>* non_patterns_to_rewrite_;
340 int non_pattern_begin_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341 unsigned invalid_productions_;
342 unsigned function_properties_;
343 Error expression_error_;
344 Error formal_parameter_initializer_error_;
345 Error binding_pattern_error_;
346 Error assignment_pattern_error_;
347 Error arrow_formal_parameters_error_;
348 Error duplicate_formal_parameter_error_;
349 Error strict_mode_formal_parameter_error_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350 Error let_pattern_error_;
351 Error cover_initialized_name_error_;
352 DuplicateFinder* duplicate_finder_;
353};
354
Ben Murdoch097c5b22016-05-18 11:27:45 +0100355
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000356} // namespace internal
357} // namespace v8
358
359#endif // V8_PARSING_EXPRESSION_CLASSIFIER_H