发现了一个数学公式解析类,共享一下。

main函数是我写的

#include "fparser.h" 
#include <iostream> 
#include <string> 
using namespace std; 

//函数表达式字符串,x,y变量值 
void calculate2V(const string & funcStr, double x, double y) 
{ 
    FunctionParser fp; 
    //【1】pass function expression string for c style 
    //【2】pass variate , split by comma 
    int ret = fp.Parse(funcStr.c_str(), "x,y"); 
    if(ret >= 0) 
    { 
        std::cerr << "At col " << ret << ": " << fp.ErrorMsg() << std::endl; 
        return ; 
    } 
    double vals[] = { x, y}; 
    cout << funcStr << " = " << fp.Eval(vals) << endl; 
} 

void calculate3V(const string & funcStr, double x, double y, double z) 
{ 
    FunctionParser fp; 
    //【1】pass function expression string for c style 
    //【2】pass variate , split by comma 
    int ret = fp.Parse(funcStr.c_str(), "x,y,z"); 
    if(ret >= 0) 
    { 
        std::cerr << "At col " << ret << ": " << fp.ErrorMsg() << std::endl; 
        return ; 
    } 

    double vals[] = { x, y, z}; 
    cout << funcStr << " = " << fp.Eval(vals) << endl; 
} 


int main() 
{ 
    calculate2V("x+y-1", 4, 8); 
    calculate2V("x*y", 2, 3); 
    calculate2V("sin(x)+y", 3.1415926/2, 3); 
    calculate3V("x+y*z", 2, 3,5); 
    //calculate2V("x*y", 2, 3); 
    //calculate2V("x*y", 2, 3); 
    system("pause");
    return 1; 
} 
#ifndef ONCE_FPARSER_H_
#define ONCE_FPARSER_H_
#include <string>
#include <map>
#include <vector>
#ifdef FUNCTIONPARSER_SUPPORT_DEBUG_OUTPUT
#include <iostream>
#endif
class FunctionParser
{
public:
	enum ParseErrorType
	{
		SYNTAX_ERROR = 0, MISM_PARENTH, MISSING_PARENTH, EMPTY_PARENTH,
		EXPECT_OPERATOR, OUT_OF_MEMORY, UNEXPECTED_ERROR, INVALID_VARS,
		ILL_PARAMS_AMOUNT, PREMATURE_EOS, EXPECT_PARENTH_FUNC,
		FP_NO_ERROR
	};

	int Parse(const std::string& Function, const std::string& Vars,
		bool useDegrees = false);
	const char* ErrorMsg() const;
	inline ParseErrorType GetParseErrorType() const { return parseErrorType; }
	double Eval(const double* Vars);
	inline int EvalError() const { return evalErrorType; }
	bool AddConstant(const std::string& name, double value);
	typedef double(*FunctionPtr)(const double*);
	bool AddFunction(const std::string& name,
		FunctionPtr, unsigned paramsAmount);
	bool AddFunction(const std::string& name, FunctionParser&);
	void Optimize();

	FunctionParser();
	~FunctionParser();
	// Copy constructor and assignment operator (implemented using the
	// copy-on-write technique for efficiency):
	FunctionParser(const FunctionParser&);
	FunctionParser& operator=(const FunctionParser&);

#ifdef FUNCTIONPARSER_SUPPORT_DEBUG_OUTPUT
	// For debugging purposes only:
	void PrintByteCode(std::ostream& dest) const;
#endif

	//========================================================================
private:
	//========================================================================
	// Private data:
	// ------------
	ParseErrorType parseErrorType;
	int evalErrorType;
	struct Data
	{
		unsigned referenceCounter;
		int varAmount;
		bool useDegreeConversion;
		//�������� ����������(�Զ���)
		typedef std::map<std::string, unsigned> VarMap_t;
		VarMap_t Variables;
		typedef std::map<std::string, double> ConstMap_t;
		ConstMap_t Constants;
		VarMap_t FuncPtrNames;
		struct FuncPtrData
		{
			FunctionPtr ptr; unsigned params;
			FuncPtrData(FunctionPtr p, unsigned par) : ptr(p), params(par) {}
		};
		std::vector<FuncPtrData> FuncPtrs;
		VarMap_t FuncParserNames;
		std::vector<FunctionParser*> FuncParsers;
		unsigned* ByteCode;
		unsigned ByteCodeSize;
		double* Immed;
		unsigned ImmedSize;
		double* Stack;
		unsigned StackSize;
		Data();
		~Data();
		Data(const Data&);
		Data& operator=(const Data&); // not implemented on purpose
	};
	Data* data;
	// Temp data needed in Compile():
	unsigned StackPtr;
	std::vector<unsigned>* tempByteCode;
	std::vector<double>* tempImmed;

	// Private methods:
	// ---------------
	inline void copyOnWrite();

	bool checkRecursiveLinking(const FunctionParser*) const;
	bool isValidName(const std::string&) const;
	Data::VarMap_t::const_iterator FindVariable(const char*,
		const Data::VarMap_t&) const;
	Data::ConstMap_t::const_iterator FindConstant(const char*) const;
	int CheckSyntax(const char*);
	bool Compile(const char*);
	bool IsVariable(int);
	void AddCompiledByte(unsigned);
	void AddImmediate(double);
	void AddFunctionOpcode(unsigned);
	inline void incStackPtr();
	int CompileIf(const char*, int);
	int CompileFunctionParams(const char*, int, unsigned);
	int CompileElement(const char*, int);
	int CompilePow(const char*, int);
	int CompileUnaryMinus(const char*, int);
	int CompileMult(const char*, int);
	int CompileAddition(const char*, int);
	int CompileComparison(const char*, int);
	int CompileAnd(const char*, int);
	int CompileOr(const char*, int);
	int CompileExpression(const char*, int, bool = false);

