Files
mist/parser/src/grammar.pest
T
2026-05-07 22:32:53 +02:00

213 lines
4.9 KiB
Plaintext

WHITESPACE = _{ " " | "\t" | "\r" | "\n" }
COMMENT = _{ "//" ~ (!"\n" ~ ANY)* }
program = { SOI ~ top_level* ~ EOI }
// primitives
identifier = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }
integer = @{ ASCII_DIGIT+ }
float = @{ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ }
boolean = { "true" | "false" }
string_lit = { "\"" ~ inner_str ~ "\"" }
inner_str = @{ (!"\"" ~ ("\\\"" | ANY))* }
static_path = { identifier ~ ("::" ~ identifier)* }
// pattern
tuple_pattern = { "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")" }
named_tuple_pattern = { static_path ~ "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")" }
struct_pattern = { static_path ~ "{" ~ (identifier ~ ("," ~ identifier)*)? ~ "}" }
pattern = _{ named_tuple_pattern | tuple_pattern | struct_pattern | identifier }
export = { "public" }
mutable = { "mut" }
var = { "var" }
var_decl = { (var | type_expr) ~ mutable? ~ pattern }
semicolon = _{ ";" }
// ================= CLASS =================
class_constructor = {
export? ~ "constructor" ~ "(" ~ param_list? ~ ")" ~ block
}
class_fields = { var_decl_statement* }
self_param = { "self" ~ mutable? ~ deref_px? }
method = {
export? ~ type_expr ~ identifier ~ "(" ~ self_param? ~ param_list? ~ ")" ~ block
}
class_decl = {
"class" ~ identifier ~ "{" ~ class_fields ~ class_constructor ~ method* ~ "}"
}
// ================= TOP LEVEL =================
enum_named = { identifier }
enum_tuple = { identifier ~ tuple_type }
enum_struct = { identifier ~ "{" ~ field_list ~ "}" }
enum_field = _{ enum_tuple | enum_struct | enum_named }
enum_fields = _{ enum_field ~ ("," ~ enum_field)* ~ ","? }
enum_decl = { export? ~ "enum" ~ identifier ~ "{" ~ enum_fields ~ "}" }
top_level = { (attributes ~ (import | function_decl | struct_decl | enum_decl | class_decl | mod_package)) | mod_attribute }
attribute = {
"#" ~ "[" ~ meta ~ "]"
}
mod_attribute = {
"#" ~ "!" ~ "[" ~ meta ~ "]"
}
meta = {
static_path ~ ("=" ~ primary | "(" ~ meta_list? ~ ")")?
}
meta_list = {
meta ~ ("," ~ meta)* ~ ","?
}
attributes = { attribute* }
import = { "use" ~ "<" ~ static_path ~ ">" ~ semicolon }
mod_package = { "mod" ~ identifier ~ semicolon }
field_list = { field ~ ("," ~ field)* ~ ","? }
field = { export? ~ type_expr ~ identifier }
param_list = { var_decl ~ ("," ~ var_decl)* ~ ","? }
struct_decl = {
export? ~ "struct" ~ identifier ~ "{" ~ field_list? ~ "}"
}
function_decl = {
export? ~ type_expr ~ identifier ~ "(" ~ param_list? ~ ")" ~ block
}
// ================= STATEMENTS =================
block = { "{" ~ statement_list ~ "}" }
statement_list = { statement* }
statement = _{
expr_stmt
| match_stmt
| var_decl_statement
| assign_statement
| if_stmt
| while_stmt
| c_for_stmt
| for_stmt
| return_stmt
| break_stmt
| continue_stmt
| block
}
// --- basic statements ---
expr_stmt = { expr ~ semicolon }
return_stmt = { "return" ~ expr? ~ semicolon }
break_stmt = { "break" ~ semicolon }
continue_stmt = { "continue" ~ semicolon }
var_decl_statement = { var_decl ~ ("=" ~ expr)? ~ semicolon }
assign_statement = { expr ~ "=" ~ expr ~ semicolon }
else_if = { "else" ~ "if" ~ "(" ~ expr ~ ")" ~ statement }
else_if_list = { else_if* }
if_stmt = {
"if" ~ "(" ~ expr ~ ")" ~ statement ~ else_if_list ~ ("else" ~ statement)?
}
while_stmt = {
"while" ~ "(" ~ expr ~ ")" ~ statement
}
c_for_stmt = {
"for" ~ "(" ~ statement ~ expr ~ semicolon ~ statement ~ ")" ~ statement
}
for_stmt = {
"for" ~ "(" ~ identifier ~ "in" ~ expr ~ ")" ~ statement
}
match_item = { pattern ~ "=>" ~ block }
match_stmt = {
"match" ~ "(" ~ expr ~ ")" ~ match_item*
}
// ================= EXPRESSIONS =================
tuple_type = { "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" }
path_type = { static_path ~ ("<" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ">")? }
ref_type = { mutable? ~ "*" }
type_expr = { (path_type | tuple_type) ~ ref_type* }
macro_inner_v = {
"(" ~ macro_inner_v* ~ ")"
| (!("(" | ")") ~ ANY)
}
tuple = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" }
primary = {
float
| integer
| boolean
| string_lit
| static_path
| tuple
}
postfix = {
field_px
| call_px
| macro_call_px
| struct_px
| index_px
| binary_px
}
field_px = { "." ~ identifier }
call_px = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" }
macro_call_px = { "!" ~ "(" ~ macro_inner_v* ~ ")" }
struct_px = { "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ ","? ~ "}" }
index_px = { "[" ~ expr ~ "]" }
binary_px = { bin_op ~ expr }
bin_op = { "<=" | ">=" | "==" | "!=" | "+" | "-" | "*" | "/" | "%" | "<" | ">" }
struct_field_decl = { identifier ~ ":" ~ expr }
prefix = {
deref_px
| mut_ref_px
| ref_px
| new_px
| not_px
}
deref_px = { "*" }
mut_ref_px = { "&" ~ mutable }
ref_px = { "&" }
new_px = { "new" }
not_px = { "!" }
prefix_list = { prefix* }
expr = {
prefix_list ~ primary ~ postfix*
}