program = {
SOI
~ rules
~ EOI
}
rules = {
assignment*
~ (function_call ~ end)*
~ value?
}
end = {
";"?
}
assignment = {
assignment_operator? ~ identifier_assignment ~ end
}
assignment_operator = {
"let"
| "mut"
}
import = {
"import" ~ (identifier | object) ~ "from" ~ (import_source) ~ end
}
import_source = {
string
| identifier
}
export = {
"export" ~ (identifier | scope) ~ ("as" ~ identifier)? ~ end
}
function_definition = {
"fn" ~ identifier ~ function_body? ~ scope
}
identifier_assignment = {
identifier ~ "=" ~ (value | scope)
}
function_call = {
(
(identifier ~ scope)
| (
(identifier ~ function_body? ~ scope?)
)
)
}
scope = {
("do" ~ scope_args? ~ rules ~ "end")
| ("{" ~ scope_args? ~ rules ~ "}")
| if_else
}
scope_args = {
(("(" ~ args? ~ ")") | args) ~ "->"
}
if_else = {
"if" ~ value ~ scope ~ ("else" ~ scope)? ~ "end"
}
identifier = @{
!(none | "let" | "mut") ~ (
"$"
| (("$" | ".")? ~ (VALID_CHARS+ | ".")+)
)
}
symbol = @{
":" ~ VALID_CHARS+
}
function_body = {
("(" ~ args? ~ ")")
| (args)
}
args = {
(named_arg | value)
~ (("," | ";") ~ (named_arg | value))*
~ (("," | ";")?)
}
named_arg = {
field ~ value
}
field = @{
identifier ~ ":"
}
value = {
none
| bool
| number
| string
| object
| list
| symbol
| function_call
}
none = {
"none"
}
object = {
(
"{"
~ (attribute ~ ((";" | ",") ~ attribute)* ~ (";" | ",")?)?
~ "}"
) |
(
"do"
~ (attribute ~ ((";" | ",") ~ attribute)* ~ (";" | ",")?)?
~ "end"
)
}
attribute = {
(identifier ~ "=" ~ value)
| function_call
}
list = {
"["
~ (
value
~ (("," | ";") ~ value)* ~ ("," | ";")?
)?
~ "]"
}
bool = {
"true"
| "false"
}
number = @{
ASCII_DIGIT+
~ ("." ~ ASCII_DIGIT+)?
}
string = {
"'" ~ (!"'" ~ ANY)* ~ "'"
| "\"" ~ (!"\"" ~ ANY)* ~ "\""
| "`" ~ (!"`" ~ ANY)* ~ "`"
}
VALID_CHARS = @{
ASCII_ALPHANUMERIC
| "_"
}
WHITESPACE = _{
" "
| "\t"
| NEWLINE
}
COMMENT = _{
single_line_comment
| multi_line_comment
}
single_line_comment = {
"#"
~ (!NEWLINE ~ ANY)*
~ (NEWLINE | EOI)
}
multi_line_comment = {
"/*"
~ (!"*/" ~ ANY)*
~ "*/"
}