constructor(plugin) {
        this.MIXIN = QualifierMixin
        this.config = plugin.config
        this.utils = plugin.utils
        this.i18n = plugin.i18n
        this.parser = new Parser()
        this.qualifiers = new Map()
    }
The matching process consists of the following steps: (Steps 1-4 are executed once; steps 5-6 are executed repeatedly)
  1. Parse:      Parses the input to generate an Abstract Syntax Tree (AST)
  2. Preprocess: Convert certain specific, predefined, and special meaning vocabulary (e.g. converting 'today' in 'mtime=today' to '2024-01-01')
  3. Validate:   Validates the AST for correctness
  4. Cast:       Converts operand within the AST nodes into a usable format (e.g. converting '2024-01-01' in 'mtime=2024-01-01' to a timestamp for easier matching). The result is `castResult`
  5. Query:      Retrieves file data, resulting in `queryResult`
  6. Match:      Matches `castResult` (from step 4) with `queryResult` (from step 5)

A qualifier has the following attributes:
  {string}   scope:          The query scope
  {string}   name:           A descriptive name for explanation purposes
  {string}   ancestor:       The ancestor Element in DOM. Only available when is_meta=false. Defaults to `QualifierMixin.ANCESTOR.none`
  {boolean}  is_meta:        Indicates if the qualifier scope is a metadata property
  {boolean}  need_read_file: Determines if the qualifier needs to read file content
  {number}   cost:           The performance cost associated with the `query` function. 1: Read file stats; 2: Read file content; 3: Parse file content; Plus 0.5 when the user input is a regex
  {function} preprocess:     Convert certain specific, predefined, and special meaning vocabulary from the user input. Defaults to `QualifierMixin.PREPROCESS.noop`
  {function} validate:       Checks user input and obtain `validateError`. Defaults to `QualifierMixin.VALIDATE.isStringOrRegexp`
  {function} cast:           Converts user input for easier matching and obtain `castResult`. Defaults to `QualifierMixin.CAST.toStringOrRegexp`
  {function} query:          Retrieves data from source and obtain `queryResult`
  {function} match_keyword:  Matches `castResult` with `queryResult` when the user input is a keyword. Defaults to `QualifierMixin.MATCH.compare`
  {function} match_phrase:   Matches `castResult` with `queryResult` when the user input is a phrase. Behaves the same as `match_keyword` by default
  {function} match_regexp:   Matches `castResult` with `queryResult` when the user input is a regexp. Defaults to `QualifierMixin.MATCH.regexp`