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