ion7-grammar / except

module

except

local Except = require "ion7.grammar.except"

-- Only non-vowel lowercase letters
local consonants = Except.except_chars("a-z", {"a","e","i","o","u"})

-- Match any status except "error"
local ok_status = Except.except_values(
    { "ok", "pending", "error", "closed" },
    { "error" }
)

-- Keys not starting with underscore
local public_key = Except.except_prefix(
    Grammar.from_regex("[a-z][a-z0-9_]*"),
    { "_" }
)

Functions

Except.except_chars

Exclude specific characters from a character class. Returns an AST node (char class) with the specified characters removed. Exact - no approximation needed for character-level exclusions.

Except.except_chars(base_spec, exclude, negated)
base_specstringBase character class spec (e.g. "a-zA-Z0-9").
excludetableCharacters to exclude (e.g. {"a","e","i"}).
negatedboolean?Whether base_spec is already negated.
→ nodeAST char node.
-- All lowercase letters except vowels
Except.except_chars("a-z", {"a","e","i","o","u"})
-- Digits except zero
Except.except_chars("0-9", {"0"})

Except.except_values

Match any value from a universe EXCEPT the excluded values. Exact when the universe of valid values is finite and known. Returns the whitelist complement as an alternation grammar.

Except.except_values(universe, exclude, name)
universetableAll possible values (the full set).
excludetableValues to exclude.
namestring?Rule name (default: "except").
→ Builder
-- Any HTTP method except DELETE
Except.except_values(
    { "GET", "POST", "PUT", "DELETE", "PATCH" },
    { "DELETE" }
)

Except.except_prefix

Match strings that do NOT start with any of the given prefixes. Approximate: implemented by requiring the first character to not be in the prefix set. Works well for single-char prefixes (like "_", "$"). For multi-char prefixes, falls back to char-class exclusion of first char.

Except.except_prefix(base_grammar, prefixes, name)
base_grammarBuilderGrammar to add prefix constraint to.
prefixestableForbidden prefix strings.
namestring?Rule name (default: "no_prefix").
→ Builder
-- Identifiers not starting with underscore
Except.except_prefix(
    Grammar.builder():rule("root", Grammar.seq(
        Grammar.char("a-zA-Z_"), Grammar.star(Grammar.char("a-zA-Z0-9_"))
    )),
    { "_" }
)

Except.except_pattern

Backtrack-based exclusion - use with Grammar.backtrack(). The most general approach: generate freely but reject strings matching the exclusion pattern. Requires ion7-core Backtrack object. This is a factory that returns a validator function suitable for Backtrack:constrain() or Backtrack:backward().

Except.except_pattern(pattern)
patternstringLua pattern string. Strings matching this are rejected.
→ functionfn(text) → bool true = accept, false = reject.
local bt = Grammar.backtrack(ctx, vocab, sampler)
bt:checkpoint("field_name")
bt:forward(function(p) return p:find("%s") end)
bt:constrain("field_name", Except.except_pattern("^_"))