Exemple #1
0
        /// <summary>
        /// Constant terms are negated immediately.
        /// </summary>
        private ExpressionTreeNode <TIn> _VisitNegate <TIn>(ExpressionTreeNode <TIn> left)
        {
            // Always apply Negate to path values
            if (left is PathValueExpression <TIn> )
            {
                return new NegateExpression <TIn> {
                           Root = left
                }
            }
            ;

            if (left is ValueExpression <TIn> value && value.Value != null)
            {
                // Fold.
                var negatedValue = _Negate(value.Value);

                if (negatedValue != null)
                {
                    return(new ValueExpression <TIn> {
                        Value = negatedValue
                    });
                }
            }

            // Always apply Negate to anything other than a negatable value
            return(new NegateExpression <TIn> {
                Root = left
            });
        }
        /// <summary>
        /// Generates the contents (properties and methods) for the class that defines the parser rule.
        /// </summary>
        /// <param name="match">Current parse tree node</param>
        private void EnterRuleBody(ITextParseTreeNode match)
        {
            ruleBodyExpression = new SequenceExpression();

            output.WriteLine(" : TextProductionRule");
            output.WriteLine("{");

            WriteExcludedGlobalRules();

            WriteRuleNameProperty();

            output.WriteLine("protected override IParserRule<char> GetBody()");
            output.WriteLine("{");

            base.Enter(match);

            output.WriteLine("return");

            ruleBodyExpression.Visit(
                new CodeGenVisitor(grammarName, output));

            output.WriteLine(";");

            output.WriteLine("}");
        }
        /// <summary>
        /// Adds alternate expression (Rule1 | Rule2) to the expression tree for the current rule.
        /// </summary>
        /// <param name="match">Current parse tree node</param>
        private void EnterAlternate(ITextParseTreeNode match)
        {
            /* Alternate expressions are parsed like this:
             *
             * Rule1 | Rule2 | Rule3
             *
             * RuleName (Rule1)
             * AlternateExpression
             * -RuleName (Rule2)
             * -AlternateExpression
             * --RuleName (Rule3)
             */

            if (ruleBodyExpression is OneOfExpression)
            {
                // Already alternating, just add to children
                base.Enter(match);
            }
            else
            {
                // Start new alternate with previous expression
                var previousExpression = ruleBodyExpression.RemoveLastChild();

                var alternateExpression = new OneOfExpression();
                alternateExpression.AddChild(previousExpression);

                ruleBodyExpression.AddChild(alternateExpression);
                ruleBodyExpression = alternateExpression;

                base.Enter(match);

                ruleBodyExpression = ruleBodyExpression.Parent;
            }
        }
