You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1411 lines
48 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Text;
namespace Mesnac.Basic
{
class Analyzer
{
}
/// <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;
}
}
}
/// <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
{
private string m_Operator = "()!*/%+-<>=&|,"; //运算符
private Stack<object> m_tokens = null; //语法单元堆栈
private string m_Message = ""; //消息
/// <summary>
///
/// </summary>
public AccidenceAnalyzer()
{
m_tokens = new Stack<object>();
}
/// <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);
}
}
}
}
/// <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;
/// <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
{
bool isNS = false;
currentOpd = exp.Substring(0, currentPos);
if ((currentPos == 0) && (currentOpt != ")") & (exp.Substring(currentPos, 1) == "-"))
{
isNS = true;
}
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))
{
//lizheng add
if (operandType == OperandType.STRING)
{
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;
}
}
}
//
else
{
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))
{
//lizheng add
if (operandType == OperandType.STRING)
{
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;
}
}
}
//
else
{
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);
if (isNS)
{
operatorType = this.ConvertOperator(currentOpt, false);
}
else
{
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;
}
/// <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))//函数内部都是数字时直接运算如果有变量则进入else现在没有处理呢李正
{
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;
}
/// <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
{
if (tokens.Count == 0)
{
return false;
}
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>-10,相等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)
{
if (value is bool)
{
return (bool)value;
}
else
{
if (Convert.ToDecimal(value) != 0)
{
return true;
}
else
{
return false;
}
}
}
}
}