浏览代码

Fix offset tests

jD91mZM2 6 年之前
父节点
当前提交
8c5e7d9d94
共有 2 个文件被更改,包括 52 次插入30 次删除
  1. 9 5
      src/lib.rs
  2. 43 25
      src/matcher.rs

+ 9 - 5
src/lib.rs

@@ -8,18 +8,22 @@ extern crate alloc;
 
 #[cfg(feature = "no_std")]
 mod std {
-    pub use core::*;
     pub use alloc::rc;
+    pub use core::*;
 
-    pub mod prelude {
-        pub use alloc::borrow::ToOwned;
-        pub use alloc::string::String;
-        pub use alloc::vec::Vec;
+    pub mod borrow {
+        pub use alloc::borrow::Cow;
+        pub use core::borrow::Borrow;
     }
     pub mod collections {
         pub use alloc::collections::*;
         pub use alloc::collections::BTreeMap as HashMap;
     }
+    pub mod prelude {
+        pub use alloc::borrow::ToOwned;
+        pub use alloc::string::String;
+        pub use alloc::vec::Vec;
+    }
 }
 
 pub mod compile;

+ 43 - 25
src/matcher.rs

@@ -4,8 +4,8 @@
 use std::prelude::*;
 
 use compile::{Token, Range};
+use std::borrow::{Borrow, Cow};
 use std::fmt;
-use std::borrow::Borrow;
 use std::ops::Deref;
 use std::rc::Rc;
 
@@ -110,6 +110,31 @@ impl<'a> Branch<'a> {
             next: next.map(Rc::new)
         })
     }
+    fn get_token(&self) -> &(Token, Range) {
+        &self.tokens[self.index]
+    }
+    /// Returns if this node is "explored" enough times,
+    /// meaning it has repeated as many times as it want to and has nowhere to go next.
+    fn is_explored(&self) -> bool {
+        let mut branch = Cow::Borrowed(self);
+
+        loop {
+            if branch.repeat_min > 0 {
+                // Did not repeat enough times!
+                return false;
+            }
+
+            let (_, Range(min, _)) = *branch.get_token();
+            if branch.repeated < min {
+                return false;
+            }
+            match branch.next_branch() {
+                Some(next) => branch = Cow::Owned(next),
+                None => break
+            }
+        }
+        true
+    }
     fn next_branch(&self) -> Option<Self> {
         if self.repeat_min > 0 {
             // Don't add the next branch until we've repeated this one enough
@@ -144,9 +169,6 @@ impl<'a> Branch<'a> {
             }
         }
     }
-    fn get_token(&self) -> &(Token, Range) {
-        &self.tokens[self.index]
-    }
 }
 
 fn expand<'a>(branches: &[Branch<'a>]) -> Vec<Branch<'a>> {
@@ -189,7 +211,6 @@ impl<'a> PosixRegexMatcher<'a> {
     fn matches_exact(&mut self, mut branches: Vec<Branch>) -> bool {
         while let Some(&next) = self.input.get(self.offset) {
             //println!();
-            self.offset += 1;
 
             let mut index = 0;
             let mut remove = 0;
@@ -197,6 +218,11 @@ impl<'a> PosixRegexMatcher<'a> {
             let mut insert = expand(&branches);
             branches.append(&mut insert);
 
+            // Whether or not all deleted branched got fully explored. This
+            // makes sure that "abc" matches "abcd", even though "d" would give
+            // a false negative.
+            let mut happy = true;
+
             //println!("Branches: {:?}", branches);
             loop {
                 if index >= branches.len() {
@@ -220,6 +246,7 @@ impl<'a> PosixRegexMatcher<'a> {
                     _ => unimplemented!("TODO")
                 };
                 if !accepts || max.map(|max| branch.repeated > max).unwrap_or(false) {
+                    happy = happy && branch.is_explored();
                     //println!("-> Delete!");
                     remove += 1;
                     continue;
@@ -229,26 +256,17 @@ impl<'a> PosixRegexMatcher<'a> {
             branches.truncate(end);
 
             if branches.is_empty() {
-                return false;
+                return happy;
             }
+
+            self.offset += 1;
         }
         //println!("Everything went successful so far, returning.");
         //println!("Branches: {:?}", branches);
 
-        for mut branch in branches {
-            loop {
-                let (ref _token, Range(min, _)) = *branch.get_token();
-                if branch.repeated < min {
-                    //println!("Token {:?} did not get explored fully ({}/{})", _token, branch.repeated, min);
-                    break;
-                }
-
-                if let Some(next) = branch.next_branch() {
-                    branch = next;
-                } else {
-                    //println!("Token {:?} *did* get explored fully", token);
-                    return true;
-                }
+        for branch in &branches {
+            if branch.is_explored() {
+                return true;
             }
         }
         false
@@ -324,11 +342,11 @@ mod tests {
         assert!(matches_exact(r"[A-Z]\+\|yee", "yee").is_some());
         assert!(matches_exact(r"[A-Z]\+\|yee", "hello").is_none());
     }
-    //#[test]
-    //fn offsets() {
-    //    assert_eq!(matches_exact("abc", "abcd"), Some(PosixRegexResult { start: 0, end: 3 }));
-    //    assert_eq!(matches_exact(r"[[:alpha:]]\+", "abcde12345"), Some(PosixRegexResult { start: 0, end: 5 }));
-    //}
+    #[test]
+    fn offsets() {
+        assert_eq!(matches_exact("abc", "abcd"), Some(PosixRegexResult { start: 0, end: 3 }));
+        assert_eq!(matches_exact(r"[[:alpha:]]\+", "abcde12345"), Some(PosixRegexResult { start: 0, end: 5 }));
+    }
     //#[test]
     //fn start_and_end() {
     //    assert!(matches_exact("^abc$", "abc").is_some());