本文是逆波兰表达式的算法极其实现,可直接应用于项目中,要引用请注明来源,在使用时若遇到错误请及时指正。
逆波兰表达式在一些项目中的应用是很频繁的,例如财务管理软件中对财务进行取数等。
表达式一般由操作数(Operand)、运算符(Operator)组成,例如算术表达式中,通常把运算符放在两个操作数的中间,
这称为中缀表达式(Infix Expression),如A+B。
波兰数学家Jan Lukasiewicz提出了另一种数学表示法,它有两种表示形式:
把运算符写在操作数之前,称为波兰表达式(Polish Expression)或前缀表达式(Prefix Expression),如+AB;
把运算符写在操作数之后,称为逆波兰表达式(Reverse Polish Expression)或后缀表达式(Suffix Expression),如AB+;
其中,逆波兰表达式在编译技术中有着普遍的应用。
算法:
一、 将中缀表达式转换成后缀表达式算法:
1、从左至右扫描一中缀表达式。
2、若读取的是操作数,则判断该操作数的类型,并将该操作数存入操作数堆栈
3、若读取的是运算符
(1) 该运算符为左括号"(",则直接存入运算符堆栈。
(2) 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止。
(3) 该运算符为非括号运算符:
(a) 若运算符堆栈栈顶的运算符为括号,则直接存入运算符堆栈。
(b) 若比运算符堆栈栈顶的运算符优先级高或相等,则直接存入运算符堆栈。
(c) 若比运算符堆栈栈顶的运算符优先级低,则输出栈顶运算符到操作数堆栈,并将当前运算符压入运算符堆栈。
4、当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。
二、逆波兰表达式求值算法:
1、循环扫描语法单元的项目。
2、如果扫描的项目是操作数,则将其压入操作数堆栈,并扫描下一个项目。
3、如果扫描的项目是一个二元运算符,则对栈的顶上两个操作数执行该运算。
4、如果扫描的项目是一个一元运算符,则对栈的最顶上操作数执行该运算。
5、将运算结果重新压入堆栈。
6、重复步骤2-5,堆栈中即为结果值。
只要你有兴趣,利用下面的代码可编写一个比Windows计算器功能更强大的计算器。
本代码是一个完善的逆波兰表达式算法,但本代码并没有经过严格的测试,有些地方需要你来优化、完善。
代码实现:


