--- layout: default title: Reference --- ## Stuff I considered Note there is an implicit `filename` included in the AST generated. Its basically any valid filename on your OS and reic that doesnt include certain special chars. - Each production is associated with an internal node - Each terminal production is associated with a leaf node "v0" grammar of rei: ```rust // ------------- // CONTENT // ------------- content: expr* // ------------- // EXPRESSIONS // ------------- expr: function_def | class_def | data_def | variable_def | operator_expr | if_expr | for_expr | while_expr | return_expr | trivial_expr | use_expr return_expr: "return" ~ [expr] trivial_expr: "yield" | "continue" | "break" variable_def: var_keywords ~ expr ~ "=" ~ expr variable_redef: (ident ~ "=" ~ expr) // variables var_keywords: "let" | "const" | "mut" | "static" // same as mod something::something // use x::*::y doesnt make sense use_expr: "use" ~ ident ~ ("::" ~ ident)* ~ ["::" ~ "*"] // !Function Expressions function_def: { anonymous_function_expr | standard_function_expr | arrow_function_expr } // just a let/const but function like anonymous_function_expr: { "(" ~ param_list ~ ")" ~ single_or_scoped_block } // note: function_body is basically any_statement* // but apparently no left recursive standard_function_expr: { fn_keyword ~ ident ~ "(" ~ param_list ~ ")" ~ "{" ~ expr* ~ "}" } arrow_function_expr: { "(" ~ param_list ~ ")" ~ "=>" ~ single_or_scoped_block } // !Class Expressions class_def: { "class" ~ scoped_class_body } class_field_expr: { "let"|"const" ~ ident ~ ":" ~ ident } scoped_class_body: { "{" ~ (class_field_expr|allowed_scoped_Expressions)* ~ "}" } // !Data Expressions data_def: { "data" ~ field_scoped_block } field_scoped_block: { "{" ~ data_field_expr* ~ "}" } data_field_expr: { ident ~ ":" ~ ident } // !Control Expressions // should technically be a boolean expr, should be parseable if_expr: { if_block ~ (elif_block* ~ [else_block]) } if_block: "if" ~ expr* ~ single_or_scoped_block elif_block: { "elif" ~ expr* ~ if_block } else_block: { "else" ~ if_block } for_expr: { standard_for_expr | range_based_for_expr } standard_for_expr: { "for" ~ for_expr_cond ~ single_or_scoped_block } // for i in start..end for_expr_cond: { ident ~ "in" ~ expr ~ ".." ~ expr } single_or_scoped_block: { scoped_block | "->" ~ expr } template_expr: "<" ~ generic_list ~ ">" generic_list: ident ~ (":" ~ ident)* ~ // should you make identifiers namespaceable? // so instead, you actually make idents: // ([\d\w_]+::)*([\d\w_]+|\*)$ // ------------- // EXPRESSIONS // ------------- // expr needs to be more generic I think..? // or maybe use expr instead? // expr should result in a returnable var, including () // Expressions always results in () // so a statement is technically a subset of expr? expr: term ~ {op ~ term} array_index_expr: ident ~ "[" ~ ident ~ "]" term: ident | number | "(" expr ")" number: ["+"|"-"] ~ numeric numeric: int | float int: hex | decimal float: [int] ~ "." ~ int ident: (word* ~ "::")* ~ (word*|"*") word: r"\w" // ------------- // OPERATORS // ------------- op: "<" | ">" | "<<" | ">>" | "." | "," | ".." | "*" | "+" | "-" | "=" | "==" | ":" | "::" | "->" | "=>" | "/" | "\\" | "//" | "%" | "^" | "&" | "&&" | "$" | "#" | "@" | "!" | "[" | "]" | "+=" | "++" | "-=" | "--" | "?" // ------------- // SCOPED BLOCKS // ------------- scoped_block { "{" ~ "}" } ```