使用AST时有什么最佳做法吗? 我有一个解析表达式AST。 ConstantExpression,BinaryExpression等。 我想用来自AST的信息填充一个GUI对话框,在这里,我有点困惑,因为我的代码变得非常混乱。
示例:
expression = "Var1 > 10 AND Var2 < 20"
我想填充两个值为10 resp的文本框。来自AST的20。 我现在正在做的是一个递归方法,它检查正确的子表达式类型(使用.Net Is-operator)并相应地执行操作,代码真的很“臭”:)
是否有任何设计模式,如访客等,使其更容易/更易读/可维护?
答案 0 :(得分:1)
使用AST的最佳做法是:
对于使用AST的认真工作,最好通过使用旨在生成和操作AST的包来完成。这些软件包通常包含许多额外的支持,例如模式匹配和/或使用源到源转换的AST重写。
以下是几个:
This example展示了如何仅使用BNF,模式和源到源转换来构建和操作AST。
答案 1 :(得分:0)
大多数编译器都使用
解决了这个问题以下是如何将表达式中出现的所有常量值(文字)收集到List
个整数中。然后,调用代码可以使用此列表中的值填充文本框。
方法覆盖
最顶层的AST类定义了一个在子类中重写的抽象方法。
class AstNode {
.. // Some stuff
public abstract void collectValues(List<Integer> ints);
}
class ConstantExpression : AstNode {
private int value;
.. // Some stuff
public override void collectValues(List<Integer> ints) { ints.Add(value); }
}
class BinaryExpression : AstNode {
private AstNode left;
private AstNode right;
.. // Some stuff
public override void collectValues(List<Integer> ints) {
left.collectValues(ints);
right.collectValues(ints);
}
}
class Identifier : AstNode {
.. // Some stuff
public override void collectValues(List<Integer> ints) {
// do nothing!
}
}
<强>访问者强>
相同的程序,但使用访问者编写。
class Visitor {
public abstract void visit(ConstantExpression e);
public abstract void visit(BinaryExpression e);
public abstract void visit(Identifier e);
}
class AstNode {
.. // Some stuff
public abstract void accept(Visitor v);
}
class ConstantExpression : AstNode {
public int value;
.. // Some stuff
public override void accept(Visitor v) { v.visit(this); }
}
class BinaryExpression : AstNode {
private AstNode left;
private AstNode right;
.. // Some stuff
public override void accept(Visitor v) {
left.accept(v);
right.accept(v);
v.visit(this);
}
}
class Identifier : AstNode {
.. // Some stuff
public override void accept(Visitor v) { v.visit(this); }
}
class ValueCollector : Visitor {
public List<Integer> ints = ...;
public void visit(ConstantExpression e) { ints.Add(e.value); }
public void visit(BinaryExpression e) { }
public void visit(Identifier e) { }
}