lezer-ludus/ludus.grammar

271 lines
4.7 KiB
Plaintext
Raw Normal View History

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 }
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
}