# `Ichor.ABNF.Actions`
[🔗](https://github.com/joetjen/ichor/blob/v0.3.0/lib/ichor/abnf/actions.ex#L1)

Turns a parsed ABNF `rulelist` (RFC 5234 + RFC 7405) into a real
`%{rule_name_atom => Grammar.IR.expr()}` map -- one `Grammar.IR` tree
per ABNF rule, mirroring how `Regex.Actions` turns a single
`/pattern/` into one `Grammar.IR` tree. This is an importer's own
output, not a runnable `Aether.Grammar` -- ABNF has no lexer/rule
(token/parser) split the way Aether does, so deciding which of an
ABNF ruleset's productions become Aether tokens vs. rules is a
separate concern this module doesn't address.

Rule names are matched case-insensitively per RFC 5234 (rule name
comparison is defined to ignore case) -- every name is downcased
before becoming an atom, so `Ip4-Octet` and `ip4-octet` are the same
key. `"=/"` (RFC 7405's incremental-alternatives form) appends to an
already-`"="`-defined rule's own top-level `Grammar.IR.Choice`
(wrapping a non-`Choice` single alternative into one first); using
`"=/"` before any `"="` for that name, or repeating a plain `"="` for
the same name twice, is a real error (`Ichor.Error`, `stage: :action`),
not silently accepted -- RFC 5234 section 3.3 defines `"=/"` as
extending a rule that already exists.

`prose_val` (`<...>`, RFC 5234 section 3.6 -- free-form English text
standing in for a rule body, "a last resort") has no executable
meaning at all, so it's rejected the same deliberate way regex's own
backreferences/named-groups/anchors are: `Ichor.Error`, not silently
ignored or half-supported.

One known, narrow, deliberately-accepted gap: a comment trailing a
rule's own definition on the *same* line isn't supported, only a
comment on its own line -- real RFC 5234 allows `c-nl = comment /
CRLF` right after a rule's `elements`; this grammar requires a bare
`CRLF` there instead.

---

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