type symbol_table = {
     parent : symbol_table option;
     mutable variables : (string * type_specifier * string list) list;
     mutable functions : ((string * type_specifier) * ((string * type_specifier) list)) list;
     mutable structs: (string * (string * type_specifier) list) list;
     ret_type : type_specifier;		   
}

and lvalue =
       Lval_id of string
     | Lval_arr of lvalue * expr
     | Lval_struct of lvalue * string

and expr =
       Expr_func of string * expr list
     | Expr_const of constant
     | Expr_op of string * expr
     | Expr_lval of lvalue
     | Expr_lval_op of lvalue * string
     | Expr_binop of expr * string * expr
     | Expr_asgop of lvalue * string * expr
     | Expr_paren of expr

and expr_opt =  Expr_opt of expr option  

and stmt =
       Stmt of expr
     | Stmt_block of stmt list
     | Stmt_if of expr * stmt
     | Stmt_ifelse of expr * stmt * stmt
     | Stmt_for of expr_opt * expr_opt * expr_opt * stmt
     | Stmt_break
     | Stmt_ret of expr
     | Stmt_noop

and constant = 
       Const_int of int
     | Const_dbl of float
     | Const_str of string

and constant_expr = 
       Const_expr of constant
     | Const_expr_neg of constant

and type_specifier = 
          Int
        | Double
        | List of type_specifier
        | String
        | Struct of string

and initializer_ =
          Init_const_expr of constant_expr
        | Init_const_expr_list of constant_expr list	

and declarator = Declarator of string * initializer_ option

and declaration =
    	  Decl of type_specifier * declarator list
	| Decl_struct of string * struct_decl_list

and struct_decl_list = (string * type_specifier) list

and function_body = { func_decl_list : declaration list;
     		      mutable stmt_list : stmt list; }

and function_parameter = string * type_specifier

and function_declarator = string * function_parameter list

and function_definition = { type_spec : type_specifier;
     			    func_decl : function_declarator;
			    func_body : function_body; }

and program = { decl_list : declaration list;
                func_def_list : function_definition list; }

and program_data = { prog_env : symbol_table;
                     prog_functions : function_data list; }

and function_data = { func_env : symbol_table;
     		      func_definition : function_definition; }
	  

