@ 261106.1
current
#ifndef SRC_GLOB_GLOB_PROGRAM_H_
#define SRC_GLOB_GLOB_PROGRAM_H_

#include <cstdint>
#include <memory>
#include <string>
#include <vector>

#include "glob/glob_ast.h"
#include "glob/glob_unicode.h"

namespace node::glob {

struct RxNode {
  enum class Kind : uint8_t {
    kEmpty,    // matches ''
    kAssert,   // zero-width start guard (see assert_* flags)
    kText,     // literal unit run
    kAnyChar,  // [^/]
    kStarAny,  // [^/]*?  (flags below select +? and dot guards)
    kClass,
    kConcat,
    kAlt,
    kOpt,      // (?:body)?
    kStar,     // (?:body)*
    kPlus,     // (?:body)+
    kTwoBody,  // (?:first)(?:rest)*?   children = [first, rest]
    kNeg,      // !(..) group: guard alts + [^/]*? consume
  };
  Kind kind = Kind::kEmpty;
  bool star_no_empty = false;        // at least one unit
  bool star_no_dot = false;          // (?!\.) at entry
  bool assert_no_dot = false;        // `(?!\.)`
  bool assert_no_traversal = false;  // `(?!(?:^|/)\.\.?(?:$|/))`

  struct CharClass {
    CharSet positive;
    CharSet negative;
    bool has_positive = false;
    bool has_negative = false;
    bool negate = false;
  };
  CharClass klass;
  PatternString text;
  std::vector<uint32_t> children;
};

// One compiled path segment.
struct SegmentProgram {
  enum class Tier : uint8_t {
    kEmpty,        // '', which matches only ''
    kLiteral,      // f === text
    kStar,         // /^\*+$/
    kStarDotExt,   // /^\*+([^+@!?*[(]*)$/
    kStarDotStar,  // /^\*+\.\*+$/
    kDotStar,      // /^\.\*+$/
    kQmarks,       // /^\?+([^+@!?*[(]*)?$/
    kRegex,        // generic
  };
  Tier tier = Tier::kRegex;
  bool uflag = false;   // code-point semantics + 'iu' folding
  bool nocase = false;  // fold case (kLiteral: only if !nocase_magic_only)
  bool dot = false;

  // If kLiteral: the text. If kStarDotExt/kQmarks: the extension.
  PatternString literal;
  PatternString literal_lower;

  // kQmarks: full pattern length in UTF-16 units ($0.length).
  size_t qmarks_len = 0;

  // kRegex:
  std::vector<RxNode> nodes;
  uint32_t root = 0;
  bool start_no_dot = false;        // (?!\.)
  bool start_no_traversal = false;  // rejects '.' and '..'
  bool invalid_regex = false;
};

// One lowered path part.
struct PartMatcher {
  enum class Kind : uint8_t { kGlobstar, kLiteral, kProgram };
  Kind kind = Kind::kProgram;
  PatternString literal;  // kLiteral: '===' comparison (Windows roots etc.)

  // Source info
  PatternString source;
  SegmentProgram program;
};

struct CompiledPattern {
  bool empty = false;  // empty pattern: matches only ''
  CompileFlags flags;
  struct Row {
    std::vector<PartMatcher> parts;
    bool has_globstar = false;
  };
  std::vector<Row> rows;

  // Set when the pattern does not compile
  CompileError error = CompileError::kNone;
};

using CompiledPatternPtr = std::shared_ptr<CompiledPattern>;
CompiledPattern CompileProgram(ParsedPattern&& parsed,
                               const CompileFlags& flags);

// "Lowering", as in toLowerCase-ing
SegmentProgram LowerSegment(SegmentNode* root,
                            const CompileFlags& flags,
                            PatternView source);

}  // namespace node::glob

#endif  // SRC_GLOB_GLOB_PROGRAM_H_