/// `mbe` (short for Macro By Example) crate contains code for handling /// `macro_rules` macros. It uses `TokenTree` (from `ra_tt` package) as the /// interface, although it contains some code to bridge `SyntaxNode`s and /// `TokenTree`s as well! macro_rules! impl_froms { ($e:ident: $($v:ident), *) => { $( impl From<$v> for $e { fn from(it: $v) -> $e { $e::$v(it) } } )* } } mod mbe_parser; mod mbe_expander; mod syntax_bridge; mod tt_cursor; mod subtree_source; mod subtree_parser; use ra_syntax::SmolStr; use smallvec::SmallVec; pub use tt::{Delimiter, Punct}; #[derive(Debug, PartialEq, Eq)] pub enum ParseError { Expected(String), } #[derive(Debug, PartialEq, Eq)] pub enum ExpandError { NoMatchingRule, UnexpectedToken, BindingError(String), ConversionError, } pub use crate::syntax_bridge::{ ast_to_token_tree, token_tree_to_ast_item_list, syntax_node_to_token_tree, token_tree_to_expr, token_tree_to_pat, token_tree_to_ty, token_tree_to_macro_items, token_tree_to_macro_stmts, }; /// This struct contains AST for a single `macro_rules` definition. What might /// be very confusing is that AST has almost exactly the same shape as /// `tt::TokenTree`, but there's a crucial difference: in macro rules, `$ident` /// and `$()*` have special meaning (see `Var` and `Repeat` data structures) #[derive(Clone, Debug, PartialEq, Eq)] pub struct MacroRules { pub(crate) rules: Vec, } impl MacroRules { pub fn parse(tt: &tt::Subtree) -> Result { mbe_parser::parse(tt) } pub fn expand(&self, tt: &tt::Subtree) -> Result { mbe_expander::expand(self, tt) } } #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) struct Rule { pub(crate) lhs: Subtree, pub(crate) rhs: Subtree, } #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) enum TokenTree { Leaf(Leaf), Subtree(Subtree), Repeat(Repeat), } impl_froms!(TokenTree: Leaf, Subtree, Repeat); #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) enum Leaf { Literal(Literal), Punct(Punct), Ident(Ident), Var(Var), } impl_froms!(Leaf: Literal, Punct, Ident, Var); #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) struct Subtree { pub(crate) delimiter: Delimiter, pub(crate) token_trees: Vec, } #[derive(Clone, Debug, Eq)] pub(crate) enum Separator { Literal(tt::Literal), Ident(tt::Ident), Puncts(SmallVec<[tt::Punct; 3]>), } // Note that when we compare a Separator, we just care about its textual value. impl PartialEq for crate::Separator { fn eq(&self, other: &crate::Separator) -> bool { use crate::Separator::*; match (self, other) { (Ident(ref a), Ident(ref b)) => a.text == b.text, (Literal(ref a), Literal(ref b)) => a.text == b.text, (Puncts(ref a), Puncts(ref b)) if a.len() == b.len() => { let a_iter = a.iter().map(|a| a.char); let b_iter = b.iter().map(|b| b.char); a_iter.eq(b_iter) } _ => false, } } } #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) struct Repeat { pub(crate) subtree: Subtree, pub(crate) kind: RepeatKind, pub(crate) separator: Option, } #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) enum RepeatKind { ZeroOrMore, OneOrMore, ZeroOrOne, } #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) struct Literal { pub(crate) text: SmolStr, } #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) struct Ident { pub(crate) text: SmolStr, } #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) struct Var { pub(crate) text: SmolStr, pub(crate) kind: Option, } #[cfg(test)] mod tests;