4 ms·
I respect this article a lot (and I appreciated the Rust compiler generator pointer in it!); my own personal take is one of partial agreement, but I would like
by jll29 4y ago
I respect this article a lot (and I appreciated the Rust compiler generator pointer in it!); my own
personal take is one of partial agreement, but I would like to raise two points here:
1. Part of compiler construction courses is to instill in the students the notion
of metea-linguistic abstraction (SICP), namely to solve problems by creating
and implementing domain-specific languages (DSLs) that permit declarative statements
about the domain in a natural and therefore maintainable notation, which is separate
from an engine that can interpret or compile it.
Compiler classes are ideal to teach about DSLs because the topic is parsing and
compiling/iterpreting anyhow, but not only that, they can see that compiler people
do as they say: they use the techniques for compiler construction themselves, which
is often but not always done using even more than one DSLs (one for lexers, one for grammars,
sometimes even DSLs). Parser generators are also used outside of programming languages,
for example in computational linguistics formal grammars are often used to model
human language morphology, phonology or syntax (with ambiguous grammars). Tomita's GLR parsing
- mentioned elsewhere in this thread - comes from that application area.
2. Another part of compiler construction tertiary education is to get across the
utility of theory for practical applications and the closeness of theory and practice
in computer science: Formal language theory is beautiful and well-developed, and to
show to students that it is also useful because it gives runtime and space complexity
guarantees and systematic approaches for reducing faulty implementations is a wonderful
thing.
- mjburgess 4y agoOne could also interpret the "failure" of compiler writers to do this as evidence that the "DSL paradigm" for programming itself is, at best, extremely limited. One obvious problem is that the semantics of a DSL arent extendable in that DSL, making it highly brittle. So, eg., with parsing, as soon as you need bespoke syntax-error handling, etc. etc. you're leaving the world of any DSL you can create. Since "bespoke" here will, ultimately mean, a semantic specialisation that no generic DSL will support. At the point where your DSL enables these abitary specialisations, it is just the host language.
- danielheath 4y agoThat’s why DSL-in-ruby is a moderately popular technique; the host language is expressive enough to host a DSL without a custom parser.
- silon42 4y agoGive me an xml/json schema any day over this.
- danielheath 4y agoI fail to see how those things are at all alike. An xml/json schema is for validating a serialization format; a DSL-in-ruby is a programming language (to be fair, it's likely a mess, but I've definitely seen it be less mess). When you look at business rules / requirements, it's common for 99% of them to be trivial. Of the remainder, 99% are only moderately complex. If you have, say, fewer than 10k distinct rules, you probably don't have more than one that's really wicked. However, if you have 100k rules, it's more likely than not that you have quite a few that are going to completely wreck your xml/json model.
- seanmcdirmid 4y agoDSL in Kotlin is popular as well.
- crapaud23 4y agoIn Clojure, the adage says "When building DSL, favor data over functions over macros". When I write a DSL I start by writing a sample of it as pure data (think of Clojure as a data processing oriented language with embedded JSON (to be exact, the format is called EDN)). Then I write the parsing function. What I do though is to make sure the parser is extensible. To do so I cast any data element that this function parses into a corresponding function, except if that element is already a function. This way I can directly write custom functions within the DSL. This is very handy when handling conditions and their composition through function combinators. I can just reuse the language boolean logic (if, if-not, switch-cases etc) and don't have to reimplement it withing the DSL. Once the DSL data has been parsed into functions, they are then composed through classical function composition available in the language. Sometimes I also wish I had access to the DSL through macros, mostly to optmize those DSL. The situation I have found myself to need this required me to impact the compiler's state in some way, so I didn't carried my investigations forward regarding this subject, and I'm very interested in the development of Lux/luxlang since it comes with macros that are passed the compiler's state monadically.