2023-12-16 01:20:35 +00:00
|
|
|
@precedence { line_end @left, line_break @left }
|
|
|
|
|
|
|
|
@top Script { (newline | terminator)* line+ }
|
2023-11-26 18:00:23 +00:00
|
|
|
|
2023-11-26 18:32:25 +00:00
|
|
|
@skip { space | comment }
|
|
|
|
|
2023-12-16 01:20:35 +00:00
|
|
|
line { (expression | toplevel) !line_end (newline | terminator)+ }
|
2023-11-26 18:32:25 +00:00
|
|
|
|
2023-12-16 01:20:35 +00:00
|
|
|
toplevel { Import | Use | Ns | Test }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
2023-11-27 06:18:30 +00:00
|
|
|
Import { silent<"import"> String silent<"as"> Word }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
2023-11-27 06:18:30 +00:00
|
|
|
Use { silent<"use"> Word }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
|
|
|
Ns {
|
2023-11-27 06:18:30 +00:00
|
|
|
silent<"ns"> Word "{"
|
2023-11-26 22:28:15 +00:00
|
|
|
separator*
|
|
|
|
assoc_term (separator+ assoc_term)*
|
|
|
|
separator*
|
|
|
|
"}"
|
|
|
|
}
|
|
|
|
|
2023-12-16 01:20:35 +00:00
|
|
|
Test { silent<"test"> String non_binding }
|
|
|
|
|
2023-11-26 22:28:15 +00:00
|
|
|
expression { non_binding | binding }
|
|
|
|
|
|
|
|
binding { Let | Ref | Fn_Named | Fn_Compound }
|
|
|
|
|
2023-11-27 06:18:30 +00:00
|
|
|
Ref { silent<"ref"> Word "=" expression }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
|
|
|
non_binding { simple | complex }
|
|
|
|
|
|
|
|
synth_root { Word | Keyword }
|
|
|
|
|
|
|
|
synth_term { Args | Keyword }
|
|
|
|
|
2023-11-27 06:11:01 +00:00
|
|
|
arg_term { Placeholder | simple }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
|
|
|
Args {
|
2023-12-16 01:20:35 +00:00
|
|
|
("(" (newline | separator)* ")")
|
2023-11-26 22:28:15 +00:00
|
|
|
| ("("
|
2023-12-16 01:20:35 +00:00
|
|
|
(newline | separator)*
|
|
|
|
arg_term ((newline | separator)+ arg_term)*
|
|
|
|
(newline | separator)*
|
2023-11-26 22:28:15 +00:00
|
|
|
")")
|
|
|
|
}
|
|
|
|
|
|
|
|
Synthetic { synth_root synth_term+ }
|
|
|
|
|
|
|
|
complex {
|
|
|
|
Block
|
|
|
|
| If
|
|
|
|
| If_Let
|
|
|
|
| Match
|
|
|
|
| When
|
2023-12-16 01:20:35 +00:00
|
|
|
| Do
|
2023-11-26 22:28:15 +00:00
|
|
|
| Loop
|
|
|
|
| Repeat
|
|
|
|
}
|
|
|
|
|
2023-11-27 06:18:30 +00:00
|
|
|
Repeat { silent<"repeat"> (Word | Number) Block }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
2023-11-27 06:18:30 +00:00
|
|
|
Recur { silent<"recur"> Args }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
2023-11-27 06:18:30 +00:00
|
|
|
Loop { silent<"loop"> simple "with" (Fn_Clause | Fn_Clauses) }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
|
|
|
simple { atom | collection | Synthetic | Fn_Lambda | Recur }
|
|
|
|
|
2023-11-27 06:23:18 +00:00
|
|
|
Fn_Clause { Tuple_Pattern "->" expression }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
|
|
|
Fn_Clauses {
|
|
|
|
"{"
|
2023-12-16 01:20:35 +00:00
|
|
|
(newline | terminator)*
|
|
|
|
Fn_Clause ((newline | terminator)+ Fn_Clause)*
|
|
|
|
(newline | terminator)*
|
2023-11-26 22:28:15 +00:00
|
|
|
"}"
|
|
|
|
}
|
|
|
|
|
2023-11-27 06:18:30 +00:00
|
|
|
Fn_Compound { silent<"fn"> Word Fn_Clauses }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
2023-11-27 06:18:30 +00:00
|
|
|
Fn_Named { silent<"fn"> Word Fn_Clause }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
2023-11-27 06:18:30 +00:00
|
|
|
Fn_Lambda { silent<"fn"> Fn_Clause }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
|
|
|
// TODO: figure out precedence with do/bind exprs
|
2023-12-16 01:20:35 +00:00
|
|
|
do_expr { Fn_Lambda | Synthetic | Word | Keyword }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
2023-12-16 01:20:35 +00:00
|
|
|
Do {
|
|
|
|
silent<"do"> simple !line_break (newline* ">" do_expr)+
|
|
|
|
}
|
2023-11-26 22:28:15 +00:00
|
|
|
|
|
|
|
Pattern {
|
|
|
|
Tuple_Pattern
|
|
|
|
| List_Pattern
|
|
|
|
| Dict_Pattern
|
|
|
|
| atom
|
|
|
|
| Placeholder
|
2023-12-16 01:20:35 +00:00
|
|
|
| Ignored
|
2023-11-26 22:28:15 +00:00
|
|
|
}
|
|
|
|
|
2023-12-16 01:20:35 +00:00
|
|
|
Ignored { "_" Word }
|
|
|
|
|
2023-11-26 22:28:15 +00:00
|
|
|
Placeholder { "_" }
|
|
|
|
|
|
|
|
ellipsis { "..." }
|
|
|
|
|
2023-12-16 01:20:35 +00:00
|
|
|
Splattern { ellipsis (Word | Placeholder | Ignored) }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
|
|
|
Tuple_Pattern {
|
2023-12-16 01:20:35 +00:00
|
|
|
("(" (newline | separator)* ")")
|
2023-11-26 22:28:15 +00:00
|
|
|
| ("("
|
2023-12-16 01:20:35 +00:00
|
|
|
(newline | separator)*
|
|
|
|
(Pattern (newline | separator)+)* (Pattern | Splattern)
|
|
|
|
(newline | separator)*
|
2023-11-26 22:28:15 +00:00
|
|
|
")")
|
|
|
|
}
|
|
|
|
|
|
|
|
List_Pattern {
|
2023-12-16 01:20:35 +00:00
|
|
|
("[" (newline | separator)* "]")
|
2023-11-26 22:28:15 +00:00
|
|
|
| ("["
|
2023-12-16 01:20:35 +00:00
|
|
|
(newline | separator)*
|
|
|
|
(Pattern (newline | separator)+)* (Pattern | Splattern)
|
|
|
|
(newline | separator)*
|
2023-11-26 22:28:15 +00:00
|
|
|
"]")
|
|
|
|
}
|
|
|
|
|
2023-11-27 06:11:01 +00:00
|
|
|
Assoc_Pattern { Word | (Keyword Pattern) }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
|
|
|
Dict_Pattern {
|
2023-12-16 01:20:35 +00:00
|
|
|
("#{" (newline | separator)* "}")
|
2023-11-26 22:28:15 +00:00
|
|
|
| ("#{"
|
2023-12-16 01:20:35 +00:00
|
|
|
(newline | separator)*
|
|
|
|
(Assoc_Pattern (newline | separator)+)* (Assoc_Pattern | Splattern)
|
|
|
|
(newline | separator)*
|
2023-11-26 22:28:15 +00:00
|
|
|
"}")
|
|
|
|
}
|
|
|
|
|
2023-12-16 01:20:35 +00:00
|
|
|
Let { silent<"let"> Pattern "=" !line_break newline* non_binding }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
2023-11-27 06:18:30 +00:00
|
|
|
Else { silent<"else"> }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
2023-12-16 01:20:35 +00:00
|
|
|
Match_Clause {(Pattern | Else) "->" !line_break newline* expression}
|
2023-11-26 22:28:15 +00:00
|
|
|
|
|
|
|
match_body {
|
|
|
|
Match_Clause
|
|
|
|
| (
|
|
|
|
"{"
|
2023-12-16 01:20:35 +00:00
|
|
|
(newline | terminator)*
|
|
|
|
Match_Clause ((newline | terminator)+ Match_Clause)*
|
|
|
|
(newline | terminator)*
|
2023-11-26 22:28:15 +00:00
|
|
|
"}"
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
Match {
|
2023-11-27 06:18:30 +00:00
|
|
|
silent<"match">
|
2023-11-26 22:28:15 +00:00
|
|
|
simple
|
2023-11-27 06:18:30 +00:00
|
|
|
silent<"with">
|
2023-11-26 22:28:15 +00:00
|
|
|
match_body
|
|
|
|
}
|
|
|
|
|
|
|
|
When_Clause {
|
2023-12-16 01:20:35 +00:00
|
|
|
(simple | Placeholder | Else) "->" !line_break newline* expression
|
2023-11-26 22:28:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
When {
|
2023-12-16 01:20:35 +00:00
|
|
|
silent<"when">
|
|
|
|
"{"
|
|
|
|
(newline | terminator)*
|
|
|
|
When_Clause ((newline | terminator)+ When_Clause)*
|
|
|
|
(newline | terminator)*
|
2023-11-26 22:28:15 +00:00
|
|
|
"}"
|
|
|
|
}
|
|
|
|
|
|
|
|
If {
|
2023-12-16 01:20:35 +00:00
|
|
|
silent<"if"> simple !line_break newline*
|
|
|
|
silent<"then"> expression !line_break newline*
|
2023-11-27 06:18:30 +00:00
|
|
|
silent<"else"> expression
|
2023-11-26 22:28:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
If_Let {
|
2023-11-27 06:18:30 +00:00
|
|
|
silent<"if"> silent<"let">
|
2023-12-16 01:20:35 +00:00
|
|
|
Pattern "=" simple !line_break newline*
|
|
|
|
silent<"then"> expression !line_break newline*
|
2023-11-27 06:18:30 +00:00
|
|
|
silent<"else"> expression
|
2023-11-26 22:28:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Block {
|
|
|
|
"{"
|
2023-12-16 01:20:35 +00:00
|
|
|
(newline | terminator)*
|
|
|
|
expression ((newline | terminator)+ expression)*
|
|
|
|
(newline | terminator)*
|
2023-11-26 22:28:15 +00:00
|
|
|
"}"
|
|
|
|
}
|
|
|
|
|
|
|
|
collection {
|
|
|
|
Tuple
|
|
|
|
| List
|
|
|
|
| Set
|
|
|
|
| Dict
|
|
|
|
}
|
|
|
|
|
|
|
|
Tuple {
|
|
|
|
( "(" // non-empty
|
2023-12-16 01:20:35 +00:00
|
|
|
(newline | separator)*
|
|
|
|
non_binding ((newline | separator)+ non_binding)*
|
|
|
|
(newline | separator)*
|
2023-11-26 22:28:15 +00:00
|
|
|
")" )
|
2023-12-16 01:20:35 +00:00
|
|
|
| "(" (newline | separator)* ")" // empty
|
2023-11-26 22:28:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Splat { ellipsis Word }
|
|
|
|
|
|
|
|
linear_term { Splat | non_binding }
|
|
|
|
|
|
|
|
List {
|
|
|
|
("["
|
2023-12-16 01:20:35 +00:00
|
|
|
(newline | separator)*
|
|
|
|
linear_term ((newline | separator)+ linear_term)*
|
|
|
|
(newline | separator)*
|
2023-11-26 22:28:15 +00:00
|
|
|
"]" )
|
2023-12-16 01:20:35 +00:00
|
|
|
| "[" (newline | separator)* "]"
|
2023-11-26 22:28:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Set {
|
|
|
|
("${"
|
2023-12-16 01:20:35 +00:00
|
|
|
(newline | separator)*
|
|
|
|
linear_term ((newline | separator)+ linear_term)*
|
|
|
|
(newline | separator)*
|
2023-11-26 22:28:15 +00:00
|
|
|
"}")
|
2023-12-16 01:20:35 +00:00
|
|
|
| "${" (newline | separator)* "}"
|
2023-11-26 22:28:15 +00:00
|
|
|
}
|
|
|
|
|
2023-11-27 06:11:01 +00:00
|
|
|
assoc_term { Word | (Keyword non_binding) }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
2023-11-27 06:11:01 +00:00
|
|
|
dict_term { assoc_term | Splat }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
|
|
|
Dict {
|
|
|
|
("#{"
|
2023-12-16 01:20:35 +00:00
|
|
|
(newline | separator)*
|
|
|
|
dict_term ((newline | separator)+ dict_term)*
|
|
|
|
(newline | separator)*
|
2023-11-26 22:28:15 +00:00
|
|
|
"}" )
|
2023-12-16 01:20:35 +00:00
|
|
|
| "#{" (newline | separator)* "}"
|
2023-11-26 22:28:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
atom { Boolean | Nil | String | Number | Keyword | Word }
|
|
|
|
|
2023-11-27 06:20:43 +00:00
|
|
|
reserved<term> { @specialize[@name={term}]<Word, term> }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
2023-11-27 06:18:30 +00:00
|
|
|
silent<term> { @specialize<Word, term> }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
|
|
|
Keyword { ":" Word }
|
|
|
|
|
2023-11-27 06:20:43 +00:00
|
|
|
Boolean { reserved<"true"> | reserved<"false"> }
|
2023-11-26 22:28:15 +00:00
|
|
|
|
2023-11-27 06:18:30 +00:00
|
|
|
Nil { silent<"nil"> }
|
2023-11-26 18:00:23 +00:00
|
|
|
|
|
|
|
@tokens {
|
2023-11-26 22:28:15 +00:00
|
|
|
Word { $[a-z] $[a-zA-Z_\-?/!]* }
|
2023-11-26 18:32:25 +00:00
|
|
|
space { $[ \t\r]+ }
|
|
|
|
comment { "&" ![\n]* }
|
|
|
|
String { '"' (!["\\] | "\\" _)* '"' }
|
2023-11-26 22:28:15 +00:00
|
|
|
int { $[1-9]$[0-9]* | "0" }
|
|
|
|
float { ("0" | int ) "." $[0-9]+}
|
|
|
|
Number { "-"? (int | float) }
|
2023-12-16 01:20:35 +00:00
|
|
|
separator { "," }
|
|
|
|
terminator { ";" }
|
2023-11-26 22:28:15 +00:00
|
|
|
newline { "\n" }
|
2023-11-26 18:00:23 +00:00
|
|
|
}
|