_seps: "(){}[],.:;=<>*+-/%^?"
200 multi_line_comment = ["/*" ..."*/"? .r?({
[!"*/" "*" ..."*/"?]
[multi_line_comment ..."*/"?]
["/" ..."*/"?]
}) "*/"]
201 comment = {multi_line_comment ["//" ..."\n"?]}
// 202 w = .r!({.w! comment})
202 w = .r!({.w! comment})
0 fn = ["fn" .w! .."("!:"name" ?w "(" args ")" ?w ?"->":"returns" ?w block:"block"]
1 args = .s?.([?w "," ?w] arg:"arg")
2 arg = [.._seps!:"name" ?[?w ":" ?w "'" ?w .._seps!:"lifetime"]]
// Support both multi-line expressions and single line.
3 block = ["{" ?w {.l([?w expr:"expr" ?w]) [?w expr:"expr"]} ?w "}"]
4 expr = [{
object:"object"
array:"array"
array_fill:"array_fill"
["return" .w! expr:"return"]
for:"for"
loop:"loop"
if:"if"
break:"break"
continue:"continue"
block:"block"
assign:"assign"
compare:"compare"
["return":"return_void"]
add:"add"
["(" ?w expr ?w ")"]
unop:"unop"
text
call:"call"
named_call:"named_call"
num
bool
item:"item"
} ?[?w "?":"try"]]
// Interprets "return" as variable, does not expect loops or assignment.
5 arg_expr = [{
object:"object"
array:"array"
array_fill:"array_fill"
if:"if"
block:"block"
compare:"compare"
add:"add"
["(" ?w expr ?w ")"]
unop:"unop"
text
call:"call"
named_call:"named_call"
num
bool
item:"item"
} ?[?w "?":"try"]]
6 lexpr = [{
object:"object"
array:"array"
array_fill:"array_fill"
block:"block"
["(" ?w expr ?w ")"]
unop:"unop"
text
call:"call"
named_call:"named_call"
num
bool
item:"item"
} ?[?w "?":"try"]]
7 object = ["{" ?w .s?.([?w "," ?w] key_value:"key_value") ?w "}"]
8 array = ["[" ?w .s?.([?w "," ?w] expr:"array_item") ?w "]"]
9 array_fill = ["[" ?w [expr:"fill" ?w ";" ?w expr:"n"] ?w "]"]
10 key_value = [.._seps!:"key" ?w ":" ?w expr:"val"]
11 num = .$_:"num"
12 text = .t?:"text"
13 bool = {"true":"bool" "false":!"bool"}
14 unop = ["!":"!" ?w lexpr:"expr"]
15 item = [.._seps!:"name" ?[?w "?":"try_item"] .r?([{
[?w "[" ?w {.t?:"id" .$_:"id" expr:"id"} ?w "]"]
[?w "." ?w .._seps!:"id"]
} ?[?w "?":"try_id"]])]
16 for = [?["'" .._seps!:"label" ?w ":" ?w] "for" .w!
expr:"init" ?w ";" ?w
expr:"cond" ?w ";" ?w
expr:"step" ?w block:"block"]
17 loop = [?["'" .._seps!:"label" ?w ":" ?w] "loop" .w! block:"block"]
18 break = ["break" ?w ?["'" .._seps!:"label"]]
19 continue = ["continue" ?w ?["'" .._seps!:"label"]]
20 if = [
"if" .w! expr:"cond" ?w block:"true_block"
.r?([?w "else" w "if" ?w expr:"else_if_cond" ?w block:"else_if_block"])
?[?w "else" ?w block:"else_block"]
]
21 call = [.._seps!:"name" ?w "(" .s?.([?w "," ?w] arg_expr:"call_arg") ?w ")"]
22 named_call = [.._seps!:"word" ?w "(" ?w
.s?.([?w "," ?w] [.._seps!:"word" ?w ":" ?w arg_expr:"call_arg" ?w]) ")"]
23 assign = [lexpr:"left" ?w assign_op ?w expr:"right"]
24 assign_op = {
":=":":="
"=":"="
"+=":"+="
"-=":"-="
"*=":"*="
"/=":"/="
"%=":"%="
}
25 compare = [lexpr:"left" ?w compare_op ?w expr:"right"]
26 compare_op = {
"==":"=="
"!=":"!="
"<=":"<="
"<":"<"
">=":">="
">":">"
}
101 + = [?w {"+":"+" "||":"+"} ?w]
102 - = [?w "-":"-" ?w]
103 * = [?w {"*":"*" "&&":"*"} ?w]
104 / = [?w "/":"/" ?w]
105 % = [?w "%":"%" ?w]
107 pow = [lexpr:"base" ?w "^" ?w lexpr:"exp"]
108 mul = .s!({* / %} {
pow:"pow"
lexpr:"val"
})
109 add = .s!({+ -} {
mul:"mul"
})
1000 document = .l({fn:"fn" comment})