/*
* 名称:逆波兰表达式算法
* 作者:rayrain
* 日期:2009-06-20
* 描述:逆波兰表达式主要用于一些项目中表达式、函数的求值。
* EMAIL:rayrains@yahoo.cn
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Analyzer
{
#region 运算符
/// <summary>
/// 运算符类型(从上到下优先级依次递减)
/// </summary>
public enum OperatorType
{
/// <summary>
/// 左括号:(,left bracket
/// </summary>
LB = 10,
/// <summary>
/// 右括号),right bracket
/// </summary>
RB = 11,
/// <summary>
/// 逻辑非,!,NOT
/// </summary>
NOT = 20,
/// <summary>
/// 正号,+,positive sign
/// </summary>
PS = 21,
/// <summary>
/// 负号,-,negative sign
/// </summary>
NS = 22,
/// <summary>
/// 乘,*,multiplication
/// </summary>
MUL = 30,
/// <summary>
/// 除,/,division
/// </summary>
DIV = 31,
/// <summary>
/// 余,%,modulus
/// </summary>
MOD = 32,
/// <summary>
/// 加,+,Addition
/// </summary>
ADD = 40,
/// <summary>
/// 减,-,subtraction
/// </summary>
SUB = 41,
/// <summary>
/// 小于,less than
/// </summary>
LT = 50,
/// <summary>
/// 小于或等于,less than or equal to
/// </summary>
LE = 51,
/// <summary>
/// 大于,>,greater than
/// </summary>
GT = 52,
/// <summary>
/// 大于或等于,>=,greater than or equal to
/// </summary>
GE = 53,
/// <summary>
/// 等于,=,equal to
/// </summary>
ET = 60,
/// <summary>
/// 不等于,unequal to
/// </summary>
UT = 61,
/// <summary>
/// 逻辑与,&,AND
/// </summary>
AND = 70,
/// <summary>
/// 逻辑或,|,OR
/// </summary>
OR = 71,
/// <summary>
/// 逗号,comma
/// </summary>
CA = 80,
/// <summary>
/// 结束符号
/// </summary>
END = 255,
/// <summary>
/// 错误符号
/// </summary>
ERR = 256
}
/// <summary>
/// 运算符
/// </summary>
public class Operator
{
private OperatorType type = OperatorType.END;
private string value = "";
public Operator(OperatorType type, string value)
{
this.type = type;
this.value = value;
}
/// <summary>
/// 运算符类型
/// </summary>
public OperatorType Type
{
get
{
return this.type;
}
set
{
this.type = value;
}
}
/// <summary>
/// 运算符值
/// </summary>
public string Value
{
get
{
return this.value;
}
set
{
this.value = value;
}
}
}
#endregion
#region 操作数
/// <summary>
/// 操作数类型
/// </summary>
public enum OperandType
{
/// <summary>
/// 函数
/// </summary>
FUNC = 1,
/// <summary>
/// 日期
/// </summary>
DATE = 2,
/// <summary>
/// 数字
/// </summary>
NUMBER = 3,
/// <summary>
/// 布尔
/// </summary>
BOOLEAN = 4,
/// <summary>
/// 字符串
/// </summary>
STRING = 5
}
/// <summary>
/// 操作数
/// </summary>
public class Operand
{
private OperandType type = OperandType.STRING;
private string key = "";
private object value = null;
public Operand(OperandType type, object value)
{
this.type = type;
this.value = value;
}
/// <summary>
/// 操作数类型
/// </summary>
public OperandType Type
{
get
{
return this.type;
}
set
{
this.type = value;
}
}
/// <summary>
/// 关键字
/// </summary>
public string Key
{
get
{
return this.key;
}
set
{
this.key = value;
}
}
/// <summary>
/// 操作数值
/// </summary>
public object Value
{
get
{
return this.value;
}
set
{
this.value = value;
}
}
}


/// <summary>
/// 语法分析器
/// </summary>
public class AccidenceAnalyzer
{
#region 成员变量
private string m_Operator = "()!*/%+-<>=&|,"; //运算符
private Stack<object> m_tokens = null; //语法单元堆栈
private string m_Message = ""; //消息
#endregion
#region 构造与析构
/// <summary>
///
/// </summary>
public AccidenceAnalyzer()
{
m_tokens = new Stack<object>();
}
#endregion
#region 属性
/// <summary>
/// 消息
/// </summary>
public string Message
{
get
{
return m_Message;
}
}
/// <summary>
/// 返回语法单元集合
/// </summary>
public Stack<object> Tokens
{
get
{
return m_tokens;
}
}
/// <summary>
/// 包含的运算符
/// </summary>
public string Inclusive
{
set
{
char[] cs = value.ToCharArray();
foreach (char c in cs)
{
if (m_Operator.IndexOf(c) == -1)
{
m_Operator += c.ToString();
}
}
}
}
/// <summary>
/// 排除的运算符
/// </summary>
public string Repulsive
{
set
{
char[] cs = value.ToCharArray();
int pos = 0;
foreach (char c in cs)
{
pos = m_Operator.IndexOf(c);
if (pos > -1)
{
m_Operator = m_Operator.Remove(pos, 1);
}
}
}
}
#endregion
#region 事件
/// <summary>
/// 语法分析事件
/// </summary>
/// <param name="opd">操作数</param>
/// <returns></returns>
public delegate bool AccidenceAnalysis(ref Operand opd);
/// <summary>
/// 语法分析事件
/// </summary>
/// <param name="opd">操作数</param>
/// <returns></returns>
public event AccidenceAnalysis OnAccidenceAnalysis;
/// <summary>
/// 回调函数
/// </summary>
/// <param name="opd">操作数</param>
/// <param name="msg">错误消息</param>
public delegate object CallBack(string funcName, object[] param, ref bool isOk);
/// <summary>
/// 回调函数
/// </summary>
/// <param name="opd">操作数</param>
/// <param name="msg">错误消息</param>
public event CallBack OnCallBack;


#region 方法
#region 语法解析
/// <summary>
/// 语法解析,将中缀表达式转换成后缀表达式(即逆波兰表达式)
/// </summary>
/// <param name="exp">一个中缀表达式,例如:a+b*c</param>
/// <returns></returns>
public bool Parse(string exp)
{
/* 将中缀表达式转换成后缀表达式算法:
1、从左至右扫描一中缀表达式。
2、若读取的是操作数,则判断该操作数的类型,并将该操作数存入操作数堆栈
3、若读取的是运算符
(1) 该运算符为左括号"(",则直接存入运算符堆栈。
(2) 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止。
(3) 该运算符为非括号运算符:
(a) 若运算符堆栈栈顶的运算符为括号,则直接存入运算符堆栈。
(b) 若比运算符堆栈栈顶的运算符优先级高或相等,则直接存入运算符堆栈。
(c) 若比运算符堆栈栈顶的运算符优先级低,则输出栈顶运算符到操作数堆栈,并将当前运算符压入运算符堆栈。
4、当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。
*/
m_tokens.Clear();//清空语法单元堆栈
if (exp.Trim() == "")//表达式不能为空
{
return false;
}
else if(!this.IsMatching(exp))//括号、引号、单引号等必须配对
{
return false;
}
else
{
Stack<object> tokens = new Stack<object>(); //语法单元堆栈
Stack<Operator> operators = new Stack<Operator>(); //运算符堆栈
OperandType operandType = OperandType.STRING; //操作数类型
OperatorType operatorType = OperatorType.ERR; //运算符类型
string currentOpd = ""; //当前操作数
string currentOpt = ""; //当前运算符
int currentPos = 0; //当前位置
int funcCount = 0; //函数数量
exp += "";//加入结束标记
while (exp != "")
{
currentPos = FindOperator(exp);
if (currentPos == -1)
{
//无运算符,触发语法分析事件
Operand opd = new Operand(ConvertOperand(exp), exp);
if (this.OnAccidenceAnalysis == null)
{
tokens.Push(opd);
}
else
{
if (OnAccidenceAnalysis(ref opd))
{
tokens.Push(opd);
}
else
{
m_Message = "解析操作数:" + Convert.ToString(opd.Value) + "失败";
tokens.Clear();
return false;
}
}
break;
}
else
{
currentOpd = exp.Substring(0, currentPos);
currentOpt = exp.Substring(currentPos, 1);
currentOpd = currentOpd.Trim();
if (currentOpt == "(")
{
//函数数量增加
if (currentOpd != "")
{
funcCount++;
}
//将函数名称存入语法单元堆栈
if (currentOpd != "")
{
tokens.Push(new Operand(ConvertOperand(currentOpd + "("), currentOpd));
}
//若当前运算符为左括号,则直接存入堆栈。
operators.Push(new Operator(OperatorType.LB, "("));
}
else if (currentOpt == ")")
{
//分析并存入运算符到语法单元堆栈
if (currentOpd != "")
{
operandType = this.ConvertOperand(currentOpd);
if ((operandType != OperandType.STRING) || (funcCount > 0))
{
tokens.Push(new Operand(ConvertOperand(currentOpd), currentOpd));
}
else
{
Operand opd = new Operand(ConvertOperand(currentOpd), currentOpd);
if(this.OnAccidenceAnalysis == null)
{
tokens.Push(opd);
}
else
{
if (OnAccidenceAnalysis(ref opd))
{
tokens.Push(opd);
}
else
{
m_Message = "解析操作数:" + Convert.ToString(opd.Value) + "失败";
tokens.Clear();
return false;
}
}
}
}
//若当前运算符为右括号,则依次弹出运算符堆栈中的运算符并存入到语法单元堆栈,直到遇到左括号为止.
while (operators.Count > 0)
{
if (operators.Peek().Type != OperatorType.LB)
{
tokens.Push(operators.Pop());
}
else
{
tokens.Push(operators.Pop());
tokens.Push(new Operator(OperatorType.RB, ")"));
break;
}
}
//函数数量减少
if (funcCount > 0)
{
funcCount--;
}
}
else
{
//分析并存入运算符到语法单元堆栈
if (currentOpd != "")
{
operandType = this.ConvertOperand(currentOpd);
if ((operandType != OperandType.STRING) || (funcCount > 0))
{
tokens.Push(new Operand(ConvertOperand(currentOpd), currentOpd));
}
else
{
Operand opd = new Operand(ConvertOperand(currentOpd), currentOpd);
if (this.OnAccidenceAnalysis == null)
{
tokens.Push(opd);
}
else
{
if (OnAccidenceAnalysis(ref opd))
{
tokens.Push(opd);
}
else
{
m_Message = "解析操作数:" + Convert.ToString(opd.Value) + "失败";
tokens.Clear();
return false;
}
}
}
}
//调整运算符
currentOpt = this.AdjustOperator(currentOpt, exp, currentPos, out currentPos);
operatorType = this.ConvertOperator(currentOpt, this.IsDyadicOperator(ref tokens, ref operators, currentOpd));
//分析并存入操作数到操作数堆栈
if (operatorType == OperatorType.ERR)
{
m_Message = "无效运算符:" + currentOpt;
tokens.Clear();
return false;
}
else
{
if (operators.Count == 0)
{
//若运算符堆栈为空,则直接存入.
operators.Push(new Operator(operatorType, currentOpt));
}
else
{
if (operators.Peek().Type == OperatorType.LB)
{
//若运算符堆栈栈顶为左括号,则将当前运算符直接存入运算符堆栈.
operators.Push(new Operator(operatorType, currentOpt));
}
else
{
if (OperatorPriority(operatorType, operators.Peek().Type) > 0)
{
//若当前运算符比运算符栈顶运算符优先级高,则将当前运算符直接存入运算符堆栈.
operators.Push(new Operator(operatorType, currentOpt));
}
else
{
//若当前运算符比运算符堆栈栈顶运算符优先级低或相等,则弹出运算符堆栈栈顶运算符并存入到语法单元堆栈,并将当前运算符存入堆栈.
tokens.Push(operators.Pop());
operators.Push(new Operator(operatorType, currentOpt));
}
}
}
}
}
exp = exp.Substring(currentPos + 1).Trim();
}
}
//转换完成,若运算符堆栈中尚有运算符时,
//则依序取出运算符到语法单元堆栈,直到运算符堆栈为空
while (operators.Count > 0)
{
tokens.Push(operators.Pop());
}
//调整语法单元中对象的顺序并输出到最终语法单元
while (tokens.Count > 0)
{
m_tokens.Push(tokens.Pop());
}
}
return true;
}
#endregion
#region 表达式求值
/// <summary>
/// 对逆波兰表达式求值
/// </summary>
/// <param name="isOk">是否成功</param>
/// <returns>结果值</returns>
public object Evaluate(ref bool isOk)
{
/*
逆波兰表达式求值算法:
1、循环扫描语法单元的项目。
2、如果扫描的项目是操作数,则将其压入操作数堆栈,并扫描下一个项目。
3、如果扫描的项目是一个二元运算符,则对栈的顶上两个操作数执行该运算。
4、如果扫描的项目是一个一元运算符,则对栈的最顶上操作数执行该运算。
5、将运算结果重新压入堆栈。
6、重复步骤2-5,堆栈中即为结果值。
*/
if (m_tokens.Count == 0) return null;
isOk = false;
object value = null;
bool existFunc = false;
Stack<Operand> opds = new Stack<Operand>();
Stack<object> pars = new Stack<object>();
Operand opd, opdA, opdB;
foreach(object item in m_tokens)
{
if (item is Operand)
{
//如果为操作数则压入操作数堆栈
opds.Push((Operand)item);
}
else
{
switch(((Operator)item).Type)
{
#region 左括号
case OperatorType.LB:
if (opds.Count > 0)
{
//清除函数参数堆栈
pars.Clear();
//检查是否有函数调用
existFunc = false;
foreach(Operand opdItem in opds)
{
if(opdItem.Type == OperandType.FUNC)
{
existFunc = true;
break;
}
}
//将函数参数压入堆栈
if(existFunc)
{
while(opds.Count > 0)
{
opd = opds.Peek();
if (opd.Type != OperandType.FUNC)
{
opd = opds.Pop();
pars.Push(opd.Value);
}
else
{
break;
}
}
}
}
break;
#endregion
#region 右括号
case OperatorType.RB:
if (pars.Count > 0)
{
object val;
bool ok = false;
if (this.OnCallBack != null)
{
val = OnCallBack(Convert.ToString(opds.Pop().Value), pars.ToArray(), ref ok);
if(ok)
{
opds.Push(new Operand(OperandType.NUMBER, val));
}
}
pars.Clear();
}
break;
#endregion
#region 逻辑非,!,NOT
case OperatorType.NOT:
opdA = opds.Pop();
if (IsCanConvertToNumber(opdA.Value))
{
opds.Push(new Operand(OperandType.BOOLEAN, !ConvertToBoolean(opdA.Value)));
}
else
{
}
break;
#endregion
#region 正号,+,positive sign
case OperatorType.PS:
opdA = opds.Pop();
if (IsNumber(opdA.Value))
{
opds.Push(new Operand(OperandType.NUMBER, +ConvertToNumber(opdA.Value)));
}
else
{
}
break;
#endregion
#region 负号,-,negative sign
case OperatorType.NS:
opdA = opds.Pop();
if (IsNumber(opdA.Value))
{
opds.Push(new Operand(OperandType.NUMBER, -ConvertToNumber(opdA.Value)));
}
else
{
}
break;
#endregion
#region 乘,*,multiplication
case OperatorType.MUL:
opdA = opds.Pop();
opdB = opds.Pop();
if (IsNumber(opdA.Value) && IsNumber(opdB.Value))
{
opds.Push(new Operand(OperandType.NUMBER, ConvertToNumber(opdB.Value) * ConvertToNumber(opdA.Value)));
}
else
{
}
break;
#endregion
#region 除,/,division
case OperatorType.DIV:
opdA = opds.Pop();
opdB = opds.Pop();
if (IsNumber(opdA.Value) && IsNumber(opdB.Value))
{
opds.Push(new Operand(OperandType.NUMBER, ConvertToNumber(opdB.Value) / ConvertToNumber(opdA.Value)));
}
else
{
}
break;
#endregion
#region 余,%,modulus
case OperatorType.MOD:
opdA = opds.Pop();
opdB = opds.Pop();
if (IsNumber(opdA.Value) && IsNumber(opdB.Value))
{
opds.Push(new Operand(OperandType.NUMBER, ConvertToNumber(opdB.Value) % ConvertToNumber(opdA.Value)));
}
else
{
}
break;
#endregion
#region 加,+,Addition
case OperatorType.ADD:
opdA = opds.Pop();
opdB = opds.Pop();
if (IsNumber(opdA.Value) && IsNumber(opdB.Value))
{
opds.Push(new Operand(OperandType.NUMBER, ConvertToNumber(opdB.Value) + ConvertToNumber(opdA.Value)));
}
else
{
}
break;
#endregion
#region 减,-,subtraction
case OperatorType.SUB:
opdA = opds.Pop();
opdB = opds.Pop();
if (IsNumber(opdA.Value) && IsNumber(opdB.Value))
{
opds.Push(new Operand(OperandType.NUMBER, ConvertToNumber(opdB.Value) - ConvertToNumber(opdA.Value)));
}
else
{
}
break;
#endregion
#region 小于,less than
case OperatorType.LT:
opdA = opds.Pop();
opdB = opds.Pop();
if (IsCanConvertToNumber(opdA.Value) && IsCanConvertToNumber(opdB.Value))
{
opds.Push(new Operand(OperandType.NUMBER, ConvertToNumber(opdB.Value) < ConvertToNumber(opdA.Value)));
}
else
{
}
break;
#endregion
#region 小于或等于,less than or equal to
case OperatorType.LE:
opdA = opds.Pop();
opdB = opds.Pop();
if (IsCanConvertToNumber(opdA.Value) && IsCanConvertToNumber(opdB.Value))
{
opds.Push(new Operand(OperandType.NUMBER, ConvertToNumber(opdB.Value) <= ConvertToNumber(opdA.Value)));
}
else
{
}
break;
#endregion
#region 大于,>,greater than
case OperatorType.GT:
opdA = opds.Pop();
opdB = opds.Pop();
if (IsCanConvertToNumber(opdA.Value) && IsCanConvertToNumber(opdB.Value))
{
opds.Push(new Operand(OperandType.NUMBER, ConvertToNumber(opdB.Value) > ConvertToNumber(opdA.Value)));
}
else
{
}
break;
#endregion
#region 大于或等于,>=,greater than or equal to
case OperatorType.GE:
opdA = opds.Pop();
opdB = opds.Pop();
if (IsCanConvertToNumber(opdA.Value) && IsCanConvertToNumber(opdB.Value))
{
opds.Push(new Operand(OperandType.NUMBER, ConvertToNumber(opdB.Value) >= ConvertToNumber(opdA.Value)));
}
else
{
}
break;
#endregion
#region 等于,=,equal to
case OperatorType.ET:
opdA = opds.Pop();
opdB = opds.Pop();
if (IsCanConvertToNumber(opdA.Value) && IsCanConvertToNumber(opdB.Value))
{
opds.Push(new Operand(OperandType.NUMBER, ConvertToNumber(opdB.Value) == ConvertToNumber(opdA.Value)));
}
else
{
}
break;
#endregion
#region 不等于,unequal to
case OperatorType.UT:
opdA = opds.Pop();
opdB = opds.Pop();
if (IsCanConvertToNumber(opdA.Value) && IsCanConvertToNumber(opdB.Value))
{
opds.Push(new Operand(OperandType.NUMBER, ConvertToNumber(opdB.Value) != ConvertToNumber(opdA.Value)));
}
else
{
}
break;
#endregion
#region 逻辑与,&,AND
case OperatorType.AND:
opdA = opds.Pop();
opdB = opds.Pop();
if (IsCanConvertToNumber(opdA.Value) && IsCanConvertToNumber(opdB.Value))
{
opds.Push(new Operand(OperandType.NUMBER, ConvertToBoolean(opdB.Value) && ConvertToBoolean(opdA.Value)));
}
else
{
}
break;
#endregion
#region 逻辑或,|,OR
case OperatorType.OR:
opdA = opds.Pop();
opdB = opds.Pop();
if (IsCanConvertToNumber(opdA.Value) && IsCanConvertToNumber(opdB.Value))
{
opds.Push(new Operand(OperandType.NUMBER, ConvertToBoolean(opdB.Value) || ConvertToBoolean(opdA.Value)));
}
else
{
}
break;
#endregion
#region 逗号,comma
case OperatorType.CA:
opdA = opds.Pop();
opdB = opds.Pop();
opds.Push(new Operand(opdB.Type, opdB.Value));
opds.Push(new Operand(opdA.Type, opdA.Value));
break;
#endregion
#region 结束符号
case OperatorType.END:
break;
#endregion
#region 错误符号
case OperatorType.ERR:
break;
#endregion
}
}
}
if (opds.Count > 0)
{
if (opds.Count == 1)
{
isOk = true;
value = opds.Pop().Value;
}
}
return value;
}
#endregion
#endregion
#region Private
/// <summary>
/// 从表达式中查找运算符位置
/// </summary>
/// <param name="exp">表达式</param>
/// <returns>返回运算符位置</returns>
private int FindOperator(string exp)
{
return FindOperator(exp, "");
}
/// <summary>
/// 从表达式中查找运算符位置
/// </summary>
/// <param name="exp">表达式</param>
/// <param name="findOpt">要查找的运算符</param>
/// <returns>返回运算符位置</returns>
private int FindOperator(string exp, string findOpt)
{
string opt = "";
string chr = "";
for (int i = 0; i < exp.Length; i++)
{
chr = exp.Substring(i, 1);
if ( "\"'#".Contains(chr))//忽略双引号、单引号、井号中的运算符
{
if (opt.Contains(chr))
{
opt = opt.Remove(opt.IndexOf(chr), 1);
}
else
{
opt += chr;
}
}
if (opt == "")
{
if (findOpt != "")
{
if (findOpt == chr)
{
return i;
}
}
else
{
if (m_Operator.IndexOf(chr) > -1)
{
return i;
}
}
}
}
return -1;
}
/// <summary>
/// 检查表达式中特殊符号是否匹配
/// </summary>
/// <returns>匹配返回真</returns>
private bool IsMatching(string exp)
{
string opt = "";
string chr = "";
for (int i = 0; i < exp.Length; i++)
{
chr = exp.Substring(i, 1);
if ( "\"'#".Contains(chr))//忽略双引号、单引号、井号中的运算符
{
if (opt.Contains(chr))
{
opt = opt.Remove(opt.IndexOf(chr), 1);
}
else
{
opt += chr;
}
}
else if ("()".Contains(chr))//左右括号要成对匹配
{
if (chr == "(")
{
opt += chr;
}
else if (chr == ")")
{
if (opt.Contains("("))
{
opt = opt.Remove(opt.IndexOf("("), 1);
}
}
}
}
return (opt == "");
}
/// <summary>
/// 转换操作数到指定的类型
/// </summary>
/// <param name="opd">操作数</param>
/// <returns>返回制定的操作数类型</returns>
private OperandType ConvertOperand(string opd)
{
if (opd.IndexOf("(") > -1)
{
return OperandType.FUNC;
}
else if (this.IsNumber(opd))
{
return OperandType.NUMBER;
}
else if (this.IsDate(opd))
{
return OperandType.DATE;
}
else
{
return OperandType.STRING;
}
}
/// <summary>
/// 转换运算符到指定的类型
/// </summary>
/// <param name="opt">运算符</param>
/// <param name="isDyadicOperator">是否为二元运算符</param>
/// <returns>返回制定的运算符类型</returns>
private OperatorType ConvertOperator(string opt, bool isDyadicOperator)
{
switch (opt)
{
case "!": return OperatorType.NOT;
case "+": return isDyadicOperator ? OperatorType.ADD : OperatorType.PS;
case "-": return isDyadicOperator ? OperatorType.SUB : OperatorType.NS;
case "*": return isDyadicOperator ? OperatorType.MUL : OperatorType.ERR;
case "/": return isDyadicOperator ? OperatorType.DIV : OperatorType.ERR;
case "%": return isDyadicOperator ? OperatorType.MOD : OperatorType.ERR;
case "<": return isDyadicOperator ? OperatorType.LT : OperatorType.ERR;
case ">": return isDyadicOperator ? OperatorType.GT : OperatorType.ERR;
case "<=": return isDyadicOperator ? OperatorType.LE : OperatorType.ERR;
case ">=": return isDyadicOperator ? OperatorType.GE : OperatorType.ERR;
case "<>": return isDyadicOperator ? OperatorType.UT : OperatorType.ERR;
case "=": return isDyadicOperator ? OperatorType.ET : OperatorType.ERR;
case "&": return isDyadicOperator ? OperatorType.AND : OperatorType.ERR;
case "|": return isDyadicOperator ? OperatorType.OR : OperatorType.ERR;
case ",": return isDyadicOperator ? OperatorType.CA : OperatorType.ERR;
case "": return isDyadicOperator ? OperatorType.END : OperatorType.ERR;
default: return OperatorType.ERR;
}
}
/// <summary>
/// 运算符是否为二元运算符
/// </summary>
/// <param name="tokens">语法单元堆栈</param>
/// <param name="operators">运算符堆栈</param>
/// <param name="currentOpd">当前操作数</param>
/// <returns>是返回真,否返回假</returns>
private bool IsDyadicOperator(ref Stack<object> tokens, ref Stack<Operator> operators, string currentOpd)
{
if (currentOpd != "")
{
return true;
}
else
{
object token = tokens.Peek();
if (token is Operand)
{
if (operators.Peek().Type != OperatorType.LB)
{
return true;
}
else
{
return false;
}
}
else
{
if (((Operator)token).Type == OperatorType.RB)
{
return true;
}
else
{
return false;
}
}
}
}
/// <summary>
/// 调整运算符
/// </summary>
/// <param name="currentOpt">当前运算符</param>
/// <param name="currentExp">当前表达式</param>
/// <param name="currentOptPos">当前运算符位置</param>
/// <param name="adjustOptPos">调整后运算符位置</param>
/// <returns>返回调整后的运算符</returns>
private string AdjustOperator(string currentOpt, string currentExp, int currentOptPos,out int adjustOptPos)
{
switch (currentOpt)
{
case "<":
if (currentExp.Substring(currentOptPos, 2) == "<=")
{
adjustOptPos = currentOptPos + 1;
return "<=";
}
else if (currentExp.Substring(currentOptPos, 2) == "<>")
{
adjustOptPos = currentOptPos + 1;
return "<>";
}
else
{
adjustOptPos = currentOptPos;
return "<";
}
case ">":
if (currentExp.Substring(currentOptPos, 2) == ">=")
{
adjustOptPos = currentOptPos + 1;
return ">=";
}
else
{
adjustOptPos = currentOptPos;
return ">";
}
default:
adjustOptPos = currentOptPos;
return currentOpt;
}
}
/// <summary>
/// 运算符优先级比较
/// </summary>
/// <param name="optA">运算符类型A</param>
/// <param name="optB">运算符类型B</param>
/// <returns>-1,低;0,相等;1,高</returns>
private int OperatorPriority(OperatorType optA, OperatorType optB)
{
if (optA == optB)
{
//A、B优先级相等
return 0;
}
else if (optA > optB)
{
//A优先级高于B
return 1;
}
else
{
//乘,除,余(*,/,%)
if ((optA >= OperatorType.MUL && optA <= OperatorType.MOD) &&
(optB >= OperatorType.MUL && optB <= OperatorType.MOD))
{
return 0;
}
//加,减(+,-)
if ((optA >= OperatorType.ADD && optA <= OperatorType.SUB) &&
(optB >= OperatorType.ADD && optB <= OperatorType.SUB))
{
return 0;
}
//小于,小于或等于,大于,大于或等于(<,<=,>,>=)
if ((optA >= OperatorType.LT && optA <= OperatorType.GE) &&
(optB >= OperatorType.LT && optB <= OperatorType.GE))
{
return 0;
}
//等于,不等于(=,<>)
if ((optA >= OperatorType.ET && optA <= OperatorType.UT) &&
(optB >= OperatorType.ET && optB <= OperatorType.UT))
{
return 0;
}
//A优先级低于B
return -1;
}
}
/// <summary>
/// 判断对象是否为数字
/// </summary>
/// <param name="value">对象值</param>
/// <returns>是返回真,否返回假</returns>
private bool IsNumber(object value)
{
decimal dec;
return decimal.TryParse(Convert.ToString(value), out dec);
}
/// <summary>
/// 判断对象是否为日期
/// </summary>
/// <param name="value">对象值</param>
/// <returns>是返回真,否返回假</returns>
private bool IsDate(object value)
{
DateTime dt;
return DateTime.TryParse(Convert.ToString(value), out dt);
}
/// <summary>
/// 判断对象是否为布尔型
/// </summary>
/// <param name="value">对象值</param>
/// <returns>是返回真,否返回假</returns>
private bool IsBoolean(object value)
{
bool b = false;
return Boolean.TryParse(Convert.ToString(value), out b);
}
/// <summary>
/// 判断对象是否可转换成数字
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private bool IsCanConvertToNumber(object value)
{
return (IsNumber(value) || IsBoolean(value));
}
/// <summary>
/// 将对象转换成数字
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private decimal ConvertToNumber(object value)
{
return Convert.ToDecimal(value);
}
/// <summary>
/// 将对象转换成布尔型
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private bool ConvertToBoolean(object value)
{
return Convert.ToBoolean(value);
}
#endregion
}


using System;
using System.Collections.Generic;
using System.Text;
namespace Analyzer
{
class Program
{
static void Main(string[] args)
{
bool ok = false;
AccidenceAnalyzer aa = new AccidenceAnalyzer();
aa.OnAccidenceAnalysis += new AccidenceAnalyzer.AccidenceAnalysis(aa_OnAccidenceAnalysis);
aa.OnCallBack+= new AccidenceAnalyzer.CallBack(aa_OnCallBack);
aa.Parse("m*(a*(-10) + (b - 10)) / 3");
//aa.Parse("f1(f2(a),b) + 10");
//aa.Parse("10 - 3 + 3");
//aa.Parse("18/2*3");
object d = aa.Evaluate(ref ok);
System.Console.WriteLine(d);
System.Console.Read();
}
static object aa_OnCallBack(string funcName, object[] param, ref bool isOk)
{
isOk = true;
return 2;
}
static bool aa_OnAccidenceAnalysis(ref Operand opd)
{
//throw new Exception("The method or operation is not implemented.");
//opd.Id = 10;
//opd.Key = "kk";
opd.Type = OperandType.NUMBER;
opd.Value = 2;
return true;
}
}
}