# Rust grammar

The Reference grammar is written in Markdown code blocks using a modified BNF-like syntax (with a blend of regex and other arbitrary things). The [`mdbook-spec`] extension parses these rules and converts them into a renderable format, including railroad diagrams.

The code block should have a lang string with the word `grammar`, a comma, and the category of the grammar, like this:

~~~
```grammar,items
ProductionName -> SomeExpression
```
~~~

The category is used to group similar productions on the grammar summary page in the appendix.

## Grammar syntax

The syntax for the grammar itself is similar to what is described in **[Notation]**, though there are some rendering differences.

A "root" production, marked with `@root`, is one that is not used in any other production.

The syntax for the grammar notation, described here using its own notation, is:

```
Grammar -> Production+

BACKTICK -> U+0060

LF -> U+000A

Production ->
    ( Comment LF )*
    `@root`? Name ` ->` Expression

Name -> <Alphanumeric or `_`>+

Expression -> Sequence (` `* `|` ` `* Sequence)*

Sequence ->
        (` `* AdornedExpr)* ` `* Cut
      | (` `* AdornedExpr)+

AdornedExpr -> Prefix? Expr1 Quantifier? Suffix? Footnote?

Prefix -> NegativeLookahead

NegativeLookahead -> `!`

Suffix -> ` _` <not underscore, unless in backtick>* `_`

Footnote -> `[^` ~[`]` LF]+ `]`

Quantifier ->
      Optional
    | Repeat
    | RepeatPlus
    | RepeatRange
    | RepeatRangeInclusive
    | RepeatRangeNamed

Optional -> `?`

Repeat -> `*`

RepeatPlus -> `+`

RepeatRange -> `{` ( Name `:` )? Range? `..` Range? `}`

RepeatRangeInclusive -> `{` ( Name `:` )? Range? `..=` Range `}`

RepeatRangeNamed -> `{` Name `}`

Range -> [0-9]+

Expr1 ->
      Unicode
    | NonTerminal
    | Break
    | Comment
    | Terminal
    | Charset
    | Prose
    | Group
    | NegativeExpression

Unicode -> `U+` [`A`-`Z` `0`-`9`]4..=6

NonTerminal -> Name

Break -> LF ` `+

Comment -> `//` ~[LF]+

Terminal -> BACKTICK ~[LF]+ BACKTICK

Charset -> `[` (` `* Characters)+ ` `* `]`

Characters ->
      CharacterRange
    | CharacterTerminal
    | CharacterName

CharacterRange -> Character `-` Character

Character ->
        BACKTICK <any char> BACKTICK
      | Unicode

CharacterTerminal -> Terminal

CharacterName -> Name

Prose -> `<` ~[`>` LF]+ `>`

Group -> `(` ` `* Expression ` `* `)`

NegativeExpression -> `~` ( Charset | Terminal | NonTerminal )

Cut -> `^` Sequence
```

The general format is a series of productions separated by blank lines. The expressions are as follows:

| Expression | Example | Description |
|------------|---------|-------------|
| Unicode | U+0060 | A single Unicode character. |
| NonTerminal | FunctionParameters | A reference to another production by name. |
| Break | | Used internally by the renderer to detect line breaks and indentation. |
| Comment | // Single line comment. | A comment extending to the end of the line. |
| Terminal | \`example\` | A sequence of exact characters, surrounded by backticks. |
| Charset | \[ \`A\`-\`Z\` \`0\`-\`9\` \`_\` \] | A choice from a set of characters, space-separated. There are three different forms. |
| CharacterRange | \[ \`A\`-\`Z\` \] | A range of characters. Characters can be a Unicode expression or be a literal character surrounded by backticks. |
| CharacterTerminal | \[ \`x\` \] | A single character, surrounded by backticks. |
| CharacterName | \[ LF \] | A nonterminal, referring to another production. |
| Prose | \<any ASCII character except CR\> | An English description of what should be matched, surrounded in angle brackets. |
| Group | (\`,\` Parameter)+ | Groups an expression for the purpose of precedence, such as applying a repetition operator to a sequence of other expressions. |
| NegativeExpression | ~\[\` \` LF\] | Matches anything except the given Charset, Terminal, or Nonterminal. |
| Cut | Expr1 ^ Expr2 \| Expr3 | The hard cut operator. Once the expressions preceding `^` in the sequence match, the rest of the sequence must match or parsing fails unconditionally --- no enclosing expression can backtrack past the cut point. |
| Sequence | \`fn\` Name Parameters | A sequence of expressions that must match in order. |
| Alternation | Expr1 \| Expr2 | Matches only one of the given expressions, separated by the vertical pipe character. |
| Suffix | \_except \[LazyBooleanExpression\]\_  | Adds a suffix to the previous expression to provide an additional English description, rendered in subscript. This can contain limited Markdown, but try to avoid anything except basics like links. |
| Footnote | \[^extern-safe\] | Adds a footnote, which can supply extra information that may be helpful to the user. The footnote itself should be defined outside of the code block like a normal Markdown footnote. |
| Optional | Expr? | The preceding expression is optional. |
| NegativeLookahead | !Expr | Matches if Expr does not follow, without consuming any input. |
| Repeat | Expr* | The preceding expression is repeated 0 or more times. |
| RepeatPlus | Expr+ | The preceding expression is repeated 1 or more times. |
| RepeatRange | Expr{2..4} | The preceding expression is repeated between the range of times specified. Either bound can be excluded, which works just like Rust ranges. |
| RepeatRangeInclusive | Expr{2..=4} | The preceding expression is repeated between the inclusive range of times specified. The lower bound can be omitted. |
| RepeatRange (named) | Expr{name:2..4} | When a name precedes the range, the number of repetitions is bound to that name so that subsequent RepeatRangeNamed expressions can refer to it. The same applies to RepeatRangeInclusive. |
| RepeatRangeNamed | Expr{name} | The preceding expression is repeated the number of times determined by a previously named RepeatRange or RepeatRangeInclusive. |

## Automatic linking

The [`mdbook-spec`] plugin automatically adds Markdown link definitions for all production names on every page. To link directly to a production name, simply surround it in square brackets, like `[ArrayExpression]`.

In some cases, there might be name collisions with the automatic linking of rule names. In that case, disambiguate with the `grammar-` prefix, such as `[Type][grammar-Type]`. The prefix can also be used when explicitness would aid clarity.

Production names can also be used in link reference definitions to provide custom link text, both with and without the `grammar-` prefix.

```markdown
We accept any [type].

[type]: grammar-Type
```

```markdown
We accept any [type].

[type]: Type
```

[`mdbook-spec`]: tooling/mdbook-spec.md
[Notation]: https://doc.rust-lang.org/nightly/reference/notation.html
