<!-- Generated by `cargo xtask antlr generate {{ slug }}` from xtask/templates/parser-readme.md. Do not edit by hand. -->
# {{ crate_name }}

ANTLR-generated **{{ display_name }}** lexer and parser, running on the
[`antlr-rust-runtime`](https://github.com/ophi-dev/antlr-rust-runtime) Rust
runtime.

This crate is produced by the [`mehen`]({{ repo_url }}) code-metrics tool but
carries **no mehen-specific logic** and **no dependency on `mehen-core`**: it
ships only the machine-generated lexer/parser plus the vendored `.g4` grammar.
That makes it usable on its own — the same way `mehen` itself consumes the
ruff / oxc / sqruff parser crates — so you can parse {{ display_name }} in your
own tool without pulling in an analyzer.

<!-- Both the modules under `src/generated/` and this README are generated and
     checked in verbatim; regenerate with `cargo xtask antlr generate {{ slug }}`. -->

## Add the dependency

The crate is published from a git tag on the [`mehen` repository]({{ repo_url }}),
not to crates.io. Depend on it by tag or branch:

```toml
[dependencies]
# Pin a release tag (recommended) — see the repository's Releases page:
{{ crate_name }} = { git = "{{ repo_url }}", tag = "vX.Y.Z" }
# …or track the default branch:
# {{ crate_name }} = { git = "{{ repo_url }}", branch = "main" }
```

You do **not** need to depend on `antlr-rust-runtime` yourself: this crate
re-exports the exact runtime revision the modules were generated against as
`{{ crate_ident }}::antlr4_runtime`. Reach the runtime types (`ParsedFile`,
`Node`, `TokenView`, …) through that path so your version can never drift from
the generated code.
{% if lexer_hooks.is_some() || parser_hooks.is_some() %}
## Parse some {{ display_name }}

The grammar declares helper methods on a superclass (`superClass=…`); this
crate ships exact Rust ports as typed hooks in [`src/hooks.rs`](src/hooks.rs),
and they **must be installed at construction**. The modules are generated
under `--sem-unknown error`, so a lexer/parser built without its hooks
fails loud (`AntlrError::Unsupported`) the moment an input reaches a hooked
predicate or action — it never silently mis-parses. In particular, skip the
hook-less one-call `{{ parser_module }}::parse` / `parse_with_parser`
helpers and construct with hooks:

```rust
{%- if let Some(hooks) = parser_hooks %}
use {{ crate_ident }}::{{ hooks.path }};
{%- endif %}
{%- if let Some(hooks) = lexer_hooks %}
use {{ crate_ident }}::{{ hooks.path }};
{%- endif %}
use {{ crate_ident }}::{{ parser_module }}::{{ parser_type }};
use {{ crate_ident }}::{{ lexer_module }}::{{ lexer_type }};
use {{ crate_ident }}::antlr4_runtime::{CommonTokenStream, InputStream, Parser};

fn main() -> Result<(), {{ crate_ident }}::antlr4_runtime::AntlrError> {
    let input = InputStream::new("{{ sample_source }}\n");
{%- if let Some(hooks) = lexer_hooks %}
    let lexer = {{ lexer_type }}::with_typed_hooks(input, {{ hooks.type_name }}::default());
{%- else %}
    let lexer = {{ lexer_type }}::new(input);
{%- endif %}
    let tokens = CommonTokenStream::new(lexer);
{%- if let Some(hooks) = parser_hooks %}
    let mut parser = {{ parser_type }}::with_typed_hooks(tokens, {{ hooks.type_name }}::default());
{%- else %}
    let mut parser = {{ parser_type }}::new(tokens);
{%- endif %}
    let result = parser.{{ entry_rule }}()?;

    // Parser diagnostics, then the owned `ParsedFile` (token store + flat CST).
    let errors = parser.number_of_syntax_errors();
    let parsed = parser.into_parsed_file(result);
    let root = parsed.tree();
    let _ = (errors, root);
    Ok(())
}
```
{%- else %}
## Parse some {{ display_name }}

`{{ parser_module }}::parse` wires up the lexer, token stream, parser, and a
chosen entry rule in one call, returning an owned `ParsedFile` that holds the
token store and the flat CST:

```rust
use {{ crate_ident }}::{{ parser_module }}::{self, {{ parser_type }}};
use {{ crate_ident }}::{{ lexer_module }}::{{ lexer_type }};

fn main() -> Result<(), {{ crate_ident }}::antlr4_runtime::AntlrError> {
    let parsed = {{ parser_module }}::parse(
        "{{ sample_source }}\n",
        {{ lexer_type }}::new,
        {{ parser_type }}::{{ entry_rule }},
    )?;

    // Walk the CST from the entry-rule root, or read the buffered tokens.
    let root = parsed.tree();
    let _ = root;
    Ok(())
}
```

Need parser diagnostics (e.g. the syntax-error count) after the entry rule
runs? Use `parse_with_parser`, which hands the parser back:

```rust
use {{ crate_ident }}::{{ parser_module }}::{self, {{ parser_type }}};
use {{ crate_ident }}::{{ lexer_module }}::{{ lexer_type }};
// `number_of_syntax_errors` is a `Parser`-trait method, so the trait must be
// in scope to call it.
use {{ crate_ident }}::antlr4_runtime::Parser;

fn main() -> Result<(), {{ crate_ident }}::antlr4_runtime::AntlrError> {
    let out = {{ parser_module }}::parse_with_parser(
        "{{ sample_source }}\n",
        {{ lexer_type }}::new,
        {{ parser_type }}::{{ entry_rule }},
    )?;
    let errors = out.parser.number_of_syntax_errors();
    let parsed = out.parser.into_parsed_file(out.result);
    let _ = (errors, parsed.tree());
    Ok(())
}
```
{%- endif %}

The parse tree has **no parent pointers** (the runtime stores `Node` views in a
flat arena), so thread any parent-dependent context top-down as you walk.

## Grammar & provenance

- **Upstream grammar:** [`{{ upstream_name }}`]({{ upstream_url }})
- **Vendored `.g4` files + any local patches:** [`grammar/`](grammar/) — see [`grammar/PROVENANCE.md`](grammar/PROVENANCE.md) for the exact commit
- **ANTLR Rust runtime + codegen:** [`antlr-rust-runtime`](https://crates.io/crates/antlr-rust-runtime) / [`antlr-rust-codegen`](https://crates.io/crates/antlr-rust-codegen) `v{{ runtime_version }}`

## License

`AGPL-3.0-only`, same as the `mehen` workspace.