Exemple #4
0
        private void SetSelectedExpression(ExpressionTreeNode selectedExpression)
        {
            var comparisonNode = selectedExpression as ComparisonOperatorNode;

            if (comparisonNode != null)
            {
                var fieldLeaf = comparisonNode.Left as ExpressionTreeFieldLeaf;
                if (fieldLeaf != null)
                {
                    var foundFieldDescr =
                        FilterableArguments.FirstOrDefault(
                            prop => prop.BoundProperty.Equals(fieldLeaf.PropertyDescription));
                    if (foundFieldDescr != null)
                    {
                        var newAvailableComparisonOperators = new LocalizableEnumItemsSource();
                        newAvailableComparisonOperators.Initialize(typeof(ComparisonOperators), foundFieldDescr.AvailableOperators.Cast <object>());
                        AvailableComparisonOperators = newAvailableComparisonOperators;

                        //Set available values for expression
                        if (foundFieldDescr.HasAvailableValues)
                        {
                            var valueLeaf = comparisonNode.Right as ExpressionTreeValueLeaf;
                            if (valueLeaf != null)
                            {
                                valueLeaf.AvailableValues =
                                    _filterableCollection.GetExpressionAvailableValues(foundFieldDescr.BoundProperty);
                            }
                        }
                    }
                }

                SelectedComparisonOperator = comparisonNode.Operator;
            }
        }
        public bool TryCreateExpressionTreeNode <TIn>([NotNullWhen(true)] out ExpressionTreeNode <TIn> root, [NotNullWhen(false)] out string errorMessage)
        {
            if (Output.Count != 1)
            {
                root         = null !;
                errorMessage = "No expression to parse.";
                return(false);
            }

            if (Operators.Count > 0)
            {
                root         = null !;
                errorMessage = "Unbalanced expression.";
                return(false);
            }

            var first = Output.Pop();

            if (first == null)
            {
                root         = null !;
                errorMessage = "No expression found.";
                return(false);
            }
            var node = _Visit <TIn>(first);

            root         = _MakeHasPropertyIfNameExpression(node);
            errorMessage = null !;
            return(true);
        }
        /// <summary>
        /// Converts specified Token Stack into an expression tree.
        /// </summary>
        /// <param name="tokens">Token representation of a logical expression.</param>
        /// <returns></returns>
        public ExpressionTreeNode BuildExpressionTree(Stack <IToken> tokens)
        {
            Stack <IToken> reverseTokens = new Stack <IToken>(tokens);

            ExpressionTreeNode root = GenerateNode(reverseTokens);

            return(root);
        }
        private static void Evaluate(ExpressionTreeNode node, OperandStack operandStack, IBackingStore backingStore)
        {
            var token = node.Token;

            if (token.TokenType == TokenType.Operand)
            {
                operandStack.Push((IOperand)token);
            }
            else
            {
                var op = ((OperatorWrapper)token).WrappedOperator;
                if (op.ShortCircuit == ShortCircuitMode.LogicalAnd)
                {
                    Evaluate(node.Children[1], operandStack, backingStore);

                    var thing = OperatorActions.PeekAndResolve(operandStack, backingStore);

                    if ((bool)thing.GetValue() == false)
                    {
                        // The operator has done its work, discard it.
                        operandStack.Pop();
                        operandStack.Push(new Operand(OperandType.Bool, false));
                        return;
                    }
                    else
                    {
                        Evaluate(node.Children[0], operandStack, backingStore);
                    }
                }
                else if (op.ShortCircuit == ShortCircuitMode.LogicalOr)
                {
                    Evaluate(node.Children[1], operandStack, backingStore);

                    var thing = OperatorActions.PeekAndResolve(operandStack, backingStore);

                    if ((bool)thing.GetValue() == true)
                    {
                        // The operator has done its work, discard it.
                        operandStack.Pop();
                        operandStack.Push(new Operand(OperandType.Bool, true));
                        return;
                    }
                    else
                    {
                        Evaluate(node.Children[0], operandStack, backingStore);
                    }
                }
                else
                {
                    // TODO: Build it backwards so we can just foreach here.
                    for (int c = node.Children.Count - 1; c >= 0; c--)
                    {
                        Evaluate(node.Children[c], operandStack, backingStore);
                    }
                }
                op.DoOperation(operandStack, backingStore, token.ParserPosition);
            }
        }
        /// <summary>
        /// Adds simple expression to the expression tree for the current rule.
        /// There are some expressions that don't require any special handling
        /// and just need to be added to the expression tree at the point where
        /// they are met in the parse tree.
        /// </summary>
        /// <param name="match">Current parse tree node</param>
        private void EnterSimpleExpression <TExpression>(ITextParseTreeNode match)
            where TExpression : ExpressionTreeNode, new()
        {
            var newExpression = new TExpression();

            ruleBodyExpression.AddChild(newExpression);
            ruleBodyExpression = newExpression;

            base.Enter(match);

            ruleBodyExpression = ruleBodyExpression.Parent;
        }
Exemple #9
0
        /// <summary>Обработка очередного добавляемого в дерево узла</summary>
        /// <param name="NewNode">Новый добавляемый узел дерева выражения</param>
        protected virtual void OnNewNodeAdded([NotNull] ref ExpressionTreeNode NewNode)
        {
            ProcessNewNode(ref NewNode);

            var e = new EventArgs <ExpressionTreeNode>(NewNode);

            NewNodeAdded?.Invoke(this, e);
            if (!ReferenceEquals(e.Argument, NewNode))
            {
                NewNode = e.Argument;
            }
        }
Exemple #10
0
        public void CreateTree(ExpressionTreeNode <TEntity> node)
        {
            string logic = AND;

            node.Query = REGEX_AND.Replace(node.Query, "#", 1, 0);
            var list = node.Query.Split("#");

            if (list.Length == 1)
            {
                int endAt = 0;
                if (list[0][0] == '(')
                {
                    node.Query = list[0].Substring(1, list[0].Length - 2);
                    IsValid(node.Query, out endAt);
                }
                logic      = Regex.Match(node.Query.Substring(endAt, node.Query.Length - 1 - endAt), AND_OR).Value;
                node.Query = REGEX_AND_OR.Replace(node.Query, "#", 1, endAt);
                list       = node.Query.Split("#");
                if (list.Length == 1)
                {
                    var data = REGEX_OPERATOR.Split(node.Query);
                    var cond = new UserCondition {
                        Key = data[0], Value = data[2], Operator = data[1]
                    };
                    node.Data = GetCriterion(cond);
                    return;
                }
            }
            node.LogicalOperator = logic;
            var left = new ExpressionTreeNode <TEntity>()
            {
                Query = list[0]
            };

            node.Left = left;
            CreateTree(node.Left);
            var right = new ExpressionTreeNode <TEntity>()
            {
                Query = list[1]
            };

            node.Right = right;
            CreateTree(node.Right);
            if (node.LogicalOperator == "AND")
            {
                node.Data = new AndCriterion <TEntity>(left.Data, right.Data);
            }
            else
            {
                node.Data = new OrCriterion <TEntity>(left.Data, right.Data);
            }
        }
