ANTLR on the web: why?
I started writing my first programs on MS-DOS. So I am very used to have my tools installed on my machine. However in 2016 the web is ubiquitous and so our languages could be needed also there.
- ANTLR also on the web:
- users could want to access and possibly to minor changes files written in a DSL also from the web, while keeping using their fat-clients for complex tasks.
- ANTLR only on the web:
- you are dealing with domain-experts which are reluctant to install IDEs, so they prefer to have some web application where to write their DSL programs.
- you want to offer a simple DSL to specify queries to be executed directly in the browser.
You maybe also interested in our article Writing a browser based editor using Monaco and ANTLR.
A simple example: a Todo list
The DSL we are going to use in this example will be super easy: it will represents a todo list, where each todo item is contained in a separate line and started by an asterisk.
An example of a valid input:
* do this * do that * do something else after an empty line
And this is our grammar:
grammar todo; elements : (element|emptyLine)* EOF ; element : '*' ( ' ' | '\t' )* CONTENT NL+ ; emptyLine : NL ; NL : '\r' | '\n' ; CONTENT : [a-zA-Z0-9_][a-zA-Z0-9_ \t]* ;
You can now generate your parser by running:
Ok, this one was easy.
Invoking the parser
Unfortunately the JS libraries we are using do not work when simply opening local files: it means that also for our little example we need to use HTTP. Our web server will just have to serve a bunch of static files. To do this I chose to write a super simple application in flask. There are millions of alternatives to serve static files so pick the one you prefer. I will not detail how to serve static files through flask here but code is available on GitHub and if you have issues with that you can add a comment to this post to let me know.
Our static files will include:
- the generated parser we got by running gradle generateParser
- the Antlr4 JS runtime
- the JS library require.js
- HTML and CSS
You can get the Antlr4 JS runtime from here. To avoid having to import tens of files manually we will use require.js. You can get that flavor of require.js we need from here.
We are going to add a textarea and a button. When the user clicks on the button we will parse the content of the textarea. Simple, right?
This is the HTML code for this design masterpiece:
<div id="inputs"> <textarea id="code"> * play with antlr4 * write a tutorial </textarea> <br/> <button id="parse">Parse</button> </div>
First thing first, import require.js:
By the way, we are not using jquery, I know this could be shocking.
Good, now we have to invoke the parser
Cool, now our code is parsed but we do not do anything with it. Sure we can fire the developer console in the browser and print some information about the tree to verify it is working and to familiarize with the structure of the tree ANTLR is returning.
If we were building some kind of TODO application we may want to somehow represent the information the user inserted through the DSL.
Let’s get something like this:
To do so we basically need to add the function updateTree which navigate the tree returned by ANTLR and build some DOM nodes to represent its content
Here you go!
If it is not the first time you are reading this blog you will be suspecting that some code is coming. As usual, code is on GitHub: https://github.com/ftomassetti/antlr-web-example
The next step is to perform error handling: we want to catch errors and point them to the users. Then we may want to add syntax highlighting by using ACE for example. This seems a good starting point:
I really think that simple textual DSLs could help to make several applications much more powerful. However, it is not straightforward to create a nice editing experience on the web. I would like to spend some more time playing with this.
If you wan to know how to use ANTLR, you can read our article about The ANTLR Mega Tutorial.
The ANTLR Mega Tutorial as a PDF
Get the Mega Tutorial delivered to your email and read it when you want on the device you want