open Ast

let rec eval_prog = function
          Print_prog(None, func_def_list) -> eval_func_def_list(func_def_list)
        | Print_prog(Some(decl_list), func_def_list) -> eval_decl_list(decl_list); eval_func_def_list(func_def_list)

and eval_expr = function
          Print_expr_func(string, expr_list_opt) -> print_string(string); print_string("(");
              eval_expr_list_opt(expr_list_opt); print_string(")")
        | Print_expr_const(constant) -> eval_const(constant)
        | Print_expr_op(string, expr) -> print_string(string); eval_expr(expr)
        | Print_expr_lval(lvalue, None) -> eval_lval(lvalue)
        | Print_expr_lval(lvalue, Some(string)) -> eval_lval(lvalue); print_string(string)
        | Print_expr_binop(expr1, string, expr2) -> eval_expr(expr1); print_string(string); eval_expr(expr2)
        | Print_expr_asgop(lvalue, string, expr) -> eval_lval(lvalue); print_string(string); eval_expr(expr)
        | Print_expr_paren(expr) -> print_string("("); eval_expr(expr); print_string(")")

and eval_expr_list_opt = function
          Print_expr_list_opt(None) -> ()
        | Print_expr_list_opt(Some(expr_list)) -> eval_expr_list(expr_list)

and eval_expr_list = function
          Print_expr_list(None, expr) -> eval_expr(expr)
        | Print_expr_list(Some(expr_list), expr) -> eval_expr_list(expr_list);
              print_string(","); eval_expr(expr)

and eval_stmt_list = function
          Print_stmt_list(None, stmt) -> eval_stmt(stmt)
        | Print_stmt_list(Some(stmt_list), stmt) -> eval_stmt_list(stmt_list); eval_stmt(stmt)

and eval_stmt = function
          Print_stmt(expr) -> eval_expr(expr); print_string(";")
        | Print_stmt_block(stmt_list) -> print_string("{"); eval_stmt_list(stmt_list); print_string("}")
        | Print_stmt_if(expr, stmt) -> print_string("if("); eval_expr(expr); print_string(")"); eval_stmt(stmt)
	| Print_stmt_ifelse(expr, stmt1, stmt2) -> print_string("if("); eval_expr(expr); print_string(")");
              eval_stmt(stmt1); print_string("else"); eval_stmt(stmt2)
        | Print_stmt_for(expr_opt1, expr_opt2,expr_opt3, stmt) -> print_string("for("); eval_expr_opt(expr_opt1); print_string(";");
              eval_expr_opt(expr_opt2); print_string(";"); eval_expr_opt(expr_opt3); print_string(")"); eval_stmt(stmt)
        | Print_stmt_break -> print_string("break;")
        | Print_stmt_ret(expr) -> print_string("return"); eval_expr(expr); print_string(";")
        | Print_stmt_noop -> print_string(";")

and eval_expr_opt = function
          Print_expropt(None) -> ()
        | Print_expropt(Some(expr)) -> eval_expr(expr)
     
and eval_decl = function 
          Print_decl(type_spec, declarator_list) -> eval_type_spec(type_spec); eval_declarator_list(declarator_list);
              print_string(";")
        | Print_decl_struct(string, decl_list) -> print_string("struct"); print_string(string); print_string("{");
              eval_decl_list(decl_list); print_string("}");

and eval_type_spec = function
          Print_type_str(string) -> print_string(string)
	| Print_type_list(type_spec) -> print_string("list<"); eval_type_spec(type_spec); print_string(">")
	| Print_type_struct(string) -> print_string("struct"); print_string(string)

and eval_declarator_list = function
          Print_declarator_list(None, declarator) -> eval_declarator(declarator)
        | Print_declarator_list(Some(declarator_list), declarator) -> eval_declarator_list(declarator_list); 
              print_string(","); eval_declarator(declarator)

and eval_declarator = function
          Print_declarator(string, None) -> print_string(string)
        | Print_declarator(string, Some(init)) -> print_string(string); eval_init(init)

and eval_init = function
          Print_init_const(const_expr) -> print_string("="); eval_const_expr(const_expr)
        | Print_init_const_list(const_expr_list) -> print_string("={"); eval_const_expr_list(const_expr_list); print_string("}")

and eval_const_expr_list = function
          Print_const_expr_list(None, const_expr) -> eval_const_expr(const_expr)
        | Print_const_expr_list(Some(const_expr_list), const_expr) -> eval_const_expr_list(const_expr_list); print_string(";");
              eval_const_expr(const_expr)

and eval_func_def = function
          Print_func_def(type_spec, func_decl, func_body) -> eval_type_spec(type_spec); eval_func_decl(func_decl);
              eval_func_body(func_body)
	
and eval_func_decl = function
          Print_func_decl(string, param_list_opt) -> print_string(string); print_string("("); 
              eval_param_list_opt(param_list_opt); print_string(")")

and eval_param_list_opt = function
          Print_param_list_opt(None) -> ()
        | Print_param_list_opt(Some(param_list)) -> eval_param_list(param_list)

and eval_param_list = function
          Print_param_list(None, func_param) -> eval_func_param(func_param)
        | Print_param_list(Some(param_list), func_param) -> eval_param_list(param_list); print_string(",");
              eval_func_param(func_param)

and eval_func_param = function
          Print_func_param(type_spec, string) -> eval_type_spec(type_spec); print_string(string)

and eval_func_body = function
          Print_funcbody(decl_list_opt, stmt_list) -> print_string("{"); eval_decl_list_opt(decl_list_opt);
              eval_stmt_list(stmt_list); print_string("}")

and eval_decl_list_opt = function
          Print_decl_list_opt(None) -> ()
        | Print_decl_list_opt(Some(decl_list)) -> eval_decl_list(decl_list)

and eval_func_def_list = function 
          Print_func_def_list(None, func_def) -> eval_func_def(func_def)
	| Print_func_def_list(Some(func_def_list), func_def) -> eval_func_def_list(func_def_list); eval_func_def(func_def)

and eval_decl_list = function
          Print_decl_list(None, decl) -> eval_decl(decl)  
        | Print_decl_list(Some(decl_list), decl) -> eval_decl_list(decl_list); eval_decl(decl)

and eval_const_expr = function
          Print_const_expr(const) -> eval_const(const)
	| Print_const_expr_neg(const_expr) -> print_string("-"); eval_const_expr(const_expr)
	| Print_const_expr_not(const_expr) -> print_string("!"); eval_const_expr(const_expr)
	| Print_const_expr_binop(const_expr1, str, const_expr2) -> eval_const_expr(const_expr1);
              print_string(str); eval_const_expr(const_expr2);
	| Print_const_expr_paren(const_expr) -> print_string("("); eval_const_expr(const_expr); print_string(")")

and eval_const = function
          Print_const_int(int) -> print_string(string_of_int(int))
	| Print_const_dbl(float) -> print_string(string_of_float(float))
        | Print_const_str(string) -> print_string(string)

and eval_lval = function
          Print_lval_id(string) -> print_string(string)
        | Print_lval_arr(lvalue, expr) -> eval_lval(lvalue); print_string("["); eval_expr(expr); print_string("]")
        | Print_lval_obj(lvalue, string) -> eval_lval(lvalue); print_string("."); print_string(string) 


let _ =
    let lexbuf = Lexing.from_channel stdin in
        let prog =
             Parser.program Scanner.token lexbuf in eval_prog prog; print_endline("")