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}