In Groovy 1.6 (and prior) there is one way to build Abstract Syntax Trees (AST) in code: using the constructors on the ASTNode subclasses.
Here is an example of building a block of code that returns the String 'Hello'. A use case for this would be to create a method body implementation that simply returns 'Hello':
AstNode node = new BlockStatement(
[new ReturnStatement(
new ConstantExpression("Hello")
)],
new VariableScope())
|
Groovy 1.7 introduces three new ways to build AST:
The AstBuilder object provides an API to build AST from Strings of Groovy source code. The original example using buildFromString is:
List<ASTNode> nodes = new AstBuilder().buildFromString("\"Hello\"")
|
The AstBuilder object also provides an API to create AST from source code. The original example using buildFromCode is:
List<ASTNode> nodes = new AstBuilder().buildFromCode { "Hello" }
|
new AstBuilder().buildFromCode { ... }
|
rather than having a local variable or field of type AstBuilder.
The AstBuilder object also provides a DSL like API for building AST. The original example using buildFromSpec is:
List<ASTNode> nodes = new AstBuilder().buildFromSpec {
block {
returnStatement {
constant "Hello"
}
}
}
|
Sometimes the best solution is to mix several types of the AST Builders. For instance, consider the following method:
public String myMethod(String parameter) {
println 'Hello from a synthesized method!'
println "Parameter value: $parameter"
}
|
It might be best to use buildFromSpec to build the method declaration and buildFromCode to create the method body:
List<ASTNode> result = new AstBuilder().buildFromSpec {
method('myMethod', Opcodes.ACC_PUBLIC, String) {
parameters {
parameter 'parameter': String.class
}
exceptions {}
block {
owner.expression.addAll new AstBuilder().buildFromCode {
println 'Hello from a synthesized method!'
println "Parameter value: $parameter"
}
}
annotations {}
}
}
|
The test cases shipping with Groovy are an excellent resource.
More examples can be found in GEP-2, the original proposal. http://docs.codehaus.org/display/GroovyJSR/GEP+2+-+AST+Builder+Support
Examples and questions can be found on the groovy-user and groovy-dev mailing lists.