[antlr-interest] Using antlr to retreive logical expressions
Miguel Almeida
migueldealmeida at gmail.com
Thu Mar 1 10:31:04 PST 2012
Dear all,
I need to parse and evaluate expressions which are in the format:
- x eq 1 && y eq 10
- (x lt 10 && x gt 1) || x eq -1
I have the evaluator part working (ie, I have code that evaluates all the
gt/lt/eq/neq expressions. All I need is the part that breaks the clause
into these expressions and then applies the logical and/or's
I saw a recommendation on ANTLR to do this. My idea is to:
1) Build a tree
2) Execute the leafs using my already existing code (eg, replace "1 eq 10"
with false)
3) Execute a method that then applies the logical operation to get the
result of the tree
While I've spend the last couple of days reading things about ANTLR, I am
kind of lost at the moment: I can't seem to be able to get a tree structure
whose tokens hold either the && and || or the complete expressions.
My current grammar is [1]. An example test case is [2]
- If I omit the | ' ' from the ID, "x eq 1" will be 3 tokens instead of the
one token I need
- If I leave it there, then for example this "1 eq 1 && (bb eq 1)"
expression won't work (No viable alternative at input '(' )
Could you shed some light on what could be wrong?
[1]
grammar Logic;
options {
output = AST;
}
tokens {
AND = '&&';
OR = '||';
}
// parser/production rules start with a lower case letter
parse
: expression EOF! // omit the EOF token
;
expression
: implication
;
implication
: or ('->'^ or)* // make `->` the root
;
or
: and ('||'^ and)* // make `||` the root
;
and
: not ('&&'^ not)* // make `&&` the root
;
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'
| ' '
)+
;
Space : (' ' | '\t' | '\r' | '\n')+ {$channel=HIDDEN;};
[2] Example test case
@Test
public void complexAndOr() throws RecognitionException{
// the expression
String src = "(1 eq 1 && 2 eq 2) || 3 eq 3";
// create a lexer & parser
LogicLexer lexer = new LogicLexer(new ANTLRStringStream(src));
LogicParser parser = new LogicParser(new CommonTokenStream(lexer));
// invoke the entry point of the parser (the parse() method) and
get the AST
CommonTree tree = (CommonTree)parser.parse().getTree();
assertEquals("||",tree.getText());
Tree child1 = tree.getChild(0);
assertEquals("&&",or.getText());
assertEquals("1 eq 1",child1.getChild(0));
assertEquals("2 eq 2",child1.getChild(1));
assertEquals("3 eq 3",tree.getChild(1).getText());
}
Thank you,
Miguel
More information about the antlr-interest
mailing list