Home | History | Annotate | Download | only in parsing
      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