// 嵌入式表达式代码
// 作者: Janhail Luo
// 最后整理: 2003-03-03
//////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <math.h>
#include <stdarg.h>
#include "Expression.h"
class CSafeArray
{
public:
CSafeArray(int num){point = new double[num];}
~CSafeArray(){delete[] point;}
double* GetPoint(){return point;}
private:
double *point;
};
#define EG 1 // GREATE
#define EL 2 // LESS
#define EE 3 // EQUALS
#define EU 0 // UNKNOW
// 操作符列表
// '#' 表示单目 '+', '$' 表示单目 '-'
char CExpression::_Operate[EXPR_MAX_OPERATE]={
'+','-','*','/', '#', '$', '>', '<', '=', '!', '&', '|', '\0'};
// 操作符优先级别的定义
// EG >, El <, EE =, EU Unknow
int CExpression::_Precede[EXPR_MAX_OPERATE][EXPR_MAX_OPERATE]={
EG,EG,EL,EL,EL,EL,EG,EG,EG,EL,EG,EG,EG,
EG,EG,EL,EL,EL,EL,EG,EG,EG,EL,EG,EG,EG,
EG,EG,EG,EG,EL,EL,EG,EG,EG,EL,EG,EG,EG,
EG,EG,EG,EG,EL,EL,EG,EG,EG,EL,EG,EG,EG,
EG,EG,EG,EG,EG,EG,EG,EG,EG,EL,EG,EG,EG,
EG,EG,EG,EG,EG,EG,EG,EG,EG,EL,EG,EG,EG,
EL,EL,EL,EL,EL,EL,EG,EG,EG,EL,EG,EG,EG,
EL,EL,EL,EL,EL,EL,EG,EG,EG,EL,EG,EG,EG,
EL,EL,EL,EL,EL,EL,EL,EL,EG,EL,EG,EG,EG,
EG,EG,EG,EG,EG,EG,EG,EG,EG,EG,EG,EG,EG,
EL,EL,EL,EL,EL,EL,EL,EL,EL,EL,EG,EG,EG,
EL,EL,EL,EL,EL,EL,EL,EL,EL,EL,EG,EG,EG,
EL,EL,EL,EL,EL,EL,EL,EL,EL,EL,EL,EL,EE};
// 类构造函数
CExpression::CExpression()
{
}
// 类析构函数
CExpression::~CExpression()
{
// 清除数据
this->_Clear();
}
// 清除所有数据
void CExpression::_Clear()
{
while(!_NumStack.empty()) _NumStack.pop();
while(!_OprStack.empty()) _OprStack.pop();
while(!_ParmStack.empty()) _ParmStack.pop();
while(!_CallStack.empty()) _CallStack.pop();
while(!_CallParmCntStack.empty()) _CallParmCntStack.pop();
while(!_SceneStack.empty()) _SceneStack.pop();
while(!_NumTotalStack.empty()) _NumTotalStack.pop();
while(!_OprTotalStack.empty()) _OprTotalStack.pop();
}
// 计算表达式
// const char *szExpStr: 表达式的字符串
// double *var : 用于保存表达式的计算结果的值
// 返回:
// true 表示表达式计算成功,值保存到*var中
// false 表示表达式计算失败,用GetError可以取得失败的原因
bool CExpression::Computer(const char *szExpStr, double *var)
{
// 开始计算
_bError = false;
// 计算逗号表达式,可以认为一个表达式是由逗号表达式组成
if (this->_DoComma((char*)szExpStr))
{
// 从参数栈中取出栈顶的数值为表达式的计算结果
*var = _ParmStack.top();
this->_Clear();
return true;
}else
{
this->_Clear();
return false;
}
}
// 设置错误信息
void CExpression::SetError(const char* errMsg, ...)
{
_bError = true;
va_list list;
va_start( list , errMsg );
vsprintf(_szErrorLog , errMsg , list);
va_end( list );
}
// 取得错误信息
const char* CExpression::GetError(void)
{
if (_bError==false)
{
this->SetError("No error");
}
return _szErrorLog;
}
// 检查符号 o 是否是操作符
// 如果是操作符就返回操作符的编号
// 否则返回 0
int CExpression::inOperate(char o)
{
int i;
if ( o==')' || o==',')
return EXPR_MAX_OPERATE;
for (i=0; i<EXPR_MAX_OPERATE; i++)
{
if (o==_Operate[i])
{
break;
}
}
if (i==EXPR_MAX_OPERATE)
{
i = 0;
}else
{
i++;
}
return i;
}
// 取得符号o1对符号o2的优先级别
int CExpression::Precede(char o1, char o2)
{
int i, j;
i = this->inOperate(o1);
j = this->inOperate(o2);
if (i==0 || j==0)
{
return 0;
}
return _Precede[i-1][j-1];
}
// 检查操作符 opr 是否是单目操作符
// 是返回 true
// 不是返回 false
bool CExpression::_IsSingle(char opr)
{
if (opr=='#' || opr=='$' || opr=='!')
return true;
return false;
}
// 计算一个操作
double CExpression::Operate(double n1, double n2, char o)
{
double ret = 0;
switch(o)
{
case '+': ret = n1+n2;break;
case '-': ret = n1-n2;break;
case '*': ret = n1*n2;break;
case '/': ret = n1/n2;break;
case '#': ret = +n1;break;
case '$': ret = -n1;break;
case '>': ret = (n1>n2)?1:0;break;
case '<': ret = (n1<n2)?1:0;break;
case '=': ret = ((int)n1==(int)n2)?1:0;break;
case '!': ret = ((int)n1)?0:1;break;
case '&': ret = ((int)n1 && (int)n2);break;
case '|': ret = ((int)n1 || (int)n2);break;
default: ret = 0.0f;break;
}
return ret;
}
// 检查一个字符是否是字母、数字、下划线或点
// 如果是返回 true
// 否则返回 false
bool CExpression::inRange(char c)
{
if ((c>='a'&&c<='z')||(c>='A'&&c<='Z')||(c>='0'&&c<='9')||(c=='_')||(c=='.'))
{
return true;
}else
{
return false;
}
}
// 保存现场到堆栈中
void CExpression::SaveScene()
{
// 保存操作数堆栈
_SceneStack.push(_NumStack.size()); // 操作数个数
// 把当前操作数堆栈内容转移到存盘堆栈中
while (!_NumStack.empty())
{
_NumTotalStack.push(_NumStack.top());
_NumStack.pop();
}
// 保存操作符堆栈
_SceneStack.push(_OprStack.size()); // 操作符个数
// 把当前操作符堆栈内容转移到存盘堆栈中
while (!_OprStack.empty())
{
_OprTotalStack.push(_OprStack.top());
_OprStack.pop();
}
// 保存当前的函数名
_CallStack.push(_Symbol);
}
// 从堆栈中载入现场
void CExpression::LoadScene()
{
int i;
// 把当前堆栈的内容清空
while(!_NumStack.empty()) _NumStack.pop();
while(!_OprStack.empty()) _OprStack.pop();
// 取出操作符堆栈
i = _SceneStack.top(); // 操作符个数
while (i)
{
// 把操作符转移到当前计算堆栈
_OprStack.push(_OprTotalStack.top());
_OprTotalStack.pop();
i--;
}
_SceneStack.pop();
// 取出操作数堆栈
i = _SceneStack.top(); // 操作数个数
while (i)
{
// 把操作数转移到当前计算堆栈
_NumStack.push(_NumTotalStack.top());
_NumTotalStack.pop();
i--;
}
_SceneStack.pop();
// 取出函数名
strcpy(_Symbol, _CallStack.top().c_str());
_CallStack.pop();
}
// 求函数的值
// 当遇到一个表达式的函数时调用这个函数
// szCallName 是表达式函数的名字
// szExpr 是这个表达式函数后面的字符串,是表达式的参数
// 如果出现错误,返回0
// 否则返回剩余表达式的指针
char* CExpression::_DoCall(char *szCallName, char *szExpr)
{
char* str=szExpr;
int i;
double var;
// 保存现场
this->SaveScene();
// 计算逗号表达式
str=this->_DoComma(szExpr);
// 如果出现错误,则返回0
if (str==0)
return 0;
// 载入现场
this->LoadScene();
if (_Symbol[0]=='\0') // 逗号表达式
{
// 如果参数堆栈有数据
if (_CallParmCntStack.top())
{
// 栈顶数值为返回值
var = _ParmStack.top();
// 清除堆栈里面剩余的数据
for (i=_CallParmCntStack.top(); i>0; i--)
{
_ParmStack.pop();
}
}else
{
// 空表达式错误
this->SetError("expression is NULL");
return 0;
}
}else // 函数调用
{
// 参数个数
int iParmCnt = _CallParmCntStack.top();
// 定义一个用于保存参数的数组
CSafeArray array(iParmCnt);
double *parm = array.GetPoint();
// 取得所有参数的数值并保存到数组中
// 同时把参数堆栈的数据清除
for (i=iParmCnt-1; i>=0; i--)
{
parm[i] = _ParmStack.top();
_ParmStack.pop();
}
// 调用虚函