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