aboutsummaryrefslogtreecommitdiff
path: root/crates/mbe/src/expander
diff options
context:
space:
mode:
Diffstat (limited to 'crates/mbe/src/expander')
-rw-r--r--crates/mbe/src/expander/matcher.rs266
-rw-r--r--crates/mbe/src/expander/transcriber.rs19
2 files changed, 218 insertions, 67 deletions
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs
index 9d3d28055..2c69e8968 100644
--- a/crates/mbe/src/expander/matcher.rs
+++ b/crates/mbe/src/expander/matcher.rs
@@ -59,6 +59,8 @@
59//! eof: [a $( a )* a b ·] 59//! eof: [a $( a )* a b ·]
60//! ``` 60//! ```
61 61
62use std::rc::Rc;
63
62use crate::{ 64use crate::{
63 expander::{Binding, Bindings, Fragment}, 65 expander::{Binding, Bindings, Fragment},
64 parser::{Op, OpDelimited, OpDelimitedIter, RepeatKind, Separator}, 66 parser::{Op, OpDelimited, OpDelimitedIter, RepeatKind, Separator},
@@ -76,43 +78,15 @@ impl Bindings {
76 // FIXME: Do we have a better way to represent an empty token ? 78 // FIXME: Do we have a better way to represent an empty token ?
77 // Insert an empty subtree for empty token 79 // Insert an empty subtree for empty token
78 let tt = tt::Subtree::default().into(); 80 let tt = tt::Subtree::default().into();
79 self.inner.push((name.clone(), Binding::Fragment(Fragment::Tokens(tt)))); 81 self.inner.insert(name.clone(), Binding::Fragment(Fragment::Tokens(tt)));
80 } 82 }
81 83
82 fn push_empty(&mut self, name: &SmolStr) { 84 fn push_empty(&mut self, name: &SmolStr) {
83 self.inner.push((name.clone(), Binding::Empty)); 85 self.inner.insert(name.clone(), Binding::Empty);
84 }
85
86 fn push_nested(&mut self, idx: usize, nested: Bindings) -> Result<(), ExpandError> {
87 for (key, value) in nested.inner {
88 if self.get_mut(&key).is_none() {
89 self.inner.push((key.clone(), Binding::Nested(Vec::new())));
90 }
91 match self.get_mut(&key) {
92 Some(Binding::Nested(it)) => {
93 // insert empty nested bindings before this one
94 while it.len() < idx {
95 it.push(Binding::Nested(vec![]));
96 }
97 it.push(value);
98 }
99 _ => {
100 return Err(ExpandError::BindingError(format!(
101 "could not find binding `{}`",
102 key
103 )));
104 }
105 }
106 }
107 Ok(())
108 }
109
110 fn get_mut(&mut self, name: &str) -> Option<&mut Binding> {
111 self.inner.iter_mut().find_map(|(n, b)| if n == name { Some(b) } else { None })
112 } 86 }
113 87
114 fn bindings(&self) -> impl Iterator<Item = &Binding> { 88 fn bindings(&self) -> impl Iterator<Item = &Binding> {
115 self.inner.iter().map(|(_, b)| b) 89 self.inner.values()
116 } 90 }
117} 91}
118 92
@@ -163,6 +137,181 @@ pub(super) fn match_(pattern: &MetaTemplate, input: &tt::Subtree) -> Match {
163} 137}
164 138
165#[derive(Debug, Clone)] 139#[derive(Debug, Clone)]
140enum BindingKind {
141 Empty(SmolStr),
142 Optional(SmolStr),
143 Fragment(SmolStr, Fragment),
144 Nested(usize, usize),
145}
146
147#[derive(Debug, Clone)]
148struct BindingsIdx(usize, usize);
149
150#[derive(Debug, Clone)]
151enum LinkNode<T> {
152 Node(T),
153 Parent { idx: usize, len: usize },
154}
155
156#[derive(Default)]
157struct BindingsBuilder {
158 nodes: Vec<Vec<LinkNode<Rc<BindingKind>>>>,
159 nested: Vec<Vec<LinkNode<usize>>>,
160}
161
162impl BindingsBuilder {
163 fn alloc(&mut self) -> BindingsIdx {
164 let idx = self.nodes.len();
165 self.nodes.push(Vec::new());
166 let nidx = self.nested.len();
167 self.nested.push(Vec::new());
168 BindingsIdx(idx, nidx)
169 }
170
171 fn copy(&mut self, bindings: &BindingsIdx) -> BindingsIdx {
172 let idx = copy_parent(bindings.0, &mut self.nodes);
173 let nidx = copy_parent(bindings.1, &mut self.nested);
174 return BindingsIdx(idx, nidx);
175
176 fn copy_parent<T>(idx: usize, target: &mut Vec<Vec<LinkNode<T>>>) -> usize
177 where
178 T: Clone,
179 {
180 let new_idx = target.len();
181 let len = target[idx].len();
182 if len < 4 {
183 target.push(target[idx].clone())
184 } else {
185 target.push(vec![LinkNode::Parent { idx, len }]);
186 }
187 new_idx
188 }
189 }
190
191 fn push_empty(&mut self, idx: &mut BindingsIdx, var: &SmolStr) {
192 self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Empty(var.clone()))));
193 }
194
195 fn push_optional(&mut self, idx: &mut BindingsIdx, var: &SmolStr) {
196 self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Optional(var.clone()))));
197 }
198
199 fn push_fragment(&mut self, idx: &mut BindingsIdx, var: &SmolStr, fragment: Fragment) {
200 self.nodes[idx.0]
201 .push(LinkNode::Node(Rc::new(BindingKind::Fragment(var.clone(), fragment))));
202 }
203
204 fn push_nested(&mut self, parent: &mut BindingsIdx, child: &BindingsIdx) {
205 let BindingsIdx(idx, nidx) = self.copy(&child);
206 self.nodes[parent.0].push(LinkNode::Node(Rc::new(BindingKind::Nested(idx, nidx))));
207 }
208
209 fn push_default(&mut self, idx: &mut BindingsIdx) {
210 self.nested[idx.1].push(LinkNode::Node(idx.0));
211 let new_idx = self.nodes.len();
212 self.nodes.push(Vec::new());
213 idx.0 = new_idx;
214 }
215
216 fn build(self, idx: &BindingsIdx) -> Bindings {
217 let mut bindings = Bindings::default();
218 self.build_inner(&mut bindings, &self.nodes[idx.0]);
219 bindings
220 }
221
222 fn build_inner(&self, bindings: &mut Bindings, link_nodes: &Vec<LinkNode<Rc<BindingKind>>>) {
223 let mut nodes = Vec::new();
224 self.collect_nodes(&link_nodes, &mut nodes);
225
226 for cmd in nodes {
227 match &**cmd {
228 BindingKind::Empty(name) => {
229 bindings.push_empty(name);
230 }
231 BindingKind::Optional(name) => {
232 bindings.push_optional(name);
233 }
234 BindingKind::Fragment(name, fragment) => {
235 bindings.inner.insert(name.clone(), Binding::Fragment(fragment.clone()));
236 }
237 BindingKind::Nested(idx, nested_idx) => {
238 let mut nested_nodes = Vec::new();
239 self.collect_nested(*idx, *nested_idx, &mut nested_nodes);
240
241 for (idx, iter) in nested_nodes.into_iter().enumerate() {
242 for (key, value) in &iter.inner {
243 let bindings = bindings
244 .inner
245 .entry(key.clone())
246 .or_insert_with(|| Binding::Nested(Vec::new()));
247
248 if let Binding::Nested(it) = bindings {
249 // insert empty nested bindings before this one
250 while it.len() < idx {
251 it.push(Binding::Nested(Vec::new()));
252 }
253 it.push(value.clone());
254 }
255 }
256 }
257 }
258 }
259 }
260 }
261
262 fn collect_nested_ref<'a>(
263 &'a self,
264 id: usize,
265 len: usize,
266 nested_refs: &mut Vec<&'a Vec<LinkNode<Rc<BindingKind>>>>,
267 ) {
268 self.nested[id].iter().take(len).for_each(|it| match it {
269 LinkNode::Node(id) => nested_refs.push(&self.nodes[*id]),
270 LinkNode::Parent { idx, len } => self.collect_nested_ref(*idx, *len, nested_refs),
271 });
272 }
273
274 fn collect_nested(&self, idx: usize, nested_idx: usize, nested: &mut Vec<Bindings>) {
275 let last = &self.nodes[idx];
276 let mut nested_refs = Vec::new();
277 self.nested[nested_idx].iter().for_each(|it| match *it {
278 LinkNode::Node(idx) => nested_refs.push(&self.nodes[idx]),
279 LinkNode::Parent { idx, len } => self.collect_nested_ref(idx, len, &mut nested_refs),
280 });
281 nested_refs.push(last);
282
283 nested_refs.into_iter().for_each(|iter| {
284 let mut child_bindings = Bindings::default();
285 self.build_inner(&mut child_bindings, &iter);
286 nested.push(child_bindings)
287 })
288 }
289
290 fn collect_nodes_ref<'a>(
291 &'a self,
292 id: usize,
293 len: usize,
294 nodes: &mut Vec<&'a Rc<BindingKind>>,
295 ) {
296 self.nodes[id].iter().take(len).for_each(|it| match it {
297 LinkNode::Node(it) => nodes.push(it),
298 LinkNode::Parent { idx, len } => self.collect_nodes_ref(*idx, *len, nodes),
299 });
300 }
301
302 fn collect_nodes<'a>(
303 &'a self,
304 link_nodes: &'a Vec<LinkNode<Rc<BindingKind>>>,
305 nodes: &mut Vec<&'a Rc<BindingKind>>,
306 ) {
307 link_nodes.into_iter().for_each(|it| match it {
308 LinkNode::Node(it) => nodes.push(it),
309 LinkNode::Parent { idx, len } => self.collect_nodes_ref(*idx, *len, nodes),
310 });
311 }
312}
313
314#[derive(Debug, Clone)]
166struct MatchState<'t> { 315struct MatchState<'t> {
167 /// The position of the "dot" in this matcher 316 /// The position of the "dot" in this matcher
168 dot: OpDelimitedIter<'t>, 317 dot: OpDelimitedIter<'t>,
@@ -187,7 +336,7 @@ struct MatchState<'t> {
187 sep_parsed: Option<usize>, 336 sep_parsed: Option<usize>,
188 337
189 /// Matched meta variables bindings 338 /// Matched meta variables bindings
190 bindings: SmallVec<[Bindings; 4]>, 339 bindings: BindingsIdx,
191 340
192 /// Cached result of meta variable parsing 341 /// Cached result of meta variable parsing
193 meta_result: Option<(TtIter<'t>, ExpandResult<Option<Fragment>>)>, 342 meta_result: Option<(TtIter<'t>, ExpandResult<Option<Fragment>>)>,
@@ -218,6 +367,7 @@ fn match_loop_inner<'t>(
218 src: TtIter<'t>, 367 src: TtIter<'t>,
219 stack: &[TtIter<'t>], 368 stack: &[TtIter<'t>],
220 res: &mut Match, 369 res: &mut Match,
370 bindings_builder: &mut BindingsBuilder,
221 cur_items: &mut SmallVec<[MatchState<'t>; 1]>, 371 cur_items: &mut SmallVec<[MatchState<'t>; 1]>,
222 bb_items: &mut SmallVec<[MatchState<'t>; 1]>, 372 bb_items: &mut SmallVec<[MatchState<'t>; 1]>,
223 next_items: &mut Vec<MatchState<'t>>, 373 next_items: &mut Vec<MatchState<'t>>,
@@ -251,12 +401,10 @@ fn match_loop_inner<'t>(
251 if item.sep_parsed.is_none() { 401 if item.sep_parsed.is_none() {
252 // Get the `up` matcher 402 // Get the `up` matcher
253 let mut new_pos = *item.up.clone().unwrap(); 403 let mut new_pos = *item.up.clone().unwrap();
404 new_pos.bindings = bindings_builder.copy(&new_pos.bindings);
254 // Add matches from this repetition to the `matches` of `up` 405 // Add matches from this repetition to the `matches` of `up`
255 if let Some(bindings) = new_pos.bindings.last_mut() { 406 bindings_builder.push_nested(&mut new_pos.bindings, &item.bindings);
256 for (i, b) in item.bindings.iter_mut().enumerate() { 407
257 bindings.push_nested(i, b.clone()).unwrap();
258 }
259 }
260 // Move the "dot" past the repetition in `up` 408 // Move the "dot" past the repetition in `up`
261 new_pos.dot.next(); 409 new_pos.dot.next();
262 new_pos.is_error = new_pos.is_error || item.is_error; 410 new_pos.is_error = new_pos.is_error || item.is_error;
@@ -280,7 +428,7 @@ fn match_loop_inner<'t>(
280 else if item.sep_kind != Some(RepeatKind::ZeroOrOne) { 428 else if item.sep_kind != Some(RepeatKind::ZeroOrOne) {
281 item.dot = item.dot.reset(); 429 item.dot = item.dot.reset();
282 item.sep_parsed = None; 430 item.sep_parsed = None;
283 item.bindings.push(Bindings::default()); 431 bindings_builder.push_default(&mut item.bindings);
284 cur_items.push(item); 432 cur_items.push(item);
285 } 433 }
286 } else { 434 } else {
@@ -298,12 +446,12 @@ fn match_loop_inner<'t>(
298 OpDelimited::Op(Op::Repeat { tokens, kind, separator }) => { 446 OpDelimited::Op(Op::Repeat { tokens, kind, separator }) => {
299 if matches!(kind, RepeatKind::ZeroOrMore | RepeatKind::ZeroOrOne) { 447 if matches!(kind, RepeatKind::ZeroOrMore | RepeatKind::ZeroOrOne) {
300 let mut new_item = item.clone(); 448 let mut new_item = item.clone();
449 new_item.bindings = bindings_builder.copy(&new_item.bindings);
301 new_item.dot.next(); 450 new_item.dot.next();
302 let mut vars = Vec::new(); 451 let mut vars = Vec::new();
303 let bindings = new_item.bindings.last_mut().unwrap();
304 collect_vars(&mut vars, tokens); 452 collect_vars(&mut vars, tokens);
305 for var in vars { 453 for var in vars {
306 bindings.push_empty(&var); 454 bindings_builder.push_empty(&mut new_item.bindings, &var);
307 } 455 }
308 cur_items.push(new_item); 456 cur_items.push(new_item);
309 } 457 }
@@ -314,7 +462,7 @@ fn match_loop_inner<'t>(
314 sep: separator.clone(), 462 sep: separator.clone(),
315 sep_kind: Some(*kind), 463 sep_kind: Some(*kind),
316 sep_parsed: None, 464 sep_parsed: None,
317 bindings: smallvec![Bindings::default()], 465 bindings: bindings_builder.alloc(),
318 meta_result: None, 466 meta_result: None,
319 is_error: false, 467 is_error: false,
320 }) 468 })
@@ -339,7 +487,7 @@ fn match_loop_inner<'t>(
339 item.meta_result = Some((fork, match_res)); 487 item.meta_result = Some((fork, match_res));
340 try_push!(bb_items, item); 488 try_push!(bb_items, item);
341 } else { 489 } else {
342 item.bindings.last_mut().unwrap().push_optional(name); 490 bindings_builder.push_optional(&mut item.bindings, &name);
343 item.dot.next(); 491 item.dot.next();
344 cur_items.push(item); 492 cur_items.push(item);
345 } 493 }
@@ -348,11 +496,11 @@ fn match_loop_inner<'t>(
348 res.add_err(err); 496 res.add_err(err);
349 match match_res.value { 497 match match_res.value {
350 Some(fragment) => { 498 Some(fragment) => {
351 item.bindings 499 bindings_builder.push_fragment(
352 .last_mut() 500 &mut item.bindings,
353 .unwrap() 501 &name,
354 .inner 502 fragment,
355 .push((name.clone(), Binding::Fragment(fragment))); 503 );
356 } 504 }
357 _ => {} 505 _ => {}
358 } 506 }
@@ -394,6 +542,8 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
394 let mut res = Match::default(); 542 let mut res = Match::default();
395 let mut error_reover_item = None; 543 let mut error_reover_item = None;
396 544
545 let mut bindings_builder = BindingsBuilder::default();
546
397 let mut cur_items = smallvec![MatchState { 547 let mut cur_items = smallvec![MatchState {
398 dot: pattern.iter_delimited(None), 548 dot: pattern.iter_delimited(None),
399 stack: Default::default(), 549 stack: Default::default(),
@@ -401,7 +551,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
401 sep: None, 551 sep: None,
402 sep_kind: None, 552 sep_kind: None,
403 sep_parsed: None, 553 sep_parsed: None,
404 bindings: smallvec![Bindings::default()], 554 bindings: bindings_builder.alloc(),
405 is_error: false, 555 is_error: false,
406 meta_result: None, 556 meta_result: None,
407 }]; 557 }];
@@ -419,6 +569,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
419 src.clone(), 569 src.clone(),
420 &stack, 570 &stack,
421 &mut res, 571 &mut res,
572 &mut bindings_builder,
422 &mut cur_items, 573 &mut cur_items,
423 &mut bb_items, 574 &mut bb_items,
424 &mut next_items, 575 &mut next_items,
@@ -428,9 +579,9 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
428 stdx::always!(cur_items.is_empty()); 579 stdx::always!(cur_items.is_empty());
429 580
430 if error_items.len() > 0 { 581 if error_items.len() > 0 {
431 error_reover_item = error_items.pop(); 582 error_reover_item = error_items.pop().map(|it| it.bindings);
432 } else if eof_items.len() > 0 { 583 } else if eof_items.len() > 0 {
433 error_reover_item = Some(eof_items[0].clone()); 584 error_reover_item = Some(eof_items[0].bindings.clone());
434 } 585 }
435 586
436 // We need to do some post processing after the `match_loop_inner`. 587 // We need to do some post processing after the `match_loop_inner`.
@@ -440,11 +591,11 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
440 if eof_items.len() == 1 { 591 if eof_items.len() == 1 {
441 // remove all errors, because it is the correct answer ! 592 // remove all errors, because it is the correct answer !
442 res = Match::default(); 593 res = Match::default();
443 res.bindings = eof_items[0].bindings[0].clone(); 594 res.bindings = bindings_builder.build(&eof_items[0].bindings);
444 } else { 595 } else {
445 // Error recovery 596 // Error recovery
446 if error_reover_item.is_some() { 597 if error_reover_item.is_some() {
447 res.bindings = error_reover_item.unwrap().bindings[0].clone(); 598 res.bindings = bindings_builder.build(&error_reover_item.unwrap());
448 } 599 }
449 res.add_err(ExpandError::UnexpectedToken); 600 res.add_err(ExpandError::UnexpectedToken);
450 } 601 }
@@ -467,8 +618,8 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
467 } 618 }
468 res.add_err(err!("leftover tokens")); 619 res.add_err(err!("leftover tokens"));
469 620
470 if let Some(mut error_reover_item) = error_reover_item { 621 if let Some(error_reover_item) = error_reover_item {
471 res.bindings = error_reover_item.bindings.remove(0); 622 res.bindings = bindings_builder.build(&error_reover_item);
472 } 623 }
473 return res; 624 return res;
474 } 625 }
@@ -494,12 +645,13 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
494 645
495 if let Some(OpDelimited::Op(Op::Var { name, .. })) = item.dot.peek() { 646 if let Some(OpDelimited::Op(Op::Var { name, .. })) = item.dot.peek() {
496 let (iter, match_res) = item.meta_result.take().unwrap(); 647 let (iter, match_res) = item.meta_result.take().unwrap();
497 let bindings = item.bindings.last_mut().unwrap();
498 match match_res.value { 648 match match_res.value {
499 Some(fragment) => { 649 Some(fragment) => {
500 bindings.inner.push((name.clone(), Binding::Fragment(fragment))); 650 bindings_builder.push_fragment(&mut item.bindings, &name, fragment);
651 }
652 None if match_res.err.is_none() => {
653 bindings_builder.push_optional(&mut item.bindings, &name);
501 } 654 }
502 None if match_res.err.is_none() => bindings.push_optional(name),
503 _ => {} 655 _ => {}
504 } 656 }
505 if let Some(err) = match_res.err { 657 if let Some(err) = match_res.err {
diff --git a/crates/mbe/src/expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs
index ad9953a7d..dd7fa97d7 100644
--- a/crates/mbe/src/expander/transcriber.rs
+++ b/crates/mbe/src/expander/transcriber.rs
@@ -2,7 +2,7 @@
2//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}` 2//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}`
3 3
4use syntax::SmolStr; 4use syntax::SmolStr;
5use tt::Delimiter; 5use tt::{Delimiter, Subtree};
6 6
7use super::ExpandResult; 7use super::ExpandResult;
8use crate::{ 8use crate::{
@@ -13,17 +13,13 @@ use crate::{
13 13
14impl Bindings { 14impl Bindings {
15 fn contains(&self, name: &str) -> bool { 15 fn contains(&self, name: &str) -> bool {
16 self.inner.iter().any(|(n, _)| n == name) 16 self.inner.contains_key(name)
17 } 17 }
18 18
19 fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> { 19 fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> {
20 let mut b: &Binding = self 20 let mut b: &Binding = self.inner.get(name).ok_or_else(|| {
21 .inner 21 ExpandError::BindingError(format!("could not find binding `{}`", name))
22 .iter() 22 })?;
23 .find_map(|(n, b)| if n == name { Some(b) } else { None })
24 .ok_or_else(|| {
25 ExpandError::BindingError(format!("could not find binding `{}`", name))
26 })?;
27 for nesting_state in nesting.iter_mut() { 23 for nesting_state in nesting.iter_mut() {
28 nesting_state.hit = true; 24 nesting_state.hit = true;
29 b = match b { 25 b = match b {
@@ -179,7 +175,10 @@ fn expand_repeat(
179 counter += 1; 175 counter += 1;
180 if counter == limit { 176 if counter == limit {
181 log::warn!("expand_tt in repeat pattern exceed limit => {:#?}\n{:#?}", template, ctx); 177 log::warn!("expand_tt in repeat pattern exceed limit => {:#?}\n{:#?}", template, ctx);
182 break; 178 return ExpandResult {
179 value: Fragment::Tokens(Subtree::default().into()),
180 err: Some(ExpandError::Other("Expand exceed limit".to_string())),
181 };
183 } 182 }
184 183
185 if e.is_some() { 184 if e.is_some() {