<program> ::= <statement>*

<statement> ::= <variable_declaration>
              | <function_declaration>
              | <while_loop>
              | <if_statement>
              | <type_declaration>
              | <return_statement>

<variable_declaration> ::= "let" <identifier> ":" <type> "=" <expression> ";"

<function_declaration> ::= "fn" <identifier> "(" <parameters> ")" "->" <type> "{" <body> "}"

<parameters> ::= <parameter> ("," <parameter>)*
<parameter> ::= <identifier> ":" <type>

<while_loop> ::= "while" "(" <expression> ")" "{" <body> "}"

<if_statement> ::= "if" "(" <expression> ")" "{" <body> "}" <elif_statements> <else_statement>?
<elif_statements> ::= ("elif" "(" <expression> ")" "{" <body> "}")*
<else_statement> ::= "else" "{" <body> "}"

<type_declaration> ::= "type" <identifier> "=" <type_definition> ";"
<type_definition> ::= "{" <field> ("," <field>)* "}"
                    | "[" <integer> ":" <type> "]"
                    | "<" <identifier> ("," <identifier>)* ">"

<return_statement> ::= "return" <expression> ";"

<body> ::= <statement>*

<expression> ::= <literal>
               | <identifier>
               | <binary_operation>
               | <unary_operation>
               | <function_call>
               | "(" <expression> ")"

<binary_operator> ::= "+" | "-" | "*" | "/" 
                   | "&&" | "||" 
                   | "==" | "!=" | "<" | ">" | "<=" | ">=" 
                   | "&" | "|" | "^" | "<<" | ">>"

<unary_operator> ::= "!" | "-" | "~"

<function_call> ::= <identifier> "(" <arguments> ")"
<arguments> ::= <expression> ("," <expression>)*

<literal> ::= <integer_literal>
            | <float_literal>
            | <string_literal>
            | <boolean_literal>

<integer_literal> ::= [0-9]+
<float_literal> ::= [0-9]+"."[0-9]+
<string_literal> ::= "\"" [^"]* "\""
<boolean_literal> ::= "true" | "false"

<identifier> ::= [a-zA-Z_][a-zA-Z0-9_]*
<type> ::= "i32" | "i64" | "f32" | "f64" | <identifier>