A colleague of mine is working with natural language parsing and came up with some simplified grammar syntax to define expected input structures. The expected words/tokens are placed on a text file, and, over the weekend, I decided it would be interesting to have a way to visualize that and also how to implement that. TLDR, the code can be found here.
The rules on this grammar are defined through a simple language. Tokens are just regular words, but they can be made optional or part of a choice group. Optional tokens are enclosed in brackets (
), and choices are inside parentheses (
()) and with pipes (
|) in between.
Words enclosed by less-than and greater-than signs (
<>) will be drawn inside square boxes. They might have a special meaning, like referencing to another rule.
For example, a valid rule would be:
[please] (what is|what's) your <name>
Now, the missing part was to transform my colleague’s format to the one used by railroad-diagrams…
I was so convinced about using Scala that I decided to implement it first, and then try to make it Scala.js compatible.
The way I implemented it is this: I tokenize the rules, parse them into an intermediate Scala representation using case classes, and them translate them to the railroad-diagrams functions.
After I was able to get it running and see that I obtained the right output, I started to make it Scala.js ready. The process was quite simple. I added the necessary sbt plugin, and created an entry point that extended
scala.scalajs.js.JSApp. There, I created a function, annotated with
@JSExport, that would receive the user input, pass it through my parser, and return it’s output.
Unfortunately, I had used Java’s
Lastly, I created an HTML page with a small script that glued everything together. The page has a text area where you can place your rules, and once that’s is done, it will create and append the generated diagrams to the page. So, for the rule I gave before, we would have the following diagram drawn:
Once again, the project can be found on GitHub. More details are available on its README.
- Services Version Lock with Docker and Jenkins
- Tips for your Distributed Project Inception or Meeting
- RFID, Dryers, and IoT
- Efficient Timer using a Circular Buffer
- Secure Configuration Management for Microservices
- Trunk Based Development with Multiple Services
- Circuit Breakers and retries in Scala with autobreaker
- Integration testing for nginx Routes
- Useful UNIX Signals (SIGQUIT, SIGSTOP, SIGCONT)