program -> { declaration } ; declaration -> var_declaration ; declaration -> func_declaration ; func_declaration -> type_specifier ID LPARAN params RPARAN compound_stmt ; var_declaration -> type_specifier ID [ LSQUARE NUM RSQUARE ] SEMI ; type_specifier -> INT ; type_specifier -> VOID ; params -> VOID ; params -> param_list ; param_list -> param { COMMA param } ; param -> type_specifier ID [ LSQUARE RSQUARE ] ; compound_stmt -> LBRACE { local_var_declaration } statement_list RBRACE ; local_var_declaration -> type_specifier ID [ LSQUARE NUM RSQUARE ] SEMI ; statement_list -> { statement } ; statement -> assign_stmt ; statement -> compound_stmt ; statement -> selection_stmt ; statement -> iteration_stmt ; statement -> return_stmt ; statement -> write_stmt ; assign_stmt -> var ASSIGN expression SEMI ; selection_stmt -> IF LPARAN expression RPARAN statement [ ELSE statement ] ; iteration_stmt -> WHILE LPARAN expression RPARAN statement ; return_stmt -> RETURN SEMI ; return_stmt -> RETURN expression SEMI ; write_stmt -> WRITE LPARAN expression RPARAN SEMI ; expression -> additive_expression { realop additive_expression } ; additive_expression -> term { addop term } ; term -> factor { mulop factor } ; factor -> LPARAN expression RPARAN ; factor -> var ; factor -> call ; factor -> NUM ; var -> ID [ LSQUARE expression RSQUARE ] ; call -> ID LPARAN args RPARAN ; args -> EMPTY ; args -> expression { COMMA expression } ; realop -> EQ ; realop -> NEQ ; realop -> LT ; realop -> GT ; realop -> NLT ; realop -> NGT ; addop -> PLUS ; addop -> MINUS ; mulop -> DIV ; mulop -> TIMES ;