WHITESPACE = _{ " " | "\t" }
COMMENT = _{ "#" ~ (!NEWLINE ~ ANY)* }
file = { SOI ~ (statement? ~ NEWLINE)* ~ EOI }
statement = { define | capability | position | property | pixelmap | animdef | animframe | mapping }
string = { ("\"" ~ (!"\"" ~ ANY)* ~ "\"") | ("'" ~ (!"'" ~ ANY)* ~ "'") }
reserved = _{ "\"" | ":" | "," | ";" | "[" | "]" | "(" | ")" }
char = @{ !(WHITESPACE | reserved) ~ ANY }
name_char = @{ LETTER | NUMBER | CONNECTOR_PUNCTUATION }
name = @{ name_char+ }
word = @{ char+ }
value = @{ string | word }
number = @{ "0x" ~ ASCII_HEX_DIGIT+ | NUMBER+ }
id = _{ string | number }
id_with_state = _{ id ~ state? }
range = { id_with_state ~ ("-" ~ id_with_state)? }
ids = { range ~ ("," ~ range)* }
index = _{ "[" ~ ids ~ "]" }
time = { NUMBER ~ ("s" | "ms" | "us") }
state = _{ "(" ~ kvmap ~ ")" }
layer_type = { "LayerShift" | "LayerLatch" | "LayerLock" | "Layer" }
charcode = { ("'" | "u'") ~ (!"'" ~ ANY) ~ "'" }
pixel = { "P" ~ (index | id) }
pixellayer = _{ "PL" ~ (index | id) }
scancode = { "S" ~ (index | id) }
unicode = { "U+" ~ value }
unistr = { "u" ~ string }
usbcode = { "U" ~ (index | id) }
consumer = { "CONS" ~ (index | id) }
system = { "SYS" ~ (index | id) }
indicator = { "I" ~ (index | id) }
layer = { layer_type ~ index }
trig = { "T[" ~ number ~ "," ~ number ~ "]" }
none = { "None" }
key = { scancode | charcode | usbcode }
kv = { word ~ (":" ~ word)? }
kvmap = { kv ~ ("," ~ kv)* }
array = { name ~ "[" ~ number? ~ "]" }
function = { name ~ "(" ~ kvmap? ~ ")" }
rhs = { value ~ value* }
lhs = _{ array | name | string }
property = { lhs ~ "=" ~ rhs ~ ";" }
define = { name ~ "=>" ~ value ~ ";" }
capability = { name ~ "=>" ~ function ~ ";" }
position = { (scancode | pixel) ~ "<=" ~ kvmap ~ ";" }
trigger_type = { key | layer | indicator | trig | animation }
trigger = { trigger_type ~ ("(" ~ kvmap ~")")? }
trigger_group = { trigger ~ ("+" ~ trigger)* }
triggers = { trigger_group ~ ("," ~ trigger_group)* }
result_type = { charcode | unicode | unistr | usbcode | consumer | system | trig | layer | function | pixelval | animation_result | string | none }
result = { result_type ~ ("(" ~ kvmap ~")")? }
result_group = { result ~ ("+" ~ result)* }
results = { result_group ~ ("," ~ result_group)* }
binding = { "::" | ":+" | ":-" | ":" | "i::" | "i:+" | "i:-" | "i:" }
mapping = { triggers ~ binding ~ results ~ ";" }
pixeldef = _{ (pixellayer | pixel) ~ "(" ~ kvmap ~ ")" }
pixelmap = { pixeldef ~ ":" ~ (scancode | none) ~ ";" }
animation = _{ ("A" ~ string) | ("A[" ~ name ~ "]") }
animation_result = { animation ~ ("(" ~ kvmap? ~ ")")? }
animdef = { animation ~ "<=" ~ kvmap ~ ";" }
op = { "+:" | "-:" | "+" | "-" | "<<" | ">>" }
channel = { op? ~ number }
channels = _{ channel ~ ("," ~ channel)* }
pixelindex = _{ ("PL"|"P") ~ "[" ~ kvmap ~ "]" }
pixelval = { (pixelindex | scancode | usbcode) ~ "(" ~ channels ~ ")" }
pixelvals = _{ pixelval ~ ("," ~ pixelval)* }
frame = _{ "A[" ~ name ~ "," ~ ids ~ "]" }
animframe = { frame ~ "<=" ~ pixelvals ~ ";" }