Skip to content

Commit 33589da

Browse files
committed
Put a facade between the nfa ast and the Patterns coming from the parser
The nfa should be independent of the ast that the parser produces
1 parent 40d3b4e commit 33589da

File tree

3 files changed

+185
-109
lines changed

3 files changed

+185
-109
lines changed

src/translator.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use self::graph::Boundary;
88

99
mod boundaries;
1010
mod graph;
11+
mod match_pattern;
1112
mod nfa;
1213
mod trie;
1314

@@ -25,7 +26,7 @@ pub enum TranslationError {
2526
},
2627
}
2728

28-
#[derive(Debug, PartialEq, Clone)]
29+
#[derive(Debug, PartialEq, Clone, Default)]
2930
pub struct Translation {
3031
/// Input string to be translated
3132
input: String,

src/translator/match_pattern.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
use std::ops::Deref;
2+
3+
use crate::parser::{Pattern, Patterns};
4+
5+
use crate::translator::nfa::{AST, NFA};
6+
7+
use super::Translation;
8+
9+
impl From<&Patterns> for AST {
10+
fn from(patterns: &Patterns) -> Self {
11+
match patterns.len() {
12+
0 => todo!(),
13+
1 => AST::from(&patterns[0]),
14+
_ => {
15+
let mut ast = AST::from(&patterns[0]);
16+
for pattern in patterns.iter().skip(1) {
17+
let other = AST::from(pattern);
18+
ast = AST::Concat(Box::new(ast), Box::new(other));
19+
}
20+
ast
21+
}
22+
}
23+
}
24+
}
25+
26+
impl From<&Box<Pattern>> for AST {
27+
fn from(pattern: &Box<Pattern>) -> Self {
28+
AST::from(pattern.deref())
29+
}
30+
}
31+
32+
impl From<&Pattern> for AST {
33+
fn from(item: &Pattern) -> Self {
34+
match item {
35+
Pattern::Empty => todo!(),
36+
Pattern::Characters(s) => AST::String(s.to_string()),
37+
Pattern::Boundary => todo!(),
38+
Pattern::Any => AST::Any,
39+
Pattern::Set(hash_set) => AST::Set(hash_set.clone()),
40+
Pattern::Attributes(hash_set) => todo!(),
41+
Pattern::Group(vec) => todo!(),
42+
Pattern::Negate(pattern) => todo!(),
43+
Pattern::Optional(pattern) => AST::Optional(Box::new(AST::from(pattern))),
44+
Pattern::ZeroOrMore(pattern) => AST::ZeroOrMore(Box::new(AST::from(pattern))),
45+
Pattern::OneOrMore(pattern) => AST::OneOrMore(Box::new(AST::from(pattern))),
46+
Pattern::Either(left, right) => AST::Either(Box::new(AST::from(left)), Box::new(AST::from(right)))
47+
}
48+
}
49+
}
50+
51+
impl AST {
52+
/// Combine the pre and post patterns with the match characters into one big regexp AST by joining the with concat
53+
fn from_match_rule(pre: &Patterns, chars: String, post: &Patterns) -> Self {
54+
AST::Concat(Box::new(AST::Concat(Box::new(AST::from(pre)), Box::new(AST::String(chars)))), Box::new(AST::from(post)))
55+
}
56+
}
57+
58+
impl NFA {
59+
fn merge_patterns(&mut self, patterns: &Patterns) {
60+
match patterns.len() {
61+
0 => (),
62+
1 => {
63+
let ast = AST::from(&patterns[0]);
64+
self.add_fragment(&ast);
65+
}
66+
_ => {
67+
let ast = AST::from(&patterns[0]);
68+
let mut union = self.add_fragment(&ast);
69+
for pattern in patterns.iter().skip(1) {
70+
let ast = AST::from(pattern);
71+
let fragment = self.add_fragment(&ast);
72+
union = self.add_union(&union, &fragment)
73+
}
74+
}
75+
}
76+
}
77+
}
78+
79+
#[cfg(test)]
80+
mod tests {
81+
use super::*;
82+
use crate::parser::PatternParser;
83+
84+
#[test]
85+
fn find_pattern() {
86+
let patterns = PatternParser::new("abc").pattern().unwrap();
87+
let translation = Translation::default();
88+
let ast = AST::from(&patterns);
89+
let nfa = NFA::from(&ast);
90+
assert_eq!(nfa.find_translations("abc"), vec![translation]);
91+
assert!(nfa.find_translations("def").is_empty());
92+
}
93+
94+
#[test]
95+
fn find_character_class() {
96+
let patterns = PatternParser::new("[abc]").pattern().unwrap();
97+
let translation = Translation::default();
98+
let ast = AST::from(&patterns);
99+
let nfa = NFA::from(&ast);
100+
assert_eq!(nfa.find_translations("a"), vec![translation.clone()]);
101+
assert_eq!(nfa.find_translations("b"), vec![translation.clone()]);
102+
assert_eq!(nfa.find_translations("c"), vec![translation]);
103+
assert!(nfa.find_translations("def").is_empty());
104+
}
105+
106+
#[test]
107+
fn find_character_class_one_or_more() {
108+
let patterns = PatternParser::new("[abc]+").pattern().unwrap();
109+
let translation = Translation::default();
110+
let ast = AST::from(&patterns);
111+
let nfa = NFA::from(&ast);
112+
assert_eq!(nfa.find_translations("a"), vec![translation.clone()]);
113+
assert_eq!(nfa.find_translations("b"), vec![translation.clone()]);
114+
assert_eq!(nfa.find_translations("c"), vec![translation]);
115+
assert!(nfa.find_translations("def").is_empty());
116+
}
117+
118+
}

0 commit comments

Comments
 (0)