Hime - Quickstart for Java

This guide gets you started with Hime using Java. It is also available for C# and Rust. The program here is to download the tooling, get a prepared grammar, compile it with himecc and use the generated parser.

Pre-requisites for this guide are:
  • A local installation of a compatible .Net platform such as:
    • The .Net Framework 2.0 or higher on Windows (installed by default on Windows Vista and up).
    • Mono 4.6 or higher on Linux and MacOS.
    • .Net Core 2.0 or higher on a compatible OS.
  • A location installation of the Java JDK 7 or higher, for example OpenJDK and Maven.

Get the tooling

The toolchain for Hime can be found on the download page.
Step 1 Download and extract the toolchain package.
You may want some editing support for Hime grammars. In this case, head to the editors line-up page. For an IDE experience, we recommend the Visual Studio Code extension.

Get the grammar

Step 2 Create and open a file named MathExp.gram.
Step 3 Then copy-paste in this file the following grammar:

grammar MathExp
{
    options
    {
        Axiom = "exp"; // the top variable for this grammar
        Separator = "SEPARATOR"; // the terminal that represent white space
    }
    terminals
    {
        WHITE_SPACE -> U+0020 | U+0009 | U+000B | U+000C ;
        SEPARATOR   -> WHITE_SPACE+;

        INTEGER     -> [1-9] [0-9]* | '0' ;
        REAL        -> INTEGER? '.' INTEGER  (('e' | 'E') ('+' | '-')? INTEGER)?
                    |  INTEGER ('e' | 'E') ('+' | '-')? INTEGER ;
        NUMBER      -> INTEGER | REAL ;
    }
    rules
    {
        exp_atom   -> NUMBER
                    | '(' exp ')' ;
        exp_factor -> exp_atom
                    |  exp_factor '*' exp_atom
                    |  exp_factor '/' exp_atom ;
        exp_term   -> exp_factor
                    |  exp_term '+' exp_factor
                    |  exp_term '-' exp_factor ;
        exp        -> exp_term ;
    }
}

Compile the grammar

Now that we have a grammar, let's compile it to generate the parser. The toolchain package contains at its root useful front scripts that can be to invoke the himecc compiler. On Windows, you should look for the himecc.bat script. On Linux and MacOS you should look for the himecc script. If this does not suit you, you may invoke the himecc.exe assembly for your installed framework.

Step 4 Compile the MathExp.gram:

  • On Windows: himecc.bat MathExp.gram -t:java or explicitly with net461/himecc.exe MathExp.gram -t:java
  • On Linux and MacOS: ./himecc MathExp.gram -t:java
  • On any OS, explicitly with .Net Core: dotnet netcore20/himecc.dll MathExp.gram -t:java
  • On any OS, explicitly with Mono: mono net461/himecc.exe MathExp.gram -t:java

The tool will generate 4 files:

  • MathExpLexer.java, the source file for the lexer
  • MathExpLexer.bin, the binary representation of the lexer’s automaton
  • MathExpParser.java, the source file for the parser
  • MathExpParser.bin, the binary representation of the parser’s automaton

Note here that the default target for himecc is the .Net platform; so that we have to specify Java as the target with the -t:java option. For a complete guide to the options of himecc, head to the reference page.

Setup the test project

Step 5 Setup a test project as a standard Maven project. Use the following project layout:

test/
+-> pom.xml
+-> src/
    +-> main/
        +-> java/
        |   +-> mathexp/
        |       +-> Program.java
        |       +-> MathExpLexer.java
        |       +-> MathExpParser.java
        +-> resources/
            +-> mathexp
                +-> MathExpLexer.bin
                +-> MathExpParser.bin

Step 6 Set the minimal pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>fr.cenotelie.hime</groupId>
    <artifactId>test-hime</artifactId>
    <packaging>jar</packaging>
    <version>1.0.0</version>
    <dependencies>
        <!-- reference to the Java runtime for generated parsers -->
        <dependency>
            <groupId>fr.cenotelie.hime</groupId>
            <artifactId>hime-redist</artifactId>
            <version>3.4.0</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.0.2</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.0.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <!-- register the main class for the program -->
                            <mainClass>mathexp.Program</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <!-- produce a jar with all dependencies (Hime runtime is embedded) -->
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Step 7 Set the minimal Program.cs:

package mathexp; // default namespace for the parser is the grammar's name

import fr.cenotelie.hime.redist.ASTNode;
import fr.cenotelie.hime.redist.ParseResult;

public class Program {
    public static void main(String[] args) {
        MathExpLexer lexer = new MathExpLexer("2 + 3");
        MathExpParser parser = new MathExpParser(lexer);
        ParseResult result = parser.parse();
        ASTNode root = result.getRoot();
        print(root, new boolean[]{});
    }

    private static void print(ASTNode node, boolean[] crossings) {
        for (int i = 0; i < crossings.length - 1; i++)
            System.out.print(crossings[i] ? "|   " : "    ");
        if (crossings.length > 0)
            System.out.print("+-> ");
        System.out.println(node.toString());
        for (int i = 0; i != node.getChildren().size(); i++) {
            boolean[] childCrossings = Arrays.copyOf(crossings, crossings.length + 1);
            childCrossings[childCrossings.length - 1] = (i < node.getChildren().size() - 1);
            print(node.getChildren().get(i), childCrossings);
        }
    }
}

Build and execute the test project

Step 8 Build the test project:

mvn clean verify

Step 9 Execute the test project:

java -jar target/test-hime-1.0.0-jar-with-dependencies.jar

The output of the program should a text printout of the produced syntax tree be as follow:

exp
+-> exp_term
    +-> exp_term
    |   +-> exp_factor
    |       +-> exp_atom
    |           +-> NUMBER = 2
    +-> + = +
    +-> exp_factor
        +-> exp_atom
            +-> NUMBER = 3

This concludes this guide. For a more complete tutorial, head over to the the first Java tutorial.