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