Lingo: A Go micro language framework for building Domain Specific Languages
Domain Specific Languages (DSL) are small, focused languages with a narrow domain of applicability. DSLs are tailored towards their target domain so that domain experts can formalize ideas based on their knowledge and background. This makes DSLs powerful tools that can be used for the purpose of increasing programmer efficiency by being more expressive in their target domain, compared to general purpose languages, and by providing concepts to reduce the cognitive load on their users. Consider the problem of summing up the balances of different bank accounts in a CSV file. A sample CSV file is provided in the example below where the first column contains the name of the account holder and the second column contains the account balance. name, balance Lisa, 100.30 Bert, 241.41 Maria, 151.13 You could solve the problem of summing up balances by using a general-purpose language such as Ruby as in the code snippet below. Apart from the fact that the code below is not very robust, it contains a lot of boilerplate that is irrelevant to the problem at hand, i.e., summing up the account balances. #!/usr/bin/env ruby exit(1) if ARGV.empty? || !File.exist?(ARGV[0]) sum = 0 File.foreach(ARGV[0]).each_with_index do |line, idx| next if idx == 0 sum += Float(line.split(‘,’)[1]) end puts sum.round(2) Below is an example AWK script that solves the same problem. AWK is a DSL that was specifically designed to address problems related to text-processing. #!/usr/bin/awk -f BEGIN{FS=”,”}{sum+=$2}END{print sum} The Ruby program has a size of 208 characters, whereas the AWK program has a size of 56. The AWK program is roughly 4x smaller than its Ruby counterpart. In addition, the AWK implementation is more robust by being less prone to glitches that may appear in the CSV file (e.g., empty newlines, wrongly formatted data-fields). The significant difference in terms of size illustrates that DSLs, by being more focused on solving specific problems, can make their users more productive by sparing them the burden to write boilerplate code and narrowing the focus of the language on the problem at hand. Some popular DSLs most software developers use on a regular basis include Regular Expressions for pattern matching, AWK for text transformation or Standard Query Language for interacting with databases. Challenges when designing Domain Specific Languages Prototyping, designing and evolving DSLs is a challenging process. In our experience this is an exploratory cycle where you constantly prototype ideas, incorporate them into the language, try them out in reality, collect feedback and improve the DSL based on the feedback. When designing a DSL, there are many components that have to be implemented and evolved. At a very high level there are two main components: the language lexer/parser and the language processor. The lexer/parser is the component that accepts input as per the language definition which is usually specified specified by means of a language grammar. The parsing/lexing phase produces a syntax tree which is then passed onto the language processor. A language processor evaluates the syntax tree. In the example we saw earlier, we ran both the Ruby and AWK interpreters providing our scripts and the CSV file as input; both interpreters evaluated the scripts and this evaluation yielded the sum of all the account balances as a result. Tools such as parser generators can significantly reduce the effort of lexer/parser development by means […]
