1 //! FIXME: write short doc here
4 expander::{Binding, Bindings, Fragment},
5 parser::{Op, RepeatKind, Separator},
6 subtree_source::SubtreeTokenSource,
8 ExpandError, MetaTemplate,
11 use super::ExpandResult;
12 use parser::{FragmentKind::*, TreeSink};
13 use syntax::{SmolStr, SyntaxKind};
14 use tt::buffer::{Cursor, TokenBuffer};
17 fn push_optional(&mut self, name: &SmolStr) {
18 // FIXME: Do we have a better way to represent an empty token ?
19 // Insert an empty subtree for empty token
20 let tt = tt::Subtree::default().into();
21 self.inner.insert(name.clone(), Binding::Fragment(Fragment::Tokens(tt)));
24 fn push_empty(&mut self, name: &SmolStr) {
25 self.inner.insert(name.clone(), Binding::Empty);
28 fn push_nested(&mut self, idx: usize, nested: Bindings) -> Result<(), ExpandError> {
29 for (key, value) in nested.inner {
30 if !self.inner.contains_key(&key) {
31 self.inner.insert(key.clone(), Binding::Nested(Vec::new()));
33 match self.inner.get_mut(&key) {
34 Some(Binding::Nested(it)) => {
35 // insert empty nested bindings before this one
36 while it.len() < idx {
37 it.push(Binding::Nested(vec![]));
42 return Err(ExpandError::BindingError(format!(
43 "could not find binding `{}`",
55 ExpandError::BindingError(format!(""))
58 ExpandError::BindingError(format!($($tt)*))
62 #[derive(Debug, Default)]
63 pub(super) struct Match {
64 pub(super) bindings: Bindings,
65 /// We currently just keep the first error and count the rest to compare matches.
66 pub(super) err: Option<ExpandError>,
67 pub(super) err_count: usize,
68 /// How many top-level token trees were left to match.
69 pub(super) unmatched_tts: usize,
73 fn add_err(&mut self, err: ExpandError) {
74 let prev_err = self.err.take();
75 self.err = prev_err.or(Some(err));
80 /// Matching errors are added to the `Match`.
81 pub(super) fn match_(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
82 let mut res = Match::default();
83 let mut src = TtIter::new(src);
85 match_tokens(&mut res, pattern, &mut src);
88 res.unmatched_tts += src.len();
89 res.add_err(err!("leftover tokens"));
95 fn match_tokens(res: &mut Match, pattern: &MetaTemplate, src: &mut TtIter) {
96 for op in pattern.iter() {
99 if let Err(err) = match_leaf(lhs, src) {
104 Op::Subtree { tokens, delimiter: delim } => {
105 let rhs = match src.expect_subtree() {
108 res.add_err(err!("expected subtree"));
112 if delim.map(|it| it.kind) != rhs.delimiter_kind() {
113 res.add_err(err!("mismatched delimiter"));
116 let mut src = TtIter::new(rhs);
117 match_tokens(res, tokens, &mut src);
119 res.add_err(err!("leftover tokens"));
122 Op::Var { name, kind, .. } => {
123 let kind = match kind {
126 res.add_err(ExpandError::UnexpectedToken);
130 let ExpandResult { value: matched, err: match_err } =
131 match_meta_var(kind.as_str(), src);
134 res.bindings.inner.insert(name.clone(), Binding::Fragment(fragment));
136 None if match_err.is_none() => res.bindings.push_optional(name),
139 if let Some(err) = match_err {
143 Op::Repeat { tokens: subtree, kind, separator } => {
144 match_repeat(res, subtree, *kind, separator, src);
150 fn match_leaf(lhs: &tt::Leaf, src: &mut TtIter) -> Result<(), ExpandError> {
151 let rhs = match src.expect_leaf() {
154 return Err(err!("expected leaf: `{}`", lhs));
159 tt::Leaf::Punct(tt::Punct { char: lhs, .. }),
160 tt::Leaf::Punct(tt::Punct { char: rhs, .. }),
161 ) if lhs == rhs => (),
163 tt::Leaf::Ident(tt::Ident { text: lhs, .. }),
164 tt::Leaf::Ident(tt::Ident { text: rhs, .. }),
165 ) if lhs == rhs => (),
167 tt::Leaf::Literal(tt::Literal { text: lhs, .. }),
168 tt::Leaf::Literal(tt::Literal { text: rhs, .. }),
169 ) if lhs == rhs => (),
171 return Err(ExpandError::UnexpectedToken);
180 pattern: &MetaTemplate,
182 separator: &Option<Separator>,
185 // Dirty hack to make macro-expansion terminate.
186 // This should be replaced by a proper macro-by-example implementation
187 let mut limit = 65536;
191 let mut fork = src.clone();
193 if let Some(separator) = &separator {
194 if i != 0 && !fork.eat_separator(separator) {
199 let mut nested = Match::default();
200 match_tokens(&mut nested, pattern, &mut fork);
201 if nested.err.is_none() {
205 "match_lhs exceeded repeat pattern limit => {:#?}\n{:#?}\n{:#?}\n{:#?}",
215 if let Err(err) = res.bindings.push_nested(counter, nested.bindings) {
220 if let RepeatKind::ZeroOrOne = kind {
229 match (kind, counter) {
230 (RepeatKind::OneOrMore, 0) => {
231 res.add_err(ExpandError::UnexpectedToken);
234 // Collect all empty variables in subtrees
235 let mut vars = Vec::new();
236 collect_vars(&mut vars, pattern);
238 res.bindings.push_empty(&var)
245 fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragment>> {
246 let fragment = match kind {
256 let tt_result = match kind {
259 .map(|ident| Some(tt::Leaf::from(ident.clone()).into()))
260 .map_err(|()| err!("expected ident")),
261 "tt" => input.expect_tt().map(Some).map_err(|()| err!()),
265 .map_err(|()| err!("expected lifetime")),
267 let neg = input.eat_char('-');
271 let lit = tt::Leaf::from(literal.clone());
273 None => Some(lit.into()),
274 Some(neg) => Some(tt::TokenTree::Subtree(tt::Subtree {
276 token_trees: vec![neg, lit.into()],
280 .map_err(|()| err!())
283 "vis" => match input.eat_vis() {
284 Some(vis) => Ok(Some(vis)),
287 _ => Err(ExpandError::UnexpectedToken),
289 return tt_result.map(|it| it.map(Fragment::Tokens)).into();
292 let result = input.expect_fragment(fragment);
293 result.map(|tt| if kind == "expr" { tt.map(Fragment::Ast) } else { tt.map(Fragment::Tokens) })
296 fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &MetaTemplate) {
297 for op in pattern.iter() {
299 Op::Var { name, .. } => buf.push(name.clone()),
301 Op::Subtree { tokens, .. } => collect_vars(buf, tokens),
302 Op::Repeat { tokens, .. } => collect_vars(buf, tokens),
307 impl<'a> TtIter<'a> {
308 fn eat_separator(&mut self, separator: &Separator) -> bool {
309 let mut fork = self.clone();
310 let ok = match separator {
311 Separator::Ident(lhs) => match fork.expect_ident() {
312 Ok(rhs) => rhs.text == lhs.text,
315 Separator::Literal(lhs) => match fork.expect_literal() {
316 Ok(rhs) => match rhs {
317 tt::Leaf::Literal(rhs) => rhs.text == lhs.text,
318 tt::Leaf::Ident(rhs) => rhs.text == lhs.text,
319 tt::Leaf::Punct(_) => false,
323 Separator::Puncts(lhss) => lhss.iter().all(|lhs| match fork.expect_punct() {
324 Ok(rhs) => rhs.char == lhs.char,
334 fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> {
335 match self.peek_n(0) {
336 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) if punct.char == '\'' => {
337 return self.expect_lifetime();
342 let tt = self.next().ok_or_else(|| ())?.clone();
343 let punct = match tt {
344 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if punct.spacing == tt::Spacing::Joint => {
350 let (second, third) = match (self.peek_n(0), self.peek_n(1)) {
352 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))),
353 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p3))),
354 ) if p2.spacing == tt::Spacing::Joint => (p2.char, Some(p3.char)),
355 (Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))), _) => (p2.char, None),
359 match (punct.char, second, third) {
360 ('.', '.', Some('.'))
361 | ('.', '.', Some('='))
362 | ('<', '<', Some('='))
363 | ('>', '>', Some('=')) => {
364 let tt2 = self.next().unwrap().clone();
365 let tt3 = self.next().unwrap().clone();
366 Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2, tt3] }.into())
388 let tt2 = self.next().unwrap().clone();
389 Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2] }.into())
395 fn expect_lifetime(&mut self) -> Result<tt::TokenTree, ()> {
396 let punct = self.expect_punct()?;
397 if punct.char != '\'' {
400 let ident = self.expect_ident()?;
405 tt::Leaf::Punct(*punct).into(),
406 tt::Leaf::Ident(ident.clone()).into(),
414 fragment_kind: parser::FragmentKind,
415 ) -> ExpandResult<Option<tt::TokenTree>> {
416 struct OffsetTokenSink<'a> {
421 impl<'a> TreeSink for OffsetTokenSink<'a> {
422 fn token(&mut self, kind: SyntaxKind, mut n_tokens: u8) {
423 if kind == SyntaxKind::LIFETIME_IDENT {
426 for _ in 0..n_tokens {
427 self.cursor = self.cursor.bump_subtree();
430 fn start_node(&mut self, _kind: SyntaxKind) {}
431 fn finish_node(&mut self) {}
432 fn error(&mut self, _error: parser::ParseError) {
437 let buffer = TokenBuffer::from_tokens(&self.inner.as_slice());
438 let mut src = SubtreeTokenSource::new(&buffer);
439 let mut sink = OffsetTokenSink { cursor: buffer.begin(), error: false };
441 parser::parse_fragment(&mut src, &mut sink, fragment_kind);
444 if !sink.cursor.is_root() || sink.error {
445 err = Some(err!("expected {:?}", fragment_kind));
448 let mut curr = buffer.begin();
449 let mut res = vec![];
451 if sink.cursor.is_root() {
452 while curr != sink.cursor {
453 if let Some(token) = curr.token_tree() {
459 self.inner = self.inner.as_slice()[res.len()..].iter();
460 if res.len() == 0 && err.is_none() {
461 err = Some(err!("no tokens consumed"));
463 let res = match res.len() {
464 1 => Some(res[0].cloned()),
466 _ => Some(tt::TokenTree::Subtree(tt::Subtree {
468 token_trees: res.into_iter().map(|it| it.cloned()).collect(),
471 ExpandResult { value: res, err }
474 fn eat_vis(&mut self) -> Option<tt::TokenTree> {
475 let mut fork = self.clone();
476 match fork.expect_fragment(Visibility) {
477 ExpandResult { value: tt, err: None } => {
481 ExpandResult { value: _, err: Some(_) } => None,
485 fn eat_char(&mut self, c: char) -> Option<tt::TokenTree> {
486 let mut fork = self.clone();
487 match fork.expect_char(c) {
489 let tt = self.next().cloned();