# Rust grammar

`Rust.g4` is pinned from
[`uw-pluverse/perses`](https://github.com/uw-pluverse/perses/blob/29f9553367654ca682a8aca40b92ce5139114a7e/src/org/perses/grammar/rust/Rust.g4)
at commit `29f9553367654ca682a8aca40b92ce5139114a7e`. Perses attributes
the original grammar to
[`jorendorff/rust-grammar`](https://github.com/jorendorff/rust-grammar),
which distributes it under the MIT or Apache-2.0 license.

This copy is intentionally action-free. Relative to the pinned Perses source,
it removes:

- the Java `@lexer::members` token-tracking override;
- the predicate that distinguishes a decimal point from ranges and field
  access, with trailing-dot floats recognized at parser level instead; and
- the predicate that checks the previously emitted token for chained tuple
  indexing.

It also adds an action-free `let_chain` production so recovery does not discard
the remainder of an embedded body after modern chained conditions, including
chains whose first operand is not `let`, and a `let ... else` statement
alternative so those bindings parse without recovery. Associated-type bounds
in generic arguments and `pub(self)` visibility are accepted without
target-specific actions. Tuple-field indices include their leading dot as a
token so chained accesses such as `pair.0.1` cannot be lexed as a decimal
floating-point literal. Raw-reference expressions model `&` and the contextual
`raw` keyword as separate tokens, so comments or whitespace may separate them
without preventing `raw` from being used as an identifier elsewhere.
Closure parameters use Rust's `PatternNoTopAlt` split so a following closure's
opening pipe cannot be consumed as part of the preceding parameter pattern,
async closures accept the stable form without `move`, and stable inline
`const { ... }` blocks are accepted as block expressions. Stable normal and
raw C string literals use their C-specific byte escapes and reject embedded NUL
and carriage-return characters. Edition 2024 `unsafe extern` blocks and their
`safe` function/static qualifiers are accepted. Stable raw lifetime names are
accepted as lifetime tokens. Identifier fragments use the generator's scalar
`XID_Start` and `XID_Continue` Unicode properties instead of the source
grammar's Java-oriented UTF-16 pairs.

Additional local corrections accept recursive raw references, underscore-led
exponents, one-sided range patterns, attributed higher-ranked lifetimes, const
generic expression defaults, `safe` as a contextual identifier, underscored
Unicode escapes, multiple match-body inner attributes, `pub(in self)`, empty
turbofish argument lists, empty `where` clauses, explicit `unsafe` foreign
statics, attributed variadic parameters, attributed shorthand struct fields,
full patterns after numeric tuple-field names, unbraced literal const-generic
arguments, standalone inner attributes at the start of impl bodies, and the
atomic `>=` token in no-struct comparison expressions.

The recognizer is used only to classify embedded Rust syntax needed by
compatibility alias lowering. It does not aim to reproduce every rustc
tokenization detail, but it does preserve distinctions that affect structural
classification, such as chained tuple-field access.

The checked-in recognizers under
`crates/antlr-rust-rs-parser/src/generated/` are generated by this project's own
`antlr4-rust-gen` binary. Verify them with:

```text
tools/rust-syntax/update-generated.sh --check
```

Regenerate them with `tools/rust-syntax/update-generated.sh --update`.

The baseline generator output is retained because the optional optimization
passes do not reduce this recognizer: reachability pruning removes no rules,
while precedence-ladder collapse and fixed-lookahead specialization both
increase the generated Rust source size.