Exemple #11
0
        private List <int> SearchInTree(ExpressionTreeNode node, bool notCompareWithAll = false)
        {
            if (node == null)
            {
                throw new Exception("Invalid expression tree");
            }

            if (!string.IsNullOrEmpty(node.Term))
            {
                return(_index.Find(node.Term));
            }

            var result = new List <int>();

            if (node.Operation == "AND")
            {
                if (node.Child2.Operation == "NOT")
                {
                    return(SearchInTree(node.Child1).Except(SearchInTree(node.Child2, true)).ToList());
                }

                return(SearchInTree(node.Child1).Intersect(SearchInTree(node.Child2)).ToList());
            }

            if (node.Operation == "OR")
            {
                return(SearchInTree(node.Child1).Concat(SearchInTree(node.Child2)).ToList());
            }

            if (node.Operation == "NOT")
            {
                if (notCompareWithAll)
                {
                    return(SearchInTree(node.Child1).ToList());
                }

                return(_dataSource.GetAllIds().Except(SearchInTree(node.Child1)).ToList());
            }

            if (node.Operation == "ALL")
            {
                return(_dataSource.GetAllIds());
            }

            if (node.Operation == "ZERO")
            {
                return(new List <int>());
            }

            throw new Exception("Invalid expression tree");
        }
        public void And_ExpressionTree()
        {
            // Arrange
            string         expression    = "1 && 2";
            Stack <IToken> postfixTokens = _postFixer.ConvertToStack(expression);

            // Act
            ExpressionTreeNode root = _expressionTreeBuilder.BuildExpressionTree(postfixTokens);

            // Assert
            ExpressionTreeNode expected = new ExpressionTreeNode(Operators.And, 1, 2);

            root.Should().BeEquivalentTo(expected);
        }
Exemple #13
0
 //query string interpretor
 public async Task <IQueryable <TEntity> > QueryByConditions(string queryString, IQueryable <TEntity> query)
 {
     queryString = queryString.Replace(" ", "");
     //var query = GetQueryable();
     if (!string.IsNullOrEmpty(queryString))
     {
         var head = new ExpressionTreeNode <TEntity> {
             Query = queryString
         };
         CreateTree(head);
         query = head.Data.HandleQueryable(query);
     }
     return(query);
 }
        public void OrAndNot_ExpressionTree()
        {
            // Arrange
            string         expression    = "1 || 2 && !3";
            Stack <IToken> postfixTokens = _postFixer.ConvertToStack(expression);

            // Act
            ExpressionTreeNode root = _expressionTreeBuilder.BuildExpressionTree(postfixTokens);

            // Assert
            ExpressionTreeNode expected = new ExpressionTreeNode(Operators.Or, 1,
                                                                 new ExpressionTreeNode(Operators.And, 2, new ExpressionTreeNode(Operators.Not, 3)));

            root.Should().BeEquivalentTo(expected);
        }
Exemple #15
0
        public string CreateExpressionTreeNode <TIn>(out ExpressionTreeNode <TIn> root)
        {
            root = null;
            if (Output.Count != 1)
            {
                return("No expression to parse.");
            }
            if (Operators.Count > 0)
            {
                return("Unbalanced expression.");
            }

            root = _MakeHasPropertyIfNameExpression(_Visit <TIn>(Output.Pop()));
            return(null);
        }
