ANTLR4: Парсер для логического выражения

Я пытаюсь разобрать логическое выражение следующего типа B1=p & A4=p | A6=p &(~A5=c)

Мне нужно дерево, которое я могу использовать для оценки приведенного выше выражения. Итак, я попробовал это в Antlr3 с примером в Antlr-парсер для логики и/или - как получить выражения между логическими операторами?

Это работало в Antlr3. Теперь я хочу сделать то же самое для Antlr 4. Я придумал грамматику ниже, и она компилируется. Но у меня проблемы с написанием кода Java.

Начало грамматики Antlr4

grammar TestAntlr4;

options {
  output = AST;
}

tokens { AND, OR, NOT }

  AND : '&';
  OR  : '|';
  NOT : '~';


// parser/production rules start with a lower case letter
parse
  :  expression EOF!    // omit the EOF token
  ;

expression
  :  or
  ;

or
  :  and (OR^ and)*    // make `||` the root
  ;

and
  :  not (AND^ not)*      // make `&&` the root
  ;

not
  :  NOT^ atom    // make `~` the root
  |  atom
  ;

atom
  :  ID
  |  '('! expression ')'!    // omit both `(` and `)`
  ;

// lexer/terminal rules start with an upper case letter
ID
  :
    (
    'a'..'z'
    | 'A'..'Z'
    | '0'..'9' | ' '
    | ('+'|'-'|'*'|'/'|'_')
    | '='
  )+ 
  ;

Я написал код Java (фрагмент ниже) для получения дерева для выражения "B1=p & A4=p | A6=p &(~A5=c)". Я ожидаю & с детьми B1=p и |. Ребенок | оператор будет иметь потомков A4=p и A6=p &(~A5=c). И так далее. Вот этот код Java, но я застрял, пытаясь понять, как я получу дерево. Я смог сделать это в Antlr 3.

Java-код

String src = "B1=p & A4=p | A6=p &(~A5=c)";
CharStream stream = (CharStream)(new ANTLRInputStream(src));
TestAntlr4Lexer lexer = new TestAntlr4Lexer(stream);
parser.setBuildParseTree(true);
ParserRuleContext tree = parser.parse();
tree.inspect(parser); 
if ( tree.children.size() > 0) {
    System.out.println(" **************");
    test.getChildren(tree, parser);
}

Метод get Children приведен ниже. Но это, похоже, не извлекает никаких токенов.

public void getChildren(ParseTree tree, TestAntlr4Parser parser ) {
   for (int i=0; i<tree.getChildCount(); i++){
       System.out.println(" Child i= " + i);
       System.out.println(" expression = <" + tree.toStringTree(parser) + ">");
       if ( tree.getChild(i).getChildCount() != 0 ) {
           this.getChildren(tree.getChild(i), parser);
       }
   }
}

Может ли кто-нибудь помочь мне понять, как написать парсер на Java?


person Ashwini Bhandary    schedule 22.03.2013    source источник


Ответы (1)


Опция output=AST была удалена в ANTLR 4, как и операторы ^ и !, которые вы использовали в грамматике. ANTLR 4 создает деревья синтаксического анализа вместо AST, поэтому корнем дерева, созданного правилом, является само правило. Например, учитывая следующее правило:

and : not (AND not)*;

Вы получите дерево AndContext, содержащее NotContext и TerminalNode потомков для ссылок not и AND соответственно. Чтобы упростить работу с деревьями, AndContext будет содержать сгенерированный метод not(), который возвращает список объектов контекста, возвращаемых вызовами правила not (тип возвращаемого значения List<? extends NotContext>). Он также содержит сгенерированный метод AND, который возвращает список экземпляров TerminalNode, созданных для каждого сопоставленного токена AND.

person Sam Harwell    schedule 22.03.2013
comment
Я новичок в ANTLR и все еще пытаюсь понять, как я могу захватить узлы в выражении B1=p и A4=p. Мне нужен результат B1=p и другой дочерний узел как A4=p, чтобы я мог его оценить. Не могли бы вы объяснить, как я могу распечатать узлы с помощью некоторого кода. - person Ashwini Bhandary; 25.03.2013
comment
@AshwiniBhandary, вместо обхода дерева вручную, я предлагаю вам использовать для этого встроенные функции ANTLR4. См.: stackoverflow.com/questions /15610183/ или stackoverflow.com/questions/15050137/ - person Bart Kiers; 25.03.2013