	void MakeTree(void*) const;
};
#endif
#include "fparser.h"

#include "fparser.h"
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
using namespace std;
#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795
#endif
namespace
{
	// The functions must be in alphabetical order:
	enum OPCODE
	{
		cAbs, cAcos,
#ifndef NO_ASINH
		cAcosh,
#endif
		cAsin,
#ifndef NO_ASINH
		cAsinh,
#endif
		cAtan,
		cAtan2,
#ifndef NO_ASINH
		cAtanh,
#endif
		cCeil, cCos, cCosh, cCot, cCsc,
#ifndef DISABLE_EVAL
		cEval,
#endif
		cExp, cFloor, cIf, cInt, cLog, cLog10, cMax, cMin,
		cSec, cSin, cSinh, cSqrt, cTan, cTanh,
		// These do not need any ordering:
		cImmed, cJump,
		cNeg, cAdd, cSub, cMul, cDiv, cMod, cPow,
		cEqual, cLess, cGreater, cAnd, cOr,
		cDeg, cRad,
		cFCall, cPCall,
#ifdef SUPPORT_OPTIMIZER
		cVar, cDup, cInv,
#endif
		VarBegin
	};
	struct FuncDefinition
	{
		const char* name;
		unsigned nameLength;
		unsigned opcode;
		unsigned params;
		// This is basically strcmp(), but taking 'nameLength' as string
		// length (not ending '/0'):
		bool operator<(const FuncDefinition& rhs) const
		{
			for (unsigned i = 0; i < nameLength; ++i)
			{
				if (i == rhs.nameLength) return false;
				const char c1 = name[i], c2 = rhs.name[i];
				if (c1 < c2) return true;
				if (c2 < c1) return false;
			}
			return nameLength < rhs.nameLength;
		}
	};

	// This list must be in alphabetical order:
	const FuncDefinition Functions[] =
	{
		{ "abs", 3, cAbs, 1 },
		{ "acos", 4, cAcos, 1 },
#ifndef NO_ASINH
		{ "acosh", 5, cAcosh, 1 },
#endif
		{ "asin", 4, cAsin, 1 },
#ifndef NO_ASINH
		{ "asinh", 5, cAsinh, 1 },
#endif
		{ "atan", 4, cAtan, 1 },
		{ "atan2", 5, cAtan2, 2 },
#ifndef NO_ASINH
		{ "atanh", 5, cAtanh, 1 },
#endif
		{ "ceil", 4, cCeil, 1 },
		{ "cos", 3, cCos, 1 },
		{ "cosh", 4, cCosh, 1 },
		{ "cot", 3, cCot, 1 },
		{ "csc", 3, cCsc, 1 },
#ifndef DISABLE_EVAL
		{ "eval", 4, cEval, 0 },
#endif
		{ "exp", 3, cExp, 1 },
		{ "floor", 5, cFloor, 1 },
		{ "if", 2, cIf, 0 },
		{ "int", 3, cInt, 1 },
		{ "log", 3, cLog, 1 },
		{ "log10", 5, cLog10, 1 },
		{ "max", 3, cMax, 2 },
		{ "min", 3, cMin, 2 },
		{ "sec", 3, cSec, 1 },
		{ "sin", 3, cSin, 1 },
		{ "sinh", 4, cSinh, 1 },
		{ "sqrt", 4, cSqrt, 1 },
		{ "tan", 3, cTan, 1 },
		{ "tanh", 4, cTanh, 1 }
	};
	const unsigned FUNC_AMOUNT = sizeof(Functions) / sizeof(Functions[0]);

	// BCB4 does not implement the standard lower_bound function.
	// This is used instead:
	const FuncDefinition* fp_lower_bound(const FuncDefinition* first,
		const FuncDefinition* last,
		const FuncDefinition& value)
	{
		while (first < last)
		{
			const FuncDefinition* middle = first + (last - first) / 2;
			if (*middle < value) first = middle + 1;
			else last = middle;
		}
		return last;
	}

	// Returns a pointer to the FuncDefinition instance which 'name' is
	// the same as the one given by 'F'. If no such function name exists,
	// returns 0.
	inline const FuncDefinition* FindFunction(const char* F)
	{
		FuncDefinition func = { F, 0, 0, 0 };
		while (isalnum(F[func.nameLength])) ++func.nameLength;
		if (func.nameLength)
		{
			const FuncDefinition* found =
				fp_lower_bound(Functions, Functions + FUNC_AMOUNT, func);
			if (found == Functions + FUNC_AMOUNT || func < *found)
				return 0;
			return found;
		}
		return 0;
	}
};

//---------------------------------------------------------------------------
// Copy-on-write method
//---------------------------------------------------------------------------
inline void FunctionParser::copyOnWrite()
{
	if (data->referenceCounter > 1)
	{
		Data* oldData = data;
		data = new Data(*oldData);
		--(oldData->referenceCounter);
		data->referenceCounter = 1;
	}
}

//---------------------------------------------------------------------------
// Constructors and destructors
//---------------------------------------------------------------------------
//===========================================================================
FunctionParser::FunctionParser() :
	parseErrorType(FP_NO_ERROR), evalErrorType(0),
	data(new Data)
{
	data->referenceCounter = 1;
}
FunctionParser::~FunctionParser()
{
	if (--(data->referenceCounter) == 0)
	{
		delete data;
	}
}
FunctionParser::FunctionParser(const FunctionParser& cpy) :
	parseErrorType(cpy.parseErrorType),
	evalErrorType(cpy.evalErrorType),
	data(cpy.data)
{
	++(data->referenceCounter);
}
FunctionParser& FunctionParser::operator=(const FunctionParser& cpy)
{
	if (data != cpy.data)
	{
		if (--(data->referenceCounter) == 0) delete data;
		parseErrorType = cpy.parseErrorType;
		evalErrorType = cpy.evalErrorType;
		data = cpy.data;
		++(data->referenceCounter);
	}
	return *this;
}

