Mercurial > lbo > hg > rex
changeset 43:0a19bc59e7d6
[intermediate] parse: Implement specific repetitions
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Fri, 24 Nov 2017 18:30:31 +0000 |
parents | 8932c5b37a89 |
children | 11af4959e69a |
files | src/parse.rs |
diffstat | 1 files changed, 49 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/src/parse.rs Wed Nov 08 19:17:19 2017 +0100 +++ b/src/parse.rs Fri Nov 24 18:30:31 2017 +0000 @@ -4,7 +4,9 @@ #![allow(dead_code)] +use std::iter::FromIterator; use std::ops::{Index, Range, RangeFull}; +use std::str::FromStr; use repr::{AnchorLocation, Pattern, Repetition}; @@ -152,9 +154,15 @@ } s = s.from(1); } - '+' => { + r @ '+' | r @ '*' | r @ '?' => { if let Some(p) = stack.pop() { - stack.push(Pattern::Repeated(Box::new(Repetition::OnceOrMore(p)))); + let rep = match r { + '+' => Repetition::OnceOrMore(p), + '*' => Repetition::ZeroOrMore(p), + '?' => Repetition::ZeroOrOnce(p), + _ => unimplemented!(), + }; + stack.push(Pattern::Repeated(Box::new(rep))); s = s.from(1); } else { return s.err("+ without pattern to repeat", 0); @@ -194,6 +202,20 @@ } } ']' => return s.err("unopened ']'", 0), + '{' => { + match split_in_parens(s.clone(), CURLY_BRACKETS) { + Some((rep, newst)) => { + if let Some(p) = stack.pop() { + let rep = parse_specific_repetition(rep, p)?; + + s = newst; + } else { + return s.err("repetition {} without pattern to repeat", 0); + } + } + None => return s.err("unmatched {", s.len()), + }; + } _ => { return s.err("unimplemented pattern", 0); } @@ -243,6 +265,31 @@ } } +// Parse a repetition spec inside curly braces: {1} | {1,} | {,1} | {1,2} +fn parse_specific_repetition<'a>(rep: ParseState<'a>, p: Pattern) -> Result<Repetition, String> { + let mut nparts = 0; + let mut parts: [Option<&[char]>; 2] = Default::default(); + + for p in rep[..].split(|c| *c == ',') { + parts[nparts] = Some(p); + nparts += 1; + if nparts == 2 { + break; + } + } + + if nparts == 1 { + // {1} + if let Ok(n) = u32::from_str(&String::from_iter(parts[0].unwrap().iter())) { + return Ok(Repetition::Specific(p, n, None)); + } else { + return Err(format!("invalid repetition '{}'", String::from_iter(rep[..].iter()))); + } + } + + Err(String::from("abc")) +} + const ROUND_PARENS: (char, char) = ('(', ')'); const SQUARE_BRACKETS: (char, char) = ('[', ']'); const CURLY_BRACKETS: (char, char) = ('{', '}');