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