Recently I had an opportunity to dwell into an interesting UI problem - with the proliferation of Single Page Application (SPA) as a design pattern for UI development, you sometimes end up with many screens that are not significantly different from each other. In this case the screens were web-forms. Most web-forms have a standard bunch of UI components - textbox's, textarea's, radio-button's, combo-box's et al. Instead of building each of these web-form's as a separate UI project the idea was to roll a DSL with 4 requirements -
eval
is EvilThe very first approach I quickly considered and discarded was using JavaScript eval
. The hypothesis was since there exist JS parsers which are used in IDE's for checking JS correctness (JS lib that parse JS code) - could they even execute JS without using the built-in eval
. Looked at Acorn, Esprima & Uglify and found they don't provide a 'execute' functionality (and logically so). Also discovered safe-eval
lib's on NPM are mostly useless and the MDN suggestion of using Function()
does not work. The basic problem with eval
itself in JS are plenty including - (a) Prone to injection attacks (b) Debugging is hard (no line number).
UI developers love JSON. So, why not use JSON itself as the DSL. JSON fit the bill perfectly for requirement #1. Now, could I use the logical expression evaluator lib's in the JSON world for #2? I looked at JsonLogic and Json-Rules-Engine. Tho both these are fine projects, what made me anxious was the verbosity and complexity. The logical expressions were not intuitive and required thorough understanding of the intricacies of these lib's. The language got too verbose too quickly - 2 or 3 levels of nesting was going to make the JSON look monstrous.
Having built large DSL's in my prior engineering career I wanted to checkout the different parser-combinator and parser-generator frameworks that exist in the world of JavaScript. After all, personally, I was coming back to JavaScript world after about 6 years and the language landscape had changed dramatically for the good. This blog by DSL's guru Frederico Tomissetti was very useful in getting started. Based on it and some google search, this is the listing I came up with -
Thinking about parser-generators, the following thoughts bothered me -
Personally, my most favored languages in current times are Scala and Haskell. My ability to write code is fastest in Scala. And I had heard that ScalaJS packs a punch. I also wanted to add the following non-technical requirements -
My interest on this ScalaJS way got a filip when I found that Scala parser-combinators, which is a standalone lib, is available and works perfectly well for ScalaJS. So here is what I built on a bright Saturday 3 months ago -
RegexParsers
data type of Scala parser-combinator. The statements in the DSL are tokenized into a bunch of neat instances of case class/object
- Scala's wonderful support to build ADT helps in giving structure to the token'sIt has some very simple functionality encoded in the DSL. When textInput3
has value of "kumar" entered, it adds a new TextBox etc
The DSL I built is not complete. I wanted to attempt requirement #3 but could not due to paucity of time. But it should be pretty straightforward to add some new keywords for REST/GQL calls connecting these components, or POSTing their values on form submission. What the project did was open my eyes to the possibilities - both within the Scala ecosystem and how the walls between backend/frontend are being shattered in amazing ways. Finally, it also allowed me to code in Scala after a bit of hiatus :)