/// <summary> /// 处理逻辑非"!"运算符 /// </summary> /// <returns></returns> private ExpTreeNode DoSgOP(ParsingContext context) { SkipSpaces(context); ExpTreeNode node = null; char ch = context.CurrentChar; if (ch == '!') { OutputID(context, Operation_IDs.OI_NOT, "!", context.Position); int nPos = context.Position; context.Position++; ExpTreeNode node2 = DoSgOP(context); node = NewTreeNode(context, null, node2, Operation_IDs.OI_NOT, nPos); } else { node = DoFactor(context); } return(node); }
/// <summary> /// 处理加减运算 /// </summary> /// <returns></returns> private ExpTreeNode DoAddSub(ParsingContext context) { ExpTreeNode node = null; ExpTreeNode node1 = DoMulDiv(context); ExpTreeNode node2 = null; char ch = context.CurrentChar; while (ch == '-' || ch == '+') { Operation_IDs oID = Operation_IDs.OI_NONE; oID = (ch == '-') ? Operation_IDs.OI_MINUS : Operation_IDs.OI_ADD; OutputID(context, oID, ch.ToString(), context.Position); int nPos = context.Position; context.Position++; node2 = DoMulDiv(context); node = NewTreeNode(context, node1, node2, oID, nPos); node1 = node; ch = context.CurrentChar; } return(node1); }
/// <summary> /// 处理乘除运算 /// </summary> /// <returns></returns> private ExpTreeNode DoMulDiv(ParsingContext context) { ExpTreeNode node1 = DoSgOP(context); char ch = context.CurrentChar; while (ch == '*' || ch == '/') { Operation_IDs oID = Operation_IDs.OI_NONE; oID = (ch == '*') ? Operation_IDs.OI_MUL : Operation_IDs.OI_DIV; OutputID(context, oID, ch.ToString(), context.Position); int nPos = context.Position; context.Position++; ExpTreeNode node2 = DoSgOP(context); node1 = NewTreeNode(context, node1, node2, oID, nPos); ch = context.CurrentChar; } return(node1); }
private static ExpTreeNode DoLogical_AND_OR(ParsingContext context, char chSensitive, Operation_IDs oID, Func <ParsingContext, ExpTreeNode> doNextOP) { ExpTreeNode node = null; ExpTreeNode node1 = doNextOP(context); ExpTreeNode node2 = null; while (context.CurrentChar == chSensitive) { int nPos = context.Position; char op = context.ExpressionChars[context.Position++]; if (op == chSensitive) { OutputID(context, oID, chSensitive.ToString() + chSensitive.ToString(), nPos); context.Position++; } node2 = doNextOP(context); node = NewTreeNode(context, node1, node2, oID, nPos); node1 = node; } return(node1); }
private object DoInFunction(ExpTreeNode funcNode, IReadOnlyList <ExpTreeNode> arrParams, CalculateContext calcContext) { bool result = false; if (arrParams.Count > 0) { object sourceData = this.VExp(arrParams[0], calcContext); if (sourceData != null) { for (int i = 1; i < arrParams.Count; i++) { object itemValue = this.VExp(arrParams[i], calcContext); if (itemValue != null) { if ((bool)CompareEqualOP(sourceData, itemValue, 0)) { result = true; break; } } } } } return(result); }
private object DoIIFFunction(ExpTreeNode funcNode, IReadOnlyList <ExpTreeNode> arrParams, CalculateContext calcContext) { if (arrParams.Count != 3) { throw ParsingException.NewParsingException(ParseError.peInvalidParam, funcNode.Position, funcNode.FunctionName, "3"); } object result = false; if (arrParams.Count > 0) { object sourceData = this.VExp(arrParams[0], calcContext); if (sourceData != null) { bool sourceCondition = (bool)DataConverter.ChangeType(sourceData, typeof(bool)); if (sourceCondition) { result = this.VExp(arrParams[1], calcContext); } else { result = this.VExp(arrParams[2], calcContext); } } } return(result); }
/// <summary> /// 分析表达式, /// </summary> /// <param name="expression">表达式</param> /// <returns>分析结果</returns> /// <remarks> /// 对传入的表达式进行分析 /// <code source="..\Framework\TestProjects\DeluxeWorks.Library.Test\Expression\ExpressionParserTest.cs" region="parse" lang="cs" title="调用分析表达式的函数" /> /// </remarks> public static ParseResult Parse(string expression) { ParseResult result = null; if (string.IsNullOrEmpty(expression) == false) { ParsingContext context = new ParsingContext(expression); context.OutputIdentifiers = true; ExpTreeNode tree = ExpressionParser.instance.DoExpression(context); if (context.CurrentChar != '\0') { throw ParsingException.NewParsingException(ParseError.peInvalidOperator, context.Position, context.CurrentChar.ToString()); } result = new ParseResult(tree, context.Identifiers); } else { result = new ParseResult(null, null); } return(result); }
private static ExpTreeNode NewTreeNode(ParsingContext context, ExpTreeNode left, ExpTreeNode right, Operation_IDs oID, int nPosition) { ExpTreeNode node = NewTreeNode(context, left, right, oID); node.Position = nPosition; return(node); }
/// <summary> /// 生成一个新的二叉树节点 /// </summary> private static ExpTreeNode NewTreeNode(ParsingContext context) { ExpTreeNode node = new ExpTreeNode(); node.Position = context.Position; return(node); }
/// <summary> /// 处理各种系数、负数、括号等 /// </summary> /// <returns></returns> private ExpTreeNode DoFactor(ParsingContext context) { SkipSpaces(context); ExpTreeNode node = null; char ch = context.CurrentChar; int nPos = context.Position; switch (ch) { case '-': //处理负号 OutputID(context, Operation_IDs.OI_NEG, "-", context.Position); context.Position++; ExpTreeNode node2 = DoExpression(context); ExpTreeNode left = NewTreeNode(context); left.OperationID = Operation_IDs.OI_NEG; left.Value = (decimal) - 1; left.Position = nPos; node = NewTreeNode(context, left, node2, Operation_IDs.OI_MUL, nPos); break; case '(': OutputID(context, Operation_IDs.OI_LBRACKET, "(", context.Position); context.Position++; node = DoExpression(context); SkipSpaces(context); if (context.CurrentChar != ')') { if (context.ThrowParseException) { throw ParsingException.NewParsingException(ParseError.peCharExpected, context.Position, ")"); } } else { OutputID(context, Operation_IDs.OI_RBRACKET, ")", context.Position); } context.Position++; break; default: node = DoIdentifier(context); break; } SkipSpaces(context); return(node); }
/// <summary> /// 生成一个新的二叉树节点 /// </summary> /// <param name="context">运行上下文</param> /// <param name="left">左子树</param> /// <param name="right">右子树</param> /// <param name="oID">操作类型</param> /// <returns></returns> private static ExpTreeNode NewTreeNode(ParsingContext context, ExpTreeNode left, ExpTreeNode right, Operation_IDs oID) { ExpTreeNode node = NewTreeNode(context); node.Left = left; node.Right = right; node.OperationID = oID; return(node); }
private static ExpTreeNode DoDatetime(ParsingContext context) { int nPos = context.Position; char ch = context.ExpressionChars[++context.Position]; StringBuilder strB = new StringBuilder(256); strB.Append("#"); while (ch != '\0') { strB.Append(ch); if (ch == '#') { context.Position++; break; } ch = context.ExpressionChars[++context.Position]; } if (ch == '\0') { if (context.ThrowParseException) { throw ParsingException.NewParsingException(ParseError.peCharExpected, context.Position, "#"); } } ExpTreeNode node = NewTreeNode(context); node.Position = nPos; node.OperationID = Operation_IDs.OI_DATETIME; try { string strID = strB.ToString(); node.Value = DateTime.Parse(strID); OutputID(context, Operation_IDs.OI_DATETIME, strID, nPos); return(node); } catch (System.FormatException) { if (context.ThrowParseException) { throw ParsingException.NewParsingException(ParseError.peFormatError, nPos); } return(null); } }
private static ExpTreeNode DoString(ParsingContext context) { int nPos = context.Position; char ch = context.ExpressionChars[++context.Position]; StringBuilder strB = new StringBuilder(256); StringBuilder strIDB = new StringBuilder(256); strIDB.Append('"'); while (ch != '\0') { if (ch != '"') { strB.Append(ch); strIDB.Append(ch); context.Position++; } else if (context.ExpressionChars[context.Position + 1] == '"') { strB.Append('"'); strIDB.Append("\"\""); context.Position += 2; } else { strIDB.Append('"'); context.Position++; break; } ch = context.CurrentChar; } if (ch == '\0') { if (context.ThrowParseException) { throw ParsingException.NewParsingException(ParseError.peCharExpected, context.Position, "\""); } } string strID = strIDB.ToString(); OutputID(context, Operation_IDs.OI_STRING, strID, nPos); ExpTreeNode node = NewTreeNode(context); node.Position = nPos; node.OperationID = Operation_IDs.OI_STRING; node.Value = strB.ToString(); return(node); }
private ParamObjectCollection GetParams(List <ExpTreeNode> arrParams, CalculateContext calcContext) { List <ParamObject> list = new List <ParamObject>(); for (int i = 0; i < arrParams.Count; i++) { ExpTreeNode node = (ExpTreeNode)arrParams[i]; list.Add(new ParamObject(VExp(node, calcContext), node.Position, i)); } return(new ParamObjectCollection(list)); }
/// <summary> /// 获取树结点值 /// </summary> /// <param name="tree">二叉树节点</param> /// <param name="builtInFunctionsWrapper">包含内置函数的实现类</param> /// <param name="callerContext">调用者上下文</param> /// <param name="optimize">最优化选项</param> /// <returns>树结点值</returns> public object GetValue(ExpTreeNode tree, object builtInFunctionsWrapper, object callerContext, bool optimize) { object result = null; if (tree != null) { CalculateContext calcContext = new CalculateContext(); calcContext.Optimize = optimize; calcContext.CallerContxt = callerContext; calcContext.BuiltInFunctionsWrapper = builtInFunctionsWrapper; result = VExp(tree, calcContext); } return(result); }
/// <summary> /// 获取树结点值 /// </summary> /// <param name="tree">二叉树节点</param> /// <param name="calcUDF">用户自定义函数的委托</param> /// <param name="callerContext">调用者上下文</param> /// <param name="optimize">最优化选项</param> /// <returns>树结点值</returns> public object GetValue(ExpTreeNode tree, CalculateUserFunction calcUDF, object callerContext, bool optimize) { object result = null; if (tree != null) { CalculateContext calcContext = new CalculateContext(); calcContext.Optimize = optimize; calcContext.CallerContxt = callerContext; calcContext.CalculateUserFunction = calcUDF; result = VExp(tree, calcContext); } return(result); }
private object CalculateFunction(ExpTreeNode funcNode, List <ExpTreeNode> arrParams, CalculateContext calcContext) { object oValue = null; switch (funcNode.FunctionName.ToLower()) { case "in": oValue = this.DoInFunction(funcNode, arrParams, calcContext); break; case "iif": oValue = this.DoIIFFunction(funcNode, arrParams, calcContext); break; } return(oValue); }
/// <summary> /// 处理各种数字、标识符、自定义函数、字符串等 /// </summary> /// <returns></returns> private ExpTreeNode DoIdentifier(ParsingContext context) { ExpTreeNode result = null; SkipSpaces(context); char ch = context.CurrentChar; if (ch != '\0') { switch (ch) { case '#': //datetime result = DoDatetime(context); break; case '"': //string result = DoString(context); break; default: if (Char.IsDigit(ch) || ch == '.') { result = DoNumber(context); } else if (Char.IsLetter(ch) || ch == '_') { result = DoFunctionID(context); } else { if (context.ThrowParseException) { throw ParsingException.NewParsingException(ParseError.peInvalidOperator, context.Position, ch.ToString()); } } break; } SkipSpaces(context); } return(result); }
/// <summary> /// 重载实现二叉树的反序列化 /// </summary> /// <param name="info">The object to be populated with serialization information.</param> /// <param name="context">The destination context of the serialization.</param> /// <remarks> /// 二叉树的反序列化 /// <code source="..\Framework\TestProjects\DeluxeWorks.Library.Test\Expression\ExpressionParserTest.cs" region="Serialization" lang="cs" /> /// </remarks> private ExpTreeNode(SerializationInfo info, StreamingContext context) { this.left = (ExpTreeNode)info.GetValue("Left", typeof(ExpTreeNode)); this.right = (ExpTreeNode)info.GetValue("Right", typeof(ExpTreeNode)); this.position = info.GetInt32("Position"); this.operationID = (Operation_IDs)info.GetInt16("OperationID"); string valueTypeName = info.GetString("ValueType"); if (valueTypeName != "NullValue") { this.nodeValue = (Object)info.GetValue("Value", Type.GetType(valueTypeName)); } else { this.nodeValue = (Object)info.GetValue("Value", typeof(Object)); } this.functionParams = (List <ExpTreeNode>)info.GetValue("Params", typeof(ExpTreeNode)); this.functionName = info.GetString("FunctionName"); }
private ExpTreeNode DoFunction(ParsingContext context, string strId) { ExpTreeNode node = null; if (string.Compare(strId, "true", true) == 0 || string.Compare(strId, "false", true) == 0) { node = NewTreeNode(context); node.Position = context.Position - strId.Length; node.OperationID = Operation_IDs.OI_BOOLEAN; node.Value = bool.Parse(strId.ToLower()); OutputID(context, Operation_IDs.OI_BOOLEAN, strId, node.Position); } else { node = GetFunctionNode(context, Operation_IDs.OI_USERDEFINE, strId); } return(node); }
private static ExpTreeNode DoNumber(ParsingContext context) { int nPos = context.Position; char ch = context.CurrentChar; while (Char.IsDigit(ch) || (ch == '.')) { ch = context.ExpressionChars[++context.Position]; } ExpTreeNode node = NewTreeNode(context); node.Position = nPos; node.OperationID = Operation_IDs.OI_NUMBER; string ns = new String(context.ExpressionChars, nPos, context.Position - nPos); node.Value = decimal.Parse(ns); OutputID(context, Operation_IDs.OI_NUMBER, ns, nPos); return(node); }
/// <summary> /// 根据语法解析完的Tree,计算出结果 /// </summary> /// <param name="tree"></param> /// <param name="calculateUserFunction">用户自定义函数的实现</param> /// <param name="callerContext"></param> /// <param name="optimize">是否进行bool运算优化,缺省为true</param> /// <returns></returns> /// <remarks> /// 对含自定义函数的表达式进行解析后生成的二叉树,调用该函数进行运算得出结果值 /// <code source="..\Framework\TestProjects\DeluxeWorks.Library.Test\Expression\ExpressionParserTest.cs" region="parse" lang="cs" title="对解析生成的二叉树进行计算" /> /// </remarks> public static object GetTreeValue(ExpTreeNode tree, CalculateUserFunction calculateUserFunction, object callerContext, bool optimize) { return(ExpTreeExecutor.Instance.GetValue(tree, calculateUserFunction, callerContext, optimize)); }
/// <summary> /// 根据语法解析完的Tree,计算出结果 /// </summary> /// <param name="tree"></param> /// <param name="builtInFunctionsWrapper">包含内置函数的实现类</param> /// <param name="callerContext">调用者上下文</param> /// <param name="optimize">最优化选项</param> /// <returns>树结点值</returns> public static object GetTreeValue(ExpTreeNode tree, object builtInFunctionsWrapper, object callerContext, bool optimize) { return(ExpTreeExecutor.Instance.GetValue(tree, builtInFunctionsWrapper, callerContext, optimize)); }
internal ParseResult(ExpTreeNode tree, ParseIdentifier identifiers) { this.tree = tree; this.identifiers = identifiers; }
/// <summary> /// 逻辑比较运算 /// </summary> /// <returns></returns> private ExpTreeNode DoLogicalOP(ParsingContext context) { ExpTreeNode node = null; ExpTreeNode node1 = DoAddSub(context); ExpTreeNode node2 = null; char op = context.CurrentChar; string strID = string.Empty; while (op == '>' || op == '<' || op == '=') { int nPos = context.Position; Operation_IDs oID = Operation_IDs.OI_NONE; if (context.ExpressionChars[++context.Position] == '=') { switch (op) { case '>': //>= oID = Operation_IDs.OI_GREATEQUAL; strID = ">="; break; case '<': //<= oID = Operation_IDs.OI_LESSEQUAL; strID = "<="; break; case '=': //== oID = Operation_IDs.OI_EQUAL; strID = "=="; break; default: { if (context.ThrowParseException) { throw ParsingException.NewParsingException(ParseError.peInvalidOperator, context.Position, op.ToString()); } break; } } context.Position++; } else { if (context.CurrentChar == '>') { if (op == '<') //<> { strID = "<>"; oID = Operation_IDs.OI_NOT_EQUAL; context.Position++; } else { if (context.ThrowParseException) { throw ParsingException.NewParsingException(ParseError.peInvalidOperator, context.Position, op.ToString()); } } } else { switch (op) { case '>': oID = Operation_IDs.OI_GREAT; strID = ">"; break; case '<': oID = Operation_IDs.OI_LESS; strID = "<"; break; default: { if (context.ThrowParseException) { throw ParsingException.NewParsingException(ParseError.peInvalidOperator, context.Position, op.ToString()); } break; } } } } OutputID(context, oID, strID, nPos); node2 = DoAddSub(context); node = NewTreeNode(context, node1, node2, oID, nPos); node1 = node; op = context.CurrentChar; } return(node1); }
private ExpTreeNode GetFunctionNode(ParsingContext context, Operation_IDs funcID, string strID) { ExpTreeNode node = null; ExpTreeNode nodeTemp = null; List <ExpTreeNode> paramBase = new List <ExpTreeNode>(4); int nStartFunction = context.Position - strID.Length; OutputID(context, Operation_IDs.OI_USERDEFINE, strID, nStartFunction); if (context.CurrentChar == '(') //有参数 { OutputIDToSubLevel(context); OutputID(context, Operation_IDs.OI_LBRACKET, "(", context.Position); do { context.Position++; SkipSpaces(context); nodeTemp = DoExpression(context); if (nodeTemp != null) { paramBase.Add(nodeTemp); SkipSpaces(context); } else { break; } if (context.CurrentChar == ',') { OutputID(context, Operation_IDs.OI_COMMA, ",", context.Position); } }while (context.CurrentChar == ','); if (context.CurrentChar == ')') { OutputID(context, Operation_IDs.OI_RBRACKET, ")", context.Position); OutputIDToParentLevel(context); context.Position++; node = NewTreeNode(context); node.Position = nStartFunction; node.Params = paramBase; node.OperationID = funcID; if (funcID == Operation_IDs.OI_USERDEFINE) { node.FunctionName = strID; } } else { if (context.ThrowParseException) { throw ParsingException.NewParsingException(ParseError.peCharExpected, context.Position, ")"); } } SkipSpaces(context); } else //没有参数 { node = NewTreeNode(context); node.Position = nStartFunction; node.Params = paramBase; node.OperationID = funcID; if (funcID == Operation_IDs.OI_USERDEFINE) { node.FunctionName = strID; } } return(node); }
/// <summary> /// 根据语法解析完的Tree,计算出结果 /// </summary> /// <param name="tree">解析生成的二叉树</param> /// <param name="calculateUserFunction">用户自定义函数的实现</param> /// <param name="callerContext">自定义函数上下文</param> /// <returns>运算结果</returns> /// <remarks> /// 对含自定义函数的表达式进行解析后生成的二叉树,调用该函数进行运算得出结果值 /// <code source="..\Framework\TestProjects\DeluxeWorks.Library.Test\Expression\ExpressionParserTest.cs" region="parse" lang="cs" title="对解析生成的二叉树进行计算" /> /// </remarks> public static object GetTreeValue(ExpTreeNode tree, CalculateUserFunction calculateUserFunction, object callerContext) { return(GetTreeValue(tree, calculateUserFunction, callerContext, true)); }
private object VExp(ExpTreeNode node, CalculateContext calcContext) { object oValue = null; if (node != null) { try { switch (node.OperationID) { case Operation_IDs.OI_NUMBER: case Operation_IDs.OI_STRING: case Operation_IDs.OI_NEG: case Operation_IDs.OI_BOOLEAN: case Operation_IDs.OI_DATETIME: oValue = node.Value; break; case Operation_IDs.OI_ADD: oValue = AddOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_MINUS: { object p1 = VExp(node.Left, calcContext); object p2 = VExp(node.Right, calcContext); CheckOperandNull(p1, p2, node.Position); oValue = NToD(p1) - NToD(p2); } break; case Operation_IDs.OI_MUL: { object p1 = VExp(node.Left, calcContext); object p2 = VExp(node.Right, calcContext); CheckOperandNull(p1, p2, node.Position); oValue = NToD(p1) * NToD(p2); } break; case Operation_IDs.OI_DIV: { object p1 = VExp(node.Left, calcContext); object p2 = VExp(node.Right, calcContext); CheckOperandNull(p1, p2, node.Position); if (NToD(p2) == 0.0M) { throw ParsingException.NewParsingException(ParseError.peFloatOverflow, node.Position); } oValue = NToD(p1) / NToD(p2); } break; case Operation_IDs.OI_LOGICAL_OR: { oValue = (bool)VExp(node.Left, calcContext); object oRight = (bool)false; if ((bool)oValue == false) { oRight = VExp(node.Right, calcContext); } CheckOperandNull(oValue, oRight, node.Position); oValue = (bool)oValue || (bool)oRight; } break; case Operation_IDs.OI_LOGICAL_AND: { oValue = (bool)VExp(node.Left, calcContext); object oRight = (bool)true; if ((bool)oValue == true) { oRight = VExp(node.Right, calcContext); } CheckOperandNull(oValue, oRight, node.Position); oValue = (bool)oValue && (bool)oRight; } break; case Operation_IDs.OI_NOT: oValue = VExp(node.Right, calcContext); CheckOperandNull(oValue, node.Position); oValue = !(bool)oValue; break; case Operation_IDs.OI_GREAT: oValue = CompareGreatOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_GREATEQUAL: oValue = CompareGreatEqualOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_LESS: oValue = CompareLessOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_LESSEQUAL: oValue = CompareLessEqualOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_NOT_EQUAL: oValue = CompareNotEqualOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_EQUAL: oValue = CompareEqualOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_USERDEFINE: { oValue = CalculateFunction(node, node.Params, calcContext); if (oValue == null) { ParamObjectCollection funcParams = GetParams(node.Params, calcContext); oValue = CalculateFunctionWithParameters(node.FunctionName, funcParams, calcContext); if (oValue == null) { oValue = calcContext.GetUserFunctionValue(node.FunctionName, funcParams); } if (oValue == null) { oValue = CalculateExpressionDictionary(node.FunctionName, funcParams, calcContext); } } } break; default: throw ParsingException.NewParsingException( ParseError.peInvalidOperator, node.Position, EnumItemDescriptionAttribute.GetAttribute(node.OperationID).ShortName); } } catch (System.InvalidCastException) { throw ParsingException.NewParsingException(ParseError.peTypeMismatch, node.Position); } } return(oValue); }
/// <summary> /// 根据语法解析完的Tree,计算出结果 /// </summary> /// <param name="tree">语法解析树</param> /// <returns>结果返回值</returns> /// <remarks> /// 计算解析出的二叉树,得到运算结果 /// <code source="..\Framework\TestProjects\DeluxeWorks.Library.Test\Expression\ExpressionParserTest.cs" region="getreevalue" lang="cs" title="对解析生成的二叉树进行计算" /> /// </remarks> public static object GetTreeValue(ExpTreeNode tree) { return(GetTreeValue(tree, null, null, true)); }