1
1
# Macros By Example
2
2
3
+ > ** <sup >Syntax</sup >** \
4
+ > _ MacroRulesDefinition_ :\
5
+ >   ;  ; ` macro_rules ` ` ! ` [ IDENTIFIER] _ MacroRulesDef_
6
+ >
7
+ > _ MacroRulesDef_ :\
8
+ >   ;  ;   ;  ; ` ( ` _ MacroRules_ ` ) ` ` ; ` \
9
+ >   ;  ; | ` [ ` _ MacroRules_ ` ] ` ` ; ` \
10
+ >   ;  ; | ` { ` _ MacroRules_ ` } `
11
+ >
12
+ > _ MacroRules_ :\
13
+ >   ;  ; _ MacroRule_ ( ` ; ` _ MacroRule_ )<sup >\* </sup > ` ; ` <sup >?</sup >
14
+ >
15
+ > _ MacroRule_ :\
16
+ >   ;  ; _ MacroMatcher_ ` => ` _ MacroTranscriber_
17
+ >
18
+ > _ MacroMatcher_ :\
19
+ >   ;  ;   ;  ; ` ( ` _ MacroMatch_ <sup >\* </sup > ` ) ` \
20
+ >   ;  ; | ` [ ` _ MacroMatch_ <sup >\* </sup > ` ] ` \
21
+ >   ;  ; | ` { ` _ MacroMatch_ <sup >\* </sup > ` } `
22
+ >
23
+ > _ MacroMatch_ :\
24
+ >   ;  ;   ;  ; [ _ Token_ ] <sub >_ except $ and delimiters_ </sub >\
25
+ >   ;  ; | _ MacroMatcher_ \
26
+ >   ;  ; | ` $ ` [ IDENTIFIER] ` : ` _ MacroFragSpec_ \
27
+ >   ;  ; | ` $ ` ` ( ` _ MacroMatch_ <sup >+</sup > ` ) ` _ MacroRepSep_ <sup >?</sup > _ MacroKleeneOp_
28
+ >
29
+ > _ MacroFragSpec_ :\
30
+ >   ;  ;   ;  ; ` block ` | ` expr ` | ` ident ` | ` item ` | ` lifetime ` \
31
+ >   ;  ; | ` meta ` | ` pat ` | ` path ` | ` stmt ` | ` tt ` | ` ty ` | ` vis `
32
+ >
33
+ > _ MacroRepSep_ :\
34
+ >   ;  ; [ _ Token_ ] <sub >_ except delimiters and kleene operators_ </sub >
35
+ >
36
+ > _ MacroKleeneOp_ <sub >2015</sub > :\
37
+ >   ;  ; ` * ` | ` + `
38
+ >
39
+ > _ MacroKleeneOp_ <sub >2018+</sub > :\
40
+ >   ;  ; ` * ` | ` + ` | ` ? `
41
+ >
42
+ > _ MacroTranscriber_ :\
43
+ >   ;  ; [ _ DelimTokenTree_ ]
44
+
3
45
` macro_rules ` allows users to define syntax extension in a declarative way. We
4
46
call such extensions "macros by example" or simply "macros".
5
47
6
- Currently, macros can expand to expressions, statements, items, or patterns.
7
-
8
- (A ` sep_token ` is any token other than ` * ` and ` + ` . A ` non_special_token ` is
9
- any token other than a delimiter or ` $ ` .)
48
+ Macros can expand to expressions, statements, items, types, or patterns.
10
49
11
50
The macro expander looks up macro invocations by name, and tries each macro
12
51
rule in turn. It transcribes the first successful match. Matching and
@@ -20,31 +59,32 @@ balanced, but they are otherwise not special.
20
59
In the matcher, ` $ ` _ name_ ` : ` _ designator_ matches the nonterminal in the Rust
21
60
syntax named by _ designator_ . Valid designators are:
22
61
23
- * ` item ` : an [ item]
24
- * ` block ` : a [ block]
25
- * ` stmt ` : a [ statement]
26
- * ` pat ` : a [ pattern]
27
- * ` expr ` : an [ expression]
28
- * ` ty ` : a [ type]
29
- * ` ident ` : an [ identifier] or [ keyword]
30
- * ` path ` : a [ path]
31
- * ` tt ` : a token tree (a single [ token] by matching ` () ` , ` [] ` , or ` {} ` )
32
- * ` meta ` : the contents of an [ attribute]
33
- * ` lifetime ` : a lifetime. Examples: ` 'static ` , ` 'a ` .
34
- * ` vis ` : a (visibility qualifier)[ visibility-and-privacy]
35
-
36
- [ item ] : items.html
37
- [ block ] : expressions/block-expr.html
38
- [ statement ] : statements.html
39
- [ pattern ] : patterns.html
40
- [ expression ] : expressions.html
41
- [ type ] : types.html
42
- [ identifier ] : identifiers.html
43
- [ keyword ] : keywords.html
44
- [ path ] : paths.html
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_ ]   ; (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
+
75
+ [ IDENTIFIER_OR_KEYWORD ] : identifiers.html
76
+ [ LIFETIME_TOKEN ] : tokens.html#lifetimes-and-loop-labels
77
+ [ _BlockExpression_ ] : expressions/block-expr.html
78
+ [ _Expression_ ] : expressions.html
79
+ [ _Item_ ] : items.html
80
+ [ _MetaItem_ ] : attributes.html
81
+ [ _Pattern_ ] : patterns.html
82
+ [ _Statement_ ] : statements.html
83
+ [ _TokenTree_ ] : macros.html#macro-invocation
84
+ [ _TypePath_ ] : paths.html#paths-in-types
85
+ [ _Type_ ] : types.html
86
+ [ _Visibility_ ] : visibility-and-privacy.html
45
87
[ token ] : tokens.html
46
- [ attribute ] : attributes.html
47
- [ visibility-and-privacy ] : visibility-and-privacy.html
48
88
49
89
In the transcriber, the
50
90
designator is already known, and so only the name of a matched nonterminal comes
@@ -94,9 +134,36 @@ Rust syntax is restricted in two ways:
94
134
a macro definition like ` $i:expr [ , ] ` is not legal, because ` [ ` could be part
95
135
of an expression. A macro definition like ` $i:expr, ` or ` $i:expr; ` would be legal,
96
136
however, because ` , ` and ` ; ` are legal separators. See [ RFC 550] for more information.
137
+ Specifically:
138
+
139
+ * ` expr ` and ` stmt ` may only be followed by one of ` => ` , ` , ` , or ` ; ` .
140
+ * ` pat ` may only be followed by one of ` => ` , ` , ` , ` = ` , ` | ` , ` if ` , or ` in ` .
141
+ * ` path ` and ` ty ` may only be followed by one of ` => ` , ` , ` , ` = ` , ` | ` , ` ; ` ,
142
+ ` : ` , ` > ` , ` >> ` , ` [ ` , ` { ` , ` as ` , ` where ` , or a macro variable of ` block `
143
+ fragment type.
144
+ * ` vis ` may only be followed by one of ` , ` , ` priv ` , a raw identifier, any
145
+ token that can begin a type, or a macro variable of ` ident ` , ` ty ` , or
146
+ ` path ` fragment type.
147
+ * All other fragment types have no restrictions.
148
+
97
149
2 . The parser must have eliminated all ambiguity by the time it reaches a ` $ `
98
150
_ name_ ` : ` _ designator_ . This requirement most often affects name-designator
99
151
pairs when they occur at the beginning of, or immediately after, a ` $(...)* ` ;
100
- requiring a distinctive token in front can solve the problem.
152
+ requiring a distinctive token in front can solve the problem. For example:
153
+
154
+ ``` rust
155
+ // The matcher `$($i:ident)* $e:expr` would be ambiguous because the parser
156
+ // would be forced to choose between an identifier or an expression. Use some
157
+ // token to distinguish them.
158
+ macro_rules! example {
159
+ ($ (I $ i : ident )* E $ e : expr ) => { ($ ($ i )-* ) * $ e };
160
+ }
161
+ let foo = 2 ;
162
+ let bar = 3 ;
163
+ // The following expands to `(foo - bar) * 5`
164
+ example! (I foo I bar E 5 );
165
+ ```
101
166
102
167
[ RFC 550 ] : https://github.com/rust-lang/rfcs/blob/master/text/0550-macro-future-proofing.md
168
+ [ _DelimTokenTree_ ] : macros.html
169
+ [ _Token_ ] : tokens.html
0 commit comments