Beispiel #1
0
        public static ExpressionNode Parse(String expression)
        {
            if (String.IsNullOrEmpty(expression))
            {
                return(new OperatorNode {
                    Value = double.NaN
                });
            }

            expression = expression.Trim();

            if (ExpressionHelper.IsNumber(expression))
            {
                var node = new ExpressionNode
                {
                    Value     = ExpressionHelper.GetNumber(expression),
                    ValueType = ValueTypes.Number,
                };

                return(node);
            }

            if (ExpressionHelper.IsString(expression))
            {
                var node = new StringValueNode
                {
                    Value     = ExpressionHelper.GetString(expression),
                    Quota     = ExpressionHelper.GetQuota(expression),
                    ValueType = ValueTypes.String,
                };

                return(node);
            }

            if (ExpressionHelper.IsDateTime(expression))
            {
                var node = new ExpressionNode
                {
                    Value     = ExpressionHelper.GetDateTime(expression),
                    ValueType = ValueTypes.DateTime,
                };

                return(node);
            }

            int parentheses = 0;

            var leftExp  = String.Empty;
            var rightExp = String.Empty;

            var currOperator = String.Empty;
            var currPriority = -1;

            bool singleQuoteOpen = false;
            bool doubleQuoteOpen = false;

            for (int i = 0; i < expression.Length; i++)
            {
                var @char = expression[i];
                if (@char == '\'' && !doubleQuoteOpen)
                {
                    singleQuoteOpen = !singleQuoteOpen;
                }

                if (@char == '"' && !singleQuoteOpen)
                {
                    doubleQuoteOpen = !doubleQuoteOpen;
                }

                if (singleQuoteOpen || doubleQuoteOpen)
                {
                    continue;
                }

                if (@char == '(')
                {
                    parentheses++;
                }
                else if (@char == ')')
                {
                    parentheses--;
                }
                else if (parentheses == 0)
                {
                    if (reservedSymbols.Contains(@char) && i != 0)
                    {
                        int operatorStart = i;

                        while (reservedSymbols.Contains(@char))
                        {
                            @char = expression[++i];
                        }

                        int operatorEnd = i--;

                        var @operator = expression.Substring(operatorStart, operatorEnd - operatorStart).Trim();

                        int priority;
                        if (!operators.TryGetValue(@operator, out priority))
                        {
                            throw new Exception(String.Format("Unknown operator \"{0}\"", @operator));
                        }

                        if (currPriority < priority)
                        {
                            currOperator = @operator;
                            currPriority = priority;

                            leftExp  = expression.Substring(0, operatorStart).Trim();
                            rightExp = expression.Substring(operatorEnd).Trim();
                        }
                    }
                }
            }

            if (parentheses > 0)
            {
                throw new Exception(String.Format("Missing ) in \"{0}\"", expression));
            }

            if (parentheses < 0)
            {
                throw new Exception(String.Format("Too many )s in \"{0}\"", expression));
            }

            if (expression.StartsWith("(") && expression.EndsWith(")"))
            {
                var firstClosingBracketIndex = expression.IndexOf(")", StringComparison.OrdinalIgnoreCase);
                var nextOpeningBracketIndex  = expression.IndexOf("(", 1, StringComparison.OrdinalIgnoreCase);

                if (nextOpeningBracketIndex < firstClosingBracketIndex)
                {
                    var subNode = Parse(expression.Substring(1, expression.Length - 2));
                    return(subNode);
                }
            }

            if (ExpressionHelper.IsEmptyOrSpace(currOperator))
            {
                var actionName = String.Empty;
                var innerExp   = String.Empty;

                for (int i = 0; i < expression.Length; i++)
                {
                    if (!reservedSymbols.Contains(expression[i]))
                    {
                        innerExp = expression.Substring(i);
                        break;
                    }

                    actionName += expression[i];
                }

                if (!String.IsNullOrEmpty(actionName) &&
                    actionName != "-" &&
                    actionName != "--" &&
                    actionName != "+" &&
                    actionName != "++" &&
                    actionName != "!")
                {
                    throw new Exception();
                }

                var openingBracketIndex = expression.IndexOf("(", StringComparison.OrdinalIgnoreCase);
                if (openingBracketIndex > 0 && expression.EndsWith(")"))
                {
                    if (operators.ContainsKey(actionName))
                    {
                        var subNode = new OperatorNode
                        {
                            Action     = actionName,
                            ActionType = ActionTypes.Operator,

                            Right = Parse(innerExp)
                        };

                        return(subNode);
                    }

                    actionName = expression.Substring(0, openingBracketIndex);
                    innerExp   = expression.Substring(openingBracketIndex + 1, innerExp.Length - openingBracketIndex - 2);

                    var funcNode = new FunctionNode
                    {
                        Action     = actionName,
                        ActionType = ActionTypes.Function,
                    };

                    if (!ExpressionHelper.IsEmptyOrSpace(innerExp))
                    {
                        var paramsArr = SplitParams(innerExp);
                        foreach (var paramExp in paramsArr)
                        {
                            if (ExpressionHelper.IsEmptyOrSpace(paramExp))
                            {
                                var node = new ExpressionNode();
                                funcNode.Params.Add(node);
                            }
                            else
                            {
                                var node = Parse(paramExp);
                                funcNode.Params.Add(node);
                            }
                        }
                    }

                    return(funcNode);
                }

                var varNode = new ExpressionNode
                {
                    Action    = innerExp,
                    ValueType = ValueTypes.Variable,
                };

                if (String.IsNullOrEmpty(actionName))
                {
                    return(varNode);
                }

                var actNode = new OperatorNode
                {
                    Action     = actionName,
                    ActionType = ActionTypes.Operator,
                    Right      = varNode,
                };

                return(actNode);
            }

            var operNode = new OperatorNode
            {
                Action     = currOperator,
                ActionType = ActionTypes.Operator,

                Left  = Parse(leftExp),
                Right = Parse(rightExp)
            };

            return(operNode);
        }
