# `Grammar.Native.RuleCompiler`
[🔗](https://github.com/joetjen/ichor/blob/v0.7.0/lib/grammar/native/rule_compiler.ex#L1)

Compiles every rule in a grammar into quoted Elixir function
definitions run against the lexer's token stream (never raw
characters -- Aether's own two-stage split), mirroring
`Grammar.VM.RuleCompiler`'s own semantics exactly (bare-reference
implicit self-capture, `Indent`/`@samecol`, capture-shape rules) but
producing direct function calls instead of bytecode.

Every generated function has the shape `(stream :: tuple(), pos ::
non_neg_integer(), ref_stack :: [integer()], context :: term()) ->
{:ok, new_pos, new_ref_stack, raw_captures} | :fail`, where
`raw_captures` is exactly the ordered-list shape `Ichor.Actions`
expects (`{:token, name, text}` / `{:rule, name, sub_captures}` /
`{:text, text}` values, keyed by name, in first-occurrence RHS
order -- see `t:Ichor.Capture.raw_captures/0`), each value recording
the tokens `[pos, new_pos)` it matched (`Ichor.Capture.at/3`), so an
action's error can say where. `context` is read-only,
threaded through purely so a
`Grammar.IR.Custom` `@native(...)` leaf can hand it to
`c:Ichor.CustomRule.match/4` -- nothing else in this module ever reads
it, only passes it along. A `RuleRef` compiles to a call into that
other rule/token's own compiled function; the grammar's own token/rule
namespaces (passed in as `token_names`) are what tell the two apart,
exactly as in the VM.

# `compile`

```elixir
@spec compile(Aether.Grammar.t(), keyword()) :: [Macro.t()]
```

Compiles every rule into a list of quoted `defp` definitions, one named
`rule_fn_name/1` per rule plus one per anonymous sub-expression.

With `lossless: true`, the second set a lossless parser runs instead
(`lossless_rule_fn_name/1`, `design/lossless-mode.md`): the same
functions under their own names, but every rule call also records
itself for `Ichor.Syntax`, under `Ichor.Syntax.Record.key/0`. A set
of its own rather than a flag in the one set, so the ordinary
parser's functions are exactly what they were, and nothing on its path
checks which mode it is in.

# `lossless_rule_fn_name`

```elixir
@spec lossless_rule_fn_name(atom()) :: atom()
```

The lossless set's function for a rule (`compile/2` with `lossless: true`).

# `rule_fn_name`

```elixir
@spec rule_fn_name(atom()) :: atom()
```

The generated function name for a given rule name -- exposed so `Grammar.Native` can reference the root rule's own matcher.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
