Files
mist/parser/src/grammar.pest
T
2026-05-05 14:12:49 +02:00

147 lines
3.4 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)* }
export = { "public" }
mutable = { "mut" }
sharp = _{ "#" }
var_decl = { type_expr ~ mutable? ~ identifier }
// ================= TOP LEVEL =================
attribute = {
"#" ~ "[" ~ (structured_style | list_style | pair_attr | simple_style) ~ "]"
}
// Simple: #[test]
simple_style = { static_path }
// #[derive(PartialEq, PartialOrd)]
list_style = { static_path ~ "(" ~ identifier ~ ("," ~ identifier)* ~ ","? ~ ")" }
// #[link(name = "readline")]
structured_style = { static_path ~ "(" ~ pair_attr ~ ("," ~ pair_attr)* ~ ","? ~ ")" }
pair_attr = { identifier ~ "=" ~ primary }
top_level = { attribute* ~ (import | function_decl | struct_decl) }
import = { sharp ~ "include" ~ "<" ~ static_path ~ ">" }
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
| var_decl_statement
| assign_statement
| if_stmt
| while_stmt
| return_stmt
| break_stmt
| continue_stmt
| block
}
// --- basic statements ---
expr_stmt = { expr ~ ";" }
return_stmt = { "return" ~ expr? ~ ";" }
break_stmt = { "break" ~ ";" }
continue_stmt = { "continue" ~ ";" }
var_decl_statement = { var_decl ~ ("=" ~ expr)? ~ ";" }
assign_statement = { expr ~ "=" ~ expr ~ ";" }
if_stmt = {
"if" ~ "(" ~ expr ~ ")" ~ statement ~ ("else" ~ statement)?
}
while_stmt = {
"while" ~ "(" ~ expr ~ ")" ~ statement
}
// ================= 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
}
deref_px = { "*" }
mut_ref_px = { "&" ~ mutable }
ref_px = { "&" }
expr = {
prefix* ~ primary ~ postfix*
}