Skip to content

Commit 097c718

Browse files
committed
---
yaml --- r: 23470 b: refs/heads/master c: d5f0bf9 h: refs/heads/master v: v3
1 parent f455b08 commit 097c718

File tree

2 files changed

+91
-2
lines changed

2 files changed

+91
-2
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 90812c143dbc5aff21f1cee88e60d86419cc39ac
2+
refs/heads/master: d5f0bf922c96054d628bd4bca986726643c799b5
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: cd6f24f9d14ac90d167386a56e7a6ac1f0318195
55
refs/heads/try: ffbe0e0e00374358b789b0037bcb3a577cd218be

trunk/doc/rust.md

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ error.
350350
Examples of integer literals of various forms:
351351

352352
~~~~
353-
123; 0xff00; // type determined by program context;
353+
123; 0xff00; // type determined by program context
354354
// defaults to int in absence of type
355355
// information
356356
@@ -455,6 +455,95 @@ let x = id::<int>(10); // Type arguments used in a call expression
455455
# }
456456
~~~~
457457

458+
# Syntax extensions
459+
460+
A number of minor features of Rust are not central enough to have their own
461+
syntax, and yet are not implementable as functions. Instead, they are given
462+
names, and invoked through a consistent syntax: `name!(...)`. Examples
463+
include:
464+
465+
* `fmt!` : format data into a string
466+
* `env!` : look up an environment variable's value at compile time
467+
* `stringify!` : pretty-print the Rust expression given as an argument
468+
* `proto!` : define a protocol for inter-task communication
469+
* `include!` : include the Rust expression in the given file
470+
* `include_str!` : include the contents of the given file as a string
471+
* `include_bin!` : include the contents of the given file as a binary blob
472+
473+
All of the above extensions, with the exception of `proto!`, are expressions
474+
with values. `proto!` is an item, defining a new name.
475+
476+
## Macros
477+
478+
User-defined syntax extensions are called "macros", and they can be defined
479+
with the `macro_rules!` syntax extension.
480+
481+
~~~~ {.ebnf .gram}
482+
expr_macro_rules : "macro_rules" '!' ident '(' macro_rule * ')'
483+
macro_rule : '(' matcher * ')' "=>" '(' transcriber * ')' ';'
484+
matcher : '(' matcher * ')' | '[' matcher * ']'
485+
| '{' matcher * '}' | '$' ident ':' ident
486+
| '$' '(' matcher * ')' sep_token? [ '*' | '+' ]
487+
| non_special_token
488+
transcriber : '(' transcriber * ')' | '[' transcriber * ']'
489+
| '{' transcriber * '}' | '$' ident
490+
| '$' '(' transcriber * ')' sep_token? [ '*' | '+' ]
491+
| non_special_token
492+
493+
~~~~
494+
(A `sep_token` is any token other than `*` and `+`. A `non_special_token` is
495+
any token other than a delimiter or `$`.)
496+
497+
Macro invocations are looked up by name, and each macro rule is tried in turn;
498+
the first successful match is transcribed. The matching and transcribing
499+
processes are close cousins, and will be described together:
500+
501+
### Macro By Example
502+
503+
Everything that does not begin with a `$` is matched and transcirbed
504+
literally, including delimiters. For parsing reasons, they must be matched,
505+
but they are otherwise not special.
506+
507+
In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the
508+
Rust syntax named by _designator_. Valid designators are `item`, `block`,
509+
`stmt`, `pat`, `expr`, `ty`, `ident`, `path`, `tt`, `matchers`. The last two
510+
are the right-hand side and the left-hand side respectively of the `=>` in
511+
macro rules. In the transcriber, the designator is already known, and so only
512+
the name of a matched nonterminal comes after the dollar sign.
513+
514+
In bothe the matcher and transcriber, the Kleene star-like operator,
515+
consisting of `$` and parens, optionally followed by a separator token,
516+
followed by `*` or `+`, indicates repetition. (`*` means zero or more
517+
repetitions, `+` means at least one repetition. The parens are not matched or
518+
transcribed). On the matcher side, a name is bound to _all_ of the names it
519+
matches, in a structure that mimics the structure of the repetition
520+
encountered on a successful match. The job of the transcriber is to sort that
521+
structure out.
522+
523+
The rules for transcription of these repetitions are called "Macro By Example". Essentially, one "layer" of repetition is discharged at a time, and all of
524+
them must be discharged by the time a name is transcribed. Therefore,
525+
`( $( $i:ident ),* ) => ( $i )` is an invalid macro, but
526+
`( $( $i:ident ),* ) => ( $( $i:ident ),* )` is acceptable (if trivial).
527+
528+
When Macro By Example encounters a repetition, it examines all of the `$`
529+
_name_ s that occur in its body. At the "current layer", they all must repeat
530+
the same number of times, so
531+
` ( $( $i:ident ),* ; $( $j:ident ),* ) => ( $( ($i,$j) ),* )` is valid if
532+
given the argument `(a,b,c ; d,e,f)`, but not `(a,b,c ; d,e)`. The repetition
533+
walks through the choices at that layer in lockstep, so the former input
534+
transcribes to `( (a,d), (b,e), (c,f) )`.
535+
536+
Nested repetitions are allowed.
537+
538+
## Syntax extensions useful for the macro author
539+
540+
* `log_syntax!` : print out the arguments at compile time
541+
* `trace_macros!` : supply `true` or `false` to enable or disable printing
542+
of the macro expansion process.
543+
* `ident_to_str!` : turns the identifier argument into a string literal
544+
* `concat_idents!` : creates a new identifier by concatenating its arguments
545+
546+
458547

459548
# Crates and source files
460549

0 commit comments

Comments
 (0)