Week 51 of 2020 - Antlr grammar for hledger timeclock format with Clojure

- 20 Dec, 2020

Plain text accounting?

For almost a year now I have been keeping my personal finances using a plain text accounting tool called hledger. One of the issues I have with it is that I can’t use it from Clojure (or Java) and it’s hard to build apps around it. I would like to enter transactions using a Gnome extension or another GUI application and have some nice features like

  • auto-complete

  • syntax checking

  • validation

  • syntax highlighting

As you can see, having a grammar opens up many possibilities.

I was also looking for an excuse to work with Anltr.

So the universe aligned and I decided to work on building a grammar so I can work on my apps. I decided to make it open source so other people can use it and improve it.

How to support and stay updated

The project is available at hledger-grammars . Submit feedback, issues and patches there.

Right now it has a working grammar for timeclock. Check the source for updates or even ask about the status.

If you like to show interest in the project, please star the git repository and send me feedback.
If you would like to be kept up to date please follow me on https://twitter.com/ieugen222 .

Objectives for hledger-grammars

My plan is to implement Antlr grammars for hledger journal formats and some examples on how to use them.

Since the accounting journal can be quite complex I plan to support only a subset that I use. If people are interested they can contribute patches for their use-cases or they can make their own version.

I haven’t decided yet if and what bindings to publish.

Current status - initial version of timeclock grammar

I started with a grammar for timeclock journal since the format is quite simple. I am new to Antlr and wanted something easy to get results and give me time to learn.

Timeclock is a simple journal format used for time logging. The format is simple but very powerful.

Sample timeclock journal
    i 2015/03/30 09:00:00 some:account name  optional description after two spaces
    o 2015/03/30 09:20:00
    i 2015/03/31 22:21:45 another account
    o 2015/04/01 02:00:34

It is this power and flexibility that lead me to use plain text accounting tools.

A timeclock transaction is composed of a clock-in and clock-out pair with accounts and optional description.

From this entry (event) log you are able to derive a lot of information and reports.

Fast iteration with Clojure and clj-antlr

The grammar for it was simple to implement and is available in the git repository. I’ve used a clojure library called clj-antlr to develop the grammar.

This was immensely helpful since I could use REPL driven development and iterate ery fast on the design.

To give you an idea, all the code I wrote to develop the library is bellow:

Using antlr grammars in Clojure with REPL driven development
(ns ieugen.hledger.timeclock
  (:require [clj-antlr.core :as antlr]
            [clojure.pprint :as pp]))

(defn load-grammar [path]
  (antlr/parser path))

(def tclock (load-grammar "grammars/timeclock.g4"))


  (let [tclock (antlr/parser "grammars/timeclock.g4")
        source (slurp "test/samples/sample.timeclock")
        parsed (tclock source)]


During development all I had to do was work on my grammar and execute the clojure comment block for instant feedback.

I was able to iterate very fast. I managed to build the project in less than a day from no repo to a working Antlr grammar.

For learning Antlr I found a very nice tutorial online that I recommend Antlr mega tutorial .

Next steps: syntax highlighting for monaco-editor (web VSCode)

Now that I have the grammar I started working on adding syntax highlighting for monaco-editor . Monaco is the web version of Visual Studio Code from Microsoft. I use VSCode daily and Calva to develop Clojure and I think it makes for a good integration example.

To make this work I will have to improve the grammar and also split it into a lexer and a parser grammar.

I am developing the example using ClojureScript so I will have to generate JavaScript bindings for my grammar as well.

Once this is done I will have to do the monaco-editor integration.

Hopefully, next week I’ll be able to finish this up and have it working online.

After this is done I’ll probably start working on the grammar for hledger journal files. Maybe a VSCode extension for hledger timeclock is also in order.

So stay tuned.

Tags: plain text accounting timeclock parser grammar clojure hledger lexer time logging giving back Antlr

Tag cloud

plain text accounting timeclock documentation parser cryogen grammar keepassxc gnome authentication clojure tutorial pass oauth2 password management export hledger oauth2-proxy free software csv website static website kubernetes lexer dex gnome extension babashka k3s contribution time logging FreeIPA Raspberry PI LDAP giving back OpenFaaS Antlr self-hosting serverless cryogen-web contribuție live-reload open source