About jADT

| Licensing >>

jADT turns algebraic datatype description files into Java source files. The resulting Java is nearly as easy to use as an Enum, but far more flexible.

jADT uses very liberal licensing.

Download Now.

Sample

Here's a sample jADT file that describes the abstract syntax tree for a fragment of a fictional language. All the fields are marked final (immutable) but need not be.

package com.pogofish.jadt.samples.ast.data

import java.util.List

Type =
     Int
   | Long

Function = Function(final Type returnType, final String name, List<Arg> args, final List<Statement> statements)

Arg = Arg(final Type type, final String name)

Statement =
    Declaration(final Type type, final String name, final Expression expression)
  | Assignment(final String name, final Expression expression)
  | Return(final Expression expression)

Expression =
    Add(final Expression left, final Expression right)
  | Variable(final String name)
  | IntLiteral(final int value)
  | LongLiteral(final long value)

Usage

Java can be generated from jADT files using Apache Maven, Apache Ant or from the shell.

To use the generated Java, you'll need some imports

import static com.pogofish.jadt.samples.ast.data.Arg.*;
import static com.pogofish.jadt.samples.ast.data.Expression.*;
import static com.pogofish.jadt.samples.ast.data.Function.*;
import static com.pogofish.jadt.samples.ast.data.Statement.*;
import static com.pogofish.jadt.samples.ast.data.Type.*;
import static java.util.Arrays.asList;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

Here's an example of creating a complete function using generated factory methods

Function sampleFunction = _Function(_Int(), "addTwo",
        asList(_Arg(_Int(), "x"), _Arg(_Int(), "y")),
        asList(_Return(_Add(_Variable("x"), _Variable("y")))));

Here's a sample function that returns all the integer literals in an expression

    public Set<Integer> expressionLiterals(Expression expression) {
        return expression.match(new Expression.MatchBlock<Set<Integer>>() {
            @Override
            public Set<Integer> _case(Add x) {
                final Set<Integer> results = expressionLiterals(x.left);
                results.addAll(expressionLiterals(x.right));
                return results;
            }

            @Override
            public Set<Integer> _case(Variable x) {
                return new HashSet<Integer>();
            }

            @Override
            public Set<Integer> _case(IntLiteral x) {
                return new HashSet<Integer>(asList(x.value));
            }

            @Override
            public Set<Integer> _case(LongLiteral x) {
                return new HashSet<Integer>();
            }
        });
    }

And here's a sample function that returns true only if a list of statements has a return statement. Unlike the previous example, this one uses a default case so that only relevant cases need to be considered.

    public boolean hasReturn(List<Statement> statements) {
        boolean hasReturn = false;
        for (Statement statement : statements) {
            hasReturn = hasReturn || statement.match(new Statement.MatchBlockWithDefault<Boolean>() {
                @Override
                public Boolean _case(Return x) {
                    return true;
                }

                @Override
                public Boolean _default(Statement x) {
                    return false;
                }
            });
        }
        return hasReturn;
    }

| Licensing >>