Работа с выражениями ASTs - PullRequest
       6

Работа с выражениями ASTs

1 голос
/ 12 апреля 2010

Есть ли лучшие практики при работе с AST? У меня есть разобранное выражение АСТ. ConstantExpression, BinaryExpression и т. Д. Я хочу заполнить GUI-диалог информацией из AST, и именно здесь я немного запутался, потому что мой код стал довольно грязным.

Пример:

expression = "Var1 > 10 AND Var2 < 20"

Я хочу заполнить два текстовых поля значением 10 соответственно. 20 от АСТ. Сейчас я делаю рекурсивный метод, который проверяет правильные дочерние типы выражений (с .Net Is-оператором) и действует соответствующим образом, а код действительно "вонючий":)

Существует ли какой-либо шаблон проектирования, например Visitor или тому подобное, который делает его несколько легче / более читаемым / поддерживаемым?

Ответы [ 2 ]

1 голос
/ 06 июля 2011

Рекомендации по работе с AST:

  • Получите хорошие парсеры, которые помогут вам построить AST из некоторого описания грамматики
  • Получите хорошую библиотеку, которая поможет вам пройтиAST для сбора / изменения AST

Для серьезной работы с AST лучше всего это сделать с помощью пакета, предназначенного для создания и управления AST.Часто такие пакеты включают много дополнительной поддержки, такой как сопоставление с образцом и / или переписывание AST с использованием преобразований источника в источник.

Вот несколько из них:

Этот пример показывает, как создавать AST и манипулировать ими, используя только BNF, шаблоны и преобразования источника в источник.

0 голосов
/ 12 апреля 2010

Большинство компиляторов решают эту проблему, используя

  • Переопределение метода
  • посетителей

Вот как вы собираете все постоянные значения (литералы), которые появляются в вашем выражении, в 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!
  }
}

1020 посетителей * *

Та же программа, но написанная с использованием Посетителей.

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) { }
}
...