actyx_sdk 0.3.0

Tools for interacting with the services of an Actyx node
Documentation
main_query = { SOI ~ features? ~ query ~ EOI }
main_tag_expr = { SOI ~ tag_expr ~ EOI }
main_simple_expr = { SOI ~ simple_expr ~ EOI }
main_ident = @{ SOI ~ ident ~ EOI }
main_func_name = @{ SOI ~ func_name ~ EOI }

// queries
query = { "FROM" ~ tag_expr ~ query_op* ~ "END"? }
query_op = _{ filter | select | aggregate }
filter = { "FILTER" ~ simple_expr }
select = { "SELECT" ~ simple_expr ~ ( "," ~ simple_expr )* }
aggregate = { "AGGREGATE" ~ simple_expr }
features = { "FEATURES(" ~ feature_word* ~ ")" }
feature_word = @{ ( ASCII_ALPHANUMERIC | "ø" )+ }

// strings
single_quoted = @{ "'" ~ ( !"'" ~ ANY | "''" )+ ~ "'" }
double_quoted = @{ "\"" ~ ( !"\"" ~ ANY | "\"\"" )+ ~ "\"" }
nonempty_string = { single_quoted | double_quoted }
empty_string = { "\"\"" | "''" }
string = { nonempty_string | empty_string }

// literals
null = { "NULL" }
bool = { "TRUE" | "FALSE" }
decimal = @{ "-"? ~ digit+ ~ ( "." ~ digit+ )? }
natural = @{ digit+ }
digit = { '0'..'9' }
// This currently permits { a:1 b:2 }, which I’d like to try; comma is available for disambiguation
object = { "{" ~ ( ( ident | "[" ~ natural ~ "]" | "[" ~ string ~ "]" | "[" ~ simple_expr ~ "]" ) ~ ":" ~ simple_expr ~ ","? )* ~ "}" }
array = { "[" ~ "]" | "[" ~ simple_expr ~ ( "," ~ simple_expr )* ~ "]" }
app_id = @{ app_id_char+ ~ ( "." ~ app_id_char+ )* }
app_id_char = { "-" | '0'..'9' | 'a'..'z' }
stream_id = @{ crypt_char{43} ~ "-" ~ natural }
crypt_char = { "." | "/" | 'a'..'z' | 'A'..'Z' | '0'..'9' }

// identifiers
ident = @{ "_" | &( LOWERCASE | UPPERCASE ~ LOWERCASE ) ~ ( ALPHABETIC | NUMBER | "_" )+ }
func_name = @{ UPPERCASE ~ LOWERCASE ~ ( ALPHABETIC | NUMBER | "_" )* }
var = { ident }
index = _{ "." ~ ident | "[" ~ natural ~ "]" | "[" ~ string ~ "]" | "[" ~ simple_expr ~ "]" }

// ISO8601 timestamp
year = { '0'..'9'{4} }
month = { ( "0" ~ '1'..'9' ) | ("1" ~ '0'..'2') }
day = { ( "0" ~ '1'..'9' ) | ( "1" ~ '0'..'9' ) | ( "2" ~ '0'..'9' ) | "30" | "31" }
hour = { ( '0'..'1' ~ '0'..'9' ) | ( "2" ~ '0' .. '3' ) }
minute = { ( '0'..'5' ~ '0'..'9' ) }
second = { ( '0'..'5' ~ '0'..'9' ) }
millisecond = { ( '0'..'9'{3} ) }
microsecond = { ( '0'..'9'{6} ) }
nanosecond = { ( '0'..'9'{9} ) }
isodate = ${ year ~ "-" ~ month ~ "-" ~ day ~ ("T" ~ hour ~ ":" ~ minute ~ (":" ~ second ~ ("." ~ (nanosecond|microsecond|millisecond))?)?)? ~ "Z" }

// tags
tag_expr = { tag_atom ~ ( tag_op ~ tag_atom )* }
tag_atom = _{ tag | "(" ~ tag_expr ~ ")" | all_events | is_local | tag_from | tag_to | tag_app }
tag_op = _{ and | or }
tag = { nonempty_string }
all_events = { "allEvents" }
is_local = { "isLocal" }
tag_from = { "from(" ~ ( isodate | natural ~ ( "/" ~ stream_id )? ) ~ ")" }
tag_to = { "to(" ~ ( isodate | natural ~ ( "/" ~ stream_id )? ) ~ ")" }
tag_app = ${ "appId(" ~ app_id ~ ")" }

// expressions
simple_expr = { simple_atom ~ ( binary_op ~ simple_atom )* }
binary_op = _{ alternative | add | sub | mul | div | modulo | pow | and | or | xor | le | lt | ge | gt | eq | ne }
var_index = { var ~ index* }
expr_index = { "(" ~ simple_expr ~ ")" ~ index* }
func_call = { func_name ~ "(" ~ ( simple_expr ~ ("," ~ simple_expr)* )? ~ ")" }
simple_atom = _{ decimal | func_call | var_index | string | expr_index | simple_not | object | array | null | bool | simple_cases | aggr_op }
simple_not = { not ~ simple_atom }
simple_cases = { ( "CASE" ~ simple_expr ~ "=>" ~ simple_expr )+ ~ "ENDCASE" }

// aggregations
aggr_op = { aggr_sum | aggr_prod | aggr_min | aggr_max | aggr_first | aggr_last }
aggr_sum = { "SUM(" ~ simple_expr ~ ")" }
aggr_prod = { "PRODUCT(" ~ simple_expr ~ ")" }
aggr_min = { "MIN(" ~ simple_expr ~ ")" }
aggr_max = { "MAX(" ~ simple_expr ~ ")" }
aggr_first = { "FIRST(" ~ simple_expr ~ ")" }
aggr_last = { "LAST(" ~ simple_expr ~ ")" }

// operators
add = { "+" }
sub = { "-" }
mul = { "*" | "×" }
div = { "/" | "÷" | "⁄" }
modulo = { "%" }
pow = { "^" }
and = { "&" | "∧" }
or = { "|" | "∨" }
not = _{ "!" | "¬" }
xor = { "~" | "⊻" }
lt = { "<" }
le = { "<=" | "≤" }
gt = { ">" }
ge = { ">=" | "≥" }
eq = { "=" }
ne = { "!=" | "≠" }
alternative = { "//" }

WHITESPACE = _{ WHITE_SPACE }
COMMENT = _{ "--" ~ ( !("\n"|"\r") ~ ANY )* }