@top Script { terminator* line+ } @skip { space | comment } line { (expression | toplevel) terminator+ } toplevel { Import | Use | Ns } Import { silent<"import"> String silent<"as"> Word } Use { silent<"use"> Word } Ns { silent<"ns"> Word "{" separator* assoc_term (separator+ assoc_term)* separator* "}" } expression { non_binding | binding } binding { Let | Ref | Fn_Named | Fn_Compound } Ref { silent<"ref"> Word "=" expression } non_binding { simple | complex } synth_root { Word | Keyword } synth_term { Args | Keyword } arg_term { Placeholder | simple } Args { ("(" separator* ")") | ("(" separator* arg_term (separator+ arg_term)* separator* ")") } Synthetic { synth_root synth_term+ } complex { Block | If | If_Let | Match | When //| Do //| Bind | Loop | Repeat | Each } Repeat { silent<"repeat"> (Word | Number) Block } // repeat 4 { thing () } Each { silent<"each"> simple "do" (Fn_Clause | Fn_Clauses) } // each [1, 2, 3] do (n) -> thing Recur { silent<"recur"> Args } Loop { silent<"loop"> simple "with" (Fn_Clause | Fn_Clauses) } simple { atom | collection | Synthetic | Fn_Lambda | Recur } Fn_Clause { Tuple_Pattern "->" expression } Fn_Clauses { "{" terminator* Fn_Clause (terminator+ Fn_Clause)* terminator* "}" } Fn_Compound { silent<"fn"> Word Fn_Clauses } Fn_Named { silent<"fn"> Word Fn_Clause } Fn_Lambda { silent<"fn"> Fn_Clause } // TODO: figure out precedence with do/bind exprs // do_expr { Fn_Lambda | Synthetic | Word | Keyword } // Do { // silent<"do"> simple (~ambig newline* ">" do_expr)+ // } // Bind { // silent<"bind"> // simple // (!pipeline pipeline)+ // } Pattern { Tuple_Pattern | List_Pattern | Dict_Pattern | Struct_Pattern | atom | Placeholder } Placeholder { "_" } ellipsis { "..." } Splattern { ellipsis (Word | Placeholder) } Tuple_Pattern { ("(" separator* ")") | ("(" separator* (Pattern separator+)* (Pattern | Splattern) separator* ")") } List_Pattern { ("[" separator* "]") | ("[" separator* (Pattern separator+)* (Pattern | Splattern) separator* "]") } Assoc_Pattern { Word | (Keyword Pattern) } Dict_Pattern { ("#{" separator* "}") | ("#{" separator* (Assoc_Pattern separator+)* (Assoc_Pattern | Splattern) separator* "}") } Struct_Pattern { ("@{" separator* "}") | ("@{" separator* (Assoc_Pattern separator+)* (Assoc_Pattern | Splattern) separator* "}") } Let { silent<"let"> Pattern "=" non_binding } Else { silent<"else"> } Match_Clause {(Pattern | Else) "->" newline* expression} match_body { Match_Clause | ( "{" terminator* Match_Clause (terminator+ Match_Clause)* terminator* "}" ) } Match { silent<"match"> simple silent<"with"> match_body } When_Clause { (simple | Placeholder | Else) "->" newline* expression } When { silent<"when"> "{" terminator* When_Clause (terminator+ When_Clause)* terminator* "}" } If { silent<"if"> simple newline* silent<"then"> expression newline* silent<"else"> expression } If_Let { silent<"if"> silent<"let"> Pattern "=" simple newline* silent<"then"> expression newline* silent<"else"> expression } Block { "{" terminator* expression (terminator+ expression)* terminator* "}" } collection { Tuple | List | Set | Dict | Struct } Tuple { ( "(" // non-empty separator* non_binding (separator+ non_binding)* separator* ")" ) | "(" separator* ")" // empty } Splat { ellipsis Word } linear_term { Splat | non_binding } List { ("[" separator* linear_term (separator+ linear_term)* separator* "]" ) | "[" separator* "]" } Set { ("${" separator* linear_term (separator+ linear_term)* separator* "}") | "${" separator* "}" } assoc_term { Word | (Keyword non_binding) } dict_term { assoc_term | Splat } Dict { ("#{" separator* dict_term (separator+ dict_term)* separator* "}" ) | "#{" separator* "}" } Struct { ("@{" separator* assoc_term (separator+ assoc_term)* separator* "}") | "@{" separator* "}" } atom { Boolean | Nil | String | Number | Keyword | Word } reserved { @specialize[@name={term}] } silent { @specialize } Keyword { ":" Word } Boolean { reserved<"true"> | reserved<"false"> } Nil { silent<"nil"> } @tokens { Word { $[a-z] $[a-zA-Z_\-?/!]* } space { $[ \t\r]+ } comment { "&" ![\n]* } String { '"' (!["\\] | "\\" _)* '"' } int { $[1-9]$[0-9]* | "0" } float { ("0" | int ) "." $[0-9]+} Number { "-"? (int | float) } separator { $[,\n] } terminator { $[;\n] } newline { "\n" } }