//*****************************************************************************************
// Truevision - a 3d modeler for gnome and povray
//
// function.h
//
// Vincent LE PRINCE <vincentleprince@users.sourceforge.net>
// Copyright (C) 2000-2005 Vincent LE PRINCE
// This file is part of the TRUEVISION Package

//   This program is free software; you can redistribute it and/or modify
//   it under the terms of the GNU General Public License as published by
//   the Free Software Foundation; either version 2 of the License, or
//   (at your option) any later version.
//
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program; if not, write to the Free Software
//   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
//*******************************************************************************************
#ifndef TV_FUNC_H
#define TV_FUNC_H
#include <vector>
#include <fstream>

using namespace std;

enum TvFuncOp_Type { 
	TV_FUNC_OP_PLUS,
	TV_FUNC_OP_MINUS,
	TV_FUNC_OP_PROD,
	TV_FUNC_OP_DIV,
	TV_FUNC_EQUAL,
};
typedef TvFuncOp_Type TvFuncOpType ;


class TvFuncExpr;
	
class TvFuncOp {
	private:
		TvFuncOpType type;
		vector<TvFuncExpr*> Exprs;
		vector<TvFuncOp*> args;
		bool folded;
	
	public:
		TvFuncOp( TvFuncOpType atype ) { type = atype; folded = false; }
		TvFuncOp( char car );
		~TvFuncOp();
		
		void add_expr( TvFuncExpr *expr ) { Exprs.push_back( expr ); }
		void add_arg( TvFuncOp *arg ) { args.push_back( arg ); }
		TvFuncOpType get_type() { return type; }
		bool get_folded() { return folded; }
		void set_folded() { folded = true; }
		double evaluate( float x, float y, float z );
};

class TvFuncExpr {
	private:
		char *string;
		int string_len;
		int error_code;
		char *error_str;
		bool status;
		char *error_str_tmp;
		int error_str_len;
		int mode;
		vector<TvFuncOp*> AryTree;
		double constant;
		int variable;
		bool invert;
		bool negate;
		int eval_mode;
		int function;
		vector<TvFuncExpr*> function_args;
		
	public:
		TvFuncExpr( char *str, int len );
		~TvFuncExpr();
	
		bool get_status() { return status; }
		void parse_expression();
		void compile_ary_tree();
		
		double  evaluate( float x, float y, float z );
		void propagate_error( TvFuncExpr *ex ) { status = false; error_code = ex->error_code; error_str = ex->error_str; error_str_len = ex->error_str_len; }
		char *get_error();		
};


class TvFunction {
	private:
		char *string;
		TvFuncExpr *expression;
	
	public:
		TvFunction();
		~TvFunction();
	
		bool get_status() { if ( expression != NULL ) return expression->get_status(); else return false; }
		char *get_error() { return expression->get_error(); }
		void set_expression( char *str );
		char *get_expression() { return string; }
		
		double evaluate( float x, float y, float z );
		
		void define_internals( ofstream & file );
};

#endif
