|
|
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>-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)
|
|
|
{
|
|
|
if (value is bool)
|
|
|
{
|
|
|
return (bool)value;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (Convert.ToDecimal(value) != 0)
|
|
|
{
|
|
|
return true;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
} |