Skip to main content

shibari_grammar/tree/
builder.rs

1use std::{
2    hash::Hash,
3    ops::{Deref, DerefMut},
4};
5
6use indexmap::IndexMap;
7use smallvec::SmallVec;
8
9#[must_use = "Call .build() to use this builder"]
10#[derive(Debug)]
11pub struct TreeMapBuilder<
12    TokenName,
13    TreeName,
14    Output,
15    ExtendConversion,
16    TokenDef,
17    TreeLabel,
18    TreeExtra,
19> {
20    pub(super) tokens: IndexMap<TokenName, SmallVec<[TokenDef; 1]>>,
21    pub(super) trees: IndexMap<
22        TreeName,
23        SmallVec<
24            [TreeBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>; 1],
25        >,
26    >,
27}
28
29impl<A, B, C, D, E, F, G> Default for TreeMapBuilder<A, B, C, D, E, F, G> {
30    #[inline]
31    fn default() -> Self {
32        Self {
33            tokens: IndexMap::new(),
34            trees: IndexMap::new(),
35        }
36    }
37}
38
39impl<
40        TokenName: Eq + Hash,
41        TreeName: Eq + Hash,
42        Output,
43        ExtendConversion,
44        TokenDef,
45        TreeLabel,
46        TreeExtra,
47    >
48    TreeMapBuilder<TokenName, TreeName, Output, ExtendConversion, TokenDef, TreeLabel, TreeExtra>
49{
50    pub fn token(&mut self, name: TokenName, def: TokenDef) -> &mut Self {
51        self.tokens.entry(name).or_default().push(def);
52        self
53    }
54
55    pub fn tree_with_extra<
56        F: FnOnce(
57            &mut TreeBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>,
58        ) -> &mut TreeBuilder<
59            TokenName,
60            TreeName,
61            Output,
62            ExtendConversion,
63            TreeLabel,
64            TreeExtra,
65        >,
66    >(
67        &mut self,
68        name: TreeName,
69        extra: TreeExtra,
70        with: F,
71    ) -> &mut Self {
72        let mut tree = TreeBuilder {
73            children: IndexMap::new(),
74            extends: SmallVec::new(),
75            defaults: SmallVec::new(),
76            extra,
77        };
78        with(&mut tree);
79
80        self.trees.entry(name).or_default().push(tree);
81
82        self
83    }
84
85    #[inline]
86    pub fn tree<
87        F: FnOnce(
88            &mut TreeBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>,
89        ) -> &mut TreeBuilder<
90            TokenName,
91            TreeName,
92            Output,
93            ExtendConversion,
94            TreeLabel,
95            TreeExtra,
96        >,
97    >(
98        &mut self,
99        name: TreeName,
100        with: F,
101    ) -> &mut Self
102    where
103        TreeExtra: Default,
104    {
105        self.tree_with_extra(name, TreeExtra::default(), with)
106    }
107}
108
109#[derive(Debug)]
110pub struct TreeBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra> {
111    pub(super) children: IndexMap<
112        TokenName,
113        SmallVec<
114            [TreeDelta<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>; 1],
115        >,
116    >,
117    pub(super) extends: SmallVec<[(TreeName, Option<TreeLabel>, ExtendConversion); 1]>,
118    pub(super) defaults: SmallVec<[Output; 1]>,
119    pub(super) extra: TreeExtra,
120}
121
122#[derive(Debug)]
123pub(super) enum TreeDelta<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra> {
124    Output(Output),
125    Goto(TreeLabel, Option<Output>),
126    Retry(Option<TreeLabel>),
127    Branch(BranchBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>),
128}
129
130impl<TokenName: Eq + Hash, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>
131    TreeBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>
132{
133    pub fn output(&mut self, token: TokenName, output: Output) -> &mut Self {
134        self.children
135            .entry(token)
136            .or_default()
137            .push(TreeDelta::Output(output));
138
139        self
140    }
141
142    pub fn goto(
143        &mut self,
144        token: TokenName,
145        label: TreeLabel,
146        output: Option<Output>,
147    ) -> &mut Self {
148        self.children
149            .entry(token)
150            .or_default()
151            .push(TreeDelta::Goto(label, output));
152
153        self
154    }
155
156    pub fn retry(&mut self, token: TokenName, label: Option<TreeLabel>) -> &mut Self {
157        self.children
158            .entry(token)
159            .or_default()
160            .push(TreeDelta::Retry(label));
161
162        self
163    }
164
165    pub fn extend(
166        &mut self,
167        tree: TreeName,
168        from: Option<TreeLabel>,
169        conversion: ExtendConversion,
170    ) -> &mut Self {
171        self.extends.push((tree, from, conversion));
172        self
173    }
174
175    pub fn default(&mut self, output: Output) -> &mut Self {
176        self.defaults.push(output);
177        self
178    }
179
180    pub fn branch_with_extra<
181        F: FnOnce(
182            &mut BranchBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>,
183        ) -> &mut BranchBuilder<
184            TokenName,
185            TreeName,
186            Output,
187            ExtendConversion,
188            TreeLabel,
189            TreeExtra,
190        >,
191    >(
192        &mut self,
193        token: TokenName,
194        extra: TreeExtra,
195        with: F,
196    ) -> &mut Self {
197        let mut branch = BranchBuilder {
198            labels: SmallVec::new(),
199            outs: SmallVec::new(),
200            tree: TreeBuilder {
201                children: IndexMap::new(),
202                extends: SmallVec::new(),
203                defaults: SmallVec::new(),
204                extra,
205            },
206        };
207        with(&mut branch);
208
209        self.children
210            .entry(token)
211            .or_default()
212            .push(TreeDelta::Branch(branch));
213
214        self
215    }
216
217    #[inline]
218    pub fn branch<
219        F: FnOnce(
220            &mut BranchBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>,
221        ) -> &mut BranchBuilder<
222            TokenName,
223            TreeName,
224            Output,
225            ExtendConversion,
226            TreeLabel,
227            TreeExtra,
228        >,
229    >(
230        &mut self,
231        token: TokenName,
232        with: F,
233    ) -> &mut Self
234    where
235        TreeExtra: Default,
236    {
237        self.branch_with_extra(token, TreeExtra::default(), with)
238    }
239}
240
241#[derive(Debug)]
242pub struct BranchBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra> {
243    pub(super) labels: SmallVec<[TreeLabel; 1]>,
244    pub(super) outs: SmallVec<[Output; 1]>,
245    pub(super) tree: TreeBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>,
246}
247
248impl<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra> Deref
249    for BranchBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>
250{
251    type Target = TreeBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>;
252
253    #[inline]
254    fn deref(&self) -> &Self::Target { &self.tree }
255}
256
257impl<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra> DerefMut
258    for BranchBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>
259{
260    #[inline]
261    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.tree }
262}
263
264impl<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>
265    BranchBuilder<TokenName, TreeName, Output, ExtendConversion, TreeLabel, TreeExtra>
266{
267    pub fn label(&mut self, label: TreeLabel) -> &mut Self {
268        self.labels.push(label);
269        self
270    }
271
272    pub fn out(&mut self, out: Output) -> &mut Self {
273        self.outs.push(out);
274        self
275    }
276}