metrale_grammar/fsm/
compact.rs1use ahash::AHashSet;
12
13use super::compact_array::Compact2DArray;
14use super::edge::{FsmEdge, RepeatEdgeRef};
15use super::fsm::{Fsm, NO_NEXT_STATE};
16use super::traversal;
17
18#[derive(Debug, Clone, Default, PartialEq, Eq)]
20pub struct CompactFsm {
21 edges: Compact2DArray<FsmEdge>,
22 edge_aux_data: Vec<i32>,
23}
24
25impl CompactFsm {
26 pub fn new(edges: Compact2DArray<FsmEdge>, edge_aux_data: Vec<i32>) -> Self {
28 Self {
29 edges,
30 edge_aux_data,
31 }
32 }
33
34 pub fn num_states(&self) -> usize {
38 self.edges.len()
39 }
40
41 pub fn all_edges(&self) -> &Compact2DArray<FsmEdge> {
43 &self.edges
44 }
45
46 pub fn edges(&self, state: usize) -> &[FsmEdge] {
48 self.edges.row(state)
49 }
50
51 pub fn edge_aux_data(&self) -> &[i32] {
53 &self.edge_aux_data
54 }
55
56 pub fn set_edge_aux_data(&mut self, data: Vec<i32>) {
58 self.edge_aux_data = data;
59 }
60
61 pub fn repeat_edge_info(&self, idx: i16) -> RepeatEdgeRef {
63 RepeatEdgeRef::from_aux(&self.edge_aux_data, idx as usize)
64 }
65
66 pub fn num_edges(&self) -> usize {
68 self.edges.total_elems()
69 }
70
71 pub fn memory_size(&self) -> usize {
73 self.edges.memory_size() + self.edge_aux_data.len() * std::mem::size_of::<i32>()
74 }
75
76 fn adjacency(&self) -> Vec<Vec<FsmEdge>> {
81 self.edges.iter_rows().map(|r| r.to_vec()).collect()
82 }
83
84 pub fn next_states(&self, from: usize, value: i32, edge_type: i16, targets: &mut Vec<i32>) {
89 targets.clear();
90 for edge in self.edges(from) {
91 if traversal::edge_matches(edge, value, edge_type) {
92 targets.push(edge.target);
93 }
94 }
95 }
96
97 pub fn next_state(&self, from: usize, value: i32, edge_type: i16) -> i32 {
99 let mut t = Vec::new();
100 self.next_states(from, value, edge_type, &mut t);
101 t.first().copied().unwrap_or(NO_NEXT_STATE)
102 }
103
104 pub fn epsilon_closure(&self, state_set: &mut AHashSet<i32>) {
106 traversal::epsilon_closure(&self.adjacency(), state_set);
107 }
108
109 pub fn advance(
111 &self,
112 from: &AHashSet<i32>,
113 value: i32,
114 result: &mut AHashSet<i32>,
115 edge_type: i16,
116 from_is_closure: bool,
117 ) {
118 traversal::advance(
119 &self.adjacency(),
120 from,
121 value,
122 result,
123 edge_type,
124 from_is_closure,
125 );
126 }
127
128 pub fn possible_rules(&self, state: usize, rules: &mut AHashSet<i32>) {
130 rules.clear();
131 for edge in self.edges(state) {
132 if edge.is_rule_ref() {
133 rules.insert(edge.ref_rule_id());
134 }
135 }
136 }
137
138 pub fn reachable_states(&self, from: &[i32], result: &mut AHashSet<i32>) {
140 self.to_fsm().reachable_states(from, result);
141 }
142
143 pub fn to_fsm(&self) -> Fsm {
147 let edges: Vec<Vec<FsmEdge>> = self.edges.iter_rows().map(|r| r.to_vec()).collect();
148 Fsm::from_edges(edges, self.edge_aux_data.clone())
149 }
150}
151
152impl Fsm {
153 pub fn to_compact(&self) -> CompactFsm {
155 let mut sorted = self.clone();
156 sorted.sort_edges();
157 let mut arr: Compact2DArray<FsmEdge> = Compact2DArray::new();
158 for row in &sorted.edges {
159 arr.push_row(row);
160 }
161 CompactFsm::new(arr, sorted.edge_aux_data)
162 }
163}
164
165#[cfg(test)]
166#[path = "compact_tests.rs"]
167mod tests;