]> git.proxmox.com Git - rustc.git/blob - src/doc/reference/src/macros-by-example.md
New upstream version 1.34.2+dfsg1
[rustc.git] / src / doc / reference / src / macros-by-example.md
1 # Macros By Example
2
3 > **<sup>Syntax</sup>**\
4 > _MacroRulesDefinition_ :\
5 > &nbsp;&nbsp; `macro_rules` `!` [IDENTIFIER] _MacroRulesDef_
6 >
7 > _MacroRulesDef_ :\
8 > &nbsp;&nbsp; &nbsp;&nbsp; `(` _MacroRules_ `)` `;`\
9 > &nbsp;&nbsp; | `[` _MacroRules_ `]` `;`\
10 > &nbsp;&nbsp; | `{` _MacroRules_ `}`
11 >
12 > _MacroRules_ :\
13 > &nbsp;&nbsp; _MacroRule_ ( `;` _MacroRule_ )<sup>\*</sup> `;`<sup>?</sup>
14 >
15 > _MacroRule_ :\
16 > &nbsp;&nbsp; _MacroMatcher_ `=>` _MacroTranscriber_
17 >
18 > _MacroMatcher_ :\
19 > &nbsp;&nbsp; &nbsp;&nbsp; `(` _MacroMatch_<sup>\*</sup> `)`\
20 > &nbsp;&nbsp; | `[` _MacroMatch_<sup>\*</sup> `]`\
21 > &nbsp;&nbsp; | `{` _MacroMatch_<sup>\*</sup> `}`
22 >
23 > _MacroMatch_ :\
24 > &nbsp;&nbsp; &nbsp;&nbsp; [_Token_]<sub>_except $ and delimiters_</sub>\
25 > &nbsp;&nbsp; | _MacroMatcher_\
26 > &nbsp;&nbsp; | `$` [IDENTIFIER] `:` _MacroFragSpec_\
27 > &nbsp;&nbsp; | `$` `(` _MacroMatch_<sup>+</sup> `)` _MacroRepSep_<sup>?</sup> _MacroKleeneOp_
28 >
29 > _MacroFragSpec_ :\
30 > &nbsp;&nbsp; &nbsp;&nbsp; `block` | `expr` | `ident` | `item` | `lifetime`\
31 > &nbsp;&nbsp; | `meta` | `pat` | `path` | `stmt` | `tt` | `ty` | `vis`
32 >
33 > _MacroRepSep_ :\
34 > &nbsp;&nbsp; [_Token_]<sub>_except delimiters and kleene operators_</sub>
35 >
36 > _MacroKleeneOp_<sub>2015</sub> :\
37 > &nbsp;&nbsp; `*` | `+`
38 >
39 > _MacroKleeneOp_<sub>2018+</sub> :\
40 > &nbsp;&nbsp; `*` | `+` | `?`
41 >
42 > _MacroTranscriber_ :\
43 > &nbsp;&nbsp; [_DelimTokenTree_]
44
45 `macro_rules` allows users to define syntax extension in a declarative way. We
46 call such extensions "macros by example" or simply "macros".
47
48 Macros can expand to expressions, statements, items, types, or patterns.
49
50 The macro expander looks up macro invocations by name, and tries each macro
51 rule in turn. It transcribes the first successful match. Matching and
52 transcription are closely related to each other, and we will describe them
53 together.
54
55 The macro expander matches and transcribes every token that does not begin with
56 a `$` literally, including delimiters. For parsing reasons, delimiters must be
57 balanced, but they are otherwise not special.
58
59 In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the Rust
60 syntax named by _designator_. Valid designators are:
61
62 * `item`: an [_Item_]
63 * `block`: a [_BlockExpression_]
64 * `stmt`: a [_Statement_] without the trailing semicolon
65 * `pat`: a [_Pattern_]
66 * `expr`: an [_Expression_]
67 * `ty`: a [_Type_]
68 * `ident`: an [IDENTIFIER_OR_KEYWORD]
69 * `path`: a [_TypePath_] style path
70 * `tt`: a [_TokenTree_]&nbsp;(a single [token] or tokens in matching delimiters `()`, `[]`, or `{}`)
71 * `meta`: a [_MetaItem_], the contents of an attribute
72 * `lifetime`: a [LIFETIME_TOKEN]
73 * `vis`: a [_Visibility_] qualifier
74 * `literal`: matches `-`<sup>?</sup>[_LiteralExpression_]
75
76 [IDENTIFIER]: identifiers.html
77 [IDENTIFIER_OR_KEYWORD]: identifiers.html
78 [LIFETIME_TOKEN]: tokens.html#lifetimes-and-loop-labels
79 [_BlockExpression_]: expressions/block-expr.html
80 [_Expression_]: expressions.html
81 [_Item_]: items.html
82 [_LiteralExpression_]: expressions/literal-expr.html
83 [_MetaItem_]: attributes.html
84 [_Pattern_]: patterns.html
85 [_Statement_]: statements.html
86 [_TokenTree_]: macros.html#macro-invocation
87 [_TypePath_]: paths.html#paths-in-types
88 [_Type_]: types.html#type-expressions
89 [_Visibility_]: visibility-and-privacy.html
90 [token]: tokens.html
91
92 In the transcriber, the
93 designator is already known, and so only the name of a matched nonterminal comes
94 after the dollar sign.
95
96 In both the matcher and transcriber, the Kleene star-like operator indicates
97 repetition. The Kleene star operator consists of `$` and parentheses,
98 optionally followed by a separator token, followed by `*`, `+`, or `?`. `*`
99 means zero or more repetitions; `+` means _at least_ one repetition; `?` means
100 at most one repetition. The parentheses are not matched or transcribed. On the
101 matcher side, a name is bound to _all_ of the names it matches, in a structure
102 that mimics the structure of the repetition encountered on a successful match.
103 The job of the transcriber is to sort that structure out. Also, `?`, unlike `*`
104 and `+`, does _not_ allow a separator, since one could never match against it
105 anyway.
106
107 > **Edition Differences**: The `?` Kleene operator did not exist before the
108 > 2018 edition.
109
110 > **Edition Differences**: Prior to the 2018 Edition, `?` was an allowed
111 > separator token, rather than a Kleene operator. It is no longer allowed as a
112 > separator as of the 2018 edition. This avoids ambiguity with the `?` Kleene
113 > operator.
114
115 The rules for transcription of these repetitions are called "Macro By Example".
116 Essentially, one "layer" of repetition is discharged at a time, and all of them
117 must be discharged by the time a name is transcribed. Therefore, `( $( $i:ident
118 ),* ) => ( $i )` is an invalid macro, but `( $( $i:ident ),* ) => ( $( $i:ident
119 ),* )` is acceptable (if trivial).
120
121 When Macro By Example encounters a repetition, it examines all of the `$`
122 _name_ s that occur in its body. At the "current layer", they all must repeat
123 the same number of times, so ` ( $( $i:ident ),* ; $( $j:ident ),* ) => ( $(
124 ($i,$j) ),* )` is valid if given the argument `(a,b,c ; d,e,f)`, but not
125 `(a,b,c ; d,e)`. The repetition walks through the choices at that layer in
126 lockstep, so the former input transcribes to `(a,d), (b,e), (c,f)`.
127
128 Nested repetitions are allowed.
129
130 ### Parsing limitations
131
132 The parser used by the macro system is reasonably powerful, but the parsing of
133 Rust syntax is restricted in two ways:
134
135 1. Macro definitions are required to include suitable separators after parsing
136 expressions and other bits of the Rust grammar. This implies that
137 a macro definition like `$i:expr [ , ]` is not legal, because `[` could be part
138 of an expression. A macro definition like `$i:expr,` or `$i:expr;` would be legal,
139 however, because `,` and `;` are legal separators. See [RFC 550] for more information.
140 Specifically:
141
142 * `expr` and `stmt` may only be followed by one of `=>`, `,`, or `;`.
143 * `pat` may only be followed by one of `=>`, `,`, `=`, `|`, `if`, or `in`.
144 * `path` and `ty` may only be followed by one of `=>`, `,`, `=`, `|`, `;`,
145 `:`, `>`, `>>`, `[`, `{`, `as`, `where`, or a macro variable of `block`
146 fragment type.
147 * `vis` may only be followed by one of `,`, `priv`, a raw identifier, any
148 token that can begin a type, or a macro variable of `ident`, `ty`, or
149 `path` fragment type.
150 * All other fragment types have no restrictions.
151
152 2. The parser must have eliminated all ambiguity by the time it reaches a `$`
153 _name_ `:` _designator_. This requirement most often affects name-designator
154 pairs when they occur at the beginning of, or immediately after, a `$(...)*`;
155 requiring a distinctive token in front can solve the problem. For example:
156
157 ```rust
158 // The matcher `$($i:ident)* $e:expr` would be ambiguous because the parser
159 // would be forced to choose between an identifier or an expression. Use some
160 // token to distinguish them.
161 macro_rules! example {
162 ($(I $i:ident)* E $e:expr) => { ($($i)-*) * $e };
163 }
164 let foo = 2;
165 let bar = 3;
166 // The following expands to `(foo - bar) * 5`
167 example!(I foo I bar E 5);
168 ```
169
170 [RFC 550]: https://github.com/rust-lang/rfcs/blob/master/text/0550-macro-future-proofing.md
171 [_DelimTokenTree_]: macros.html
172 [_Token_]: tokens.html