Chapter 12
[ 325 ]
There is not much to the game model class, as you can see in the preceding code.
While parsing, we build a list of the pages declared in the DSL, and a map of the
events declared. We also capture all the statements declared in the state variables
block and in each of the event blocks. This aspect of the AST transform is new.
In the state machine DSL, the model was more of a specification language. This DSL
contains actual executable code and variable declarations that we need to handle.
While parsing, we don't need to do any transformation of this code, we just need to
capture it in the correct blocks so we can make use of it later.
The parser class EnginePatternParser handles this by scanning the DSL run
method for labeled statements. Anything after a state: or event: is labeled
up until the next labeled block is collected and stored in the model:
@Override
void visitMethod(MethodNode node) {
if (node.name == "run") {
collectPages(node)
collectEvents(node)
collectStateVariables(node)
collectEventMethodBodies(node)
}
}
def collectStateVariables(node) {
def collecting = false
node.code.statements.each { stmnt ->
if (!collecting && isStateBlock(stmnt))
collecting = true
if (collecting && isNonStateBlock(stmnt)) {
collecting = false
}
if (collecting) {
if (isDeclarationExpression(stmnt)) {
model.addStateDeclaration stmnt
} else {
addError "Declarations only allowed in state block",
stmnt, source
}
}
}
}
boolean isStateBlock(Statement stmnt) {
stmnt instanceof ExpressionStatement &&