1 //! This module implements declarative macros: old `macro_rules` and the newer 2 //! `macro`. Declarative macros are also known as "macro by example", and that's 3 //! why we call this module `mbe`. For external documentation, prefer the 4 //! official terminology: "declarative macros". 5 6 pub(crate) mod diagnostics; 7 pub(crate) mod macro_check; 8 pub(crate) mod macro_parser; 9 pub(crate) mod macro_rules; 10 pub(crate) mod metavar_expr; 11 pub(crate) mod quoted; 12 pub(crate) mod transcribe; 13 14 use metavar_expr::MetaVarExpr; 15 use rustc_ast::token::{Delimiter, NonterminalKind, Token, TokenKind}; 16 use rustc_ast::tokenstream::DelimSpan; 17 use rustc_span::symbol::Ident; 18 use rustc_span::Span; 19 20 /// Contains the sub-token-trees of a "delimited" token tree such as `(a b c)`. 21 /// The delimiters are not represented explicitly in the `tts` vector. 22 #[derive(PartialEq, Encodable, Decodable, Debug)] 23 struct Delimited { 24 delim: Delimiter, 25 /// FIXME: #67062 has details about why this is sub-optimal. 26 tts: Vec<TokenTree>, 27 } 28 29 #[derive(PartialEq, Encodable, Decodable, Debug)] 30 struct SequenceRepetition { 31 /// The sequence of token trees 32 tts: Vec<TokenTree>, 33 /// The optional separator 34 separator: Option<Token>, 35 /// Whether the sequence can be repeated zero (*), or one or more times (+) 36 kleene: KleeneToken, 37 /// The number of `Match`s that appear in the sequence (and subsequences) 38 num_captures: usize, 39 } 40 41 #[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)] 42 struct KleeneToken { 43 span: Span, 44 op: KleeneOp, 45 } 46 47 impl KleeneToken { new(op: KleeneOp, span: Span) -> KleeneToken48 fn new(op: KleeneOp, span: Span) -> KleeneToken { 49 KleeneToken { span, op } 50 } 51 } 52 53 /// A Kleene-style [repetition operator](https://en.wikipedia.org/wiki/Kleene_star) 54 /// for token sequences. 55 #[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)] 56 pub(crate) enum KleeneOp { 57 /// Kleene star (`*`) for zero or more repetitions 58 ZeroOrMore, 59 /// Kleene plus (`+`) for one or more repetitions 60 OneOrMore, 61 /// Kleene optional (`?`) for zero or one repetitions 62 ZeroOrOne, 63 } 64 65 /// Similar to `tokenstream::TokenTree`, except that `Sequence`, `MetaVar`, `MetaVarDecl`, and 66 /// `MetaVarExpr` are "first-class" token trees. Useful for parsing macros. 67 #[derive(Debug, PartialEq, Encodable, Decodable)] 68 enum TokenTree { 69 Token(Token), 70 /// A delimited sequence, e.g. `($e:expr)` (RHS) or `{ $e }` (LHS). 71 Delimited(DelimSpan, Delimited), 72 /// A kleene-style repetition sequence, e.g. `$($e:expr)*` (RHS) or `$($e),*` (LHS). 73 Sequence(DelimSpan, SequenceRepetition), 74 /// e.g., `$var`. 75 MetaVar(Span, Ident), 76 /// e.g., `$var:expr`. Only appears on the LHS. 77 MetaVarDecl(Span, Ident /* name to bind */, Option<NonterminalKind>), 78 /// A meta-variable expression inside `${...}`. 79 MetaVarExpr(DelimSpan, MetaVarExpr), 80 } 81 82 impl TokenTree { 83 /// Returns `true` if the given token tree is delimited. is_delimited(&self) -> bool84 fn is_delimited(&self) -> bool { 85 matches!(*self, TokenTree::Delimited(..)) 86 } 87 88 /// Returns `true` if the given token tree is a token of the given kind. is_token(&self, expected_kind: &TokenKind) -> bool89 fn is_token(&self, expected_kind: &TokenKind) -> bool { 90 match self { 91 TokenTree::Token(Token { kind: actual_kind, .. }) => actual_kind == expected_kind, 92 _ => false, 93 } 94 } 95 96 /// Retrieves the `TokenTree`'s span. span(&self) -> Span97 fn span(&self) -> Span { 98 match *self { 99 TokenTree::Token(Token { span, .. }) 100 | TokenTree::MetaVar(span, _) 101 | TokenTree::MetaVarDecl(span, _, _) => span, 102 TokenTree::Delimited(span, _) 103 | TokenTree::MetaVarExpr(span, _) 104 | TokenTree::Sequence(span, _) => span.entire(), 105 } 106 } 107 token(kind: TokenKind, span: Span) -> TokenTree108 fn token(kind: TokenKind, span: Span) -> TokenTree { 109 TokenTree::Token(Token::new(kind, span)) 110 } 111 } 112