Getting Started

Parsing

Basics

You first have to create a Parser object:

final Parser parser = new Parser();

Then, parsing is just a matter of calling the parse(...) method with the appropriate reader, file or input-stream and encoding.

final File sourceFile = new File("<path-to-java-source-file>.java");
final CompilationUnit cu = parser.parse(sourceFile, "UTF-8");

Customization

A Parser can be instantiated with a ParserConfiguration object. Through this configuration object, you can enable whitespace preservation.

final Parser parser = new Parser(
        ParserConfiguration.Default.preserveWhitespaces(true));

The Parser class also provides a finer-grain parse(...) method that accepts a ParseContext object. For instance, you can parse an expression:

final String exprString = "x -> x + x";
final Expr expr = parser.parse(ParseContext.Expression, exprString);

Printing

Basics

You have to create a Printer object and call its print(...) method:

final CompilationUnit cu = // ...
PrintWriter writer = new PrintWriter(new FileWriter("out.java"));
Printer printer = new Printer();
printer.print(cu, writer);

The Printer class also propose static helper methods:

String formatted = Printer.printToString(tree);

Please refer to the JavaDoc of Printer for more variants of the static helper methods.

Customization

A Printer can be instantiated with an additional boolean flag to enable formatting of existing nodes and a FormattingSetting object to customize rendering:

// ...
Printer printer = new Printer(true, FormattingSettings.Default.withIndentation("    "));
printer.print(cu, writer);

Two base settings are provided (FormattingSettings.Default and FormattingSettings.JavaParser). Please refer to the JavaDoc of FormattingSettings for further customization.

Abstract Syntax Tree Manipulation

Every abstract syntax tree objects derive from the base Tree class and obey the same common design rules.

For each property prop of a Tree subclass is provided an accessor prop() and a mutator withProp(...) (or isProp() and setProp(...) for boolean properties). For instance, the ImportDecl class provide the following accessors and mutators for its properties:

public QualifiedName name();
public ImportDecl withName(QualifiedName name);
public boolean isStatic();
public ImportDecl setStatic(boolean isStatic);
public boolean isOnDemand();
public ImportDecl setOnDemand(boolean isOnDemand);

Thus you can modify an ImportDecl in the following way:

final ImportDecl decl = new ImportDecl(QualifiedName.of("org.jlato.tree"), false, true);
Assert.assertEquals("import org.jlato.tree.*;", Printer.printToString(decl));

final ImportDecl newDecl = decl.withName(new QualifiedName(decl.name(), new Name("Tree")))
                               .setOnDemand(false);
Assert.assertEquals("import org.jlato.tree.Tree;", Printer.printToString(newDecl));

Once you modified a tree node, you can go back to its parent tree or up to the root by calling the parent() or root() methods. Those will accordingly recreate the intermediate immutable tree nodes:

final CompilationUnit cu = // ...

final ImportDecl anImportDecl = cu.imports().get(0);

final ImportDecl newImportDecl = anImportDecl.withName(QualifiedName.of("com.acme.MyClass"))
                                             .setStatic(false)
                                             .setOnDemand(false);

final CompilationUnit newCU = (CompilationUnit) newImportDecl.root();
Assert.assertEquals("import com.acme.MyClass;", Printer.printToString(newCU.imports().get(0)));