private static void CheckOperandNull(object p1, object p2, int nPos) { if (p1 == null || p2 == null) { throw ParsingException.NewParsingException(ParseError.peNeedOperand, nPos); } }
/// <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 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> /// <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); }
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 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); } }
/// <summary> /// 检查参数的类型 /// </summary> /// <typeparam name="T">参数是否是指定类型,或者是它的派生类</typeparam> /// <remarks> /// 检查参数类型是否为指定类型 /// <code source="..\Framework\TestProjects\DeluxeWorks.Library.Test\Expression\ExpressionParserTest.cs" region="UserDefinedFucntions" lang="cs" /> /// </remarks> public void CheckParameterType <T>() { if (this.Value != null) { System.Type expectedType = typeof(T); //bool temp = !(this.Value.GetType().IsSubclassOf(expectedType) || this.Value.GetType() == expectedType); if (false == (this.Value.GetType().IsSubclassOf(expectedType) || this.Value.GetType() == expectedType)) { throw ParsingException.NewParsingException(ParseError.InvalidParameterType, 0, expectedType.Name, this.Value.GetType().Name); } } }
/// <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); }
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); }
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> /// 逻辑比较运算 /// </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); }