How do I infer the usage of parentheses when translating an expression tree?

后端 未结 2 1126
我寻月下人不归
我寻月下人不归 2021-02-15 12:25

I am working on translating an expression tree to a format that resembles infix notation; I am not evaluating the tree or executing its operations. The tree contains both logic

2条回答
  •  南笙
    南笙 (楼主)
    2021-02-15 12:53

    I've accepted the answer of Dialecticus as it provides a good basis for implementing this algorithm. The only issue with this answer is that it requires that the VisitBinary() method know about its parent caller as a method argument, which is not feasible since these methods are overloads of a base method.

    I provide the following solution, which uses a similar algorithm, but applies the check to emit parentheses in the parent call for the child nodes of the expression tree.

    class MyVisitor : ExpressionVisitor
    {
        private readonly IComparer m_comparer = new OperatorPrecedenceComparer();
    
        protected override Expression VisitBinary(BinaryExpression node)
        {
            Visit(node, node.Left);
            Console.Write(node.NodeType.ToString());
            Visit(node, node.Right);
    
            return node;
        }
    
        private void Visit(Expression parent, Expression child)
        {
            if (m_comparer.Compare(child.NodeType, parent.NodeType) < 0)
            {
                Console.Write("(");
                base.Visit(child);
                Console.Write(")");
            }
            else
            {
                base.Visit(child);
            }
        }
    
        // VisitConstant, VisitMember, and VisitParameter omitted for brevity.
    }
    

    The precedence comparison function is implemented as an IComparer, which applies the C# rules of operator precedence.

    class OperatorPrecedenceComparer : Comparer
    {
        public override int Compare(ExpressionType x, ExpressionType y)
        {
            return Precedence(x).CompareTo(Precedence(y));
        }
    
        private int Precedence(ExpressionType expressionType)
        {
            switch(expressionType) { /* group expressions and return precedence ordinal * }
        }
    }
    

提交回复
热议问题