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