Skip to content
Skip to breadcrumbs
Skip to header menu
Skip to action menu
Skip to quick search
Quick Search
Browse
Pages
Blog
Labels
Attachments
Mail
Advanced
What’s New
Space Directory
Feed Builder
Keyboard Shortcuts
Confluence Gadgets
Log In
Dashboard
Groovy
Copy Page
You are not logged in. Any changes you make will be marked as
anonymous
. You may want to
Log In
if you already have an account. You can also
Sign Up
for a new account.
This page is being edited by
.
Paragraph
Paragraph
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Preformatted
Quote
Bold
Italic
Underline
More colours
Strikethrough
Subscript
Superscript
Monospace
Clear Formatting
Bullet list
Numbered list
Outdent
Indent
Align left
Align center
Align right
Link
Table
Insert
Insert Content
Image
Link
Attachment
Symbol
Emoticon
Wiki Markup
Horizontal rule
tinymce.confluence.insert_menu.macro_desc
Info
JIRA Issue
Status
Gallery
Tasklist
Table of Contents
Other Macros
Page Layout
No Layout
Two column (simple)
Two column (simple, left sidebar)
Two column (simple, right sidebar)
Three column (simple)
Two column
Two column (left sidebar)
Two column (right sidebar)
Three column
Three column (left and right sidebars)
Undo
Redo
Find/Replace
Keyboard Shortcuts Help
<h1>Building AST in Groovy 1.6 and Prior</h1> <p>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.</p> <p>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':</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> AstNode node = new BlockStatement( [new ReturnStatement( new ConstantExpression("Hello") )], new VariableScope()) </pre></td></tr></table> <h3>Advantages</h3> <ul> <li>Documentation is available in <a href="http://groovy.codehaus.org/api/org/codehaus/groovy/ast/ASTNode.html">Javadoc/Groovydoc</a></li> <li>Supports being invoked from Java</li> <li>Supported in all Groovy versions</li> <li>Some IDEs support code completion and parameter lookup</li> </ul> <h3>Disadvantages</h3> <ul> <li>It can be difficult to determine what AST you need to write</li> <li>Verbose - does not communicate the source being created</li> <li>Fragile - AST may need to change between major releases</li> <li>Author must know what AST looks like in a particular CompilePhase</li> </ul> <h1>Building AST in Groovy 1.7</h1> <p>Groovy 1.7 introduces three new ways to build AST:</p> <ul> <li>From Strings</li> <li>From Code</li> <li>From a DSL-like Specification</li> </ul> <h2>AstBuilder.buildFromString</h2> <p>The AstBuilder object provides an API to build AST from Strings of Groovy source code. The original example using buildFromString is:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> List<ASTNode> nodes = new AstBuilder().buildFromString("\"Hello\"") </pre></td></tr></table> <h3>Advantages</h3> <ul> <li>Does not require author to understand ASTNode subtypes</li> <li>Allows author to target a CompilePhase</li> <li>Communicates source code being generated</li> <li>Robust - Should need no changes even if AST is updated in a release</li> </ul> <h3>Disadvantages</h3> <ul> <li>IDE cannot check syntax or grammar</li> <li>IDE cannot refactor across String</li> <li>Some entities cannot be created, like the AST for a field declaration</li> </ul> <h2>AstBuilder.buildFromCode</h2> <p>The AstBuilder object also provides an API to create AST from source code. The original example using buildFromCode is:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> List<ASTNode> nodes = new AstBuilder().buildFromCode { "Hello" } </pre></td></tr></table> <h3>Advantages</h3> <ul> <li>Clearly communicates source being generated</li> <li>Does not require author to understand ASTNode subtypes</li> <li>Allows author to target a CompilePhase</li> <li>Robust - Should need no changes even if AST is updated in a release</li> <li>IDE supports syntax checking and refactoring in Closure</li> </ul> <h3>Disadvantages</h3> <ul> <li>Some entities cannot be created, like the AST for a field declaration</li> <li>buildFromCode requires that the left hand side of the invocation be of type AstBuilder. The best way to ensure this is to invoke it with:</li> </ul> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> new AstBuilder().buildFromCode { ... } </pre></td></tr></table> <p>rather than having a local variable or field of type AstBuilder.</p> <h2>AstBuilder.buildFromSpec</h2> <p>The AstBuilder object also provides a DSL like API for building AST. The original example using buildFromSpec is: </p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> List<ASTNode> nodes = new AstBuilder().buildFromSpec { block { returnStatement { constant "Hello" } } } </pre></td></tr></table> <h3>Advantages</h3> <ul> <li>Allows conditionals (or any Groovy code) to be executed during the AST building process.</li> <li>Allows any ASTNode subtype to be created</li> <li>Fully documented with lengthy examples in <a href="http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/test/org/codehaus/groovy/ast/builder/AstBuilderFromSpecificationTest.groovy">TestCase</a></li> </ul> <h3>Disadvantages</h3> <ul> <li>It can be difficult to determine what AST you need to write</li> <li>Verbose - does not always communicate the source being created</li> <li>Fragile - AST may need to change between major releases</li> <li>Author must know what AST looks like in a particular CompilePhase</li> <li>IDE does not <i>yet</i> provide code tips</li> </ul> <h1>Mixing Methods</h1> <p>Sometimes the best solution is to mix several types of the AST Builders. For instance, consider the following method:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> public String myMethod(String parameter) { println 'Hello from a synthesized method!' println "Parameter value: $parameter" } </pre></td></tr></table> <p>It might be best to use buildFromSpec to build the method declaration and buildFromCode to create the method body:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> 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 {} } } </pre></td></tr></table> <h1>Further Resources</h1> <p>The test cases shipping with Groovy are an excellent resource.<br /> More examples can be found in GEP-2, the original proposal. <a href="http://docs.codehaus.org/display/GroovyJSR/GEP+2+-+AST+Builder+Support">http://docs.codehaus.org/display/GroovyJSR/GEP+2+-+AST+Builder+Support</a><br /> Examples and questions can be found on the groovy-user and groovy-dev mailing lists.</p>
Please type the word appearing in the picture.
Attachments
Labels
Location
Watch this page
< Edit
Preview >
Loading…
Save
Cancel
Next hint
search
attachments
weblink
advanced