1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use std::collections::HashMap;
use super::node::Node;
use super::rule::Rule;
pub struct Tree {
rules: Vec<Rule>,
rules_from_chars: Vec<Vec<char>>,
nodes: Vec<Node>,
}
impl Tree {
pub fn from(rules: Vec<Rule>) -> Tree {
let rules_from_chars = rules
.iter()
.map(|rule| rule.from.chars().collect())
.collect();
let mut tree = Tree {
rules,
rules_from_chars,
nodes: Vec::new(),
};
tree.nodes.push(Node {
rule_index: None,
children_map: HashMap::new(),
});
for index in 0..tree.rules.len() {
tree.add(index);
}
tree
}
fn add(&mut self, rule_index: usize) {
let from = &self.rules_from_chars[rule_index];
let mut current_index = 0usize;
for ch in from {
current_index = match self.nodes[current_index].children_map.get(ch) {
Some(&index) => index,
None => {
let index = self.nodes.len();
self.nodes[current_index].children_map.insert(*ch, index);
self.nodes.push(Node {
rule_index: None,
children_map: HashMap::new(),
});
index
}
};
}
self.nodes[current_index].rule_index = Some(rule_index);
}
pub fn query(&self, chars: &[char], start: usize, chars_len: usize) -> Option<(&str, usize)> {
let mut pivot = start;
let mut depth = 0usize;
let mut current_index = 0usize;
let mut rule_index: Option<usize> = None;
while pivot < chars_len {
match self.nodes[current_index].children_map.get(&chars[pivot]) {
Some(&index) => {
current_index = index;
if let Some(i) = self.nodes[current_index].rule_index {
rule_index = Some(i);
}
}
None => break,
}
pivot += 1;
depth += 1;
}
rule_index.map(|index| (self.rules[index].to, depth))
}
}