1

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

例子:

expression = "Var1 > 10 AND Var2 < 20"

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

是否有任何设计模式,如访问者等,使这更容易/更具可读性/可维护性?

4

2 回答 2

1

使用 AST 的最佳实践是:

  • 获得好的解析器来帮助您从某种语法描述中构建 AST
  • 获取一个好的库来帮助你走 AST 来收集/修改 AST

对于 AST 的严肃工作,最好使用旨在生成和操作 AST 的包来完成。通常,此类包包含许多额外的支持,例如模式匹配和/或使用源到源转换的 AST 重写。

这里有几个:

此示例展示了如何仅使用 BNF、模式和源到源转换来构建和操作 AST。

于 2011-07-06T08:45:47.953 回答
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) { }
}
于 2010-04-12T15:04:23.520 回答