Chapter 8
[ 201 ]
A state machine AST transformation
Unlike the previous examples, we won't need an annotation class for a global AST
transformation. AST transformation would get quite unwieldy if we tried to build
all the logic into the AST transformation class, so we separate out the responsibilities
into four classes:
- StateMachineASTTransformation: This is the GroovyASTTransfromation
class similar to the ones we already encountered in our annotation-based
examples. - StateMachineParser: This class implements the GroovyClassVisitor
interface. This class uses a visitor pattern to allow us to work on any part
of the tree of AST nodes in our compiled source. The main responsibility of
this class is to produce a simple data model to store the key elements of the
state machine. - StateMachineModel: This class stores the data model of the parsed state
machine. It describes the possible states, the initial state, the available events,
and the allowed transitions for each event. - StateMachineBuilder: This class builds the new AST nodes we need to
implement the state machine pattern.
@GroovyASTTransformation (phase = CompilePhase.SEMANTIC_ANALYSIS)
class StateMachineASTTransformation implements ASTTransformation {
def parser
def builder
void visit(ASTNode[] nodes, SourceUnit source) {
if (!nodes) return
if (!(nodes[0] instanceof ModuleNode)) return
if (!source?.name?.endsWith('State.groovy')) {
return
}
def model = new StateMachineModel()
parser = new StatePatternParser(model)
builder = new StatePatternBuilder(nodes, model)
for (ClassNode classNode : nodes[0].classes) {
classNode.visitContents(parser)
}
builder.buildStatePattern()
}
}