Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 使用表达式AST_Design Patterns_Expression_Abstract Syntax Tree - Fatal编程技术网

Design patterns 使用表达式AST

Design patterns 使用表达式AST,design-patterns,expression,abstract-syntax-tree,Design Patterns,Expression,Abstract Syntax Tree,使用AST时是否有最佳实践? 我有一个解析表达式AST。恒常表达式、二进制表达式等。 我想用AST中的信息填充一个GUI对话框,在这里我有点困惑,因为我的代码变得非常混乱 例如: expression = "Var1 > 10 AND Var2 < 20" expression=“Var1>10和Var2

使用AST时是否有最佳实践? 我有一个解析表达式AST。恒常表达式、二进制表达式等。 我想用AST中的信息填充一个GUI对话框,在这里我有点困惑,因为我的代码变得非常混乱

例如:

expression = "Var1 > 10 AND Var2 < 20"
expression=“Var1>10和Var2<20”
我想用值10 resp填充两个文本框。来自AST的20个。 我现在做的是一个递归方法,它检查正确的子表达式类型(使用.Net is运算符),并相应地执行操作,代码真的很“难闻”:


是否有任何设计模式,比如Visitor之类的模式,使它更容易/更可读/更易于维护?

大多数编译器通过使用

  • 方法重写
  • 访客
下面是如何将表达式中出现的所有常量值(文字)收集到整数的
列表中。然后,调用代码可以使用此列表中的值填充文本框

方法重写

最顶层的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!
  }
}
类节点{
../一些东西
公共抽象值(列表整数);
}
类ConstantPression:AstNode{
私有int值;
../一些东西
公共覆盖无效集合值(列表整数){ints.Add(值);}
}
类二进制表达式:AstNode{
私有节点左;
私有节点权;
../一些东西
公共覆盖无效集合值(列表整数){
左。收集值(整数);
对。收集值(整数);
}
}
类标识符:AstNode{
../一些东西
公共覆盖无效集合值(列表整数){
//什么都不要做!
}
}
访客

相同的程序,但使用访问者编写

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) { }
}
类访问者{
公开摘要无效访问(ConstantExpression e);
公开摘要无效访问(二进制表达);
公开摘要无效访问(标识符e);
}
类AstNode{
../一些东西
公开摘要无效接受(访客v);
}
类ConstantPression:AstNode{
公共价值观;
../一些东西
公共覆盖无效接受(访问者){v.visit(this);}
}
类二进制表达式:AstNode{
私有节点左;
私有节点权;
../一些东西
公共覆盖无效接受(访客v){
左。接受(v);
对,接受(五),;
v、 访问(本);
}
}
类标识符:AstNode{
../一些东西
公共覆盖无效接受(访问者){v.visit(this);}
}
类ValueCollector:访问者{
公共列表整数=。。。;
公共无效访问(ConstantExpression e){ints.Add(e.value);}
公共无效访问(二进制表达式){}
公共无效访问(标识符e){}
}

大多数编译器通过使用

  • 方法重写
  • 访客
下面是如何将表达式中出现的所有常量值(文字)收集到整数的
列表中。然后,调用代码可以使用此列表中的值填充文本框

方法重写

最顶层的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!
  }
}
类节点{
../一些东西
公共抽象值(列表整数);
}
类ConstantPression:AstNode{
私有int值;
../一些东西
公共覆盖无效集合值(列表整数){ints.Add(值);}
}
类二进制表达式:AstNode{
私有节点左;
私有节点权;
../一些东西
公共覆盖无效集合值(列表整数){
左。收集值(整数);
对。收集值(整数);
}
}
类标识符:AstNode{
../一些东西
公共覆盖无效集合值(列表整数){
//什么都不要做!
}
}
访客

相同的程序,但使用访问者编写

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) { }
}
类访问者{
公开摘要无效访问(ConstantExpression e);
公开摘要无效访问(二进制表达);
公开摘要无效访问(标识符e);
}
类AstNode{
../一些东西
公开摘要无效接受(访客v);
}
类ConstantPression:AstNode{
公共价值观;
../一些东西
公共覆盖无效接受(访问者){v.visit(this);}
}
类二进制表达式:AstNode{
私有节点左;
私有节点权;
../一些东西
公共覆盖无效接受(访客v){
左。接受(v);
对,接受(五),;
v、 访问(本);
}
}
类标识符:AstNode{
../一些东西
公共覆盖无效接受(访问者){v.visit(this);}
}
类ValueCollector:访问者{
公共列表整数=。。。;
公共无效访问(ConstantExpression e){ints.Add(e.value);}
公共无效访问(二进制表达式){}
公共无效访问(标识符e){}
}

使用AST的最佳实践包括:

  • 获取好的解析器来帮助您从某种语法描述构建AST
  • 获取一个好的库来帮助您浏览AST以收集/修改AST
对于使用AST的严肃工作,最好使用设计用于生成和操作AST的包。通常,这样的包包括很多额外的支持,例如模式匹配和/或使用源到源转换的AST重写

以下是几点:

  • (我的产品)

演示如何仅使用BNF、模式和源代码到源代码转换来构建和操作AST。

使用AST的最佳实践包括:

  • 获取好的解析器来帮助您从某种语法描述构建AST
  • 获取一个好的库来帮助您浏览AST以收集/修改AST
对于使用AST的严肃工作,最好使用设计用于生成和操作AST的包。这类软件包通常包括很多额外的支持,例如pa