use anyhow::Result;
use regex::Regex;
pub struct PatternParser;
impl PatternParser {
pub fn parse_items(text: &str, pattern: &str) -> Result<Vec<String>> {
let regex = Regex::new(pattern)?;
let mut items = Vec::new();
for cap in regex.captures_iter(text) {
if let Some(matched) = cap.get(1).or_else(|| cap.get(0)) {
items.push(matched.as_str().to_string());
}
}
Ok(items)
}
pub fn matches(text: &str, pattern: &str) -> Result<bool> {
let regex = Regex::new(pattern)?;
Ok(regex.is_match(text))
}
pub fn extract_first(text: &str, pattern: &str) -> Result<Option<String>> {
let regex = Regex::new(pattern)?;
Ok(regex
.captures(text)
.and_then(|cap| cap.get(1).or_else(|| cap.get(0)))
.map(|m| m.as_str().to_string()))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_items() {
let text = "SUBGOAL 1: Add dependency\nSUBGOAL 2: Create module";
let pattern = r"SUBGOAL \d+: (.*)";
let items = PatternParser::parse_items(text, pattern).unwrap();
assert_eq!(items.len(), 2);
assert_eq!(items[0], "Add dependency");
assert_eq!(items[1], "Create module");
}
#[test]
fn test_matches() {
let text = "VALID: All checks passed";
assert!(PatternParser::matches(text, r"VALID").unwrap());
assert!(!PatternParser::matches(text, r"INVALID").unwrap());
}
#[test]
fn test_extract_first() {
let text = "Score: 8.5 out of 10";
let result = PatternParser::extract_first(text, r"Score: ([\d.]+)").unwrap();
assert_eq!(result, Some("8.5".to_string()));
}
}