Skip to content

Commit 816158a

Browse files
committed
Clarify proc-macro token tree
This attempts to clarify some details about proc-macro tokens, in particular the differences in handling `_` from `macro_rules`. This includes several changes: - Removed the wordy description of a `macro_rules` TokenTree. This is already defined in the grammar in more detail. This does remove the sentence discussing metavariable substitutions. I would prefer to defer this to a more detailed description in the `macro_rules` chapter on how metavariable substitutions work. - Removed the English description of a proc-macro token tree, and instead write it as a grammar production. Closes #2020 Closes #1236
1 parent e11adf6 commit 816158a

File tree

1 file changed

+64
-32
lines changed

1 file changed

+64
-32
lines changed

src/procedural-macros.md

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -318,45 +318,75 @@ r[macro.proc.token]
318318
## Declarative macro tokens and procedural macro tokens
319319

320320
r[macro.proc.token.intro]
321-
Declarative `macro_rules` macros and procedural macros use similar, but
322-
different definitions for tokens (or rather [`TokenTree`s].)
323-
324-
r[macro.proc.token.macro_rules]
325-
Token trees in `macro_rules` (corresponding to `tt` matchers) are defined as
326-
- Delimited groups (`(...)`, `{...}`, etc)
327-
- All operators supported by the language, both single-character and
328-
multi-character ones (`+`, `+=`).
329-
- Note that this set doesn't include the single quote `'`.
330-
- Literals (`"string"`, `1`, etc)
331-
- Note that negation (e.g. `-1`) is never a part of such literal tokens,
332-
but a separate operator token.
333-
- Identifiers, including keywords (`ident`, `r#ident`, `fn`)
334-
- Lifetimes (`'ident`)
335-
- Metavariable substitutions in `macro_rules` (e.g. `$my_expr` in
336-
`macro_rules! mac { ($my_expr: expr) => { $my_expr } }` after the `mac`'s
337-
expansion, which will be considered a single token tree regardless of the
338-
passed expression)
321+
Declarative `macro_rules` macros and procedural macros use similar but different definitions for tokens. Token trees in `macro_rules` (corresponding to `tt` matchers) are defined as the [TokenTree] production. Token trees for procedural macros are described below.
339322

340323
r[macro.proc.token.tree]
341-
Token trees in procedural macros are defined as
342-
- Delimited groups (`(...)`, `{...}`, etc)
343-
- All punctuation characters used in operators supported by the language (`+`,
344-
but not `+=`), and also the single quote `'` character (typically used in
345-
lifetimes, see below for lifetime splitting and joining behavior)
346-
- Literals (`"string"`, `1`, etc)
347-
- Negation (e.g. `-1`) is supported as a part of integer
348-
and floating point literals.
349-
- Identifiers, including keywords (`ident`, `r#ident`, `fn`)
324+
Token trees in procedural macros are defined as:
325+
326+
```grammar,macros
327+
@root ProcMacroTokenTree -> ProcMacroToken | ProcMacroDelimTokenTree
328+
329+
ProcMacroDelimTokenTree ->
330+
`(` ProcMacroTokenTree* `)`
331+
| `[` ProcMacroTokenTree* `]`
332+
| `{` ProcMacroTokenTree* `}`
333+
334+
ProcMacroToken ->
335+
ProcMacroTokenIdent
336+
| ProcMacroTokenPunct
337+
| ProcMacroTokenLiteral
338+
339+
ProcMacroTokenIdent -> IDENTIFIER_OR_KEYWORD | RAW_IDENTIFIER | `_`
340+
341+
ProcMacroTokenPunct ->
342+
`=`
343+
| `<`
344+
| `>`
345+
| `!`
346+
| `~`
347+
| `+`
348+
| `-`
349+
| `*`
350+
| `/`
351+
| `%`
352+
| `^`
353+
| `&`
354+
| `|`
355+
| `@`
356+
| `.`
357+
| `,`
358+
| `;`
359+
| `:`
360+
| `#`
361+
| `$`
362+
| `?`
363+
| `'`
364+
365+
ProcMacroTokenLiteral ->
366+
CHAR_LITERAL
367+
| STRING_LITERAL
368+
| RAW_STRING_LITERAL
369+
| BYTE_LITERAL
370+
| BYTE_STRING_LITERAL
371+
| RAW_BYTE_STRING_LITERAL
372+
| C_STRING_LITERAL
373+
| RAW_C_STRING_LITERAL
374+
| INTEGER_LITERAL
375+
| FLOAT_LITERAL
376+
| `-` INTEGER_LITERAL
377+
| `-` FLOAT_LITERAL
378+
```
350379

351380
r[macro.proc.token.conversion.intro]
352-
Mismatches between these two definitions are accounted for when token streams
353-
are passed to and from procedural macros. \
381+
Mismatches between the `macro_rules` and proc-macro tokens are accounted for when token streams are passed to and from procedural macros. \
354382
Note that the conversions below may happen lazily, so they might not happen if
355383
the tokens are not actually inspected.
356384

357385
r[macro.proc.token.conversion.to-proc_macro]
358-
When passed to a proc-macro
359-
- All multi-character operators are broken into single characters.
386+
When tokens are passed to a proc-macro:
387+
388+
- All multi-character punctuation is broken into single characters.
389+
- `_` is treated as an identifier.
360390
- Lifetimes are broken into a `'` character and an identifier.
361391
- The keyword metavariable [`$crate`] is passed as a single identifier.
362392
- All other metavariable substitutions are represented as their underlying
@@ -368,13 +398,15 @@ When passed to a proc-macro
368398
always represented as their underlying token trees.
369399

370400
r[macro.proc.token.conversion.from-proc_macro]
371-
When emitted from a proc macro
401+
When tokens are emitted from a proc macro:
402+
372403
- Punctuation characters are glued into multi-character operators
373404
when applicable.
374405
- Single quotes `'` joined with identifiers are glued into lifetimes.
375406
- Negative literals are converted into two tokens (the `-` and the literal)
376407
possibly wrapped into a delimited group ([`Group`]) with implicit delimiters
377408
([`Delimiter::None`]) when it's necessary for preserving parsing priorities.
409+
- The `_` identifier is interpreted as the `_` punctuation.
378410

379411
r[macro.proc.token.doc-comment]
380412
Note that neither declarative nor procedural macros support doc comment tokens

0 commit comments

Comments
 (0)