// ====================================================== // LEXICAL // ====================================================== WHITESPACE = _{ " " | "\t" | "\r" | "\n" } COMMENT = _{ "//" ~ (!"\n" ~ ANY)* } // ------------------------------------------------------ // PRIMITIVES // ------------------------------------------------------ keyword = { "if" | "else" | "fn" | "for" | "while" | "match" | "return" | "break" | "continue" | "struct" | "enum" | "class" | "trait" | "impl" | "use" | "pub" | "mut" | "let" | "true" | "false" | "dyn" | "loop" | "unsafe" | "override" | "const" | "type" } identifier = @{ !(keyword ~ !(ASCII_ALPHANUMERIC | "_")) ~ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* } integer = @{ ASCII_DIGIT+ } float = @{ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ } boolean = { "true" | "false" } string_lit = { "\"" ~ inner_str ~ "\"" } inner_str = @{ (!"\"" ~ ("\\\"" | ANY))* } semicolon = _{ ";" } static_path = { identifier ~ ("::" ~ identifier)* } // ====================================================== // PROGRAM // ====================================================== program = { SOI ~ top_level* ~ EOI } module_program = { SOI ~ top_level? } // ====================================================== // MODIFIERS // ====================================================== visibility = { "pub" ~ ("(" ~ static_path ~ ")")? } mutable = { "mut" } // ====================================================== // GENERICS // ====================================================== generic_decl = { lifetime | (identifier ~ (":" ~ generic ~ ("+" ~ generic)*)?) } generics_decl = { "<" ~ (generic_decl ~ ("," ~ generic_decl)*)? ~ ">" } generic = { lifetime | type_expr } generics = { "<" ~ (generic ~ ("," ~ generic)*)? ~ ">" } // ====================================================== // TYPES // ====================================================== tuple_type = { "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ","? ~ ")" } path_type = { static_path ~ generics? } unsafe_ref_type = { mutable? ~ "unsafe" ~ "*" } ref_type = { mutable? ~ lifetime? ~ "&" } fn_kind_fn = { "fn" } fn_kind_unsafe = { "unsafe" ~ "fn" } fn_kind_closure = { "Fn" } fn_kind_once = { "FnOnce" } fn_kind_mut = { "FnMut" } fn_kind = _{ fn_kind_fn | fn_kind_unsafe | fn_kind_closure | fn_kind_once | fn_kind_mut } fn_type = { fn_kind ~ "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" } dyn_type = { "dyn" ~ type_expr } void_type = { "void" } type_expr = { (void_type | path_type | tuple_type | dyn_type) ~ (unsafe_ref_type | ref_type | fn_type)* } lifetime = { "'" ~ identifier } // ====================================================== // LITERALS // ====================================================== literal = { float | integer | boolean | string_lit } // ====================================================== // PATTERNS // ====================================================== etc_pattern = { ".." } multi_pat_template = _{ ((pattern | etc_pattern) ~ ("," ~ (pattern | etc_pattern))* ~ ","?)? } tuple_pattern = { "(" ~ (pattern | etc_pattern) ~ "," ~ multi_pat_template ~ ")" } named_tuple_pattern = { static_path ~ "(" ~ multi_pat_template ~ ")" } struct_destruct = { identifier ~ (":" ~ pattern)? } struct_pattern = { static_path ~ "{" ~ ((struct_destruct | etc_pattern) ~ ("," ~ (struct_destruct | etc_pattern))*)? ~ "}" } path_pattern = { mutable? ~ static_path } pattern = _{ named_tuple_pattern | tuple_pattern | struct_pattern | literal | path_pattern } // ====================================================== // ATTRIBUTES / META // ====================================================== attribute = { "#" ~ "[" ~ meta ~ "]" } mod_attribute = { "#" ~ "!" ~ "[" ~ meta ~ "]" } meta = { static_path ~ ("=" ~ literal | "(" ~ meta_list? ~ ")")? } meta_list = { (meta ~ ("," ~ meta)* ~ ","?)? } attributes = { attribute* } // ====================================================== // DECLARATION HELPERS // ====================================================== as_kw = { "as" } var_decl = { ("let" ~ pattern ~ ("," ~ pattern)*) | (type_expr ~ as_kw ~ (!tuple_pattern ~ pattern ~ ("," ~ pattern)+)) | (type_expr ~ (!tuple_pattern ~ pattern ~ ("," ~ pattern)*)) } field = { visibility? ~ type_expr ~ identifier } param = { (type_expr ~ pattern) | pattern } field_list = { (field ~ ";")* } param_list = { (param ~ ("," ~ param)* ~ ","?)? } // ====================================================== // IMPORTS / MODULES // ====================================================== import = { visibility? ~ "use" ~ static_path ~ semicolon } declare_module = { visibility? ~ "module" ~ identifier ~ semicolon } // ====================================================== // STRUCTS // ====================================================== struct_decl = { visibility? ~ "struct" ~ identifier ~ generics_decl? ~ "{" ~ field_list ~ "}" } // ====================================================== // ENUMS // ====================================================== enum_named = { identifier } enum_tuple = { identifier ~ tuple_type } enum_struct = { identifier ~ "{" ~ field_list ~ "}" } enum_field = _{ enum_tuple | enum_struct | enum_named } enum_decl = { visibility? ~ "enum" ~ identifier ~ generics_decl? ~ "{" ~ (enum_field ~ ";")* ~ "}" } // ====================================================== // CLASSES // ====================================================== class_constructor = { visibility? ~ "constructor" ~ generics_decl? ~ "(" ~ param_list ~ ")" ~ block } class_fields = { class_field* } class_field = { field ~ ("=" ~ expr)? ~ semicolon } self_param = { (ref_px ~ lifetime?)? ~ mutable? ~ "self" } method_args = _{ ((self_param ~ ("," ~ param_list)?) | param_list) ~ ","? } class_item = _{ impl_decl | function_decl } class_decl = { visibility? ~ "class" ~ identifier ~ generics_decl? ~ (":" ~ expr_path)? ~ "{" ~ class_fields ~ class_constructor? ~ class_item* ~ "}" } // ====================================================== // IMPL // ====================================================== impl_for_decl = { "impl" ~ generics_decl? ~ type_expr ~ "for" ~ type_expr ~ "{" ~ function_decl* ~ "}" } impl_decl = { "impl" ~ generics_decl? ~ type_expr ~ "{" ~ function_decl* ~ "}" } // ====================================================== // Traits // ====================================================== trait_requirements = { ":" ~ generic ~ ("+" ~ generic)* } trait_item = _{ function_decl } trait_decl = { visibility? ~ "trait" ~ identifier ~ generics_decl? ~ trait_requirements? ~ "{" ~ trait_item* ~ "}" } // ====================================================== // FUNCTIONS // ====================================================== override_kw = { "override" ~ ("(" ~ expr_path ~ ")")? } function_decl = { visibility? ~ ("void" | type_expr) ~ identifier ~ generics_decl? ~ "(" ~ method_args ~ ")" ~ override_kw? ~ (block | semicolon) } // ====================================================== // CONSTANTS / STATIC // ====================================================== const_decl = { "const" ~ var_decl_statement ~ ";" } static_decl = { "static" ~ var_decl_statement ~ ";" } // ====================================================== // Type aliases // ====================================================== type_alias = { "type" ~ identifier ~ generics_decl? ~ "=" ~ type_expr ~ ";" } // ====================================================== // TOP LEVEL // ====================================================== top_level = { mod_attribute | (attributes ~ (import | impl_for_decl | impl_decl | trait_decl | struct_decl | enum_decl | class_decl | declare_module | function_decl | const_decl | static_decl | type_alias)) } // ====================================================== // STATEMENTS // ====================================================== block = { "{" ~ statement_list ~ expr? ~ "}" } unsafe_block = { "unsafe" ~ block } statement_list = { statement* } statement = _{ control_flow | top_level | (expr ~ semicolon) } // ------------------------------------------------------ // BASIC STATEMENTS // ------------------------------------------------------ basic_stmt = { return_stmt | break_stmt | continue_stmt | var_decl_statement } return_stmt = { "return" ~ expr? } break_stmt = { "break" } continue_stmt = { "continue" } var_decl_statement = { var_decl ~ ("=" ~ expr)? } // ------------------------------------------------------ // CONDITIONALS // ------------------------------------------------------ control_flow = { if_stmt | while_stmt | c_for_stmt | for_stmt | match_stmt | loop_stmt | block | unsafe_block } statement_branch = { (expr_no_struct | ("(" ~ expr ~ ")")) ~ block } else_if = _{ "else" ~ "if" ~ statement_branch } else_if_list = { else_if* } if_stmt = { "if" ~ statement_branch ~ else_if_list ~ ("else" ~ block)? } // ------------------------------------------------------ // LOOPS // ------------------------------------------------------ while_stmt = { "while" ~ statement_branch } c_for_stmt = { "for" ~ "(" ~ statement ~ statement ~ expr ~ ")" ~ block } for_stmt = { "for" ~ pattern ~ "in" ~ expr ~ block } loop_stmt = { "loop" ~ block } // ------------------------------------------------------ // MATCH // ------------------------------------------------------ pattern_list = { pattern ~ ("|" ~ pattern)* } match_item = { pattern_list ~ "=>" ~ (block | (expr ~ ",")) } match_stmt = { "match" ~ (expr_no_struct | "(" ~ expr ~ ")") ~ "{" ~ match_item* ~ "}" } // ====================================================== // EXPRESSIONS // ====================================================== // ------------------------------------------------------ // CLOSURES // ------------------------------------------------------ closure = { ("(" ~ param_list ~ ")" ~ "=>" ~ expr) | (type_expr ~ "(" ~ param_list ~ ")" ~ "=>" ~ expr) } // ------------------------------------------------------ // TUPLES & ARRAYS // ------------------------------------------------------ tuple = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ","? ~ ")" } array_repeat = { "[" ~ expr ~ ";" ~ expr ~ "]" } array = { "[" ~ (expr ~ ("," ~ expr)* ~ ","?)? ~ "]" } // ------------------------------------------------------ // MACROS // ------------------------------------------------------ macro_inner_v = @{ string_lit | ("(" ~ macro_inner_v* ~ ")") | ("[" ~ macro_inner_v* ~ "]") | ("{" ~ macro_inner_v* ~ "}") | (!("(" | ")" | "[" | "]" | "{" | "}") ~ ANY) } // ------------------------------------------------------ // PRIMARY EXPRESSIONS // ------------------------------------------------------ expr_path_segment = { identifier ~ generics? } expr_path = { expr_path_segment ~ ("::" ~ expr_path_segment)* } primary = { control_flow | closure | basic_stmt | literal | expr_path | tuple | array_repeat | array } // ------------------------------------------------------ // POSTFIX EXPRESSIONS // ------------------------------------------------------ field_px = { "." ~ identifier ~ generics? } tuple_field_px = { "." ~ integer ~ generics? } call_px = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } macro_call_paren = { "!" ~ "(" ~ macro_inner_v* ~ ")" } macro_call_bracket = { "!" ~ "[" ~ macro_inner_v* ~ "]" } macro_call_brace = { "!" ~ "{" ~ macro_inner_v* ~ "}" } struct_field_decl = { identifier ~ (":" ~ expr)? } struct_px = { "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ ","? ~ "}" } index_px = { "[" ~ expr ~ "]" } as_px = { "as" ~ type_expr } try_px = { "?" } increment = { "++" } decrement = { "--" } postfix = { field_px | tuple_field_px | call_px | macro_call_paren | macro_call_bracket | macro_call_brace | struct_px | index_px | as_px | try_px | increment | decrement } // ------------------------------------------------------ // PREFIX EXPRESSIONS // ------------------------------------------------------ deref_px = { "*" } mut_ref_px = { "&" ~ mutable } ref_px = { "&" } not_px = { "!" } neg_px = { "-" } prefix = { deref_px | mut_ref_px | ref_px | not_px | neg_px } // ------------------------------------------------------ // OPERATORS // ------------------------------------------------------ bin_op = { "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^=" | "<<=" | ">>=" | "<<" | ">>" | "..=" | ".." | "<=" | ">=" | "==" | "!=" | "&&" | "||" | "->" | "+" | "-" | "*" | "/" | "%" | "<" | ">" | "&" | "|" | "^" | "=" } // ------------------------------------------------------ // EXPRESSIONS // ------------------------------------------------------ expr = { term ~ (bin_op ~ term)* } term = { prefix* ~ primary ~ postfix* } expr_no_struct = { term_no_struct ~ (bin_op ~ term_no_struct)* } term_no_struct = { prefix* ~ primary ~ (!struct_px ~ postfix)* }