Jslt = _{ SOI ~ Expr ~ EOI }
Value = _{ FunctionCall | Accessor | Scope | Variable | Array | Object | Number | String | Boolean | Null }
Expr = _{ OperatorExpr | ValueExpr }
ValueExpr = _{ VariableDef | FunctionDef | IfStatement | Value }
OperatorExpr = { ValueExpr ~ (Operator ~ ValueExpr)+ }
Operator = _{ Add | Sub | Div | Mul | Gte | Gt | Lte | Lt | And | Or | Equal | NotEqual | Pipe }
Add = { "+" }
Sub = { "-" }
Mul = { "*" }
Div = { "/" }
Gt = { ">" }
Lt = { "<" }
Gte = { ">=" }
Lte = { "<=" }
Equal = { "==" }
NotEqual = { "!=" }
And = { "and" }
Or = { "or" }
Pipe = { "|" }
If = _{ "if" }
For = _{ "for" }
Def = _{ "def " }
Let = _{ "let " }
Scope = { "(" ~ Expr ~ ")" }
Accessor = ${
(("." ~ (Ident | String)?) | KeyAccessor) ~ Accessor?
}
KeyAccessor = !{ "[" ~ (RangeAccessor | Expr) ~ "]" }
FromRangeAccessor = { Expr ~ ":" ~ Expr? }
ToRangeAccessor = { Expr? ~ ":" ~ Expr }
RangeAccessor = { FromRangeAccessor | ToRangeAccessor }
FunctionCall = ${ Ident ~ FunctionCallArgs ~ Accessor? }
FunctionCallArgs = !{ "(" ~ Expr? ~ ("," ~ Expr)* ~ ")" }
FunctionDef = { Def ~ Ident ~ "(" ~ Ident? ~ ("," ~ Ident)* ~ ")" ~ Expr ~ Expr? }
Array = {
"[" ~ "]"
| "[" ~ (ArrayFor | Expr) ~ ("," ~ (ArrayFor | Expr))* ~ ","? ~ "]"
}
ArrayFor = {
For ~ "(" ~ Expr ~ ")" ~ Expr ~ IfCondition?
}
Object = {
"{" ~ ObjectSpread? ~ "}"
| "{" ~ (ObjectFor | Pair) ~ ("," ~ (ObjectSpread | ObjectFor | Pair))* ~ ","? ~ "}"
}
ObjectFor = {
For ~ "(" ~ Expr ~ ")" ~ Pair ~ IfCondition?
}
ObjectSpread = {
"*" ~ ":" ~ Expr
}
Pair = {
Expr ~ ":" ~ Expr
}
IfStatement = {
IfCondition ~ Expr ~ ("else" ~ Expr)?
}
IfCondition = {
If ~ "(" ~ Expr ~ ")"
}
Variable = { "$" ~ Ident ~ Accessor? }
VariableDef = { Let ~ Ident ~ "=" ~ Expr ~ Expr? }
String = ${ "\"" ~ Inner ~ "\"" }
Inner = @{ Char* }
Char = {
!("\"" | "\\") ~ ANY
| "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
| "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
}
Ident = @{ ("_" | ASCII_ALPHANUMERIC) ~ ("_" | "-" | ASCII_ALPHANUMERIC)* }
Number = @{
"-"? ~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) ~ ("." ~ ASCII_DIGIT*)? ~ (^"e" ~ ("+" | "-")? ~ ASCII_DIGIT+)?
}
Boolean = { "true" | "false" }
Null = { "null" }
COMMENT = _{ "//" ~ (!NEWLINE ~ ANY)* }
WHITESPACE = _{ " " | "\t" | NEWLINE }