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/zone/zone-containers.h" 11 12 namespace v8 { 13 namespace internal { 14 15 class DuplicateFinder; 16 17 #define ERROR_CODES(T) \ 18 T(ExpressionProduction, 0) \ 19 T(FormalParameterInitializerProduction, 1) \ 20 T(BindingPatternProduction, 2) \ 21 T(AssignmentPatternProduction, 3) \ 22 T(DistinctFormalParametersProduction, 4) \ 23 T(StrictModeFormalParametersProduction, 5) \ 24 T(ArrowFormalParametersProduction, 6) \ 25 T(LetPatternProduction, 7) \ 26 T(AsyncArrowFormalParametersProduction, 8) 27 28 // Expression classifiers serve two purposes: 29 // 30 // 1) They keep track of error messages that are pending (and other 31 // related information), waiting for the parser to decide whether 32 // the parsed expression is a pattern or not. 33 // 2) They keep track of expressions that may need to be rewritten, if 34 // the parser decides that they are not patterns. (A different 35 // mechanism implements the rewriting of patterns.) 36 // 37 // Expression classifiers are used by the parser in a stack fashion. 38 // Each new classifier is pushed on top of the stack. This happens 39 // automatically by the class's constructor. While on top of the 40 // stack, the classifier records pending error messages and tracks the 41 // pending non-patterns of the expression that is being parsed. 42 // 43 // At the end of its life, a classifier is either "accumulated" to the 44 // one that is below it on the stack, or is "discarded". The former 45 // is achieved by calling the method Accumulate. The latter is 46 // achieved automatically by the destructor, but it can happen earlier 47 // by calling the method Discard. Both actions result in removing the 48 // classifier from the parser's stack. 49 50 template <typename Types> 51 class ExpressionClassifier { 52 public: 53 enum ErrorKind : unsigned { 54 #define DEFINE_ERROR_KIND(NAME, CODE) k##NAME = CODE, 55 ERROR_CODES(DEFINE_ERROR_KIND) 56 #undef DEFINE_ERROR_KIND 57 kUnusedError = 15 // Larger than error codes; should fit in 4 bits 58 }; 59 60 struct Error { ErrorError61 V8_INLINE Error() 62 : location(Scanner::Location::invalid()), 63 message(MessageTemplate::kNone), 64 kind(kUnusedError), 65 arg(nullptr) {} 66 V8_INLINE explicit Error(Scanner::Location loc, 67 MessageTemplate::Template msg, ErrorKind k, 68 const char* a = nullptr) locationError69 : location(loc), message(msg), kind(k), arg(a) {} 70 71 Scanner::Location location; 72 MessageTemplate::Template message : 28; 73 unsigned kind : 4; 74 const char* arg; 75 }; 76 77 // clang-format off 78 enum TargetProduction : unsigned { 79 #define DEFINE_PRODUCTION(NAME, CODE) NAME = 1 << CODE, 80 ERROR_CODES(DEFINE_PRODUCTION) 81 #undef DEFINE_PRODUCTION 82 83 #define DEFINE_ALL_PRODUCTIONS(NAME, CODE) NAME | 84 AllProductions = ERROR_CODES(DEFINE_ALL_PRODUCTIONS) /* | */ 0 85 #undef DEFINE_ALL_PRODUCTIONS 86 }; 87 // clang-format on 88 89 explicit ExpressionClassifier(typename Types::Base* base, 90 DuplicateFinder* duplicate_finder = nullptr) base_(base)91 : base_(base), 92 previous_(base->classifier_), 93 zone_(base->impl()->zone()), 94 reported_errors_(base->impl()->GetReportedErrorList()), 95 duplicate_finder_(duplicate_finder), 96 invalid_productions_(0), 97 is_non_simple_parameter_list_(0) { 98 base->classifier_ = this; 99 reported_errors_begin_ = reported_errors_end_ = reported_errors_->size(); 100 } 101 ~ExpressionClassifier()102 V8_INLINE ~ExpressionClassifier() { 103 Discard(); 104 if (base_->classifier_ == this) base_->classifier_ = previous_; 105 } 106 is_valid(unsigned productions)107 V8_INLINE bool is_valid(unsigned productions) const { 108 return (invalid_productions_ & productions) == 0; 109 } 110 duplicate_finder()111 V8_INLINE DuplicateFinder* duplicate_finder() const { 112 return duplicate_finder_; 113 } 114 is_valid_expression()115 V8_INLINE bool is_valid_expression() const { 116 return is_valid(ExpressionProduction); 117 } 118 is_valid_formal_parameter_initializer()119 V8_INLINE bool is_valid_formal_parameter_initializer() const { 120 return is_valid(FormalParameterInitializerProduction); 121 } 122 is_valid_binding_pattern()123 V8_INLINE bool is_valid_binding_pattern() const { 124 return is_valid(BindingPatternProduction); 125 } 126 is_valid_assignment_pattern()127 V8_INLINE bool is_valid_assignment_pattern() const { 128 return is_valid(AssignmentPatternProduction); 129 } 130 is_valid_arrow_formal_parameters()131 V8_INLINE bool is_valid_arrow_formal_parameters() const { 132 return is_valid(ArrowFormalParametersProduction); 133 } 134 is_valid_formal_parameter_list_without_duplicates()135 V8_INLINE bool is_valid_formal_parameter_list_without_duplicates() const { 136 return is_valid(DistinctFormalParametersProduction); 137 } 138 139 // Note: callers should also check 140 // is_valid_formal_parameter_list_without_duplicates(). is_valid_strict_mode_formal_parameters()141 V8_INLINE bool is_valid_strict_mode_formal_parameters() const { 142 return is_valid(StrictModeFormalParametersProduction); 143 } 144 is_valid_let_pattern()145 V8_INLINE bool is_valid_let_pattern() const { 146 return is_valid(LetPatternProduction); 147 } 148 is_valid_async_arrow_formal_parameters()149 bool is_valid_async_arrow_formal_parameters() const { 150 return is_valid(AsyncArrowFormalParametersProduction); 151 } 152 expression_error()153 V8_INLINE const Error& expression_error() const { 154 return reported_error(kExpressionProduction); 155 } 156 formal_parameter_initializer_error()157 V8_INLINE const Error& formal_parameter_initializer_error() const { 158 return reported_error(kFormalParameterInitializerProduction); 159 } 160 binding_pattern_error()161 V8_INLINE const Error& binding_pattern_error() const { 162 return reported_error(kBindingPatternProduction); 163 } 164 assignment_pattern_error()165 V8_INLINE const Error& assignment_pattern_error() const { 166 return reported_error(kAssignmentPatternProduction); 167 } 168 arrow_formal_parameters_error()169 V8_INLINE const Error& arrow_formal_parameters_error() const { 170 return reported_error(kArrowFormalParametersProduction); 171 } 172 duplicate_formal_parameter_error()173 V8_INLINE const Error& duplicate_formal_parameter_error() const { 174 return reported_error(kDistinctFormalParametersProduction); 175 } 176 strict_mode_formal_parameter_error()177 V8_INLINE const Error& strict_mode_formal_parameter_error() const { 178 return reported_error(kStrictModeFormalParametersProduction); 179 } 180 let_pattern_error()181 V8_INLINE const Error& let_pattern_error() const { 182 return reported_error(kLetPatternProduction); 183 } 184 async_arrow_formal_parameters_error()185 V8_INLINE const Error& async_arrow_formal_parameters_error() const { 186 return reported_error(kAsyncArrowFormalParametersProduction); 187 } 188 is_simple_parameter_list()189 V8_INLINE bool is_simple_parameter_list() const { 190 return !is_non_simple_parameter_list_; 191 } 192 RecordNonSimpleParameter()193 V8_INLINE void RecordNonSimpleParameter() { 194 is_non_simple_parameter_list_ = 1; 195 } 196 197 void RecordExpressionError(const Scanner::Location& loc, 198 MessageTemplate::Template message, 199 const char* arg = nullptr) { 200 if (!is_valid_expression()) return; 201 invalid_productions_ |= ExpressionProduction; 202 Add(Error(loc, message, kExpressionProduction, arg)); 203 } 204 205 void RecordFormalParameterInitializerError(const Scanner::Location& loc, 206 MessageTemplate::Template message, 207 const char* arg = nullptr) { 208 if (!is_valid_formal_parameter_initializer()) return; 209 invalid_productions_ |= FormalParameterInitializerProduction; 210 Add(Error(loc, message, kFormalParameterInitializerProduction, arg)); 211 } 212 213 void RecordBindingPatternError(const Scanner::Location& loc, 214 MessageTemplate::Template message, 215 const char* arg = nullptr) { 216 if (!is_valid_binding_pattern()) return; 217 invalid_productions_ |= BindingPatternProduction; 218 Add(Error(loc, message, kBindingPatternProduction, arg)); 219 } 220 221 void RecordAssignmentPatternError(const Scanner::Location& loc, 222 MessageTemplate::Template message, 223 const char* arg = nullptr) { 224 if (!is_valid_assignment_pattern()) return; 225 invalid_productions_ |= AssignmentPatternProduction; 226 Add(Error(loc, message, kAssignmentPatternProduction, arg)); 227 } 228 229 void RecordPatternError(const Scanner::Location& loc, 230 MessageTemplate::Template message, 231 const char* arg = nullptr) { 232 RecordBindingPatternError(loc, message, arg); 233 RecordAssignmentPatternError(loc, message, arg); 234 } 235 236 void RecordArrowFormalParametersError(const Scanner::Location& loc, 237 MessageTemplate::Template message, 238 const char* arg = nullptr) { 239 if (!is_valid_arrow_formal_parameters()) return; 240 invalid_productions_ |= ArrowFormalParametersProduction; 241 Add(Error(loc, message, kArrowFormalParametersProduction, arg)); 242 } 243 244 void RecordAsyncArrowFormalParametersError(const Scanner::Location& loc, 245 MessageTemplate::Template message, 246 const char* arg = nullptr) { 247 if (!is_valid_async_arrow_formal_parameters()) return; 248 invalid_productions_ |= AsyncArrowFormalParametersProduction; 249 Add(Error(loc, message, kAsyncArrowFormalParametersProduction, arg)); 250 } 251 RecordDuplicateFormalParameterError(const Scanner::Location & loc)252 void RecordDuplicateFormalParameterError(const Scanner::Location& loc) { 253 if (!is_valid_formal_parameter_list_without_duplicates()) return; 254 invalid_productions_ |= DistinctFormalParametersProduction; 255 Add(Error(loc, MessageTemplate::kParamDupe, 256 kDistinctFormalParametersProduction)); 257 } 258 259 // Record a binding that would be invalid in strict mode. Confusingly this 260 // is not the same as StrictFormalParameterList, which simply forbids 261 // duplicate bindings. 262 void RecordStrictModeFormalParameterError(const Scanner::Location& loc, 263 MessageTemplate::Template message, 264 const char* arg = nullptr) { 265 if (!is_valid_strict_mode_formal_parameters()) return; 266 invalid_productions_ |= StrictModeFormalParametersProduction; 267 Add(Error(loc, message, kStrictModeFormalParametersProduction, arg)); 268 } 269 270 void RecordLetPatternError(const Scanner::Location& loc, 271 MessageTemplate::Template message, 272 const char* arg = nullptr) { 273 if (!is_valid_let_pattern()) return; 274 invalid_productions_ |= LetPatternProduction; 275 Add(Error(loc, message, kLetPatternProduction, arg)); 276 } 277 Accumulate(ExpressionClassifier * inner,unsigned productions)278 void Accumulate(ExpressionClassifier* inner, unsigned productions) { 279 DCHECK_EQ(inner->reported_errors_, reported_errors_); 280 DCHECK_EQ(inner->reported_errors_begin_, reported_errors_end_); 281 DCHECK_EQ(inner->reported_errors_end_, reported_errors_->size()); 282 // Propagate errors from inner, but don't overwrite already recorded 283 // errors. 284 unsigned non_arrow_inner_invalid_productions = 285 inner->invalid_productions_ & ~ArrowFormalParametersProduction; 286 if (non_arrow_inner_invalid_productions) { 287 unsigned errors = non_arrow_inner_invalid_productions & productions & 288 ~invalid_productions_; 289 // The result will continue to be a valid arrow formal parameters if the 290 // inner expression is a valid binding pattern. 291 bool copy_BP_to_AFP = false; 292 if (productions & ArrowFormalParametersProduction && 293 is_valid_arrow_formal_parameters()) { 294 // Also whether we've seen any non-simple parameters 295 // if expecting an arrow function parameter. 296 is_non_simple_parameter_list_ |= inner->is_non_simple_parameter_list_; 297 if (!inner->is_valid_binding_pattern()) { 298 copy_BP_to_AFP = true; 299 invalid_productions_ |= ArrowFormalParametersProduction; 300 } 301 } 302 // Traverse the list of errors reported by the inner classifier 303 // to copy what's necessary. 304 if (errors != 0 || copy_BP_to_AFP) { 305 invalid_productions_ |= errors; 306 int binding_pattern_index = inner->reported_errors_end_; 307 for (int i = inner->reported_errors_begin_; 308 i < inner->reported_errors_end_; i++) { 309 int k = reported_errors_->at(i).kind; 310 if (errors & (1 << k)) Copy(i); 311 // Check if it's a BP error that has to be copied to an AFP error. 312 if (k == kBindingPatternProduction && copy_BP_to_AFP) { 313 if (reported_errors_end_ <= i) { 314 // If the BP error itself has not already been copied, 315 // copy it now and change it to an AFP error. 316 Copy(i); 317 reported_errors_->at(reported_errors_end_-1).kind = 318 kArrowFormalParametersProduction; 319 } else { 320 // Otherwise, if the BP error was already copied, keep its 321 // position and wait until the end of the traversal. 322 DCHECK_EQ(reported_errors_end_, i+1); 323 binding_pattern_index = i; 324 } 325 } 326 } 327 // Do we still have to copy the BP error to an AFP error? 328 if (binding_pattern_index < inner->reported_errors_end_) { 329 // If there's still unused space in the list of the inner 330 // classifier, copy it there, otherwise add it to the end 331 // of the list. 332 if (reported_errors_end_ < inner->reported_errors_end_) 333 Copy(binding_pattern_index); 334 else 335 Add(reported_errors_->at(binding_pattern_index)); 336 reported_errors_->at(reported_errors_end_-1).kind = 337 kArrowFormalParametersProduction; 338 } 339 } 340 } 341 reported_errors_->resize(reported_errors_end_); 342 inner->reported_errors_begin_ = inner->reported_errors_end_ = 343 reported_errors_end_; 344 } 345 Discard()346 V8_INLINE void Discard() { 347 if (reported_errors_end_ == reported_errors_->size()) { 348 reported_errors_->resize(reported_errors_begin_); 349 reported_errors_end_ = reported_errors_begin_; 350 } 351 DCHECK_EQ(reported_errors_begin_, reported_errors_end_); 352 } 353 previous()354 ExpressionClassifier* previous() const { return previous_; } 355 356 private: reported_error(ErrorKind kind)357 V8_INLINE const Error& reported_error(ErrorKind kind) const { 358 if (invalid_productions_ & (1 << kind)) { 359 for (int i = reported_errors_begin_; i < reported_errors_end_; i++) { 360 if (reported_errors_->at(i).kind == kind) 361 return reported_errors_->at(i); 362 } 363 UNREACHABLE(); 364 } 365 // We should only be looking for an error when we know that one has 366 // been reported. But we're not... So this is to make sure we have 367 // the same behaviour. 368 UNREACHABLE(); 369 370 // Make MSVC happy by returning an error from this inaccessible path. 371 static Error none; 372 return none; 373 } 374 375 // Adds e to the end of the list of reported errors for this classifier. 376 // It is expected that this classifier is the last one in the stack. Add(const Error & e)377 V8_INLINE void Add(const Error& e) { 378 DCHECK_EQ(reported_errors_end_, reported_errors_->size()); 379 reported_errors_->push_back(e); 380 reported_errors_end_++; 381 } 382 383 // Copies the error at position i of the list of reported errors, so that 384 // it becomes the last error reported for this classifier. Position i 385 // could be either after the existing errors of this classifier (i.e., 386 // in an inner classifier) or it could be an existing error (in case a 387 // copy is needed). Copy(int i)388 V8_INLINE void Copy(int i) { 389 DCHECK_LT(i, reported_errors_->size()); 390 if (reported_errors_end_ != i) 391 reported_errors_->at(reported_errors_end_) = reported_errors_->at(i); 392 reported_errors_end_++; 393 } 394 395 typename Types::Base* base_; 396 ExpressionClassifier* previous_; 397 Zone* zone_; 398 ZoneVector<Error>* reported_errors_; 399 DuplicateFinder* duplicate_finder_; 400 unsigned invalid_productions_ : 15; 401 unsigned is_non_simple_parameter_list_ : 1; 402 // The uint16_t for reported_errors_begin_ and reported_errors_end_ will 403 // not be enough in the case of a long series of expressions using nested 404 // classifiers, e.g., a long sequence of assignments, as in: 405 // literals with spreads, as in: 406 // var N=65536; eval("var x;" + "x=".repeat(N) + "42"); 407 // This should not be a problem, as such things currently fail with a 408 // stack overflow while parsing. 409 uint16_t reported_errors_begin_; 410 uint16_t reported_errors_end_; 411 412 DISALLOW_COPY_AND_ASSIGN(ExpressionClassifier); 413 }; 414 415 416 #undef ERROR_CODES 417 418 419 } // namespace internal 420 } // namespace v8 421 422 #endif // V8_PARSING_EXPRESSION_CLASSIFIER_H_ 423