FunctionParser::Data::Data() :
	useDegreeConversion(false),
	ByteCode(0), ByteCodeSize(0),
	Immed(0), ImmedSize(0),
	Stack(0), StackSize(0)
{}
FunctionParser::Data::~Data()
{
	if (ByteCode) { delete[] ByteCode; ByteCode = 0; }
	if (Immed) { delete[] Immed; Immed = 0; }
	if (Stack) { delete[] Stack; Stack = 0; }
}
// Makes a deep-copy of Data:
FunctionParser::Data::Data(const Data& cpy) :
	varAmount(cpy.varAmount), useDegreeConversion(cpy.useDegreeConversion),
	Variables(cpy.Variables), Constants(cpy.Constants),
	FuncPtrNames(cpy.FuncPtrNames), FuncPtrs(cpy.FuncPtrs),
	FuncParserNames(cpy.FuncParserNames), FuncParsers(cpy.FuncParsers),
	ByteCode(0), ByteCodeSize(cpy.ByteCodeSize),
	Immed(0), ImmedSize(cpy.ImmedSize),
	Stack(0), StackSize(cpy.StackSize)
{
	if (ByteCodeSize) ByteCode = new unsigned[ByteCodeSize];
	if (ImmedSize) Immed = new double[ImmedSize];
	if (StackSize) Stack = new double[StackSize];
	for (unsigned i = 0; i < ByteCodeSize; ++i) ByteCode[i] = cpy.ByteCode[i];
	for (unsigned i = 0; i < ImmedSize; ++i) Immed[i] = cpy.Immed[i];
	// No need to copy the stack contents because it's obsolete outside Eval()
}

//---------------------------------------------------------------------------
// Function parsing
//---------------------------------------------------------------------------
//===========================================================================
namespace
{
	// Error messages returned by ErrorMsg():
	const char* ParseErrorMessage[] =
	{
		"Syntax error",                             // 0
		"Mismatched parenthesis",                   // 1
		"Missing ')'",                              // 2
		"Empty parentheses",                        // 3
		"Syntax error: Operator expected",          // 4
		"Not enough memory",                        // 5
		"An unexpected error ocurred. Please make a full bug report "
		"to warp@iki.fi",                           // 6
		"Syntax error in parameter 'Vars' given to "
		"FunctionParser::Parse()",                  // 7
		"Illegal number of parameters to function", // 8
		"Syntax error: Premature end of string",    // 9
		"Syntax error: Expecting ( after function", // 10
		""
	};

	//����֮һ:�ɱ����б��зֳ����� �����б���ʽ:����1,����2,...
	// Parse variables
	bool ParseVars(const string& Vars, map<string, unsigned>& dest)
	{
		unsigned varNumber = VarBegin;
		unsigned ind1 = 0, ind2;
		while (ind1 < Vars.size())
		{
			if (!isalpha(Vars[ind1]) && Vars[ind1] != '_') return false;
			for (ind2 = ind1 + 1; ind2 < Vars.size() && Vars[ind2] != ','; ++ind2)
				if (!isalnum(Vars[ind2]) && Vars[ind2] != '_') return false;
			const string varName = Vars.substr(ind1, ind2 - ind1);
			if (dest.insert(make_pair(varName, varNumber++)).second == false)
				return false;
			ind1 = ind2 + 1;
		}
		return true;
	}
};
bool FunctionParser::isValidName(const std::string& name) const
{
	if (name.empty() || (!isalpha(name[0]) && name[0] != '_')) return false;
	for (unsigned i = 0; i < name.size(); ++i)
		if (!isalnum(name[i]) && name[i] != '_') return false;
	if (FindFunction(name.c_str())) return false;
	return true;
}

// Constants:
bool FunctionParser::AddConstant(const string& name, double value)
{
	if (isValidName(name))
	{
		const char* n = name.c_str();
		if (FindVariable(n, data->FuncParserNames) !=
			data->FuncParserNames.end() ||
			FindVariable(n, data->FuncPtrNames) !=
			data->FuncPtrNames.end())
			return false;
		copyOnWrite();
		data->Constants[name] = value;
		return true;
	}
	return false;
}
// Function pointers
bool FunctionParser::AddFunction(const std::string& name,
	FunctionPtr func, unsigned paramsAmount)
{
	if (paramsAmount == 0) return false; // Currently must be at least one
	if (isValidName(name))
	{
		const char* n = name.c_str();
		if (FindVariable(n, data->FuncParserNames) !=
			data->FuncParserNames.end() ||
			FindConstant(n) != data->Constants.end())
			return false;
		copyOnWrite();
		data->FuncPtrNames[name] = data->FuncPtrs.size();
		data->FuncPtrs.push_back(Data::FuncPtrData(func, paramsAmount));
		return true;
	}
	return false;
}
bool FunctionParser::checkRecursiveLinking(const FunctionParser* fp) const
{
	if (fp == this) return true;
	for (unsigned i = 0; i < fp->data->FuncParsers.size(); ++i)
		if (checkRecursiveLinking(fp->data->FuncParsers[i])) return true;
	return false;
}
bool FunctionParser::AddFunction(const std::string& name,
	FunctionParser& parser)
{
	if (parser.data->varAmount == 0) // Currently must be at least one
		return false;
	if (isValidName(name))
	{
		const char* n = name.c_str();
		if (FindVariable(n, data->FuncPtrNames) != data->FuncPtrNames.end() ||
			FindConstant(n) != data->Constants.end())
			return false;
		if (checkRecursiveLinking(&parser)) return false;
		copyOnWrite();
		data->FuncParserNames[name] = data->FuncParsers.size();
		data->FuncParsers.push_back(&parser);
		return true;
	}
	return false;
}

