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.
-- 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.
-- 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.
-- 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().
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("^_"))