dcbor_pattern/pattern/meta/
repeat_pattern.rs

1use dcbor::prelude::*;
2
3use crate::{
4    Quantifier,
5    pattern::{Matcher, Path, Pattern, vm::Instr},
6};
7
8/// A pattern that matches with repetition using a quantifier.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct RepeatPattern {
11    pattern: Box<Pattern>,
12    quantifier: Quantifier,
13}
14
15impl RepeatPattern {
16    /// Creates a new `RepeatPattern` with the specified sub-pattern and
17    /// quantifier.
18    pub fn repeat(pattern: Pattern, quantifier: Quantifier) -> Self {
19        RepeatPattern { pattern: Box::new(pattern), quantifier }
20    }
21
22    /// Creates a new `RepeatPattern` with a quantifier that matches exactly
23    /// once.
24    pub fn new(pattern: Pattern) -> Self {
25        RepeatPattern {
26            pattern: Box::new(pattern),
27            quantifier: Quantifier::default(),
28        }
29    }
30
31    /// Returns the sub-pattern of this repeat pattern.
32    pub fn pattern(&self) -> &Pattern {
33        &self.pattern
34    }
35
36    /// Returns the quantifier of this repeat pattern.
37    pub fn quantifier(&self) -> &Quantifier {
38        &self.quantifier
39    }
40}
41
42impl Matcher for RepeatPattern {
43    fn paths(&self, haystack: &CBOR) -> Vec<Path> {
44        // For repeat patterns, we need to handle the quantifier logic
45        // This is a simplified implementation that doesn't use the full VM
46        // capability
47
48        let inner_paths = self.pattern.paths(haystack);
49        let matches = !inner_paths.is_empty();
50
51        if matches {
52            // Inner pattern matches
53            if self.quantifier.contains(1) {
54                inner_paths
55            } else {
56                vec![]
57            }
58        } else {
59            // Inner pattern doesn't match
60            if self.quantifier.contains(0) {
61                // Zero matches are allowed, so succeed
62                vec![vec![haystack.clone()]]
63            } else {
64                // Zero matches not allowed, so fail
65                vec![]
66            }
67        }
68    }
69
70    fn paths_with_captures(
71        &self,
72        haystack: &CBOR,
73    ) -> (Vec<Path>, std::collections::HashMap<String, Vec<Path>>) {
74        // For now, repeat patterns use basic implementation without captures
75        // TODO: Implement full repeat capture support
76        (self.paths(haystack), std::collections::HashMap::new())
77    }
78
79    fn compile(
80        &self,
81        code: &mut Vec<Instr>,
82        literals: &mut Vec<Pattern>,
83        _captures: &mut Vec<String>,
84    ) {
85        // Emit a high-level `Repeat` instruction for the VM
86        let idx = literals.len();
87        literals.push((*self.pattern).clone());
88        code.push(Instr::Repeat { pat_idx: idx, quantifier: self.quantifier });
89    }
90
91    fn collect_capture_names(&self, names: &mut Vec<String>) {
92        // Collect captures from the repeated pattern
93        self.pattern.collect_capture_names(names);
94    }
95}
96
97impl std::fmt::Display for RepeatPattern {
98    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99        let formatted_range = self.quantifier.to_string();
100        write!(f, "({}){}", self.pattern, formatted_range)
101    }
102}