// Main parsing function
// ---------------------
int FunctionParser::Parse(const std::string& Function,
	const std::string& Vars,
	bool useDegrees)
{
	copyOnWrite();
	data->Variables.clear();
	if (!ParseVars(Vars, data->Variables))
	{
		parseErrorType = INVALID_VARS;
		return Function.size();
	}
	data->varAmount = data->Variables.size(); // this is for Eval()
	const char* Func = Function.c_str();
	parseErrorType = FP_NO_ERROR;
	int Result = CheckSyntax(Func);
	if (Result >= 0) return Result;
	data->useDegreeConversion = useDegrees;
	if (!Compile(Func)) return Function.size();
	data->Variables.clear();
	parseErrorType = FP_NO_ERROR;
	return -1;
}
namespace
{
	// Is given char an operator?
	inline bool IsOperator(int c)
	{
		return strchr("+-*/%^=<>&|", c) != NULL;
	}
	// skip whitespace
	inline void sws(const char* F, int& Ind)
	{
		while (F[Ind] && isspace(F[Ind])) ++Ind;
	}
};
// Returns an iterator to the variable with the same name as 'F', or to
// Variables.end() if no such variable exists:
inline FunctionParser::Data::VarMap_t::const_iterator
FunctionParser::FindVariable(const char* F, const Data::VarMap_t& vars) const
{
	if (vars.size())
	{
		unsigned ind = 0;
		while (isalnum(F[ind]) || F[ind] == '_') ++ind;
		if (ind)
		{
			string name(F, ind);
			return vars.find(name);
		}
	}
	return vars.end();
}
inline FunctionParser::Data::ConstMap_t::const_iterator
FunctionParser::FindConstant(const char* F) const
{
	if (data->Constants.size())
	{
		unsigned ind = 0;
		while (isalnum(F[ind]) || F[ind] == '_') ++ind;
		if (ind)
		{
			string name(F, ind);
			return data->Constants.find(name);
		}
	}
	return data->Constants.end();
}
//---------------------------------------------------------------------------
// Check function string syntax
// ----------------------------
int FunctionParser::CheckSyntax(const char* Function)
{
	const Data::VarMap_t& Variables = data->Variables;
	const Data::ConstMap_t& Constants = data->Constants;
	const Data::VarMap_t& FuncPtrNames = data->FuncPtrNames;
	const Data::VarMap_t& FuncParserNames = data->FuncParserNames;
	vector<int> functionParenthDepth;
	int Ind = 0, ParenthCnt = 0, c;
	char* Ptr;
	while (true)
	{
		sws(Function, Ind);
		c = Function[Ind];
		// Check for valid operand (must appear)
				// Check for leading -
		if (c == '-') { sws(Function, ++Ind); c = Function[Ind]; }
		if (c == 0) { parseErrorType = PREMATURE_EOS; return Ind; }
		// Check for math function
		bool foundFunc = false;
		const FuncDefinition* fptr = FindFunction(&Function[Ind]);
		if (fptr)
		{
			Ind += fptr->nameLength;
			foundFunc = true;
		}
		else
		{
			// Check for user-defined function
			Data::VarMap_t::const_iterator fIter =
				FindVariable(&Function[Ind], FuncPtrNames);
			if (fIter != FuncPtrNames.end())
			{
				Ind += fIter->first.size();
				foundFunc = true;
			}
			else
			{
				Data::VarMap_t::const_iterator pIter =
					FindVariable(&Function[Ind], FuncParserNames);
				if (pIter != FuncParserNames.end())
				{
					Ind += pIter->first.size();
					foundFunc = true;
				}
			}
		}
		if (foundFunc)
		{
			sws(Function, Ind);
			c = Function[Ind];
			if (c != '(') { parseErrorType = EXPECT_PARENTH_FUNC; return Ind; }
			functionParenthDepth.push_back(ParenthCnt + 1);
		}
		// Check for opening parenthesis
		if (c == '(')
		{
			++ParenthCnt;
			sws(Function, ++Ind);
			if (Function[Ind] == ')') { parseErrorType = EMPTY_PARENTH; return Ind; }
			continue;
		}
		// Check for number
		if (isdigit(c) || (c == '.' && isdigit(Function[Ind + 1])))
		{
			strtod(&Function[Ind], &Ptr);
			Ind += int(Ptr - &Function[Ind]);
			sws(Function, Ind);
			c = Function[Ind];
		}
		else
		{ // Check for variable
			Data::VarMap_t::const_iterator vIter =
				FindVariable(&Function[Ind], Variables);
			if (vIter != Variables.end())
				Ind += vIter->first.size();
			else
			{
				// Check for constant
				Data::ConstMap_t::const_iterator cIter =
					FindConstant(&Function[Ind]);
				if (cIter != Constants.end())
					Ind += cIter->first.size();
				else
				{
					parseErrorType = SYNTAX_ERROR; return Ind;
				}
			}
			sws(Function, Ind);
			c = Function[Ind];
		}
		// Check for closing parenthesis
		while (c == ')')
		{
			if (functionParenthDepth.size() &&
				functionParenthDepth.back() == ParenthCnt)
				functionParenthDepth.pop_back();
			if ((--ParenthCnt) < 0) { parseErrorType = MISM_PARENTH; return Ind; }
			sws(Function, ++Ind);
			c = Function[Ind];
		}
		// If we get here, we have a legal operand and now a legal operator or
		// end of string must follow
				// Check for EOS
		if (c == 0) break; // The only way to end the checking loop without error
		// Check for operator
		if (!IsOperator(c) &&
			(c != ',' || functionParenthDepth.empty() ||
				functionParenthDepth.back() != ParenthCnt))
		{
			parseErrorType = EXPECT_OPERATOR; return Ind;
		}
		// If we get here, we have an operand and an operator; the next loop will
		// check for another operand (must appear)
		++Ind;
	} // while
	// Check that all opened parentheses are also closed
	if (ParenthCnt > 0) { parseErrorType = MISSING_PARENTH; return Ind; }
	// The string is ok
	parseErrorType = FP_NO_ERROR;
	return -1;
}

