changeset 48:5e245f1851d7

Complete parsing of specific repetitions
author Lewin Bormann <lbo@spheniscida.de>
date Fri, 19 Jul 2019 18:14:40 +0200
parents 34980229be32
children 6662ff63ce90
files src/parse.rs
diffstat 1 files changed, 33 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/parse.rs	Thu Jul 18 17:40:44 2019 +0200
+++ b/src/parse.rs	Fri Jul 19 18:14:40 2019 +0200
@@ -206,7 +206,7 @@
                     Some((rep, newst)) => {
                         if let Some(p) = stack.pop() {
                             let rep = parse_specific_repetition(rep, p)?;
-                            stack.push(Pattern::Repeated(Box::new(rep)));
+                            stack.push(rep);
                             s = newst;
                         } else {
                             return s.err("repetition {} without pattern to repeat", 0);
@@ -265,7 +265,7 @@
 }
 
 // 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> {
+fn parse_specific_repetition<'a>(rep: ParseState<'a>, p: Pattern) -> Result<Pattern, String> {
     let mut nparts = 0;
     let mut parts: [Option<&[char]>; 2] = Default::default();
 
@@ -283,7 +283,9 @@
     } else 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));
+            return Ok(Pattern::Repeated(Box::new(Repetition::Specific(
+                p, n, None,
+            ))));
         } else {
             return Err(format!(
                 "invalid repetition '{}'",
@@ -297,10 +299,35 @@
                 Err(e) => Err(format!("{}", e)),
             }
         }
+        let (p0, p1) = (parts[0].unwrap(), parts[1].unwrap());
         // {2,3}
-        let min = errtostr(u32::from_str(&String::from_iter(parts[0].unwrap().iter())))?;
-        let max = errtostr(u32::from_str(&String::from_iter(parts[1].unwrap().iter())))?;
-        return Ok(Repetition::Specific(p, min, Some(max)));
+        if !p0.is_empty() && !p1.is_empty() {
+            let min = errtostr(u32::from_str(&String::from_iter(p0.iter())))?;
+            let max = errtostr(u32::from_str(&String::from_iter(p1.iter())))?;
+            return Ok(Pattern::Repeated(Box::new(Repetition::Specific(
+                p,
+                min,
+                Some(max),
+            ))));
+        } else if p0.is_empty() && !p1.is_empty() {
+            // {,3}
+            let min = 0;
+            let max = errtostr(u32::from_str(&String::from_iter(p1.iter())))?;
+            return Ok(Pattern::Repeated(Box::new(Repetition::Specific(
+                p,
+                min,
+                Some(max),
+            ))));
+        } else if !p0.is_empty() && p1.is_empty() {
+            // {3,}
+            let min = errtostr(u32::from_str(&String::from_iter(p0.iter())))?;
+            let repetition =
+                Pattern::Repeated(Box::new(Repetition::Specific(p.clone(), min, None)));
+            return Ok(Pattern::Concat(vec![
+                repetition,
+                Pattern::Repeated(Box::new(Repetition::ZeroOrMore(p))),
+            ]));
+        }
     }
 
     Err(format!("invalid repetition pattern {:?}", &rep[..]))