1mod feature;
4mod string;
5mod string_astar;
6mod tag_string;
7mod tag_tree;
8mod tree;
9
10use crate::{BottomUpTa, DetBottomUpTa, Signature, Symbol, VisualRepresentation};
11use packed_term_arena::tree::{Tree, TreeArena};
12use std::hash::Hash;
13
14pub use string::{
15 SentenceSxHeuristic, Span, StringAlgebra, StringDecompositionAutomaton, UniversalSxHeuristic,
16};
17pub(crate) use string::{SpanProductSibling, SpanProductSiblingFinder};
18pub(crate) use string_astar::{
19 SpanAstarLeftIndex, SpanBinarySiblingGroup, SpanInterner, StringAstarSource,
20 string_fallback_rules,
21};
22pub use tag_string::{
23 CONC11, CONC12, CONC21, TAG_E, TAG_EE, TagSpan, TagStringAlgebra,
24 TagStringDecompositionAutomaton, TagStringValue, WRAP21, WRAP22,
25};
26pub use tag_tree::{
27 BinarizedTagTreeDecompositionAutomaton, BinarizedTagTreeState, TAG_HOLE, TAG_SUBSTITUTE,
28 TagTreeAlgebra, TagTreeContext, TagTreeDecompositionAutomaton,
29};
30pub use tree::{APPEND_SYMBOL, Binarizing, TreeAlgebra, TreeValue};
31
32pub trait Algebra {
44 type InternalValue: Clone + Eq + Hash;
46
47 type Value;
49
50 type ParseError;
52
53 fn signature(&self) -> &Signature;
55
56 fn evaluate(
60 &self,
61 symbol: Symbol,
62 children: &[Self::InternalValue],
63 ) -> Option<Self::InternalValue>;
64
65 fn parse_object(&mut self, input: &str) -> Result<Self::InternalValue, Self::ParseError>;
67
68 fn to_external(&self, value: &Self::InternalValue) -> Self::Value;
70
71 fn visualize(&self, value: &Self::Value) -> VisualRepresentation;
73
74 fn evaluate_term_internal(
79 &self,
80 arena: &TreeArena<Symbol>,
81 root: Tree,
82 ) -> Option<Self::InternalValue> {
83 let children: Vec<Self::InternalValue> = arena
84 .get_children(root)
85 .iter()
86 .map(|&child| self.evaluate_term_internal(arena, child))
87 .collect::<Option<_>>()?;
88 self.evaluate(*arena.get_label(root), &children)
89 }
90
91 fn evaluate_term(&self, arena: &TreeArena<Symbol>, root: Tree) -> Option<Self::Value> {
94 Some(self.to_external(&self.evaluate_term_internal(arena, root)?))
95 }
96
97 fn is_valid_value(&self, _value: &Self::InternalValue) -> bool {
99 true
100 }
101
102 fn decompose_default(
104 &self,
105 value: Self::InternalValue,
106 ) -> EvaluatingDecompositionAutomaton<'_, Self>
107 where
108 Self: Sized,
109 {
110 EvaluatingDecompositionAutomaton::new(self, value)
111 }
112}
113
114pub struct EvaluatingDecompositionAutomaton<'a, A: Algebra> {
116 algebra: &'a A,
117 accepting: A::InternalValue,
118}
119
120impl<'a, A: Algebra> EvaluatingDecompositionAutomaton<'a, A> {
121 pub fn new(algebra: &'a A, accepting: A::InternalValue) -> Self {
124 Self { algebra, accepting }
125 }
126}
127
128impl<A: Algebra> BottomUpTa for EvaluatingDecompositionAutomaton<'_, A> {
129 type State = A::InternalValue;
130
131 fn step(&self, f: Symbol, children: &[Self::State], out: &mut dyn FnMut(Self::State)) {
132 if self.algebra.signature().arity(f) != children.len() {
133 return;
134 }
135 let Some(value) = self.algebra.evaluate(f, children) else {
136 return;
137 };
138 if self.algebra.is_valid_value(&value) {
139 out(value);
140 }
141 }
142
143 fn is_accepting(&self, q: &Self::State) -> bool {
144 q == &self.accepting
145 }
146}
147
148impl<A: Algebra> DetBottomUpTa for EvaluatingDecompositionAutomaton<'_, A> {
149 fn step_det(&self, f: Symbol, children: &[Self::State]) -> Option<Self::State> {
150 if self.algebra.signature().arity(f) != children.len() {
151 return None;
152 }
153 let value = self.algebra.evaluate(f, children)?;
154 self.algebra.is_valid_value(&value).then_some(value)
155 }
156}
157
158pub use feature::{
159 FS_EMBED_PREFIX, FS_PROJECT_PREFIX, FS_REMAP_PREFIX, FS_UNIFY, FeatureStructure,
160 FeatureStructureAlgebra, FeatureStructureAttribute, FeatureStructureFilter,
161 FeatureStructureNode, FeatureStructureNodeId, FeatureStructureParseError,
162};
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167 use packed_term_arena::tree::TreeArena;
168
169 #[derive(Clone)]
170 struct Tiny {
171 signature: Signature,
172 zero: Symbol,
173 inc: Symbol,
174 }
175
176 impl Tiny {
177 fn new() -> Self {
178 let mut signature = Signature::new();
179 let zero = signature.intern("zero".to_owned(), 0).unwrap();
180 let inc = signature.intern("inc".to_owned(), 1).unwrap();
181 Self {
182 signature,
183 zero,
184 inc,
185 }
186 }
187 }
188
189 impl Algebra for Tiny {
190 type InternalValue = u8;
191 type Value = u8;
192 type ParseError = std::num::ParseIntError;
193
194 fn signature(&self) -> &Signature {
195 &self.signature
196 }
197
198 fn evaluate(
199 &self,
200 symbol: Symbol,
201 children: &[Self::InternalValue],
202 ) -> Option<Self::InternalValue> {
203 match (symbol, children) {
204 (s, []) if s == self.zero => Some(0),
205 (s, [x]) if s == self.inc => Some(x + 1),
206 _ => None,
207 }
208 }
209
210 fn parse_object(&mut self, input: &str) -> Result<Self::InternalValue, Self::ParseError> {
211 input.parse()
212 }
213
214 fn to_external(&self, value: &Self::InternalValue) -> Self::Value {
215 *value
216 }
217
218 fn visualize(&self, value: &Self::Value) -> VisualRepresentation {
219 VisualRepresentation::Text(value.to_string())
220 }
221 }
222
223 #[test]
224 fn default_decomposition_evaluates_bottom_up() {
225 let algebra = Tiny::new();
226 let decomp = algebra.decompose_default(2);
227
228 let zero = decomp.step_det(algebra.zero, &[]).unwrap();
229 let one = decomp.step_det(algebra.inc, &[zero]).unwrap();
230 let two = decomp.step_det(algebra.inc, &[one]).unwrap();
231
232 assert!(!decomp.is_accepting(&one));
233 assert!(decomp.is_accepting(&two));
234 assert_eq!(decomp.step_det(algebra.zero, &[two]), None);
235 }
236
237 #[test]
238 fn built_in_algebras_choose_structured_or_text_visualizations() {
239 let string = StringAlgebra::new();
240 assert!(matches!(
241 string.visualize(&vec!["hello".to_owned(), "world".to_owned()]),
242 VisualRepresentation::Text(text) if text == "hello world"
243 ));
244
245 let tree = TreeAlgebra::tree(Signature::new());
246 let mut arena = TreeArena::new();
247 let root = arena.add_node("root".to_owned(), Vec::new());
248 let value = TreeValue::new(arena, root);
249 assert!(matches!(
250 tree.visualize(&value),
251 VisualRepresentation::Tree(_)
252 ));
253
254 let feature = FeatureStructureAlgebra::with_signature(Signature::new());
255 let value = FeatureStructure::parse("[number: singular]").unwrap();
256 assert!(matches!(
257 feature.visualize(&value),
258 VisualRepresentation::FeatureStructure(_)
259 ));
260 }
261}