Introduction: Ward Cunningham once said that clean code clearly expresses what the code writer wants to express, while graceful code goes further, and beautiful code looks like it is specifically for the problem to be solved. In this article, we will show the design and implementation of a modular parser, the final code is graceful and extensible, as if it were to parse a particular syntax. We will also select an example in the H.248 protocol to implement its parser using the combined parser described above. In this process, readers can not only appreciate the beauty of the code, but also learn some knowledge of functional programming and the construction of DSL.
The basics of DSL design
When we implement a feature in a programming language (e.g., the Java language), we are actually directing the computer to accomplish this function. But what language can bring to us is not limited to that. More importantly, language provides a framework for organizing our thinking and expressing computational processes. The core of this framework is how to combine simple concepts into more complex concepts while preserving their closure of combinatorial methods, that is to say, complex concepts combined are identical for combinatorial approaches and simple concepts. In the words "Structure and interpretation of Computer Programs", any powerful language can achieve this goal through the following three mechanisms:
Atom: The simplest and most basic entity in a language;
Combination means: A method of combining atoms together to form more complex entities;
Abstract means: A method of naming complex entities that can be combined into more complex entities, as with atoms.
A general-purpose programming language such as Java is concerned with the general approach to solving problems. Therefore, the three mechanisms provided by this system are also common-level. There is a semantic gap between this generic approach and the concepts and rules in specific problem areas when solving specific problems, so clearly defined concepts and rules in some problem areas may become less clear when implemented. As a programmer, using clean code to achieve functionality is only a primary requirement, more importantly, to promote the level of the common language and build a language (DSL) for a particular problem domain, the key point in this process is to find and define the atomic concepts, combinatorial methods, and abstract means in the problem-oriented domain. This DSL does not have to be as complete as the common language, its goal is to clearly and intuitively express the concepts and rules in the domain of the problem, and the result is to turn a common programming language into a specialized language for solving specific problems.
We have built a DSL for interface layout in the article "Design and implementation of a java-based interface layout DSL", which presents the above ideas. In this article, we'll take the parser's construction as an example of how to build a DSL for string parsing, a DSL with powerful scalability that allows readers to define their own combinations based on their needs. In addition, the reader can also enjoy the elegance of functional programming from this article.