Exemple #16
0
        /// <summary>
        /// Converts <paramref name="left"/> and <paramref name="right"/> to <see cref="HasPropertyExpression{T}"/>
        /// nodes if either are <see cref="NameExpression{T}"/> nodes being used in boolean contexts. Otherwise,
        /// it leaves the nodes as-is.
        /// </summary>
        /// <typeparam name="TIn">Type of the resulting JSON expression.</typeparam>
        /// <param name="op">Operator applied to <paramref name="left"/> and <paramref name="right"/>.</param>
        /// <param name="left">Left hand side of <paramref name="op"/>.</param>
        /// <param name="right">Right hand side of <paramref name="op"/>.</param>
        private void _CheckAndReplaceIfHasPropertyNeeded <TIn>(JsonPathOperator op, ref ExpressionTreeNode <TIn> left, ref ExpressionTreeNode <TIn> right)
        {
            if (!(left is NameExpression <TIn>) && !(right is NameExpression <TIn>))
            {
                return;
            }

            var namedLeft  = left as NameExpression <TIn>;
            var namedRight = right as NameExpression <TIn>;

            switch (op)
            {
            case JsonPathOperator.And:
            case JsonPathOperator.Or:
            case JsonPathOperator.Not:
                // Explicit boolean context, convert one or both sides
                // as necessary.
                left  = _MakeHasPropertyIfNameExpression(left);
                right = _MakeHasPropertyIfNameExpression(right);
                break;

            case JsonPathOperator.Equal:
            case JsonPathOperator.NotEqual:
                // Convert only if one side is a named expression and the other
                // is a boolean expression tree, but not if both are named
                // expressions.
                //
                // Why? If we've got == or != with two named expressions
                // we're comparing their values and should not convert both
                // to HasPropertyExpression's.
                if (namedLeft == null ^ namedRight == null)
                {
                    var isBoolean = namedLeft == null
                                                                        ? _IsBooleanResult(left)
                                                                        : _IsBooleanResult(right);

                    if (isBoolean)
                    {
                        // We've evaluated that the context of our Equal/NotEqual
                        // operands is boolean. Convert whichever side is a
                        // named expression to a HasProperty expression.
                        left  = _MakeHasPropertyIfNameExpression(left);
                        right = _MakeHasPropertyIfNameExpression(right);
                    }
                }
                break;
            }
        }
Exemple #17
0
        private bool EvaluateNode <T>(ExpressionTreeNode node, T target, IEnumerable <IValidationCondition> validationConditions)
        {
            if (!node.Token.IsOperatorToken())
            {
                IIdentifier identifier = (IIdentifier)node.Token;

                IValidationCondition validationCondition = validationConditions.FirstOrDefault(r => r.ValidationConditionID == identifier.ID);

                return(EvaluateValidationCondition(target, validationCondition));
            }
            else
            {
                IOperator op = (IOperator)node.Token;

                return(op.Evaluate(() => EvaluateNode(node.Left, target, validationConditions),
                                   () => EvaluateNode(node.Right, target, validationConditions)));
            }
        }
Exemple #18
0
        static void Main(string[] args)
        {
            var p1   = Expression.Parameter(typeof(int), "num");
            var lam1 = Expression.Lambda <Func <int, bool> >(
                Expression.LessThan(
                    p1, Expression.Constant(5)
                    ),
                p1
                );

            Console.WriteLine(lam1.Compile()(3));

            //Expression<Func<int, bool>> lambda = num => num < 5;
            Expression <Func <int?, bool> > lambda = num => (num ?? 3) < 5;

            ExperimentalDump(lambda);

            var node = new ExpressionTreeNode(lambda);

            Dump(node);
        }
Exemple #19
0
        public List <ValidationError> Validate <T>(T target, IEnumerable <IValidation> validations, IEnumerable <IValidationCondition> validationConditions)
        {
            List <ValidationError> errors = new List <ValidationError>();

            // Evaluate validation conditions
            foreach (var validation in validations)
            {
                Stack <IToken>     postfixTokens = _postfixConverter.ConvertToStack(validation.Expression);
                ExpressionTreeNode root          = _treeBuilder.BuildExpressionTree(postfixTokens);

                if (EvaluateNode(root, target, validationConditions))
                {
                    errors.Add(new ValidationError()
                    {
                        ErrorMessage = validation.ErrorMessage,
                        ErrorCode    = validation.ErrorCode
                    });
                }
            }

            return(errors);
        }
        /// <summary>
        /// Iterates over specified tokens to recursively build an expression tree node.
        /// </summary>
        /// <param name="tokens">Token representation of a logical expression.</param>
        /// <returns></returns>
        private ExpressionTreeNode GenerateNode(Stack <IToken> tokens)
        {
            ExpressionTreeNode treeNode     = new ExpressionTreeNode();
            IToken             currentToken = tokens.Pop();

            if (currentToken.IsOperatorToken())
            {
                treeNode.Token = currentToken;

                if (currentToken.GetType() != typeof(NotOperator))
                {
                    treeNode.Right = GenerateNode(tokens);
                }

                treeNode.Left = GenerateNode(tokens);
            }
            else
            {
                treeNode.Token = currentToken;
            }

            return(treeNode);
        }
        /// <summary>
        /// Generates rule class stub.
        /// </summary>
        /// <param name="match">Current parse tree node</param>
        private void EnterRule(ITextParseTreeNode match)
        {
            output.Write("public partial class ");

            ruleBodyExpression  = null;
            excludedGlobalRules = null;

            base.Enter(match);

            if (ruleBodyExpression == null)
            {
                // Rules without a body treated as terminals.
                // There are basically two types of rules - production and terminal. All productions
                // can be expressed through the grammar. If there was no body defined, then most likely
                // it was meant to be a light-weight terminal rule.
                output.WriteLine(" : TerminalParserRule<char>");
                output.WriteLine("{");

                WriteRuleNameProperty();
            }

            output.WriteLine("}");
        }