Beispiel #2
0
 public static Object Eval(ExpressionNode node, Func<String, Object> varResolver)
 {
     var advResolver = new AdvancedDataResolver(varResolver);
     return Eval(node, advResolver);
 }
Beispiel #3
0
        public static Object Eval(ExpressionNode node, IDataResolver dataResolver)
        {
            var operatorNode = (OperatorNode)node;

            if (String.Equals(node.Action, "||"))
            {
                var leftFlag = Convert.ToBoolean(ExpressionEvaluator.Eval(operatorNode.Left, dataResolver));
                if (leftFlag)
                {
                    return(true);
                }

                return(Convert.ToBoolean(ExpressionEvaluator.Eval(operatorNode.Right, dataResolver)));
            }

            if (String.Equals(node.Action, "&&"))
            {
                var leftFlag = Convert.ToBoolean(ExpressionEvaluator.Eval(operatorNode.Left, dataResolver));
                if (!leftFlag)
                {
                    return(false);
                }

                return(Convert.ToBoolean(ExpressionEvaluator.Eval(operatorNode.Right, dataResolver)));
            }

            var leftNode  = operatorNode.Left;
            var rightNode = operatorNode.Right;

            var leftValue  = ExpressionEvaluator.Eval(leftNode, dataResolver);
            var rightValue = ExpressionEvaluator.Eval(rightNode, dataResolver);

            switch (node.Action.ToLower())
            {
            case "!":
                return(!Convert.ToBoolean(rightValue));

            case "+":
            {
                if (leftNode == null)
                {
                    return(+ExpressionHelper.GetNumber(rightValue));
                }

                if (ExpressionHelper.IsDateTimeNode(leftNode, leftValue) || ExpressionHelper.IsDateTimeNode(rightNode, rightValue))
                {
                    var leftDate  = ExpressionHelper.GetDateTime(leftValue);
                    var rightDate = ExpressionHelper.GetDateTime(rightValue);

                    return(leftDate.AddTicks(rightDate.Ticks));
                }

                return(ExpressionHelper.GetNumber(leftValue) + ExpressionHelper.GetNumber(rightValue));
            }

            case "++":
                return(ExpressionHelper.GetNumber(rightValue) + 1D);

            case "-":
            {
                if (leftNode == null)
                {
                    return(-ExpressionHelper.GetNumber(rightValue));
                }

                if (ExpressionHelper.IsDateTimeNode(leftNode, leftValue) || ExpressionHelper.IsDateTimeNode(rightNode, rightValue))
                {
                    var leftDate  = ExpressionHelper.GetDateTime(leftValue);
                    var rightDate = ExpressionHelper.GetDateTime(rightValue);
                    var ticksDiff = Math.Abs(leftDate.Ticks - rightDate.Ticks);

                    return(new DateTime(ticksDiff));
                }

                return(ExpressionHelper.GetNumber(leftValue) - ExpressionHelper.GetNumber(rightValue));
            }

            case "--":
                return(ExpressionHelper.GetNumber(rightValue) - 1D);

            case "=":
            {
                var name = leftNode.Action;
                dataResolver.SetValue(name, rightValue);

                return(rightValue);
            }

            case "==":
                return(ExpressionHelper.Compare(leftNode, leftValue, rightNode, rightValue) == 0);

            case "!=":
            case "<>":
                return(ExpressionHelper.Compare(leftNode, leftValue, rightNode, rightValue) != 0);

            case "<=":
                return(ExpressionHelper.Compare(leftNode, leftValue, rightNode, rightValue) <= 0);

            case ">=":
                return(ExpressionHelper.Compare(leftNode, leftValue, rightNode, rightValue) >= 0);

            case "&&":
                return(Convert.ToBoolean(leftValue) && Convert.ToBoolean(rightValue));

            case "||":
                return(Convert.ToBoolean(leftValue) || Convert.ToBoolean(rightValue));

            case "^":
            {
                var a = ExpressionHelper.GetNumber(leftValue);
                var b = ExpressionHelper.GetNumber(rightValue);

                return(Math.Pow(a, b));
            }

            case "&":
                return(String.Concat(leftValue, rightValue));

            case "|":
                return(ExpressionHelper.GetNumber(leftValue) % ExpressionHelper.GetNumber(rightValue));

            case "%":
                return(ExpressionHelper.GetNumber(leftValue) / 100D * ExpressionHelper.GetNumber(rightValue));

            case "*":
                return(ExpressionHelper.GetNumber(leftValue) * ExpressionHelper.GetNumber(rightValue));

            case "/":
            case "\\":
                return(ExpressionHelper.GetNumber(leftValue) / ExpressionHelper.GetNumber(rightValue));

            case "<":
                return(ExpressionHelper.Compare(leftNode, leftValue, rightNode, rightValue) < 0);

            case ">":
                return(ExpressionHelper.Compare(leftNode, leftValue, rightNode, rightValue) > 0);
            }

            var message = $"Unknown operator '{node.Action}'";

            throw new Exception(message);
        }
Beispiel #4
0
 public static Object Eval(ExpressionNode node)
 {
     return Eval(node, new DefaultDataResolver());
 }