[antlr-interest] Return values from listener methods (was "Appropriate use of honey badger listeners")

Oliver Zeigermann oliver.zeigermann at gmail.com
Sat Jan 14 04:31:03 PST 2012


I agree to what Sam says. Keeping it simple and using the means Java
provides anyway is the solution to me. I think ANTLR could introduce a
sensible general abstraction to this. Rahter provide best practices..

I have an expression parser that does not generate a result, but
rather a heterogeneous tree using exactly the same stack stuff as Sam
only that I put Expression objects on a stack.

Heterogeneous trees could also hold a reference to the parse tree they
were created from. In case you need them later.

My code that covers creating data structures from parses using
multiply approaches has grown a little bit too large to share on a
mailing list. If anyone is interested, I could set up a project
somewhere. For now, here is a fraction of my expression listener


	static class ExpressionASTConstructorListener extends BlankExprV4Listener {

		private final Stack<Expression> stack = new Stack<Expression>();

		@Override
		public void exitRule(atomContext ctx) {
			final Number number = new Number(ctx._tINT.getText());
			stack.push(number);
		}

		@Override
		public void exitRule(mulExprContext ctx) {
			final Expression expr;
			Expression leftExpr = stack.pop();
			String op = ctx.mdop.op.getText();
			Expression rightExpr = stack.pop();
			Operation operation = new Operation(op, leftExpr, rightExpr);
			expr = operation;
			stack.push(expr);
		}

		@Override
		public void exitRule(addExprContext ctx) {
			final Expression expr;
			Expression leftExpr = stack.pop();
			String op = ctx.pmop.op.getText();
			Expression rightExpr = stack.pop();
			Operation operation = new Operation(op, leftExpr, rightExpr);
			expr = operation;
			stack.push(expr);
		}
	}

for a grammar like this

expr
: '(' e=expr ')' -> parenExpr
| left=expr mdop=mdOp right=expr -> mulExpr
| left=expr pmop=pmOp right=expr -> addExpr
| atom -> atomExpr
;

- Oliver

2012/1/13 Terence Parr <parrt at cs.usfca.edu>:
>
> On Jan 12, 2012, at 1:59 PM, Sam Harwell wrote:
>
>> I've used listeners for several tasks in ANTLRWorks 2 and haven't
>> encountered any problems in returning values which I wasn't able to work
>> around in a clean manner.
>>
>> For the case of expressions like your example below, once you realize that
>> exitRule behaves as an RPN calculator you just use a simple stack to track
>> computed results. For other tasks I've used stacks, flags, counters, or
>> whatever else was relevant to the specific task.
>>
>> For a simple calculator, you might have this:
>>
>> public void exitRule(multContext context) {
>>    double right = stack.pop();
>>    double left = stack.pop();
>>    stack.push(left * right);
>> }
>>
>> If you don't mind reversing the operand order of a commutative operator, you
>> could also write:
>>
>> public void exitRule(multContext context) {
>>    stack.push(stack.pop() * stack.pop());
>> }
>
> This seems like a good solution for expressions. I wonder if we can come up with a solution that users don't have to manage…
>
> Ter
>
> List: http://www.antlr.org/mailman/listinfo/antlr-interest
> Unsubscribe: http://www.antlr.org/mailman/options/antlr-interest/your-email-address


More information about the antlr-interest mailing list