// Compile function string to bytecode
// -----------------------------------
bool FunctionParser::Compile(const char* Function)
{
	if (data->ByteCode) { delete[] data->ByteCode; data->ByteCode = 0; }
	if (data->Immed) { delete[] data->Immed; data->Immed = 0; }
	if (data->Stack) { delete[] data->Stack; data->Stack = 0; }
	vector<unsigned> byteCode; byteCode.reserve(1024);
	tempByteCode = &byteCode;
	vector<double> immed; immed.reserve(1024);
	tempImmed = &immed;
	data->StackSize = StackPtr = 0;
	CompileExpression(Function, 0);
	if (parseErrorType != FP_NO_ERROR) return false;
	data->ByteCodeSize = byteCode.size();
	data->ImmedSize = immed.size();
	if (data->ByteCodeSize)
	{
		data->ByteCode = new unsigned[data->ByteCodeSize];
		memcpy(data->ByteCode, &byteCode[0],
			sizeof(unsigned)*data->ByteCodeSize);
	}
	if (data->ImmedSize)
	{
		data->Immed = new double[data->ImmedSize];
		memcpy(data->Immed, &immed[0],
			sizeof(double)*data->ImmedSize);
	}
	if (data->StackSize)
		data->Stack = new double[data->StackSize];
	return true;
}

inline void FunctionParser::AddCompiledByte(unsigned c)
{
	tempByteCode->push_back(c);
}
inline void FunctionParser::AddImmediate(double i)
{
	tempImmed->push_back(i);
}
inline void FunctionParser::AddFunctionOpcode(unsigned opcode)
{
	if (data->useDegreeConversion)
		switch (opcode)
		{
		case cCos:
		case cCosh:
		case cCot:
		case cCsc:
		case cSec:
		case cSin:
		case cSinh:
		case cTan:
		case cTanh:
			AddCompiledByte(cRad);
		}
	AddCompiledByte(opcode);
	if (data->useDegreeConversion)
		switch (opcode)
		{
		case cAcos:
#ifndef NO_ASINH
		case cAcosh:
		case cAsinh:
		case cAtanh:
#endif
		case cAsin:
		case cAtan:
		case cAtan2:
			AddCompiledByte(cDeg);
		}
}
inline void FunctionParser::incStackPtr()
{
	if (++StackPtr > data->StackSize) ++(data->StackSize);
}

