_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.
2 block = ["{" ?w {.l([?w expr:"expr" ?w]) [?w expr:"expr"]} ?w "}"]
3 expr = {
    object:"object"
    array:"array"
    ["return" .w! expr:"return"]
    for:"for"
    loop:"loop"
    if:"if"
    break:"break"
    continue:"continue"
    block:"block"
    assign:"assign"
    compare:"compare"
    add:"add"
    ["(" ?w expr ?w ")"]
    call:"call"
    text
    num
    bool
    item:"item"
}
4 lexpr = {
    block:"block"
    ["(" ?w expr ?w ")"]
    call:"call"
    text
    num
    bool
    item:"item"
}
5 object = ["{" ?w .s?.([?w "," ?w] key_value:"key_value") ?w "}"]
6 array = ["[" ?w .s?.([?w "," ?w] expr:"array_item") ?w "]"]
7 key_value = [.._seps!:"key" ?w ":" ?w expr:"val"]
8 num = .$_:"num"
9 text = .t?:"text"
9 bool = {"true":"bool" "false":!"bool"}
10 item = [.._seps!:"name" .r?({
    [?w "[" ?w {.t?:"id" .$_:"id" expr:"id"} ?w "]"]
    [?w "." ?w .._seps!:"id"]
})]
12 for = [?["'" .._seps!:"label" ?w ":" ?w] "for" .w!
    expr:"init" ?w ";" ?w
    expr:"cond" ?w ";" ?w
    expr:"step" ?w block:"block"]
13 loop = [?["'" .._seps!:"label" ?w ":" ?w] "loop" .w!  block:"block"]
14 break = ["break" ?w ?["'" .._seps!:"label"]]
15 continue = ["continue" ?w ?["'" .._seps!:"label"]]
16 if = [
    "if" .w! expr:"cond" ?w block:"true_block"
    ?[?w "else" ?w block:"else_block"]
]
17 call = [.._seps!:"name" ?w "(" .s?.([?w "," ?w] expr:"arg") ?w ")"]
18 assign = [lexpr:"left" ?w assign_op ?w expr:"right"]
19 assign_op = {
    ":=":":="
    "=":"="
    "+=":"+="
    "-=":"-="
    "*=":"*="
    "/=":"/="
    "%=":"%="
}
20 compare = [lexpr:"left" ?w compare_op ?w expr:"right"]
21 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})
