1use std::rc::Rc;
2
3pub const EMPTY_RETURN_STATE: usize = usize::MAX;
4
5#[derive(Clone, Debug, Eq, Hash, PartialEq)]
6pub enum PredictionContext {
7 Empty,
8 Singleton {
9 parent: Rc<Self>,
10 return_state: usize,
11 },
12 Array {
13 parents: Vec<Rc<Self>>,
14 return_states: Vec<usize>,
15 },
16}
17
18impl PredictionContext {
19 pub fn empty() -> Rc<Self> {
20 Rc::new(Self::Empty)
21 }
22
23 pub fn singleton(parent: Rc<Self>, return_state: usize) -> Rc<Self> {
24 if return_state == EMPTY_RETURN_STATE {
25 Self::empty()
26 } else {
27 Rc::new(Self::Singleton {
28 parent,
29 return_state,
30 })
31 }
32 }
33
34 pub const fn len(&self) -> usize {
35 match self {
36 Self::Empty => 1,
37 Self::Singleton { .. } => 1,
38 Self::Array { return_states, .. } => return_states.len(),
39 }
40 }
41
42 pub const fn is_empty(&self) -> bool {
43 matches!(self, Self::Empty)
44 }
45
46 pub fn return_state(&self, index: usize) -> Option<usize> {
47 match self {
48 Self::Empty if index == 0 => Some(EMPTY_RETURN_STATE),
49 Self::Singleton { return_state, .. } if index == 0 => Some(*return_state),
50 Self::Array { return_states, .. } => return_states.get(index).copied(),
51 Self::Empty => None,
52 Self::Singleton { .. } => None,
53 }
54 }
55
56 pub fn parent(&self, index: usize) -> Option<Rc<Self>> {
57 match self {
58 Self::Empty => None,
59 Self::Singleton { parent, .. } if index == 0 => Some(Rc::clone(parent)),
60 Self::Array { parents, .. } => parents.get(index).cloned(),
61 Self::Singleton { .. } => None,
62 }
63 }
64
65 pub fn merge(left: Rc<Self>, right: Rc<Self>) -> Rc<Self> {
72 if left == right {
73 return left;
74 }
75 if left.is_empty() || right.is_empty() {
76 return Rc::new(Self::Array {
77 parents: vec![left, right],
78 return_states: vec![EMPTY_RETURN_STATE, EMPTY_RETURN_STATE],
79 });
80 }
81
82 let mut entries = Vec::new();
83 collect_entries(&left, &mut entries);
84 collect_entries(&right, &mut entries);
85 entries.sort_by_key(|(_, return_state)| *return_state);
86 entries.dedup_by(|a, b| a.1 == b.1 && a.0 == b.0);
87 Rc::new(Self::Array {
88 parents: entries
89 .iter()
90 .map(|(parent, _)| Rc::clone(parent))
91 .collect(),
92 return_states: entries
93 .iter()
94 .map(|(_, return_state)| *return_state)
95 .collect(),
96 })
97 }
98}
99
100fn collect_entries(
101 context: &Rc<PredictionContext>,
102 entries: &mut Vec<(Rc<PredictionContext>, usize)>,
103) {
104 match context.as_ref() {
105 PredictionContext::Empty => entries.push((Rc::clone(context), EMPTY_RETURN_STATE)),
106 PredictionContext::Singleton {
107 parent,
108 return_state,
109 } => entries.push((Rc::clone(parent), *return_state)),
110 PredictionContext::Array {
111 parents,
112 return_states,
113 } => {
114 for (parent, return_state) in parents.iter().zip(return_states) {
115 entries.push((Rc::clone(parent), *return_state));
116 }
117 }
118 }
119}
120
121#[derive(Clone, Debug, Eq, Hash, PartialEq)]
122pub struct AtnConfig {
123 pub state: usize,
124 pub alt: usize,
125 pub context: Rc<PredictionContext>,
126 pub reaches_into_outer_context: usize,
127}
128
129impl AtnConfig {
130 pub const fn new(state: usize, alt: usize, context: Rc<PredictionContext>) -> Self {
131 Self {
132 state,
133 alt,
134 context,
135 reaches_into_outer_context: 0,
136 }
137 }
138}
139
140#[derive(Clone, Debug, Default, Eq, PartialEq)]
141pub struct AtnConfigSet {
142 configs: Vec<AtnConfig>,
143 has_semantic_context: bool,
144 dips_into_outer_context: bool,
145 readonly: bool,
146}
147
148impl AtnConfigSet {
149 pub fn new() -> Self {
150 Self::default()
151 }
152
153 pub fn add(&mut self, config: AtnConfig) -> bool {
156 assert!(!self.readonly, "cannot mutate readonly ATN config set");
157 if self.configs.contains(&config) {
158 false
159 } else {
160 if config.reaches_into_outer_context > 0 {
161 self.dips_into_outer_context = true;
162 }
163 self.configs.push(config);
164 true
165 }
166 }
167
168 pub fn configs(&self) -> &[AtnConfig] {
169 &self.configs
170 }
171
172 pub const fn is_empty(&self) -> bool {
173 self.configs.is_empty()
174 }
175
176 pub const fn len(&self) -> usize {
177 self.configs.len()
178 }
179
180 pub const fn set_readonly(&mut self, readonly: bool) {
181 self.readonly = readonly;
182 }
183
184 pub const fn has_semantic_context(&self) -> bool {
185 self.has_semantic_context
186 }
187
188 pub const fn set_has_semantic_context(&mut self, value: bool) {
189 self.has_semantic_context = value;
190 }
191
192 pub const fn dips_into_outer_context(&self) -> bool {
193 self.dips_into_outer_context
194 }
195}
196
197#[cfg(test)]
198mod tests {
199 use super::*;
200
201 #[test]
202 fn config_set_deduplicates_configs() {
203 let empty = PredictionContext::empty();
204 let mut set = AtnConfigSet::new();
205 assert!(set.add(AtnConfig::new(1, 1, Rc::clone(&empty))));
206 assert!(!set.add(AtnConfig::new(1, 1, Rc::clone(&empty))));
207 assert_eq!(set.len(), 1);
208 }
209
210 #[test]
211 fn singleton_context_reports_parent_and_return_state() {
212 let empty = PredictionContext::empty();
213 let context = PredictionContext::singleton(Rc::clone(&empty), 42);
214 assert_eq!(context.return_state(0), Some(42));
215 assert_eq!(context.parent(0), Some(empty));
216 }
217}