kll-compiler 0.1.3

KLL (Keyboard Layout Language) Compiler - Rust Edition
Documentation
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 ~ ";" }