Elegant way to parse Calculator.g4 in grammars-v4 using antlr4 listener model

Viewed 57

I learned the basic grammars of antlr4 and tried to build a simple calculator. But, I have no idea how to handle PLUS | MINUS and TIMES | DIV.

expression: multiplyingExpression ((PLUS | MINUS) multiplyingExpression)*;

multiplyingExpression: signedAtom ((TIMES | DIV) signedAtom)*;

signedAtom: PLUS signedAtom | MINUS signedAtom | func_ | atom;

(code extracted from Antlr4 sample calculator grammar)

It seems like no API can handle PLUS | MINUS, because they are not defined like signedAtom/expression, which can be handled in method like exitXXX.

Does this mean, the grammar like this can only be parsed in visitor model?

Example:

Here is a extremely simple example code in golang.

calculator.g4

grammar calculator;

expression: atom ((PLUS | MINUS) atom)*;

atom: '1';

PLUS: '+';

MINUS: '-';
WS: [ \r\n\t]+ -> skip;

Code in Golang listener model

func NewCalculatorListenrImpl() *CalculatorListenrImpl {
    return &CalculatorListenrImpl{
        stack: stack.New(),
    }
}

type CalculatorListenrImpl struct {
    BasecalculatorListener
    stack *stack.Stack
}

func (s *CalculatorListenrImpl) ExitExpression(ctx *ExpressionContext) {
    left, op, right := s.stack.Pop().(int), s.stack.Pop().(string), s.stack.Pop().(int)

    switch op {
    case "+":
        s.stack.Push(left + right)
    case "-":
        s.stack.Push(left - right)
    }
}

func (s *CalculatorListenrImpl) ExitAtom(ctx *AtomContext) {
    v, _ := strconv.ParseInt(ctx.GetText(), 10, 32)

    s.stack.Push(int(v))
}

I can push the atom element to stack in exitAtom and then handle the logic in exitExpression method. However, there is no listener for (PLUS | MINUS). What I am looking for is method like exitPLUS where I can simply push them to stack like atom. May be there is other ways to do this? I knostrateforw their is some magic syntax like # and op=xxx, but these code fragements are copied from grammars-v4.

0 Answers
Related