// Compile if()
int FunctionParser::CompileIf(const char* F, int ind)
{
	int ind2 = CompileExpression(F, ind, true); // condition
	sws(F, ind2);
	if (F[ind2] != ',') { parseErrorType = ILL_PARAMS_AMOUNT; return ind2; }
	AddCompiledByte(cIf);
	unsigned curByteCodeSize = tempByteCode->size();
	AddCompiledByte(0); // Jump index; to be set later
	AddCompiledByte(0); // Immed jump index; to be set later
	--StackPtr;
	ind2 = CompileExpression(F, ind2 + 1, true); // then
	sws(F, ind2);
	if (F[ind2] != ',') { parseErrorType = ILL_PARAMS_AMOUNT; return ind2; }
	AddCompiledByte(cJump);
	unsigned curByteCodeSize2 = tempByteCode->size();
	unsigned curImmedSize2 = tempImmed->size();
	AddCompiledByte(0); // Jump index; to be set later
	AddCompiledByte(0); // Immed jump index; to be set later
	--StackPtr;
	ind2 = CompileExpression(F, ind2 + 1, true); // else
	sws(F, ind2);
	if (F[ind2] != ')') { parseErrorType = ILL_PARAMS_AMOUNT; return ind2; }
	// Set jump indices
	(*tempByteCode)[curByteCodeSize] = curByteCodeSize2 + 1;
	(*tempByteCode)[curByteCodeSize + 1] = curImmedSize2;
	(*tempByteCode)[curByteCodeSize2] = tempByteCode->size() - 1;
	(*tempByteCode)[curByteCodeSize2 + 1] = tempImmed->size();
	return ind2 + 1;
}
int FunctionParser::CompileFunctionParams(const char* F, int ind,
	unsigned requiredParams)
{
	unsigned curStackPtr = StackPtr;
	int ind2 = CompileExpression(F, ind);
	if (StackPtr != curStackPtr + requiredParams)
	{
		parseErrorType = ILL_PARAMS_AMOUNT; return ind;
	}
	StackPtr -= requiredParams - 1;
	sws(F, ind2);
	return ind2 + 1; // F[ind2] is ')'
}
// Compiles element
int FunctionParser::CompileElement(const char* F, int ind)
{
	sws(F, ind);
	char c = F[ind];
	if (c == '(')
	{
		ind = CompileExpression(F, ind + 1);
		sws(F, ind);
		return ind + 1; // F[ind] is ')'
	}
	if (isdigit(c) || c == '.' /*|| c=='-'*/) // Number
	{
		const char* startPtr = &F[ind];
		char* endPtr;
		double val = strtod(startPtr, &endPtr);
		AddImmediate(val);
		AddCompiledByte(cImmed);
		incStackPtr();
		return ind + (endPtr - startPtr);
	}
	if (isalpha(c) || c == '_') // Function, variable or constant
	{
		const FuncDefinition* func = FindFunction(F + ind);
		if (func) // is function
		{
			int ind2 = ind + func->nameLength;
			sws(F, ind2); // F[ind2] is '('
			if (strcmp(func->name, "if") == 0) // "if" is a special case
			{
				return CompileIf(F, ind2 + 1);
			}
#ifndef DISABLE_EVAL
			unsigned requiredParams =
				strcmp(func->name, "eval") == 0 ?
				data->Variables.size() : func->params;
#else
			unsigned requiredParams = func->params;
#endif
			ind2 = CompileFunctionParams(F, ind2 + 1, requiredParams);
			AddFunctionOpcode(func->opcode);
			return ind2; // F[ind2-1] is ')'
		}
		Data::VarMap_t::const_iterator vIter =
			FindVariable(F + ind, data->Variables);
		if (vIter != data->Variables.end()) // is variable
		{
			AddCompiledByte(vIter->second);
			incStackPtr();
			return ind + vIter->first.size(); //�鵽����֮�� ���ַ��������ƶ�������֮��
		}
		Data::ConstMap_t::const_iterator cIter = FindConstant(F + ind);
		if (cIter != data->Constants.end()) // is constant
		{
			AddImmediate(cIter->second);
			AddCompiledByte(cImmed);
			incStackPtr();
			return ind + cIter->first.size();
		}
		Data::VarMap_t::const_iterator fIter =
			FindVariable(F + ind, data->FuncPtrNames);
		if (fIter != data->FuncPtrNames.end()) // is user-defined func pointer
		{
			unsigned index = fIter->second;
			int ind2 = ind + fIter->first.length();
			sws(F, ind2); // F[ind2] is '('
			ind2 = CompileFunctionParams(F, ind2 + 1,
				data->FuncPtrs[index].params);
			AddCompiledByte(cFCall);
			AddCompiledByte(index);
			return ind2;
		}
		Data::VarMap_t::const_iterator pIter =
			FindVariable(F + ind, data->FuncParserNames);
		if (pIter != data->FuncParserNames.end()) // is user-defined func parser
		{
			unsigned index = pIter->second;
			int ind2 = ind + pIter->first.length();
			sws(F, ind2); // F[ind2] is '('
			ind2 = CompileFunctionParams
			(F, ind2 + 1, data->FuncParsers[index]->data->varAmount);
			AddCompiledByte(cPCall);
			AddCompiledByte(index);
			return ind2;
		}
	}
	parseErrorType = UNEXPECTED_ERROR;
	return ind;
}
// Compiles '^'
int FunctionParser::CompilePow(const char* F, int ind)
{
	int ind2 = CompileElement(F, ind);
	sws(F, ind2);
	while (F[ind2] == '^')
	{
		ind2 = CompileUnaryMinus(F, ind2 + 1);
		sws(F, ind2);
		AddCompiledByte(cPow);
		--StackPtr;
	}
	return ind2;
}
// Compiles unary '-'
int FunctionParser::CompileUnaryMinus(const char* F, int ind)
{
	sws(F, ind);
	if (F[ind] == '-')
	{
		int ind2 = ind + 1;
		sws(F, ind2);
		ind2 = CompilePow(F, ind2);
		sws(F, ind2);
		// if we are negating a constant, negate the constant itself:
		if (tempByteCode->back() == cImmed)
			tempImmed->back() = -tempImmed->back();
		// if we are negating a negation, we can remove both:
		else if (tempByteCode->back() == cNeg)
			tempByteCode->pop_back();
		else
			AddCompiledByte(cNeg);
		return ind2;
	}
	int ind2 = CompilePow(F, ind);
	sws(F, ind2);
	return ind2;
}
// Compiles '*', '/' and '%'
int FunctionParser::CompileMult(const char* F, int ind)
{
	int ind2 = CompileUnaryMinus(F, ind);
	sws(F, ind2);
	char op;
	while ((op = F[ind2]) == '*' || op == '/' || op == '%')
	{
		ind2 = CompileUnaryMinus(F, ind2 + 1);
		sws(F, ind2);
		switch (op)
		{
		case '*': AddCompiledByte(cMul); break;
		case '/': AddCompiledByte(cDiv); break;
		case '%': AddCompiledByte(cMod); break;
		}
		--StackPtr;
	}
	return ind2;
}
// Compiles '+' and '-'
int FunctionParser::CompileAddition(const char* F, int ind)
{
	int ind2 = CompileMult(F, ind);
	sws(F, ind2);
	char op;
	while ((op = F[ind2]) == '+' || op == '-')
	{
		ind2 = CompileMult(F, ind2 + 1);
		sws(F, ind2);
		AddCompiledByte(op == '+' ? cAdd : cSub);
		--StackPtr;
	}
	return ind2;
}
// Compiles '=', '<' and '>'
int FunctionParser::CompileComparison(const char* F, int ind)
{
	int ind2 = CompileAddition(F, ind);
	sws(F, ind2);
	char op;
	while ((op = F[ind2]) == '=' || op == '<' || op == '>')
	{
		ind2 = CompileAddition(F, ind2 + 1);
		sws(F, ind2);
		switch (op)
		{
		case '=': AddCompiledByte(cEqual); break;
		case '<': AddCompiledByte(cLess); break;
		case '>': AddCompiledByte(cGreater); break;
		}
		--StackPtr;
	}
	return ind2;
}
// Compiles '&'
int FunctionParser::CompileAnd(const char* F, int ind)
{
	int ind2 = CompileComparison(F, ind);
	sws(F, ind2);
	while (F[ind2] == '&')
	{
		ind2 = CompileComparison(F, ind2 + 1);
		sws(F, ind2);
		AddCompiledByte(cAnd);
		--StackPtr;
	}
	return ind2;
}
// Compiles '|'
int FunctionParser::CompileOr(const char* F, int ind)
{
	int ind2 = CompileAnd(F, ind);
	sws(F, ind2);
	while (F[ind2] == '|')
	{
		ind2 = CompileAnd(F, ind2 + 1);
		sws(F, ind2);
		AddCompiledByte(cOr);
		--StackPtr;
	}
	return ind2;
}
// Compiles ','
int FunctionParser::CompileExpression(const char* F, int ind, bool stopAtComma)
{
	int ind2 = CompileOr(F, ind);
	sws(F, ind2);
	if (stopAtComma) return ind2;
	while (F[ind2] == ',')
	{
		ind2 = CompileOr(F, ind2 + 1);
		sws(F, ind2);
	}
	return ind2;
}

