summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_expand/src/mbe.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_expand/src/mbe.rs')
-rw-r--r--compiler/rustc_expand/src/mbe.rs110
1 files changed, 110 insertions, 0 deletions
diff --git a/compiler/rustc_expand/src/mbe.rs b/compiler/rustc_expand/src/mbe.rs
new file mode 100644
index 000000000..f42576b16
--- /dev/null
+++ b/compiler/rustc_expand/src/mbe.rs
@@ -0,0 +1,110 @@
+//! This module implements declarative macros: old `macro_rules` and the newer
+//! `macro`. Declarative macros are also known as "macro by example", and that's
+//! why we call this module `mbe`. For external documentation, prefer the
+//! official terminology: "declarative macros".
+
+pub(crate) mod macro_check;
+pub(crate) mod macro_parser;
+pub(crate) mod macro_rules;
+pub(crate) mod metavar_expr;
+pub(crate) mod quoted;
+pub(crate) mod transcribe;
+
+use metavar_expr::MetaVarExpr;
+use rustc_ast::token::{Delimiter, NonterminalKind, Token, TokenKind};
+use rustc_ast::tokenstream::DelimSpan;
+use rustc_span::symbol::Ident;
+use rustc_span::Span;
+
+/// Contains the sub-token-trees of a "delimited" token tree such as `(a b c)`.
+/// The delimiters are not represented explicitly in the `tts` vector.
+#[derive(PartialEq, Encodable, Decodable, Debug)]
+struct Delimited {
+ delim: Delimiter,
+ /// FIXME: #67062 has details about why this is sub-optimal.
+ tts: Vec<TokenTree>,
+}
+
+#[derive(PartialEq, Encodable, Decodable, Debug)]
+struct SequenceRepetition {
+ /// The sequence of token trees
+ tts: Vec<TokenTree>,
+ /// The optional separator
+ separator: Option<Token>,
+ /// Whether the sequence can be repeated zero (*), or one or more times (+)
+ kleene: KleeneToken,
+ /// The number of `Match`s that appear in the sequence (and subsequences)
+ num_captures: usize,
+}
+
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
+struct KleeneToken {
+ span: Span,
+ op: KleeneOp,
+}
+
+impl KleeneToken {
+ fn new(op: KleeneOp, span: Span) -> KleeneToken {
+ KleeneToken { span, op }
+ }
+}
+
+/// A Kleene-style [repetition operator](https://en.wikipedia.org/wiki/Kleene_star)
+/// for token sequences.
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
+enum KleeneOp {
+ /// Kleene star (`*`) for zero or more repetitions
+ ZeroOrMore,
+ /// Kleene plus (`+`) for one or more repetitions
+ OneOrMore,
+ /// Kleene optional (`?`) for zero or one repetitions
+ ZeroOrOne,
+}
+
+/// Similar to `tokenstream::TokenTree`, except that `Sequence`, `MetaVar`, `MetaVarDecl`, and
+/// `MetaVarExpr` are "first-class" token trees. Useful for parsing macros.
+#[derive(Debug, PartialEq, Encodable, Decodable)]
+enum TokenTree {
+ Token(Token),
+ /// A delimited sequence, e.g. `($e:expr)` (RHS) or `{ $e }` (LHS).
+ Delimited(DelimSpan, Delimited),
+ /// A kleene-style repetition sequence, e.g. `$($e:expr)*` (RHS) or `$($e),*` (LHS).
+ Sequence(DelimSpan, SequenceRepetition),
+ /// e.g., `$var`.
+ MetaVar(Span, Ident),
+ /// e.g., `$var:expr`. Only appears on the LHS.
+ MetaVarDecl(Span, Ident /* name to bind */, Option<NonterminalKind>),
+ /// A meta-variable expression inside `${...}`.
+ MetaVarExpr(DelimSpan, MetaVarExpr),
+}
+
+impl TokenTree {
+ /// Returns `true` if the given token tree is delimited.
+ fn is_delimited(&self) -> bool {
+ matches!(*self, TokenTree::Delimited(..))
+ }
+
+ /// Returns `true` if the given token tree is a token of the given kind.
+ fn is_token(&self, expected_kind: &TokenKind) -> bool {
+ match self {
+ TokenTree::Token(Token { kind: actual_kind, .. }) => actual_kind == expected_kind,
+ _ => false,
+ }
+ }
+
+ /// Retrieves the `TokenTree`'s span.
+ fn span(&self) -> Span {
+ match *self {
+ TokenTree::Token(Token { span, .. })
+ | TokenTree::MetaVar(span, _)
+ | TokenTree::MetaVarDecl(span, _, _) => span,
+ TokenTree::Delimited(span, _)
+ | TokenTree::MetaVarExpr(span, _)
+ | TokenTree::Sequence(span, _) => span.entire(),
+ }
+ }
+
+ fn token(kind: TokenKind, span: Span) -> TokenTree {
+ TokenTree::Token(Token::new(kind, span))
+ }
+}