# `Grammar.VM.CharInterpreter`
[🔗](https://github.com/joetjen/ichor/blob/v0.3.0/lib/grammar/vm/char_interpreter.ex#L1)

Runs a `Grammar.VM.CharCompiler`-produced program against raw input
text -- the machine `Grammar.VM.Tokenizer` uses to test one token at a
given starting position.

Each backtrack (choice-point) entry snapshots the *call* stack
alongside input position, not just position -- a failed nested `:call`
(e.g. retrying a `Star` loop's body one time too many) unwinds via the
backtrack mechanism, jumping straight to some choice point's target
without ever executing that call's own `:return`. Without restoring the
call stack too, that call's return address is orphaned on it, and gets
popped at the wrong time later, corrupting execution. This is a
standard, if easy to miss, requirement for any PEG bytecode VM in this
LPeg-derived style.

`Star`'s loop-back uses `:test_progress`, not plain `:commit` -- a
runtime guard against a body that matches without consuming anything
(see `Grammar.VM.Compiler`'s docs on why this can't be left to
`Grammar.Analysis`'s static empty-repetition check alone).

# `run`

```elixir
@spec run(tuple(), non_neg_integer(), String.t()) :: {:ok, String.t()} | :fail
```

Attempts to match `entry` starting at `input`. On success, returns the
unconsumed remainder (its byte-size difference from `input` is how much
was matched -- exactly what maximal munch needs to compare candidates).

---

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