1

I am trying to parse a boolean expression of the following type B1=p & A4=p | A6=p &(~A5=c)

I want a tree that I can use to evaluate the above expression. So I tried this in Antlr3 with the example in Antlr parser for and/or logic - how to get expressions between logic operators?

It worked in Antlr3. Now I want to do the same thing for Antlr 4. I came up the grammar below and it compiles. But I am having trouble writing the Java code.

Start of Antlr4 grammar

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' | ' '
    | ('+'|'-'|'*'|'/'|'_')
    | '='
  )+ 
  ;

I have written the Java Code (snippet below) for getting a tree for the expression "B1=p & A4=p | A6=p &(~A5=c)". I am expecting & with children B1=p and |. The child | operator will have children A4=p and A6=p &(~A5=c). And so on. Here is that Java code but I am stuck trying to figure out how I will get the tree. I was able to do this in Antlr 3.

Java Code

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);
}

The get Children method is below. But this does not seem to extract any tokens.

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);
       }
   }
}

Could someone help me figure out how to write the parser in Java?

Community
  • 1
  • 1

1 Answers1

3

The output=AST option was removed in ANTLR 4, as well as the ^ and ! operators you used in the grammar. ANTLR 4 produces parse trees instead of ASTs, so the root of the tree produced by a rule is the rule itself. For example, given the following rule:

and : not (AND not)*;

You will end up with an AndContext tree containing NotContext and TerminalNode children for the not and AND references, respectively. To make it easier to work with the trees, AndContext will contain a generated method not() which returns a list of context objects returned by the invocations of the not rule (return type List<? extends NotContext>). It also contains a generated method AND which returns a list of the TerminalNode instances created for each AND token that was matched.

Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
  • I am new to ANTLR and I am still trying to figure out how I can grab the nodes in the expression B1=p & A4=p. I need the result B1=p and the other child node as A4=p so that I can evaluate it. Can you please explain further how I can print the nodes out with some code. – Ashwini Bhandary Mar 24 '13 at 21:55
  • 1
    @AshwiniBhandary, instead of walking the tree manually, I suggest you use ANTLR4's built-in functionality to do so. See: http://stackoverflow.com/questions/15610183/if-else-statements-in-antlr-using-listeners or http://stackoverflow.com/questions/15050137/once-grammar-is-complete-whats-the-best-way-to-walk-an-antlr-v4-tree – Bart Kiers Mar 25 '13 at 14:15