(* program define *) program = block; (* block define *) block = {statement}; (* statement define *) statement = class_stmt | func_stmt | var_stmt | if_stmt | while_stmt | for_stmt | break_stmt | return_stmt | expr_stmt | import_stmt | try_stmt | throw_stmt | ';'; if_stmt = 'if' expr block {'elif' expr block} ['else' block] 'end'; while_stmt = 'while' expr block 'end'; for_stmt = 'for' ID ':' expr block 'end'; break_stmt = 'break' | 'continue'; return_stmt = 'return' [expr]; (* function define statement *) func_stmt = 'def' ID func_body; func_body = '(' [arg_field {',' arg_field}] ')' block 'end'; arg_field = ['*'] ID; (* class define statement *) class_stmt = 'class' ID [':' ID] class_block 'end'; class_block = {'var' ID {',' ID} | 'static' ID ['=' expr] {',' ID ['=' expr] } | func_stmt}; import_stmt = 'import' (ID (['as' ID] | {',' ID}) | STRING 'as' ID); (* exceptional handling statement *) try_stmt = 'try' block except_block {except_block} 'end'; except_block = except_stmt block; except_stmt = 'except' (expr {',' expr} | '..') ['as' ID [',' ID]]; throw_stmt = 'raise' expr [',' expr]; (* variable define statement *) var_stmt = 'var' ID ['=' expr] {',' ID ['=' expr]}; (* expression define *) expr_stmt = expr [assign_op expr]; expr = suffix_expr | unop expr | expr binop expr | cond_expr; cond_expr = expr '?' expr ':' expr; (* conditional expression *) assign_op = '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>='; binop = '..' | '<' | '<=' | '==' | '!=' | '>' | '>=' | '||' | '&&' | '<<' | '>>' | '&' | '|' | '^' | '+' | '-' | '*' | '/' | '%'; unop = '-' | '!' | '~'; suffix_expr = primary_expr {call_expr | ('.' ID) | '[' expr ']'}; primary_expr = '(' expr ')' | simple_expr | list_expr | map_expr | anon_func | lambda_expr; simple_expr = INTEGER | REAL | STRING | ID | 'true' | 'false' | 'nil'; call_expr = '(' [expr {',' expr}] ')'; list_expr = '[' {expr ','} [expr] ']'; map_expr = '{' {expr ':' expr ','} [expr ':' expr] '}'; anon_func = 'def' func_body; (* anonymous function *) lambda_expr = '/' [arg_field {',' arg_field}] | {arg_field}] '->' expr;