Groovy for Domain-specific Languages - Second Edition

(nextflipdebug2) #1
Chapter 8

[ 205 ]

}
}
}
}

The state machine DSL should contain at least two state declarations and at least one
event declaration to make sense, so we start by collecting this in the model from the
ModuleNode object. We do this by traversing all the statements in the ModuleNode
object and find all statements that meet the following criteria. The statement is a
constant expression, which has the label event for events or state for states:


def collectStates(MethodNode node) {
collectLabeledConstantStrings(node, 'state').each { stmnt ->
model.addState stmnt.expression.value.toString()
}
}
def collectEvents(MethodNode node) {
collectLabeledConstantStrings(node, 'event').each { stmnt ->
model.addEvent stmnt.expression.value.toString()
}
}
def collectLabeledConstantStrings(MethodNode node, label) {
node.code.statements.findAll { stmnt ->
stmnt instanceof ExpressionStatement &&
stmnt.expression instanceof ConstantExpression &&
stmnt.statementLabel &&
stmnt.statementLabel == label
}
}

Handling the transitions is a little more complex because statement ordering is
important. The visitMethod method iterates all statements in the MethodNode
object. If the statement we encounter is a labeled constant string, the getLabelParam
method will return the constant string. So, the value returned will be state, event,
when, or null, depending on whether we find a valid declaration or not:


def getLabelParam(stmnt) {
if (stmnt instanceof ExpressionStatement &&
stmnt.expression instanceof ConstantExpression &&
stmnt.statementLabel
) {
return stmnt.expression.value.toString()
}
null
}
Free download pdf