使用表达式AST

时间:2010-04-12 14:56:54

标签: design-patterns expression abstract-syntax-tree

使用AST时有什么最佳做法吗? 我有一个解析表达式AST。 ConstantExpression,BinaryExpression等。 我想用来自AST的信息填充一个GUI对话框,在这里,我有点困惑,因为我的代码变得非常混乱。

示例:

expression = "Var1 > 10 AND Var2 < 20"

我想填充两个值为10 resp的文本框。来自AST的20。 我现在正在做的是一个递归方法,它检查正确的子表达式类型(使用.Net Is-operator)并相应地执行操作,代码真的很“臭”:)

是否有任何设计模式,如访客等,使其更容易/更易读/可维护?

2 个答案:

答案 0 :(得分:1)

使用AST的最佳做法是:

  • 获取好的解析器,以帮助您从某种语法描述构建AST
  • 获取一个好的库来帮助您走AST来收集/修改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) { }
}