Exemple #22
0
        private static bool _IsBooleanResult <TIn>(ExpressionTreeNode <TIn> node)
        {
            if (node == null)
            {
                return(false);
            }

            // Boolean values are a boolean result.
            if (node is ValueExpression <TIn> value && value.Value is bool)
            {
                return(true);
            }

            // NotExpressions are always a boolean result.
            if (node is NotExpression <TIn> )
            {
                return(true);
            }

            if (node is ExpressionTreeBranch <TIn> branch)
            {
                // Any subexpression returning a boolean
                // value is obviously a boolean result.
                return(branch is AndExpression <TIn> ||
                       branch is OrExpression <TIn> ||
                       branch is IsEqualExpression <TIn> ||
                       branch is IsNotEqualExpression <TIn> ||
                       branch is IsGreaterThanEqualExpression <TIn> ||
                       branch is IsGreaterThanExpression <TIn> ||
                       branch is IsLessThanEqualExpression <TIn> ||
                       branch is IsLessThanExpression <TIn>);
            }

            // All other expressions do not have boolean results.
            return(false);
        }
Exemple #23
0
 /// <summary>Обработка нового узла дерева выражения</summary>
 /// <param name="NewNode">Новый добавляемый узел</param>
 protected virtual void ProcessNewNode([NotNull] ref ExpressionTreeNode NewNode)
 {
     switch (NewNode)
     {
     case CharNode char_node:
     {
         switch (char_node.Value)
         {
         case '.' when NewNode.Parent is CharNode {
                 Value: '.'
         } :
             var value_node = NewNode[n => n.Parent].Last(n => !(n is OperatorNode) || n.Left is null);
             (NewNode["./."] ?? throw new InvalidOperationException("NewNode/. is null")).Right = null;
             var parent        = value_node.Parent;
             var interval_node = new IntervalNode(value_node);
             if (parent != null)
             {
                 parent.Right = interval_node;
             }
             NewNode = interval_node;
             break;
         }
         break;
     }
Exemple #24
0
        private static ExpressionTreeNode <TIn> _MakeHasPropertyIfNameExpression <TIn>(ExpressionTreeNode <TIn> node)
        {
            if (node is NameExpression <TIn> named)
            {
                return(new HasPropertyExpression <TIn>
                {
                    Path = named.Path,
                    IsLocal = named.IsLocal,
                    Name = named.Name
                });
            }

            return(node);
        }
Exemple #25
0
 static string Convert(ExpressionTreeNode n) => n?.ToString() ?? string.Empty;
Exemple #26
0
 public ExpressionTreeNode(char op)
 {
     this.val   = new ExpressionOperator(op);
     this.left  = null;
     this.right = null;
 }
 public void SetExpression(string key, string value, Calculator calc)
 {
     m_key = key;
     m_expression = value;
     if (calc != null)
     {
         m_tree = ExpressionTreeNode.Parse(m_expression, calc);
     }
     m_bufferSet = false;
     //Find variable on forehand to make calculation faster.
     int propIndex = m_key.LastIndexOf(Calculator.PROPERTY_CHAR);
     string varName;
     if (propIndex != -1)
     {
         varName = m_key.Substring(0, propIndex);
     }
     else
     {
         varName = m_key;
     }
     if (calc != null)
     {
         m_variable = calc.Variable(varName);
         if (m_variable == null)
             throw new System.Exception("Invalid variable key: " + key);
     }
     m_propName = m_key.Substring(propIndex + 1);
 }