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