diff --git a/src/expressions.md b/src/expressions.md index 91985c2a8..fc6104a44 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -26,6 +26,7 @@ >       | [_BreakExpression_]\ >       | [_RangeExpression_]\ >       | [_ReturnExpression_]\ +>       | [_MacroInvocation_]\ >    ) > > _ExpressionWithBlock_ :\ @@ -341,6 +342,7 @@ They are never allowed before: [_LazyBooleanExpression_]: expressions/operator-expr.html#lazy-boolean-operators [_LiteralExpression_]: expressions/literal-expr.html [_LoopExpression_]: expressions/loop-expr.html +[_MacroInvocation_]: macros.html#macro-invocation [_MatchExpression_]: expressions/match-expr.html [_MethodCallExpression_]: expressions/method-call-expr.html [_OperatorExpression_]: expressions/operator-expr.html diff --git a/src/items.md b/src/items.md index 65bcf8782..fa1fc2bdb 100644 --- a/src/items.md +++ b/src/items.md @@ -2,7 +2,12 @@ > **Syntax:**\ > _Item_:\ ->    [_OuterAttribute_]\* [_Visibility_]?\ +>    [_OuterAttribute_]\*\ +>       _VisItem_\ +>    | _MacroItem_ +> +> _VisItem_:\ +>    [_Visibility_]?\ >    (\ >          [_Module_]\ >       | [_ExternCrate_]\ @@ -17,9 +22,12 @@ >       | [_Trait_]\ >       | [_Implementation_]\ >       | [_ExternBlock_]\ ->       | _Macro_\ ->       | _MacroDefinition_\ >    ) +> +> _MacroItem_:\ +>       [_MacroInvocationSemi_]\ +>    | [_MacroRulesDefinition_] + An _item_ is a component of a crate. Items are organized within a crate by a nested set of [modules]. Every crate has a single "outermost" anonymous module; @@ -61,6 +69,8 @@ which sub-item declarations may appear. [_ExternCrate_]: items/extern-crates.html [_Function_]: items/functions.html [_Implementation_]: items/implementations.html +[_MacroInvocationSemi_]: macros.html#macro-invocation +[_MacroRulesDefinition_]: macros-by-example.html [_Module_]: items/modules.html [_OuterAttribute_]: attributes.html [_StaticItem_]: items/static-items.html diff --git a/src/items/implementations.md b/src/items/implementations.md index 8cdef8297..cab48572a 100644 --- a/src/items/implementations.md +++ b/src/items/implementations.md @@ -11,9 +11,10 @@ >    `}` > > _InherentImplItem_ :\ ->    [_OuterAttribute_]\*\ ->    [_Visibility_]?\ ->    ( [_ConstantItem_] | [_Function_] | [_Method_] ) +>    [_OuterAttribute_]\* (\ +>          [_MacroInvocationSemi_]\ +>       | ( [_Visibility_]? ( [_ConstantItem_] | [_Function_] | [_Method_] ) )\ +>    ) > > _TraitImpl_ :\ >    `unsafe`? `impl` [_Generics_] `!`? @@ -25,9 +26,10 @@ >    `}` > > _TraitImplItem_ :\ ->    [_OuterAttribute_]\*\ ->    [_Visibility_]?\ ->    ( [_TypeAlias_] | [_ConstantItem_] | [_Function_] | [_Method_] ) +>    [_OuterAttribute_]\* (\ +>          [_MacroInvocationSemi_]\ +>       | ( [_Visibility_]? ( [_TypeAlias_] | [_ConstantItem_] | [_Function_] | [_Method_] ) )\ +>    ) An _implementation_ is an item that associates items with an _implementing type_. Implementations are defined with the keyword `impl` and contain functions @@ -180,6 +182,7 @@ attributes]. [_Function_]: items/functions.html [_Generics_]: items/generics.html [_InnerAttribute_]: attributes.html +[_MacroInvocationSemi_]: macros.html#macro-invocation [_Method_]: items/associated-items.html#methods [_OuterAttribute_]: attributes.html [_TypeAlias_]: items/type-aliases.html diff --git a/src/items/traits.md b/src/items/traits.md index 6b14f540b..4323ecd6b 100644 --- a/src/items/traits.md +++ b/src/items/traits.md @@ -9,7 +9,13 @@ >    `}` > > _TraitItem_ :\ ->    [_OuterAttribute_]\* (_TraitFunc_ | _TraitMethod_ | _TraitConst_ | _TraitType_) +>    [_OuterAttribute_]\* (\ +>          _TraitFunc_\ +>       | _TraitMethod_\ +>       | _TraitConst_\ +>       | _TraitType_\ +>       | [_MacroInvocationSemi_]\ +>    ) > > _TraitFunc_ :\ >       _TraitFunctionDecl_ ( `;` | [_BlockExpression_] ) @@ -205,6 +211,7 @@ trait T { [_FunctionQualifiers_]: items/functions.html [_FunctionReturnType_]: items/functions.html [_Generics_]: items/generics.html +[_MacroInvocationSemi_]: macros.html#macro-invocation [_OuterAttribute_]: attributes.html [_Pattern_]: patterns.html [_SelfParam_]: items/associated-items.html#methods diff --git a/src/macros-by-example.md b/src/macros-by-example.md index 0cebc8d55..5e3fa88b5 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -1,12 +1,51 @@ # Macros By Example +> **Syntax**\ +> _MacroRulesDefinition_ :\ +>    `macro_rules` `!` [IDENTIFIER] _MacroRulesDef_ +> +> _MacroRulesDef_ :\ +>       `(` _MacroRules_ `)` `;`\ +>    | `[` _MacroRules_ `]` `;`\ +>    | `{` _MacroRules_ `}` +> +> _MacroRules_ :\ +>    _MacroRule_ ( `;` _MacroRule_ )\* `;`? +> +> _MacroRule_ :\ +>    _MacroMatcher_ `=>` _MacroTranscriber_ +> +> _MacroMatcher_ :\ +>       `(` _MacroMatch_\* `)`\ +>    | `[` _MacroMatch_\* `]`\ +>    | `{` _MacroMatch_\* `}` +> +> _MacroMatch_ :\ +>       [_Token_]_except $ and delimiters_\ +>    | _MacroMatcher_\ +>    | `$` [IDENTIFIER] `:` _MacroFragSpec_\ +>    | `$` `(` _MacroMatch_+ `)` _MacroRepSep_? _MacroKleeneOp_ +> +> _MacroFragSpec_ :\ +>       `block` | `expr` | `ident` | `item` | `lifetime`\ +>    | `meta` | `pat` | `path` | `stmt` | `tt` | `ty` | `vis` +> +> _MacroRepSep_ :\ +>    [_Token_]_except delimiters and kleene operators_ +> +> _MacroKleeneOp_2015 :\ +>    `*` | `+` +> +> _MacroKleeneOp_2018+ :\ +>    `*` | `+` | `?` +> +> _MacroTranscriber_ :\ +>    [_DelimTokenTree_] + `macro_rules` allows users to define syntax extension in a declarative way. We call such extensions "macros by example" or simply "macros". -Currently, macros can expand to expressions, statements, items, or patterns. - -(A `sep_token` is any token other than `*` and `+`. A `non_special_token` is -any token other than a delimiter or `$`.) +Macros can expand to expressions, statements, items, types, or patterns. The macro expander looks up macro invocations by name, and tries each macro rule in turn. It transcribes the first successful match. Matching and @@ -20,31 +59,32 @@ balanced, but they are otherwise not special. In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the Rust syntax named by _designator_. Valid designators are: -* `item`: an [item] -* `block`: a [block] -* `stmt`: a [statement] -* `pat`: a [pattern] -* `expr`: an [expression] -* `ty`: a [type] -* `ident`: an [identifier] or [keyword] -* `path`: a [path] -* `tt`: a token tree (a single [token] by matching `()`, `[]`, or `{}`) -* `meta`: the contents of an [attribute] -* `lifetime`: a lifetime. Examples: `'static`, `'a`. -* `vis`: a (visibility qualifier)[visibility-and-privacy] - -[item]: items.html -[block]: expressions/block-expr.html -[statement]: statements.html -[pattern]: patterns.html -[expression]: expressions.html -[type]: types.html -[identifier]: identifiers.html -[keyword]: keywords.html -[path]: paths.html +* `item`: an [_Item_] +* `block`: a [_BlockExpression_] +* `stmt`: a [_Statement_] without the trailing semicolon +* `pat`: a [_Pattern_] +* `expr`: an [_Expression_] +* `ty`: a [_Type_] +* `ident`: an [IDENTIFIER_OR_KEYWORD] +* `path`: a [_TypePath_] style path +* `tt`: a [_TokenTree_] (a single [token] or tokens in matching delimiters `()`, `[]`, or `{}`) +* `meta`: a [_MetaItem_], the contents of an attribute +* `lifetime`: a [LIFETIME_TOKEN] +* `vis`: a [_Visibility_] qualifier + +[IDENTIFIER_OR_KEYWORD]: identifiers.html +[LIFETIME_TOKEN]: tokens.html#lifetimes-and-loop-labels +[_BlockExpression_]: expressions/block-expr.html +[_Expression_]: expressions.html +[_Item_]: items.html +[_MetaItem_]: attributes.html +[_Pattern_]: patterns.html +[_Statement_]: statements.html +[_TokenTree_]: macros.html#macro-invocation +[_TypePath_]: paths.html#paths-in-types +[_Type_]: types.html +[_Visibility_]: visibility-and-privacy.html [token]: tokens.html -[attribute]: attributes.html -[visibility-and-privacy]: visibility-and-privacy.html In the transcriber, the 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: a macro definition like `$i:expr [ , ]` is not legal, because `[` could be part of an expression. A macro definition like `$i:expr,` or `$i:expr;` would be legal, however, because `,` and `;` are legal separators. See [RFC 550] for more information. + Specifically: + + * `expr` and `stmt` may only be followed by one of `=>`, `,`, or `;`. + * `pat` may only be followed by one of `=>`, `,`, `=`, `|`, `if`, or `in`. + * `path` and `ty` may only be followed by one of `=>`, `,`, `=`, `|`, `;`, + `:`, `>`, `>>`, `[`, `{`, `as`, `where`, or a macro variable of `block` + fragment type. + * `vis` may only be followed by one of `,`, `priv`, a raw identifier, any + token that can begin a type, or a macro variable of `ident`, `ty`, or + `path` fragment type. + * All other fragment types have no restrictions. + 2. The parser must have eliminated all ambiguity by the time it reaches a `$` _name_ `:` _designator_. This requirement most often affects name-designator pairs when they occur at the beginning of, or immediately after, a `$(...)*`; - requiring a distinctive token in front can solve the problem. + requiring a distinctive token in front can solve the problem. For example: + + ```rust + // The matcher `$($i:ident)* $e:expr` would be ambiguous because the parser + // would be forced to choose between an identifier or an expression. Use some + // token to distinguish them. + macro_rules! example { + ($(I $i:ident)* E $e:expr) => { ($($i)-*) * $e }; + } + let foo = 2; + let bar = 3; + // The following expands to `(foo - bar) * 5` + example!(I foo I bar E 5); + ``` [RFC 550]: https://github.com/rust-lang/rfcs/blob/master/text/0550-macro-future-proofing.md +[_DelimTokenTree_]: macros.html +[_Token_]: tokens.html diff --git a/src/macros.md b/src/macros.md index a68f75dda..d23ee5f97 100644 --- a/src/macros.md +++ b/src/macros.md @@ -9,6 +9,95 @@ There are two ways to define new macros: * [Macros by Example] define new syntax in a higher-level, declarative way. * [Procedural Macros] can be used to implement custom derive. +## Macro Invocation + +> **Syntax**\ +> _MacroInvocation_ :\ +>    [_SimplePath_] `!` _DelimTokenTree_ +> +> _DelimTokenTree_ :\ +>       `(` _TokenTree_\* `)`\ +>    | `[` _TokenTree_\* `]`\ +>    | `{` _TokenTree_\* `}` +> +> _TokenTree_ :\ +>    [_Token_]_except delimiters_ | _DelimTokenTree_ +> +> _MacroInvocationSemi_ :\ +>       [_SimplePath_] `!` `(` _TokenTree_\* `)` `;`\ +>    | [_SimplePath_] `!` `[` _TokenTree_\* `]` `;`\ +>    | [_SimplePath_] `!` `{` _TokenTree_\* `}` + +A macro invocation executes a macro at compile time and replaces the +invocation with the result of the macro. Macros may be invoked in the +following situations: + +* [Expressions] and [statements] +* [Patterns] +* [Types] +* [Items] including [associated items] +* [`macro_rules`] transcribers + +When used as an item or a statement, the _MacroInvocationSemi_ form is used +where a semicolon is required at the end when not using curly braces. +[Visibility qualifiers] are never allowed before a macro invocation or +[`macro_rules`] definition. + +```rust +// Used as an expression. +let x = vec![1,2,3]; + +// Used as a statement. +println!("Hello!"); + +// Used in a pattern. +macro_rules! pat { + ($i:ident) => (Some($i)) +} + +if let pat!(x) = Some(1) { + assert_eq!(x, 1); +} + +// Used in a type. +macro_rules! Tuple { + { $A:ty, $B:ty } => { ($A, $B) }; +} + +type N2 = Tuple!(i32, i32); + +// Used as an item. +# use std::cell::RefCell; +thread_local!(static FOO: RefCell = RefCell::new(1)); + +// Used as an associated item. +macro_rules! const_maker { + ($t:ty, $v:tt) => { const CONST: $t = $v; }; +} +trait T { + const_maker!{i32, 7} +} + +// Macro calls within macros. +macro_rules! example { + () => { println!("Macro call in a macro!") }; +} +// Outer macro `example` is expanded, then inner macro `println` is expanded. +example!(); +``` + [Macros by Example]: macros-by-example.html [Procedural Macros]: procedural-macros.html +[_SimplePath_]: paths.html#simple-paths +[_Token_]: tokens.html +[associated items]: items/associated-items.html [compiler plugins]: ../unstable-book/language-features/plugin.html +[delimiters]: tokens.html#delimiters +[expressions]: expressions.html +[items]: items.html +[`macro_rules`]: macros-by-example.html +[patterns]: patterns.html +[statements]: statements.html +[tokens]: tokens.html +[types]: types.html +[visibility qualifiers]: visibility-and-privacy.html diff --git a/src/patterns.md b/src/patterns.md index d674dea76..92da44467 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -12,7 +12,8 @@ >    | [_TuplePattern_]\ >    | [_GroupedPattern_]\ >    | [_SlicePattern_]\ ->    | [_PathPattern_] +>    | [_PathPattern_]\ +>    | [_MacroInvocation_] Patterns are used to match values against structures and to, optionally, bind variables to values inside these structures. They are also @@ -653,6 +654,7 @@ refer to refutable constants or enum variants for enums with multiple variants. [_GroupedPattern_]: #grouped-patterns [_IdentifierPattern_]: #identifier-patterns [_LiteralPattern_]: #literal-patterns +[_MacroInvocation_]: macros.html#macro-invocation [_PathInExpression_]: paths.html#paths-in-expressions [_PathPattern_]: #path-patterns [_Pattern_]: #patterns diff --git a/src/statements.md b/src/statements.md index c8fa66a1a..ab89cbd73 100644 --- a/src/statements.md +++ b/src/statements.md @@ -5,7 +5,8 @@ >       `;`\ >    | [_Item_]\ >    | [_LetStatement_]\ ->    | [_ExpressionStatement_] +>    | [_ExpressionStatement_]\ +>    | [_MacroInvocationSemi_] A *statement* is a component of a [block], which is in turn a component of an @@ -130,6 +131,7 @@ statement are [`cfg`], and [the lint check attributes]. [_Expression_]: expressions.html [_Item_]: items.html [_LetStatement_]: #let-statements +[_MacroInvocationSemi_]: macros.html#macro-invocation [_OuterAttribute_]: attributes.html [_Pattern_]: patterns.html [_Type_]: types.html diff --git a/src/types.md b/src/types.md index fa235c409..59203a726 100644 --- a/src/types.md +++ b/src/types.md @@ -19,7 +19,8 @@ >    | [_SliceType_]\ >    | [_InferredType_]\ >    | [_QualifiedPathInType_]\ ->    | [_BareFunctionType_] +>    | [_BareFunctionType_]\ +>    | [_MacroInvocation_] Every variable, item and value in a Rust program has a type. The _type_ of a *value* defines the interpretation of the memory holding it. @@ -868,6 +869,7 @@ impl Printable for String { [_ImplTraitType_]: #impl-trait [_InferredType_]: #inferred-type [_Lifetime_]: trait-bounds.html +[_MacroInvocation_]: macros.html#macro-invocation [_NeverType_]: #never-type [_ParenthesizedType_]: #parenthesized-types [_QualifiedPathInType_]: paths.html#qualified-paths