jslt 0.0.6

Everyones favorite xslt but for json
Documentation
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 }