diff options
author | Lars Wirzenius <liw@liw.fi> | 2020-09-26 09:59:39 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2020-09-26 17:54:28 +0300 |
commit | 7a9c629cd851d24002529aa721addd3c20a0bf95 (patch) | |
tree | 88b51fd1c6713c25c43822a8974c2ad68448202e /src/bindings.rs | |
parent | d987595f007a4d081beb1e5740868051f5d4b56c (diff) | |
download | subplot-7a9c629cd851d24002529aa721addd3c20a0bf95.tar.gz |
add: simple word pattern kinds
Diffstat (limited to 'src/bindings.rs')
-rw-r--r-- | src/bindings.rs | 116 |
1 files changed, 112 insertions, 4 deletions
diff --git a/src/bindings.rs b/src/bindings.rs index 9d80394..56936c0 100644 --- a/src/bindings.rs +++ b/src/bindings.rs @@ -7,6 +7,7 @@ use crate::{Result, SubplotError}; use serde::Deserialize; use serde_aux::prelude::*; +use std::collections::HashMap; use std::fs::File; use std::io::Read; use std::path::Path; @@ -595,6 +596,19 @@ mod test_bindings { } fn regex_from_simple_pattern(pattern: &str, explicit_plain: bool) -> Result<String> { + let kinds = vec![ + ("word", r"\S+"), + ("text", r".*"), + ("int", r"-?\d+"), + ("uint", r"\d+"), + ("number", r"-?\d+(\.\d+)?"), + ]; + let mut regexes: HashMap<String, Regex> = HashMap::new(); + for (k, v) in kinds.iter() { + let r = Regex::new(&v).unwrap(); + regexes.insert(k.to_string(), r); + } + let pat = Regex::new(r"\{[^\s\{\}]+\}").unwrap(); let mut r = String::new(); let mut end = 0; @@ -610,7 +624,20 @@ fn regex_from_simple_pattern(pattern: &str, explicit_plain: bool) -> Result<Stri } r.push_str(&escape(before)); let name = &pattern[m.start() + 1..m.end() - 1]; - r.push_str(&format!(r"(?P<{}>\S+)", name)); + + let (name, kind) = if let Some(i) = name.find(':') { + let (name, suffix) = name.split_at(i); + assert!(suffix.starts_with(':')); + (name, &suffix[1..]) + } else { + (name, "word") + }; + + if let Some(regex) = regexes.get(kind) { + r.push_str(&format!(r"(?P<{}>{})", name, regex)); + } else { + return Err(SubplotError::UnknownSimplePatternKind(kind.to_string())); + } end = m.end(); } let after = &pattern[end..]; @@ -630,6 +657,7 @@ fn regex_from_simple_pattern(pattern: &str, explicit_plain: bool) -> Result<Stri mod test_regex_from_simple_pattern { use super::regex_from_simple_pattern; use crate::SubplotError; + use regex::Regex; #[test] fn returns_empty_string_as_is() { @@ -649,10 +677,90 @@ mod test_regex_from_simple_pattern { assert_eq!(ret, r"\.\[\]\*\\\\"); } + fn matches(pattern: &str, text: &str) { + let r = regex_from_simple_pattern(pattern, false).unwrap(); + let r = Regex::new(&r).unwrap(); + let m = r.find(text); + assert!(m.is_some()); + let m = m.unwrap(); + assert_eq!(m.start(), 0); + assert_eq!(m.end(), text.len()); + } + + fn doesnt_match(pattern: &str, text: &str) { + let r = regex_from_simple_pattern(pattern, false).unwrap(); + let r = Regex::new(&r).unwrap(); + if let Some(m) = r.find(text) { + assert!(m.start() > 0 || m.end() < text.len()); + } + } + + #[test] + fn kindless_simple_pattern() { + let pattern = "{name}"; + matches(pattern, "Tomjon"); + doesnt_match(pattern, "Tomjon of Lancre"); + } + + #[test] + fn simple_word_pattern() { + let pattern = "{name:word}"; + matches(pattern, "Tomjon"); + doesnt_match(pattern, "Tomjon of Lancre"); + } + + #[test] + fn simple_text_pattern() { + let pattern = "{name:text}"; + matches(pattern, "Tomjon"); + matches(pattern, ""); + matches(pattern, "Tomjon of Lancre"); + } + + #[test] + fn simple_int_pattern() { + let pattern = "{foo:int}"; + matches(pattern, "0"); + matches(pattern, "-0"); + matches(pattern, "1"); + matches(pattern, "-1"); + matches(pattern, "1234"); + matches(pattern, "-1234"); + doesnt_match(pattern, " "); + doesnt_match(pattern, "one "); + doesnt_match(pattern, "1.2 "); + doesnt_match(pattern, "-1.2 "); + } + + #[test] + fn simple_uint_pattern() { + let pattern = "{foo:uint}"; + matches(pattern, "0"); + matches(pattern, "1"); + matches(pattern, "1234"); + doesnt_match(pattern, "-0"); + doesnt_match(pattern, "-1 "); + doesnt_match(pattern, "-1234"); + doesnt_match(pattern, " "); + doesnt_match(pattern, "one "); + doesnt_match(pattern, "1.2 "); + doesnt_match(pattern, "-1.2 "); + } + #[test] - fn returns_simple_pattern_expressed_as_regexp() { - let ret = regex_from_simple_pattern("I am {name}", false).unwrap(); - assert_eq!(ret, r"I am (?P<name>\S+)"); + fn simple_number_pattern() { + let pattern = "{foo:number}"; + matches(pattern, "0"); + matches(pattern, "-0"); + matches(pattern, "1"); + matches(pattern, "-1"); + matches(pattern, "1234"); + matches(pattern, "-1234"); + matches(pattern, "1.2"); + matches(pattern, "-1.2"); + doesnt_match(pattern, ""); + doesnt_match(pattern, " "); + doesnt_match(pattern, "one"); } #[test] |