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.