aip-filtering 0.1.0

Simple implementation of AIP-160 filtering
Documentation
filter = _{ SOI ~ expression? ~ EOI }

expression = { sequence ~ ("AND" ~ sequence)* }

sequence = { factor+ }

factor = { term ~ ("OR" ~ term)* }

term = { negation? ~ simple }

negation = { "NOT" | "-" }

simple = _{ composite | restriction }

restriction = { comparable ~ (comparator ~ arg)? }

comparable = _{ function | member }

member = { value ~ ("." ~ field)* }

function = { function_name ~ "(" ~ arg_list? ~ ")" }
function_name = { name ~ ("." ~ name)* }

comparator = { lt_eq | lt | gt_eq | gt | ne | eq | has }
    eq    = { "=" }
    gt    = { ">" }
    gt_eq = { ">=" }
    has   = { ":" }
    lt    = { "<" }
    lt_eq = { "<=" }
    ne    = { "!=" }

composite = _{ "(" ~ expression ~ ")" }

value = { string | text }

field = { keyword | value }

name = { keyword | text }

arg_list = { arg ~ ("," ~ arg)* }

arg = _{ composite | comparable }

keyword = { "NOT" | "AND" | "OR" }

text = ${ !keyword ~ text_inner }
text_inner = @{ text_char+ }
// text_char = { (ASCII_ALPHANUMERIC | "_" | "*") ~ (!("." | ":") ~ ANY*) }
text_char = { !("." | "," | ":" | "(" | ")" | WHITESPACE) ~ ANY }

string = ${ PUSH("\"" | "'") ~ string_char* ~ POP }
string_inner = @{ string_char* }
string_char = { !(PEEK | "\\") ~ ANY | "\\" ~ PEEK }

WHITESPACE = _{ " " | "\t" }