main                = { stmt } EOF
stmt                = using | recorddef | typedef | funcdef | ( local_stmt NL )
using               = "using" namespace NL
namespace           = identifier { "." identifier }
recorddef           = "record" identifier NL recorddef_stmt { recorddef_stmt }
recorddef_stmt      = INDENT identifier ":" type NL
typedef             = "type" identifier NL typedef_stmt { typedef_stmt }
typedef_stmt        = INDENT identifier [ "of" type ] NL
funcdef             = "fun" identifier [ ":" type ] [ "(" { func_param } ")" ] "->" block NL
func_param          = identifier ":" [ "ref" ] type
block               = NL block_line { block_line } | local_stmt
block_line          = INDENT local_stmt NL
type                = namespace [ ( type_params | { "[]" } ) ]
local_stmt          = var_decl_expr | assign_expr | expr
var_decl_expr       = ( "let" | "var" identifier "=" expr ) | "var" identifier ":" type
assign_expr         = lvalue "=" expr
lvalue              = [ type "::" ] identifier { accessor_expr } | atomar_expr accessor_expr { accessor_expr }
atomar_expr         = literal | "(" expr ")"
accessor_expr       = "." identifier | "[" line_expr "]"
type_params         = "<" type { "," type } ">"
expr                = block_expr | line_expr
block_expr          = if_expr | while_expr | for_expr | try_expr | throw_expr | lambda_expr 
throw_expr          = throw [ line_expr ]
if_expr             = "if" line_expr "then" block [ "else" block ]
while_expr          = "while" line_expr "do" block
for_expr            = "for" identifier "in" line_expr [ ".." line_expr ] "do" block
try_expr            = "try" block catch_expr { catch_expr } [ "finally" block ]
catch_expr          = "catch" [ identifier ":" type ] block
lambda_expr         = [ func_param | "(" { func_param } ")" ] "->" block
line_expr           = line_expr_0 { NL IDENT "|>" identifier invoke_list }
line_expr_0         = line_expr_1 [ ( "as" | "is" ) type ]
line_expr_1         = line_expr_2 { sign_1 line_expr_2 }
sign_1              = "&&" | "||" | "^^"
line_expr_2         = line_expr_3 { sign_2 line_expr_3 }
sign_2              = "==" | "<>" | "<=" | ">=" | "<" | ">"
line_expr_3         = line_expr_4 { sign_3 line_expr_4 }
sign_3              = "<:" | ":>"
line_expr_4         = line_expr_5 { sign_4 line_expr_5 }
sign_4              = "&" | "|" | "^"
line_expr_5         = [ "not" | "-" ] line_expr_4 { sign_3 line_expr_4 }
sign_5              = "+" | "-"
line_expr_6         = line_expr_5 { sign_4 line_expr_5 }
sign_6              = "*" | "/" | "%"
line_expr_7         = line_expr_8 { "**" line_expr_8 }
line_expr_8         = line_expr_9 { "[" expr "]" }
line_expr_9         = new_expr | type_operator_expr | value_expr | invoke_expr
new_expr            = "new" ( new_list_expr | new_array_expr | new_tuple_expr | new_dict_expr | new_obj_expr )
new_list_expr       = "[[" enumeration_expr "]]"
new_array_expr      = "[" enumeration_expr "]"
new_tuple_expr      = "(" enumeration_expr ")"
new_dict_expr       = "{" dict_entry_expr { ";" dict_entry_expr } "}"
dict_entry_expr     = value_expr "=>" value_expr
new_obj_expr        = type [ invoke_list ]
enumeration_expr    = line_expr { ";" line_expr }
invoke_expr         = value_expr invoke_list
invoke_list         = NL { IDENT "<|" ( byref_arg | expr ) NL } | { byref_arg | value_expr }
byref_arg           = "(" "ref" lvalue ")" | "ref" lvalue
value_expr          = rvalue | atomar_expr
rvalue              = lvalue [ type_params ]
type_operator_expr  = ( "typeof" | "default" ) type
literal             = "()" | "null" | "true" | "false" | double | int | string

string              = " [^"] " (any character except double quote inside double quotes)
int                 = [0-9]+
double              = [0-9]+\.[0-9]+
identifier          = [a-zA-Z_][0-9a-zA-Z_]*

NL                  = "\n"
INDENT              = { " " }
EOF                 = \EOF
