pub trait Token { fn is_skippable(&self) -> bool {false} fn list_first(&self) -> Vec; fn list_last(&self) -> Vec; fn list_neighbours(&self) -> Vec<(usize, usize)>; } pub struct Symbol { position: usize, value: char } pub struct Asterisk { content: Box } pub struct Plus { content: Box } pub struct Chain { content: Vec> } impl Token for Symbol { fn list_first(&self) -> Vec { return vec![self.position]; } fn list_last(&self) -> Vec { return vec![self.position]; } fn list_neighbours(&self) -> Vec<(usize, usize)> { return vec![]; } } impl Token for Asterisk { fn is_skippable(&self) -> bool {true} fn list_first(&self) -> Vec { return self.content.list_first(); } fn list_last(&self) -> Vec { return self.content.list_last(); } fn list_neighbours(&self) -> Vec<(usize, usize)> { let mut res = self.content.list_neighbours(); for x in self.list_last() { for y in self.list_first() { res.push((x, y)); } } return res; } } impl Token for Plus { fn list_first(&self) -> Vec { return self.content.list_first(); } fn list_last(&self) -> Vec { return self.content.list_last(); } fn list_neighbours(&self) -> Vec<(usize, usize)> { let mut res = self.content.list_neighbours(); for x in self.list_last() { for y in self.list_first() { res.push((x, y)); } } return res; } } impl Token for Chain { fn is_skippable(&self) -> bool { return self.content.iter().all(|x| x.is_skippable()); } fn list_first(&self) -> Vec { let mut res = Vec::new(); for token in self.content.iter() { res.append(&mut token.list_first()); if !token.is_skippable() {break;} } return res; } fn list_last(&self) -> Vec { let mut res = Vec::new(); for token in self.content.iter().rev() { res.append(&mut token.list_last()); if !token.is_skippable() {break;} } return res; } fn list_neighbours(&self) -> Vec<(usize, usize)> { let mut res = Vec::new(); let mut previous: Vec<&Box> = Vec::new(); for token in self.content.iter() { for t in previous.iter() { for x in t.list_last() { for y in token.list_first() { res.push((x, y)); } } } res.append(&mut token.list_neighbours()); if token.is_skippable() { previous.push(token); } else { previous = vec![token]; } } return res; } } fn find_closing_parenthesis(s: &String) -> Option { let chars: Vec = s.chars().collect(); let mut counter = 0; for (i, c) in chars.iter().enumerate() { if *c == '(' {counter += 1;} else if *c == ')' {counter -= 1;} if counter == 0 {return Some(i);} } return None; } pub fn parse(pattern: &String, offset: usize) -> Chain { let chars: Vec = pattern.chars().collect(); let mut res: Vec> = Vec::new(); let mut i = 0; while i < pattern.len() { let c = chars[i]; match c { '(' => { let j = find_closing_parenthesis(&pattern[i..].to_string()).unwrap() + i; let inner_content = parse(&pattern[i+1..j].to_string(), offset+i+1); res.push(Box::new(inner_content)); i = j+1; } '*' => { let token = res.pop().unwrap(); res.push(Box::new(Asterisk{content: token})); i += 1; } '+' => { let token = res.pop().unwrap(); res.push(Box::new(Plus{content: token})); i += 1; } c => { res.push(Box::new(Symbol{position: i+offset, value: c})); i += 1; } } } return Chain{content: res}; } mod test { use super::*; #[test] fn test_closing_parenthesis() { let s = "()"; assert_eq!(find_closing_parenthesis(&s.to_string()), Some(1)); } }