mathic 0.2.0

A compiler with builtin support of symbolic operations, built with LLVM/MLIR
(* ================================================================ *)
(* Mathic Grammar                                                   *)
(* ================================================================ *)
(*                                                                  *)
(* Notation:                                                        *)
(*   [ A ]     -- optional (zero or one)                            *)
(*   { A }     -- repetition (zero or more)                         *)
(*   UPPER     -- terminal token class (IDENT, INT, etc.)           *)
(*   lower     -- nonterminal                                       *)
(*                                                                  *)
(* LL(1) grammar                                                    *)
(* ================================================================ *)


(* ================================================================ *)
(* Program                                                          *)
(* ================================================================ *)

program = top_decl { top_decl } ;

top_decl    = func_decl | struct_decl ;
func_decl   = 'df' IDENT '(' [ param_list ] ')' [ type ] block ;
struct_decl = 'struct' IDENT '{' [ struct_fields ] '}' ;


(* ================================================================ *)
(* Declarations                                                     *)
(* ================================================================ *)

declaration = func_decl
            | struct_decl
            | var_decl
            | sym_decl
            ;

var_decl = 'let' IDENT ':' IDENT '=' expr ';' ;
sym_decl = 'sym' IDENT ':' type ';' ;


(* ================================================================ *)
(* Statements                                                       *)
(* ================================================================ *)

stmt = declaration
     | for_stmt
     | while_stmt
     | if_stmt
     | return_stmt
     | expr_stmt
     | block
     ;

for_stmt    = 'for' IDENT 'in' expr_no_init '..' expr_no_init block
            | 'for' IDENT 'in' expr_no_init block ;
while_stmt  = 'while' expr_no_init block ;
if_stmt     = 'if' expr_no_init block [ 'else' block ] ;
return_stmt = 'return' expr ';' ;
expr_stmt   = expr ';' ;
block       = '{' { stmt } '}' ;


(* ================================================================ *)
(* Expressions                                                      *)
(* ================================================================ *)
(* Precedence (lowest to highest):                                  *)
(*   1. or                                                          *)
(*   2. and                                                         *)
(*   3. == !=                                                       *)
(*   4. < > <= >=                                                   *)
(*   5. + -                                                         *)
(*   6. * /                                                         *)
(*   7. unary (! -)                                                 *)
(*   8. call (() [] .)                                              *)

expr         = assignment ;
assignment   = IDENT { '.' IDENT } '=' expr
             | initializer
             ;
initializer  = expr_no_init [ struct_init ] ;
expr_no_init = logical_or ;

logical_or  = logical_and { 'or' logical_and } ;
logical_and = equality { 'and' equality } ;
equality    = comparison { ( '==' | '!=' ) comparison } ;
comparison  = term { ( '>' | '>=' | '<' | '<=' ) term } ;
term        = factor { ( '+' | '-' ) factor } ;
factor      = unary { ( '*' | '/' ) unary } ;
unary       = ( '!' | '-' ) unary
            | call
            ;
call        = primary { '(' [ arg_list ] ')' | '[' expr ']' | '.' IDENT } ;
struct_init = '{' IDENT ':' expr { ',' IDENT ':' expr } '}' ;
primary     = 'true' | 'false' | IDENT | INT | FLOAT | STRING | '(' expr ')' ;


(* ================================================================ *)
(* Utilities                                                        *)
(* ================================================================ *)

param_list    = ( IDENT ':' type ) { ',' ( IDENT ':' type ) } ;
struct_fields = [ 'pub' ] IDENT ':' type { ',' [ 'pub' ] IDENT ':' type } ;
arg_list      = expr { ',' expr } ;
type = IDENT { '<' IDENT '>' } ;

(* ---- Terminal token classes ---- *)
(* IDENT    : [a-zA-Z_][a-zA-Z0-9_]*                                *)
(* INT      : '0' | [1-9] [0-9]*                                    *)
(* FLOAT    : [0-9]+ '.' [0-9]+                                     *)
(* STRING   : '"' [^"]* '"'                                         *)