Ste*_*idi 8 .net translation expression-trees parentheses inorder
我正在努力将表达式树转换为类似于中缀表示法的格式; 我不是在评估树或执行它的操作.树包含逻辑和关系操作,我想在翻译期间以智能方式发出括号.
为了说明,请考虑以下设计表达:
a < x & (a < y | a == c) & a != d
Run Code Online (Sandbox Code Playgroud)
如果我按顺序遍历此表达式生成的表达式树,那么我将打印出以下表达式,这是不正确的.
a < x & a < y | a == c & a != d
// equivalent to (a < x & a < y) | (a == c & a != d)
Run Code Online (Sandbox Code Playgroud)
或者,我可以再次执行有序遍历,但在处理二进制表达式之前和之后发出括号.这将产生以下正确的表达式,但有几个冗余的括号.
(((a < x) & ((a < y) | (a == c))) & (a != d))
Run Code Online (Sandbox Code Playgroud)
是否存在表达式树遍历算法,该算法可生成最佳括号表达式?
作为参考,这里是ExpressionVisitor我用来检查树的片段.
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.
}
Run Code Online (Sandbox Code Playgroud)
我接受了辩证法的答案,因为它为实现该算法提供了良好的基础。这个答案的唯一问题是,它要求该VisitBinary()方法知道其父调用者作为方法参数,这是不可行的,因为这些方法是基方法的重载。
我提供以下解决方案,它使用类似的算法,但应用检查以在表达式树的子节点的父调用中发出括号。
class MyVisitor : ExpressionVisitor
{
private readonly IComparer<ExpressionType> 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.
}
Run Code Online (Sandbox Code Playgroud)
优先级比较函数以 实现,它应用 C#运算符优先级IComparer<ExpressionType>规则。
class OperatorPrecedenceComparer : Comparer<ExpressionType>
{
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 * }
}
}
Run Code Online (Sandbox Code Playgroud)
尝试这样的操作,假设node.NodeType是 类型NodeType,并且该函数Precedes存在,并且如果第一个参数在第二个参数之前则返回 true。
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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1603 次 |
| 最近记录: |