// https://datatracker.ietf.org/doc/html/rfc2254

rfc2254    = _{ SOI ~ filter ~ EOI }
filter     = _{ "(" ~ filtercomp ~ ")" }
filtercomp = _{ and | or | not | item }
and        = { "&" ~ filterlist }
or         = { "|" ~ filterlist }
not        = { "!" ~ filter }
filterlist = _{ filter+ }
item       = _{ simple | present | substring | extensible }
simple     = { attr ~ filtertype ~ value ~ !"*" }
filtertype = _{ equal | approx | greater | less }
equal      = { "=" }
approx     = { "~=" }
greater    = { ">=" }
less       = { "<=" }
extensible = { (attr ~ dnattr? ~ (":" ~ ruleid)? ~ ":=" ~ value) | (dnattr? ~ ":" ~ ruleid ~ ":=" ~ value) }
present    = { attr ~ "=*" ~ !value }
substring  = { attr ~ "=" ~ initial? ~ "*" ~ (any ~ "*")* ~ final_? }
initial    = { value }
any        = { value }
final_     = { value }
attr       = _{ ident }
dnattr     = { ":dn" }
value      = _{ string }
string     = { (("\\" ~ ASCII_HEX_DIGIT{2}) | char)+ }
char       = _{ !("*" | "(" | ")" | "\\" | "\u{0000}") ~ ANY }
ident      = { (ASCII_ALPHANUMERIC | "_")+ }
ruleid     = { int ~ ("." ~ int)* ~ "."? }
int        = { "0" | (ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) }
