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 logical and relational operations, and I would like to emit parentheses in an intelligent manner during the translation.
To illustrate, consider the following contrived expression:
a < x & (a < y | a == c) & a != d
If I walk the expression tree produced by this expression in-order, then I will print out the following expression, which is incorrect.
a < x & a < y | a == c & a != d
// equivalent to (a < x & a < y) | (a == c & a != d)
Alternatively, I can again perform an in-order traversal but emit parentheses before and after processing a binary expression. This will produce the following correct expression, but with several redundant parentheses.
(((a < x) & ((a < y) | (a == c))) & (a != d))
Is there an expression tree traversal algorithm that produces optimally-parenthesized expressions?
For reference, here is a snippet of the ExpressionVisitor
I am using to inspect the tree.
class MyVisitor : ExpressionVisitor
{
protected override Expression VisitBinary(BinaryExpression node)
{
Console.Write("(");
Visit(node.Left);
Console.WriteLine(node.NodeType.ToString());
Visit(node.Right);
Console.Write(")");
return node;
}
// VisitConstant, VisitMember, and VisitParameter omitted for brevity.
}
Try something like this, assuming that node.NodeType
is of type NodeType
, and that function Precedes
exists and returns true if first parameter precedes the second.
protected override Expression Visit(BinaryExpression node, NodeType parentType)
{
bool useParenthesis = Precedes(parentType, node.NodeType);
if (useParenthesis)
Console.Write("(");
Visit(node.Left, node.NodeType);
Console.WriteLine(node.NodeType.ToString());
Visit(node.Right, node.NodeType);
if (useParenthesis)
Console.Write(")");
return node;
}