Reputation: 23032
I'm following https://blog.gopheracademy.com/advent-2017/parsing-with-antlr4-and-go/, and
I'm looking at https://github.com/bramp/goadvent-antlr/blob/master/example2.go, which has no output. Now,
I want to use the EnterEveryRule
to output each symbol encountered, with their symbolicNames. How can I do that?
I.e., how to somehow access to the symbolicNames
slice at any specific stage, to know which SymbolicName I'm dealing with.
Upvotes: 0
Views: 594
Reputation: 23032
I'm answering it for @kaby76 actually, who had led me to https://play.golang.org/p/R8Sik7sdZaz, so that I am able to move on to https://play.golang.org/p/uZqfUhHE0mt
Here is the full code:
package main
import (
"fmt"
"github.com/antlr/antlr4/runtime/Go/antlr"
"github.com/bramp/goadvent-antlr/parser"
)
type calcListener struct {
*parser.BaseCalcListener
parser *parser.CalcParser
}
// ExitEveryRule is called when any rule is exited.
func (l *calcListener) ExitEveryRule(ctx antlr.ParserRuleContext) {
count := ctx.GetChildCount()
// count == 1, NUMBER
ch := ctx.GetChild(0)
if count == 3 {
// operation
ch = ctx.GetChild(1)
}
q := ch.(antlr.Tree)
t, ok := q.(antlr.TerminalNode)
if ok {
s := t.GetSymbol()
x := s.GetTokenType()
y := l.parser.GetSymbolicNames()
fmt.Println(y[x], ctx.GetText())
}
}
func main() {
// Setup the input
is := antlr.NewInputStream("1 + 2 * 3")
// Create the Lexer
lexer := parser.NewCalcLexer(is)
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
// Create the Parser
p := parser.NewCalcParser(stream)
// Finally parse the expression (by walking the tree)
listener := calcListener{}
listener.parser = p
antlr.ParseTreeWalkerDefault.Walk(&listener, p.Start())
}
Execution result:
NUMBER 1
NUMBER 2
NUMBER 3
MUL 2*3
ADD 1+2*3
Upvotes: 1
Reputation: 6785
I'm certainly no expert with Go, but that example contains the following lines:
// Finally parse the expression (by walking the tree)
antlr.ParseTreeWalkerDefault.Walk(&calcListener{}, p.Start())
This is a bit misleading. The p.Start()
part of that statement actually does the parsing (calling p.Start()
should return an ANTLR parse tree. At that point, you've done the parsing.
antlr.ParseTreeWalkerDefault.Walk()
is how you walk a parse tree invoking methods on the listener
that is passed in along with the parse Tree you got from the p.start()
call. You may want to store it in a temporary variable before passing it to the walker (maybe inspect it in a debugger to understand it, or, it should have something like a toStringTree(...)
function that will give you a string representation of the parse tree.)
it appears that calcListener
just has a reference to a parser.BaseCalcListener
. The ANTLR-generated Base*Listener
s are "do-nothing" listeners that just provide empty implementations of all the methods a listener needs to have implemented.
You'll need to do something with the calcListener
to "override" the EnterEveryRule
function, and do something with the *Context
object passed to it.
Upvotes: 1