Add a very basic capture group iterator

- Add a basic iterator over Event
- Use single struct per capture group to store capture info
This commit is contained in:
2025-05-10 11:42:27 -07:00
parent 4be8add5c0
commit 6d33bd5838
+62 -15
View File
@@ -1,14 +1,22 @@
use std::ops::RangeInclusive;
use std::ops::{Range, RangeInclusive};
#[derive(Debug)]
pub enum Event {
Open { kind: &'static str, offset: usize },
Close { offset: usize },
}
#[derive(Debug)]
pub struct CaptureInfo {
pub kind: &'static str,
pub span: Range<usize>,
sibling_index: usize,
}
pub struct Parser {
input: String,
offset: usize,
output: Vec<Event>,
output: Vec<CaptureInfo>,
}
#[derive(Clone, Copy)]
@@ -37,6 +45,34 @@ impl Parser {
self.offset = sp.offset;
self.output.truncate(sp.num_tags);
}
pub fn iter(&self) -> CaptureIterator {
CaptureIterator {
events: &self.output,
index: 0,
}
}
}
pub struct CaptureIterator<'a> {
events: &'a [CaptureInfo],
index: usize,
}
pub struct CaptureGroup<'a> {
pub event: &'a CaptureInfo,
}
impl<'a> Iterator for CaptureIterator<'a> {
type Item = CaptureGroup<'a>;
fn next(&mut self) -> Option<Self::Item> {
while let Some(x) = self.events.get(self.index) {
self.index = x.sibling_index;
return Some(CaptureGroup { event: x });
}
None
}
}
pub trait Rule {
@@ -215,12 +251,16 @@ where
{
fn parse(&self, p: &mut Parser) -> bool {
let save = p.save();
p.output.push(Event::Open {
let index = p.output.len();
let start_offset = p.offset;
p.output.push(CaptureInfo {
kind: self.0,
offset: p.offset,
span: 0..0,
sibling_index: 0,
});
if self.1.parse(p) {
p.output.push(Event::Close { offset: p.offset });
p.output[index].span = start_offset..p.offset;
p.output[index].sibling_index = p.output.len();
true
} else {
p.restore(save);
@@ -350,21 +390,28 @@ mod test {
assert!(rule.parse(&mut p));
assert_debug_snapshot!(p.output, @r#"
[
Open {
CaptureInfo {
kind: "num",
offset: 7,
span: 7..10,
sibling_index: 1,
},
Close {
offset: 10,
},
Open {
CaptureInfo {
kind: "num",
offset: 20,
},
Close {
offset: 22,
span: 20..22,
sibling_index: 2,
},
]
"#);
let result: Vec<_> = p
.iter()
.map(|x| &p.input[x.event.span.start..x.event.span.end])
.collect();
assert_debug_snapshot!(result, @r#"
[
"123",
"45",
]
"#);
}
}