made whitespace detectable with arbitrary length
This commit is contained in:
parent
92b3c6deb1
commit
ea1c1ede62
1 changed files with 36 additions and 1 deletions
37
src/lib.rs
37
src/lib.rs
|
@ -4,21 +4,38 @@ pub struct Parser<'a> {
|
|||
|
||||
impl<'a> Parser<'a> {
|
||||
pub fn new(input: &'a str, template: &'a str) -> Option<Self> {
|
||||
// find all patterns in the template
|
||||
let patterns = template
|
||||
.split("{}")
|
||||
.filter(|pat| pat != &"")
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut captures = vec![input];
|
||||
|
||||
// recursively split the input into left and right parts, where left is a match and right is processed next iteration
|
||||
for (i, pat) in patterns.iter().enumerate() {
|
||||
let last = captures.pop()?;
|
||||
|
||||
// we need to match all whitespace, and not just a specific type of whitespace
|
||||
let (mut left, mut right) = last.split_once(pat)?;
|
||||
|
||||
// check if pattern is pure whitespace
|
||||
if pat.chars().all(|c| c.is_whitespace()) {
|
||||
// if it is, we want to remove it so we can match arbitrary whitespace
|
||||
right = right.trim_start_matches(|c: char| c.is_whitespace());
|
||||
}
|
||||
|
||||
println!("left: '{}', right: '{}'", left, right);
|
||||
|
||||
// if the right side of the split doesn't contain the pattern,
|
||||
// we don't have to check if we can expand the match
|
||||
if right.contains(pat) {
|
||||
// here we check if the pattern can be expanded without interfering with other patterns
|
||||
let mut pattern_index = right.find(pat)? + left.len();
|
||||
let next_pattern_index = right.find(patterns[i + 1])? + left.len();
|
||||
let next_pattern_index = right
|
||||
.find(patterns.get(i + 1).unwrap_or(&""))
|
||||
.unwrap_or(pat.len())
|
||||
+ left.len();
|
||||
|
||||
while next_pattern_index > pattern_index {
|
||||
let (left_side, _) = input.split_at(pattern_index + 1);
|
||||
|
@ -30,6 +47,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
// if the first chars aren't a placeholder, the first split will be empty. we don't want to add this to the list of captures
|
||||
if !left.is_empty() {
|
||||
captures.push(left);
|
||||
}
|
||||
|
@ -119,4 +137,21 @@ mod tests {
|
|||
("turn off", Ok(660), Ok(55), Ok(986), Ok(197))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn works_with_different_length_whitespace() {
|
||||
let input = " 775 785 361";
|
||||
let template = " {} {} {}";
|
||||
|
||||
println!("input: '{}'", input);
|
||||
println!("pattern: '{}'", template);
|
||||
|
||||
let (a, b, c) = try_parse!(input, template, usize, usize, usize).unwrap();
|
||||
|
||||
println!("a: {:?}", a);
|
||||
println!("b: {:?}", b);
|
||||
println!("c: {:?}", c);
|
||||
|
||||
assert_eq!((a, b, c), (Ok(775), Ok(785), Ok(361)));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue