逆波兰表达式

本文是逆波兰表达式的算法极其实现,可直接应用于项目中,要引用请注明来源,在使用时若遇到错误请及时指正。
逆波兰表达式在一些项目中的应用是很频繁的,例如财务管理软件中对财务进行取数等。

表达式一般由操作数(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计算器功能更强大的计算器。
本代码是一个完善的逆波兰表达式算法,但本代码并没有经过严格的测试,有些地方需要你来优化、完善。
代码实现:
ContractedBlock.gifExpandedBlockStart.gifCode
/*
 * 名称:逆波兰表达式算法
 * 作者: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;
            }
        }
    }

    
ContractedBlock.gifExpandedBlockStart.gifCode
  /// <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;
        
        
ContractedBlock.gifExpandedBlockStart.gifCode
 #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 == 0return 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;
                
defaultreturn 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
    }
ContractedBlock.gifExpandedBlockStart.gifCode
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;
        }
    }
}





转载于:https://www.cnblogs.com/rayrain/articles/1530646.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值