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_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 
12 namespace v8 {
13 namespace internal {
14 
15 
16 class ExpressionClassifier {
17  public:
18   struct Error {
ErrorError19     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 
ExpressionClassifier()58   ExpressionClassifier()
59       : invalid_productions_(0),
60         function_properties_(0),
61         duplicate_finder_(nullptr) {}
62 
ExpressionClassifier(DuplicateFinder * duplicate_finder)63   explicit ExpressionClassifier(DuplicateFinder* duplicate_finder)
64       : invalid_productions_(0),
65         function_properties_(0),
66         duplicate_finder_(duplicate_finder) {}
67 
is_valid(unsigned productions)68   bool is_valid(unsigned productions) const {
69     return (invalid_productions_ & productions) == 0;
70   }
71 
duplicate_finder()72   DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
73 
is_valid_expression()74   bool is_valid_expression() const { return is_valid(ExpressionProduction); }
75 
is_valid_formal_parameter_initializer()76   bool is_valid_formal_parameter_initializer() const {
77     return is_valid(FormalParameterInitializerProduction);
78   }
79 
is_valid_binding_pattern()80   bool is_valid_binding_pattern() const {
81     return is_valid(BindingPatternProduction);
82   }
83 
is_valid_assignment_pattern()84   bool is_valid_assignment_pattern() const {
85     return is_valid(AssignmentPatternProduction);
86   }
87 
is_valid_arrow_formal_parameters()88   bool is_valid_arrow_formal_parameters() const {
89     return is_valid(ArrowFormalParametersProduction);
90   }
91 
is_valid_formal_parameter_list_without_duplicates()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().
is_valid_strict_mode_formal_parameters()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().
is_valid_strong_mode_formal_parameters()104   bool is_valid_strong_mode_formal_parameters() const {
105     return is_valid(StrongModeFormalParametersProduction);
106   }
107 
is_valid_let_pattern()108   bool is_valid_let_pattern() const { return is_valid(LetPatternProduction); }
109 
expression_error()110   const Error& expression_error() const { return expression_error_; }
111 
formal_parameter_initializer_error()112   const Error& formal_parameter_initializer_error() const {
113     return formal_parameter_initializer_error_;
114   }
115 
binding_pattern_error()116   const Error& binding_pattern_error() const { return binding_pattern_error_; }
117 
assignment_pattern_error()118   const Error& assignment_pattern_error() const {
119     return assignment_pattern_error_;
120   }
121 
arrow_formal_parameters_error()122   const Error& arrow_formal_parameters_error() const {
123     return arrow_formal_parameters_error_;
124   }
125 
duplicate_formal_parameter_error()126   const Error& duplicate_formal_parameter_error() const {
127     return duplicate_formal_parameter_error_;
128   }
129 
strict_mode_formal_parameter_error()130   const Error& strict_mode_formal_parameter_error() const {
131     return strict_mode_formal_parameter_error_;
132   }
133 
strong_mode_formal_parameter_error()134   const Error& strong_mode_formal_parameter_error() const {
135     return strong_mode_formal_parameter_error_;
136   }
137 
let_pattern_error()138   const Error& let_pattern_error() const { return let_pattern_error_; }
139 
has_cover_initialized_name()140   bool has_cover_initialized_name() const {
141     return !is_valid(CoverInitializedNameProduction);
142   }
cover_initialized_name_error()143   const Error& cover_initialized_name_error() const {
144     return cover_initialized_name_error_;
145   }
146 
is_simple_parameter_list()147   bool is_simple_parameter_list() const {
148     return !(function_properties_ & NonSimpleParameter);
149   }
150 
RecordNonSimpleParameter()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 
RecordDuplicateFormalParameterError(const Scanner::Location & loc)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 
ForgiveCoverInitializedNameError()274   void ForgiveCoverInitializedNameError() {
275     invalid_productions_ &= ~CoverInitializedNameProduction;
276     cover_initialized_name_error_ = Error();
277   }
278 
ForgiveAssignmentPatternError()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
357