// Return parse error message
// --------------------------
const char* FunctionParser::ErrorMsg() const
{
	if (parseErrorType != FP_NO_ERROR) return ParseErrorMessage[parseErrorType];
	return 0;
}
//---------------------------------------------------------------------------
// Function evaluation
//---------------------------------------------------------------------------
//===========================================================================
namespace
{
	inline int doubleToInt(double d)
	{
		return d < 0 ? -int((-d) + .5) : int(d + .5);
	}
	inline double Min(double d1, double d2)
	{
		return d1 < d2 ? d1 : d2;
	}
	inline double Max(double d1, double d2)
	{
		return d1 > d2 ? d1 : d2;
	}

	inline double DegreesToRadians(double degrees)
	{
		return degrees * (M_PI / 180.0);
	}
	inline double RadiansToDegrees(double radians)
	{
		return radians * (180.0 / M_PI);
	}
}
double FunctionParser::Eval(const double* Vars)
{
	const unsigned* const ByteCode = data->ByteCode;
	const double* const Immed = data->Immed;
	double* const Stack = data->Stack;
	const unsigned ByteCodeSize = data->ByteCodeSize;
	unsigned IP, DP = 0;
	int SP = -1;
	for (IP = 0; IP < ByteCodeSize; ++IP)
	{
		switch (ByteCode[IP])
		{
			// Functions:
		case   cAbs: Stack[SP] = fabs(Stack[SP]); break;
		case  cAcos: if (Stack[SP] < -1 || Stack[SP] > 1)
		{
			evalErrorType = 4; return 0;
		}
					 Stack[SP] = acos(Stack[SP]); break;
#ifndef NO_ASINH
		case cAcosh: Stack[SP] = acosh(Stack[SP]); break;
#endif
		case  cAsin: if (Stack[SP] < -1 || Stack[SP] > 1)
		{
			evalErrorType = 4; return 0;
		}
					 Stack[SP] = asin(Stack[SP]); break;
#ifndef NO_ASINH
		case cAsinh: Stack[SP] = asinh(Stack[SP]); break;
#endif
		case  cAtan: Stack[SP] = atan(Stack[SP]); break;
		case cAtan2: Stack[SP - 1] = atan2(Stack[SP - 1], Stack[SP]);
			--SP; break;
#ifndef NO_ASINH
		case cAtanh: Stack[SP] = atanh(Stack[SP]); break;
#endif
		case  cCeil: Stack[SP] = ceil(Stack[SP]); break;
		case   cCos: Stack[SP] = cos(Stack[SP]); break;
		case  cCosh: Stack[SP] = cosh(Stack[SP]); break;
		case   cCot:
		{
			double t = tan(Stack[SP]);
			if (t == 0) { evalErrorType = 1; return 0; }
			Stack[SP] = 1 / t; break;
		}
		case   cCsc:
		{
			double s = sin(Stack[SP]);
			if (s == 0) { evalErrorType = 1; return 0; }
			Stack[SP] = 1 / s; break;
		}

#ifndef DISABLE_EVAL
		case  cEval:
		{
			data->Stack = new double[data->StackSize];
			double retVal = Eval(&Stack[SP - data->varAmount + 1]);
			delete[] data->Stack;
			data->Stack = Stack;
			SP -= data->varAmount - 1;
			Stack[SP] = retVal;
			break;
		}
#endif
		case   cExp: Stack[SP] = exp(Stack[SP]); break;
		case cFloor: Stack[SP] = floor(Stack[SP]); break;
		case    cIf:
		{
			unsigned jumpAddr = ByteCode[++IP];
			unsigned immedAddr = ByteCode[++IP];
			if (doubleToInt(Stack[SP]) == 0)
			{
				IP = jumpAddr;
				DP = immedAddr;
			}
			--SP; break;
		}
		case   cInt: Stack[SP] = floor(Stack[SP] + .5); break;
		case   cLog: if (Stack[SP] <= 0) { evalErrorType = 3; return 0; }
					 Stack[SP] = log(Stack[SP]); break;
		case cLog10: if (Stack[SP] <= 0) { evalErrorType = 3; return 0; }
					 Stack[SP] = log10(Stack[SP]); break;
		case   cMax: Stack[SP - 1] = Max(Stack[SP - 1], Stack[SP]);
			--SP; break;
		case   cMin: Stack[SP - 1] = Min(Stack[SP - 1], Stack[SP]);
			--SP; break;
		case   cSec:
		{
			double c = cos(Stack[SP]);
			if (c == 0) { evalErrorType = 1; return 0; }
			Stack[SP] = 1 / c; break;
		}
		case   cSin: Stack[SP] = sin(Stack[SP]); break;
		case  cSinh: Stack[SP] = sinh(Stack[SP]); break;
		case  cSqrt: if (Stack[SP] < 0) { evalErrorType = 2; return 0; }
					 Stack[SP] = sqrt(Stack[SP]); break;
		case   cTan: Stack[SP] = tan(Stack[SP]); break;
		case  cTanh: Stack[SP] = tanh(Stack[SP]); break;

			// Misc:
		case cImmed: Stack[++SP] = Immed[DP++]; break;
		case  cJump: DP = ByteCode[IP + 2];
			IP = ByteCode[IP + 1];
			break;
			// Operators:
		case   cNeg: Stack[SP] = -Stack[SP]; break;
		case   cAdd: Stack[SP - 1] += Stack[SP]; --SP; break;
		case   cSub: Stack[SP - 1] -= Stack[SP]; --SP; break;
		case   cMul: Stack[SP - 1] *= Stack[SP]; --SP; break;
		case   cDiv: if (Stack[SP] == 0) { evalErrorType = 1; return 0; }
					 Stack[SP - 1] /= Stack[SP]; --SP; break;
		case   cMod: if (Stack[SP] == 0) { evalErrorType = 1; return 0; }
					 Stack[SP - 1] = fmod(Stack[SP - 1], Stack[SP]);
					 --SP; break;
		case   cPow: Stack[SP - 1] = pow(Stack[SP - 1], Stack[SP]);
			--SP; break;
		case cEqual: Stack[SP - 1] = (Stack[SP - 1] == Stack[SP]);
			--SP; break;
		case  cLess: Stack[SP - 1] = (Stack[SP - 1] < Stack[SP]);
			--SP; break;
		case cGreater: Stack[SP - 1] = (Stack[SP - 1] > Stack[SP]);
			--SP; break;
		case   cAnd: Stack[SP - 1] =
			(doubleToInt(Stack[SP - 1]) &&
				doubleToInt(Stack[SP]));
			--SP; break;
		case    cOr: Stack[SP - 1] =
			(doubleToInt(Stack[SP - 1]) ||
				doubleToInt(Stack[SP]));
			--SP; break;
			// Degrees-radians conversion:
		case   cDeg: Stack[SP] = RadiansToDegrees(Stack[SP]); break;
		case   cRad: Stack[SP] = DegreesToRadians(Stack[SP]); break;
			// User-defined function calls:
		case cFCall:
		{
			unsigned index = ByteCode[++IP];
			unsigned params = data->FuncPtrs[index].params;
			double retVal =
				data->FuncPtrs[index].ptr(&Stack[SP - params + 1]);
			SP -= params - 1;
			Stack[SP] = retVal;
			break;
		}
		case cPCall:
		{
			unsigned index = ByteCode[++IP];
			unsigned params = data->FuncParsers[index]->data->varAmount;
			double retVal =
				data->FuncParsers[index]->Eval(&Stack[SP - params + 1]);
			SP -= params - 1;
			Stack[SP] = retVal;
			break;
		}

#ifdef SUPPORT_OPTIMIZER
		case   cVar: break; // Paranoia. These should never exist
		case   cDup: Stack[SP + 1] = Stack[SP]; ++SP; break;
		case   cInv:
			if (Stack[SP] == 0.0) { evalErrorType = 1; return 0; }
			Stack[SP] = 1.0 / Stack[SP];
			break;
#endif
			// Variables:
		default:
			Stack[++SP] = Vars[ByteCode[IP] - VarBegin];
		}
	}
	evalErrorType = 0;
	return Stack[SP];
}

