Add basic capture groups
This commit is contained in:
+56
-5
@@ -1,14 +1,14 @@
|
|||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
// TODO: Add offsets
|
#[derive(Debug)]
|
||||||
pub enum Tag {
|
pub enum Event {
|
||||||
Open(&'static str),
|
Open { kind: &'static str, offset: usize },
|
||||||
Close,
|
Close { offset: usize },
|
||||||
}
|
}
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
input: String,
|
input: String,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
output: Vec<Tag>,
|
output: Vec<Event>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@@ -207,6 +207,28 @@ macro_rules! star {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Tag<T>(pub &'static str, pub T);
|
||||||
|
|
||||||
|
impl<T> Rule for Tag<T>
|
||||||
|
where
|
||||||
|
T: Rule,
|
||||||
|
{
|
||||||
|
fn parse(&self, p: &mut Parser) -> bool {
|
||||||
|
let save = p.save();
|
||||||
|
p.output.push(Event::Open {
|
||||||
|
kind: self.0,
|
||||||
|
offset: p.offset,
|
||||||
|
});
|
||||||
|
if self.1.parse(p) {
|
||||||
|
p.output.push(Event::Close { offset: p.offset });
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
p.restore(save);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct EOF;
|
pub struct EOF;
|
||||||
|
|
||||||
impl Rule for EOF {
|
impl Rule for EOF {
|
||||||
@@ -226,7 +248,10 @@ macro_rules! impl_rule_for_many {
|
|||||||
|
|
||||||
impl_rule_for_many!(A B C D E F G H I J);
|
impl_rule_for_many!(A B C D E F G H I J);
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use insta::assert_debug_snapshot;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn parse<T: Rule>(rule: &T, input: &str) {
|
fn parse<T: Rule>(rule: &T, input: &str) {
|
||||||
@@ -316,4 +341,30 @@ mod test {
|
|||||||
parse(&csv, "foo, foo");
|
parse(&csv, "foo, foo");
|
||||||
parse(&csv, "foo, foo, foo");
|
parse(&csv, "foo, foo, foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_captures() {
|
||||||
|
let num = Tag("num", ('0'..='9', star!('0'..='9')));
|
||||||
|
let rule = star!(Alt((num, Dot)));
|
||||||
|
let mut p = Parser::new("I have 123 gems and 45 torches.");
|
||||||
|
assert!(rule.parse(&mut p));
|
||||||
|
assert_debug_snapshot!(p.output, @r#"
|
||||||
|
[
|
||||||
|
Open {
|
||||||
|
kind: "num",
|
||||||
|
offset: 7,
|
||||||
|
},
|
||||||
|
Close {
|
||||||
|
offset: 10,
|
||||||
|
},
|
||||||
|
Open {
|
||||||
|
kind: "num",
|
||||||
|
offset: 20,
|
||||||
|
},
|
||||||
|
Close {
|
||||||
|
offset: 22,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
"#);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user