2010-04-12 2 views
1

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

Пример:

expression = "Var1 > 10 AND Var2 < 20" 

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

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

+0

Относительно вашего комментария. Я не уверен, что понимаю трудность, которую вы описываете. Какие выражения не допускаются? Во всяком случае, я хочу сказать, что два описанных apporaches могут использоваться для всех видов манипуляций/валидаций, которые вы хотите выполнять на дереве. Вам просто нужно добавить новый метод (в первом подходе) с соответствующими параметрами или определить новый подкласс посетителя (во втором подходе) с соответствующими полями. –

+0

Вот что я имею в виду. exp1 = "1 + 1" exp2 = "Var1> 10 AND Var2 <20" С вашим решением я бы получил два целых числа из обоих выражений, но первое выражение не соответствует типу для моего приложения. GUI im population может работать только с определенными типами выражений НЕ каждый тип выражения, содержащего (в дереве) два целых числа. – Marcus

+0

Непонятно, что вы конкретно пытаетесь выполнить. –

ответ

0

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

  • Метод перекрывая
  • Visitor

Вот как вы бы идти о сборе всех постоянного значения (литералы), который появляется в вашем выражение в целые числа List. Затем код вызова может заполнять текстовые поля со значениями из этого списка.

Метод наиважнейшая

Самый верхний АСТ класс определяет абстрактный метод, который переопределен в подклассах.

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) { } 
} 
+0

Это приятное решение, но не такое «безопасное», что я хотел. Это решение только собирает значения. Например. «выражение: 1 + 1» будет работать с вашим решением, но такое выражение не допускается и т. д. – Marcus

1

Рекомендация по работе с НРХАМИ являются:

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

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

Вот несколько:

This example показывает, как создавать и манипулировать ASTS используя только BNF, узоры и источника- to-source.

Смежные вопросы