#ifdef FUNCTIONPARSER_SUPPORT_DEBUG_OUTPUT
namespace
{
	inline void printHex(std::ostream& dest, unsigned n)
	{
		dest.width(8); dest.fill('0'); hex(dest); //uppercase(dest);
		dest << n;
	}
}
void FunctionParser::PrintByteCode(std::ostream& dest) const
{
	const unsigned* const ByteCode = data->ByteCode;
	const double* const Immed = data->Immed;
	for (unsigned IP = 0, DP = 0; IP < data->ByteCodeSize; ++IP)
	{
		printHex(dest, IP);
		dest << ": ";
		unsigned opcode = ByteCode[IP];
		switch (opcode)
		{
		case cIf:
			dest << "jz/t";
			printHex(dest, ByteCode[IP + 1] + 1);
			dest << endl;
			IP += 2;
			break;
		case cJump:
			dest << "jump/t";
			printHex(dest, ByteCode[IP + 1] + 1);
			dest << endl;
			IP += 2;
			break;
		case cImmed:
			dest.precision(10);
			dest << "push/t" << Immed[DP++] << endl;
			break;
		case cFCall:
		{
			unsigned index = ByteCode[++IP];
			Data::VarMap_t::const_iterator iter =
				data->FuncPtrNames.begin();
			while (iter->second != index) ++iter;
			dest << "call/t" << iter->first << endl;
			break;
		}
		case cPCall:
		{
			unsigned index = ByteCode[++IP];
			Data::VarMap_t::const_iterator iter =
				data->FuncParserNames.begin();
			while (iter->second != index) ++iter;
			dest << "call/t" << iter->first << endl;
			break;
		}
		default:
			if (opcode < VarBegin)
			{
				string n;
				switch (opcode)
				{
				case cNeg: n = "neg"; break;
				case cAdd: n = "add"; break;
				case cSub: n = "sub"; break;
				case cMul: n = "mul"; break;
				case cDiv: n = "div"; break;
				case cMod: n = "mod"; break;
				case cPow: n = "pow"; break;
				case cEqual: n = "eq"; break;
				case cLess: n = "lt"; break;
				case cGreater: n = "gt"; break;
				case cAnd: n = "and"; break;
				case cOr: n = "or"; break;
				case cDeg: n = "deg"; break;
				case cRad: n = "rad"; break;
#ifndef DISABLE_EVAL
				case cEval: n = "call/t0"; break;
#endif
#ifdef SUPPORT_OPTIMIZER
				case cVar: n = "(var)"; break;
				case cDup: n = "dup"; break;
				case cInv: n = "inv"; break;
#endif
				default: n = Functions[opcode - cAbs].name;
				}
				dest << n << endl;
			}
			else
			{
				dest << "push/tVar" << opcode - VarBegin << endl;
			}
		}
	}
}
#endif

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值