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 pub(super) fn add_err(&mut self, err: ExpandError) {
74 let prev_err = self.err.take();
75 self.err = prev_err.or(Some(err));
80 // General note: These functions have two channels to return errors, a `Result`
81 // return value and the `&mut Match`. The returned Result is for pattern parsing
82 // errors; if a branch of the macro definition doesn't parse, it doesn't make
83 // sense to try using it. Matching errors are added to the `Match`. It might
84 // make sense to make pattern parsing a separate step?
86 pub(super) fn match_(pattern: &MetaTemplate, src: &tt::Subtree) -> Result<Match, ExpandError> {
87 assert!(pattern.delimiter == None);
89 let mut res = Match::default();
90 let mut src = TtIter::new(src);
92 match_subtree(&mut res, pattern, &mut src)?;
95 res.unmatched_tts += src.len();
96 res.add_err(err!("leftover tokens"));
104 pattern: &MetaTemplate,
106 ) -> Result<(), ExpandError> {
107 for op in pattern.iter() {
108 match op.as_ref().map_err(|err| err.clone())? {
110 let rhs = match src.expect_leaf() {
113 res.add_err(err!("expected leaf: `{}`", lhs));
119 tt::Leaf::Punct(tt::Punct { char: lhs, .. }),
120 tt::Leaf::Punct(tt::Punct { char: rhs, .. }),
121 ) if lhs == rhs => (),
123 tt::Leaf::Ident(tt::Ident { text: lhs, .. }),
124 tt::Leaf::Ident(tt::Ident { text: rhs, .. }),
125 ) if lhs == rhs => (),
127 tt::Leaf::Literal(tt::Literal { text: lhs, .. }),
128 tt::Leaf::Literal(tt::Literal { text: rhs, .. }),
129 ) if lhs == rhs => (),
131 res.add_err(ExpandError::UnexpectedToken);
135 Op::Subtree(lhs) => {
136 let rhs = match src.expect_subtree() {
139 res.add_err(err!("expected subtree"));
143 if lhs.delimiter_kind() != rhs.delimiter_kind() {
144 res.add_err(err!("mismatched delimiter"));
147 let mut src = TtIter::new(rhs);
148 match_subtree(res, lhs, &mut src)?;
150 res.add_err(err!("leftover tokens"));
153 Op::Var { name, kind, .. } => {
154 let kind = match kind {
157 res.add_err(ExpandError::UnexpectedToken);
161 let ExpandResult { value: matched, err: match_err } =
162 match_meta_var(kind.as_str(), src);
165 res.bindings.inner.insert(name.clone(), Binding::Fragment(fragment));
167 None if match_err.is_none() => res.bindings.push_optional(name),
170 if let Some(err) = match_err {
174 Op::Repeat { subtree, kind, separator } => {
175 match_repeat(res, subtree, *kind, separator, src)?;
182 impl<'a> TtIter<'a> {
183 fn eat_separator(&mut self, separator: &Separator) -> bool {
184 let mut fork = self.clone();
185 let ok = match separator {
186 Separator::Ident(lhs) => match fork.expect_ident() {
187 Ok(rhs) => rhs.text == lhs.text,
190 Separator::Literal(lhs) => match fork.expect_literal() {
191 Ok(rhs) => match rhs {
192 tt::Leaf::Literal(rhs) => rhs.text == lhs.text,
193 tt::Leaf::Ident(rhs) => rhs.text == lhs.text,
194 tt::Leaf::Punct(_) => false,
198 Separator::Puncts(lhss) => lhss.iter().all(|lhs| match fork.expect_punct() {
199 Ok(rhs) => rhs.char == lhs.char,
209 pub(crate) fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> {
210 match self.peek_n(0) {
211 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) if punct.char == '\'' => {
212 return self.expect_lifetime();
217 let tt = self.next().ok_or_else(|| ())?.clone();
218 let punct = match tt {
219 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if punct.spacing == tt::Spacing::Joint => {
225 let (second, third) = match (self.peek_n(0), self.peek_n(1)) {
227 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))),
228 Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p3))),
229 ) if p2.spacing == tt::Spacing::Joint => (p2.char, Some(p3.char)),
230 (Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))), _) => (p2.char, None),
234 match (punct.char, second, third) {
235 ('.', '.', Some('.'))
236 | ('.', '.', Some('='))
237 | ('<', '<', Some('='))
238 | ('>', '>', Some('=')) => {
239 let tt2 = self.next().unwrap().clone();
240 let tt3 = self.next().unwrap().clone();
241 Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2, tt3] }.into())
263 let tt2 = self.next().unwrap().clone();
264 Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2] }.into())
270 pub(crate) fn expect_lifetime(&mut self) -> Result<tt::TokenTree, ()> {
271 let punct = self.expect_punct()?;
272 if punct.char != '\'' {
275 let ident = self.expect_ident()?;
280 tt::Leaf::Punct(*punct).into(),
281 tt::Leaf::Ident(ident.clone()).into(),
287 pub(crate) fn expect_fragment(
289 fragment_kind: parser::FragmentKind,
290 ) -> ExpandResult<Option<tt::TokenTree>> {
291 pub(crate) struct OffsetTokenSink<'a> {
292 pub(crate) cursor: Cursor<'a>,
293 pub(crate) error: bool,
296 impl<'a> TreeSink for OffsetTokenSink<'a> {
297 fn token(&mut self, kind: SyntaxKind, mut n_tokens: u8) {
298 if kind == SyntaxKind::LIFETIME_IDENT {
301 for _ in 0..n_tokens {
302 self.cursor = self.cursor.bump_subtree();
305 fn start_node(&mut self, _kind: SyntaxKind) {}
306 fn finish_node(&mut self) {}
307 fn error(&mut self, _error: parser::ParseError) {
312 let buffer = TokenBuffer::from_tokens(&self.inner.as_slice());
313 let mut src = SubtreeTokenSource::new(&buffer);
314 let mut sink = OffsetTokenSink { cursor: buffer.begin(), error: false };
316 parser::parse_fragment(&mut src, &mut sink, fragment_kind);
319 if !sink.cursor.is_root() || sink.error {
320 err = Some(err!("expected {:?}", fragment_kind));
323 let mut curr = buffer.begin();
324 let mut res = vec![];
326 if sink.cursor.is_root() {
327 while curr != sink.cursor {
328 if let Some(token) = curr.token_tree() {
334 self.inner = self.inner.as_slice()[res.len()..].iter();
335 if res.len() == 0 && err.is_none() {
336 err = Some(err!("no tokens consumed"));
338 let res = match res.len() {
339 1 => Some(res[0].cloned()),
341 _ => Some(tt::TokenTree::Subtree(tt::Subtree {
343 token_trees: res.into_iter().map(|it| it.cloned()).collect(),
346 ExpandResult { value: res, err }
349 pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> {
350 let mut fork = self.clone();
351 match fork.expect_fragment(Visibility) {
352 ExpandResult { value: tt, err: None } => {
356 ExpandResult { value: _, err: Some(_) } => None,
360 pub(crate) fn eat_char(&mut self, c: char) -> Option<tt::TokenTree> {
361 let mut fork = self.clone();
362 match fork.expect_char(c) {
364 let tt = self.next().cloned();
373 pub(super) fn match_repeat(
375 pattern: &MetaTemplate,
377 separator: &Option<Separator>,
379 ) -> Result<(), ExpandError> {
380 // Dirty hack to make macro-expansion terminate.
381 // This should be replaced by a proper macro-by-example implementation
382 let mut limit = 65536;
386 let mut fork = src.clone();
388 if let Some(separator) = &separator {
389 if i != 0 && !fork.eat_separator(separator) {
394 let mut nested = Match::default();
395 match_subtree(&mut nested, pattern, &mut fork)?;
396 if nested.err.is_none() {
400 "match_lhs exceeded repeat pattern limit => {:#?}\n{:#?}\n{:#?}\n{:#?}",
410 if let Err(err) = res.bindings.push_nested(counter, nested.bindings) {
415 if let RepeatKind::ZeroOrOne = kind {
424 match (kind, counter) {
425 (RepeatKind::OneOrMore, 0) => {
426 res.add_err(ExpandError::UnexpectedToken);
429 // Collect all empty variables in subtrees
430 let mut vars = Vec::new();
431 collect_vars(&mut vars, pattern)?;
433 res.bindings.push_empty(&var)
441 fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragment>> {
442 let fragment = match kind {
452 let tt_result = match kind {
455 .map(|ident| Some(tt::Leaf::from(ident.clone()).into()))
456 .map_err(|()| err!("expected ident")),
457 "tt" => input.expect_tt().map(Some).map_err(|()| err!()),
461 .map_err(|()| err!("expected lifetime")),
463 let neg = input.eat_char('-');
467 let lit = tt::Leaf::from(literal.clone());
469 None => Some(lit.into()),
470 Some(neg) => Some(tt::TokenTree::Subtree(tt::Subtree {
472 token_trees: vec![neg, lit.into()],
476 .map_err(|()| err!())
479 "vis" => match input.eat_vis() {
480 Some(vis) => Ok(Some(vis)),
483 _ => Err(ExpandError::UnexpectedToken),
485 return tt_result.map(|it| it.map(Fragment::Tokens)).into();
488 let result = input.expect_fragment(fragment);
489 result.map(|tt| if kind == "expr" { tt.map(Fragment::Ast) } else { tt.map(Fragment::Tokens) })
492 fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &MetaTemplate) -> Result<(), ExpandError> {
493 for op in pattern.iter() {
494 match op.as_ref().map_err(|e| e.clone())? {
495 Op::Var { name, .. } => buf.push(name.clone()),
497 Op::Subtree(subtree) => collect_vars(buf, subtree)?,
498 Op::Repeat { subtree, .. } => collect_vars(buf, subtree)?,