Home Explore Blog CI



rustc

7th chunk of `src/macro-expansion.md`
4f61be5800af3910fb3d2c29cf8e26a01b976e3b121318e50000000100000b3e
The interface of the macro parser is as follows (this is slightly simplified):

```rust,ignore
fn parse_tt(
    &mut self,
    parser: &mut Cow<'_, Parser<'_>>,
    matcher: &[MatcherLoc]
) -> ParseResult
```

We use these items in macro parser:

- a `parser` variable is a reference to the state of a normal Rust parser,
  including the token stream and parsing session. The token stream is what we
  are about to ask the MBE parser to parse. We will consume the raw stream of
  tokens and output a binding of metavariables to corresponding token trees.
  The parsing session can be used to report parser errors.
- a `matcher` variable is a sequence of [`MatcherLoc`]s that we want to match
  the token stream against. They're converted from token trees before matching.


In the analogy of a regex parser, the token stream is the input and we are
matching it against the pattern defined by matcher. Using our examples, the
token stream could be the stream of tokens containing the inside of the example
invocation `print foo`, while matcher might be the sequence of token (trees)
`print $mvar:ident`.

The output of the parser is a [`ParseResult`], which indicates which of
three cases has occurred:

- **Success**: the token stream matches the given matcher and we have produced a
  binding from metavariables to the corresponding token trees.
- **Failure**: the token stream does not match matcher and results in an error
  message such as "No rule expected token ...".
- **Error**: some fatal error has occurred _in the parser_. For example, this
  happens if there is more than one pattern match, since that indicates the
  macro is ambiguous.

The full interface is defined [here][code_parse_int].

The macro parser does pretty much exactly the same as a normal regex parser
with one exception: in order to parse different types of metavariables, such as
`ident`, `block`, `expr`, etc., the macro parser must call back to the normal
Rust parser. Both the definition and invocation of macros are parsed using
the parser in a process which is non-intuitively self-referential. 

The code to parse macro _definitions_ is in
[`compiler/rustc_expand/src/mbe/macro_rules.rs`][code_mr]. It defines the
pattern for matching a macro definition as `$( $lhs:tt => $rhs:tt );+`. In
other words, a `macro_rules` definition should have in its body at least one
occurrence of a token tree followed by `=>` followed by another token tree.
When the compiler comes to a `macro_rules` definition, it uses this pattern to
match the two token trees per the rules of the definition of the macro, _thereby
utilizing the macro parser itself_. In our example definition, the
metavariable `$lhs` would match the patterns of both arms: `(print
$mvar:ident)` and `(print twice $mvar:ident)`. And `$rhs` would match the
bodies of both arms: `{ println!("{}", $mvar); }` and `{ println!("{}", $mvar);

Title: Macro Parser Interface, Input, Output, and Parsing Macro Definitions
Summary
This section details the macro parser interface, its inputs (token stream and matcher), and its output (ParseResult). It explains the three possible outcomes of parsing: success, failure, and error. Additionally, it describes how the macro parser interacts with the normal Rust parser to handle different types of metavariables. Finally, the parsing of macro definitions using the macro parser itself is explained, including the pattern used to match macro definitions and how the metavariables are matched according to the macro's rules.