Antlr users usually create a parser that generates the AST(Abstract syntax tree), and a walker that walks through the AST and generate the desired outcomes. As we know, java(C++, python…etc) codes has to be injected into the .g walker files to carry out the execution. However, when the target gets complicated, say we are to develop a walker that processes JAVA language, we have to pass a lot of context information between the rules in the walker through scope, parameter, or global variables, and this makes the walker so ugly and hard to maintain.
So, my questions is that, given the parser and walker(without any java code yet) done, what is the common practice to software-engineering java(or others) codes in the waker, and the rest of the java codes?
Use the Strategy pattern.
Write an interface that describes what you want to do action-wise (createSymbol(), pushScope(), defineType()..) and pass an implementation of it to the grammar. This keeps the code in the grammar minimal, and allows you to pass in different (or Decorated) implementations.
Your implementation can keep track of the data you need rather than passing it around in the grammar. Think of it as managing all the state you need, and all you do is call its methods from the grammar. The only state in the grammar is a pointer to the strategy implementation.
Does that help?
— Scott