Frag Logo
  Frag Home | Frag SF Project   index | contents | previous | next

Creating DSLs with Frag: Introduction

Overview

Developing custom software for a specific target domain is a challenging task. In this context, domain-specific languages (DSLs) receive a constantly growing attention in recent years. A domain-specific language (DSL) is a tailor-made language that does only provide abstractions suitable for one particular problem domain.

DSLs have gained popularity in the area of model-driven development (MDD), especially through the advance of so-called language workbenches. The basic idea of DSLs, however, already has a long history. Language workbenches take the well known language-oriented programming approach and use IDE tooling to make it a viable approach. Examples of language workbenches are MDD tools such as XText, Microsoft's DSL toolkit, MetaCase, Microsoft's OSLO, and MPS. In contrast to simple language-oriented programming approaches, focusing mainly on parser development and related activities, language workbenches support all aspects of DSL design and development, including for example the transformation of DSL code to a platform or the development of language editors for the DSL. In addition to language workbenches, some other DSL toolkits exist that support many aspects of DSL design and development. For example, DSLs in dynamic languages are typically developed as embedded DSLs that can use the existing tooling and platforms of the dynamic language.

Frag aims at supporting DSL development by combining the best of both worlds and a few other unique concepts.

With the DSL toolkits becoming more mature, DSLs are not only used in niches anymore, but receive widespread adoption. For many architects, DSLs are an interesting approach that can potentially be used in projects where domain knowledge is hard to capture. DSLs can help here, as they come with the promise to enable involving domain experts more closely in the software design activities.

Architecture can be seen as a set of design decisions rather than (only) a set of components and connectors. In this view, the architect needs to understand which architectural decisions are influenced by the choice of an approach or a technology. The above named toolkits require architects to make important architectural decisions about the DSLs in a project early on - when the DSL toolkit is chosen. Example decisions are: the decision for an embedded or external DSL approach, the possible integration with a host language, the options for syntax extensions, the options for the use of an explicit language model, the usability options with regard to custom error messages, the language integration options, and the choice between generation, transformation, and interpretation for defining the DSL's execution semantics. Often significant changes or even a complete reimplementation of the DSL in another technology would be necessary to change some of these architectural decisions later on, once a DSL implementation has been completed.

In our experiences, it is often necessary to focus in early stages of DSL projects on getting the domain abstractions right. Work collaboratively conducted by the domain experts and the software designers is needed, and approaches, such as rapid application development, tinkering with DSL ideas, and agile methods with many iterative feedback cycles, are highly useful in DSL-based design and development. The dilemma is: On the one hand, toolkit-specific decisions, should be deferred till the domain abstractions and requirements are sufficiently understood, but, on the other hand, tinkering with the DSL requires some realistic DSL toolkit that preselects many options for the decisions listed above.

Of course, it is possible to solve this dilemma by developing a throw-away prototype that is replaced by another technology, once a first sufficient understanding of the domain has been reached. In contrast, Frag's approach follows the idea to provide a DSL language toolkit that supports incrementally evolving a DSL and still allows DSL designers to change fundamental decisions later on.

In the following sections, we present Frag as a toolkit for DSL-based design and development. In Frag, we (optionally) base DSLs on an explicit language model for the DSL - similar to models in model-driven DSL approaches. We also combine the external DSL and the embedded DSL approaches in a unique way: For each language model, Frag provides an intuitive embedded DSL syntax. In addition, one or more external DSLs can be added and mapped to Frag, using a flexible rule-based parsing approach that aims at supporting tinkering with syntax ideas. Each DSL artifact is provided as a modular entity that can be selected/deselected at any stage of a DSL project. All specifications of DSLs in Frag are provided using DSLs that are embedded in Frag (which is itself embedded in Java; hence every Frag DSL can be used in Java applications). Such embedded DSLs are provided for specifying language models, constraints, parser specifications, and mapping specifications. That is, the Frag approach for specifying DSLs follows the DSL approach itself.

DSL Basics

DSLs can be defined for technical users, such as software developers or architects, as well as non-technical users, such as business analysts. In either case, the DSL should make the domain-knowledge explicit, and help the DSL users to accomplish their work tasks. In general, we can distinguish two different styles of DSLs:

From a language user's point of view, the DSL consists of language elements. The core definition of these language elements is provided by the language model that specifies the concepts of the DSL's target domain. For instance, if the target domain is SOA, then elements such as service, process, and business object are part of the language model. If the target domain is core banking, then elements such as account, bond, and customer are part of the language model. The MDD paradigm advocates to specify the language model (sometimes called DSL metamodel) explicitly using a modeling language such as UML or EMF. Other implementation options for DSLs, such XML-parser-based DSLs, DSLs based on scripting languages or dynamic languages, or DSLs based on parser generators, do not imply an explicit language model - it is often implemented and hidden in the DSL implementation source code.

In order to use the DSL, we must define its semantics, too. For many DSLs, static semantics are defined through constraints on the language model, as well as program code defining the execution semantics of the DSL. Both, language model and static semantics of the DSL are called the abstract syntax of the DSL. The architect must decide how static semantics are implemented: Besides constraint languages offered by some of the model-driven toolkits, expressing them in transformations, in custom code, or not at all are options.

In addition to the abstract syntax, each DSL needs a concrete syntax, offered to the user of the DSL. Each DSL can have multiple concrete syntaxes. We can distinguish textual syntaxes, graphical syntaxes, form-based syntaxes, and so on. The architect must decide for the kinds of concrete syntaxes that are supported by the DSL. Frag mainly focuses on textual concrete syntaxes. Transformations are defined to transform DSL code written in a concrete syntax to another model representation or to code that can be executed on a specific platform. In general, a transformation is a directive that defines how one (model) format is to be transformed to another (model) format. In different approaches, the transformations are realized in different ways: In the model-driven approaches, a generator performs the transformations. In scripting and dynamic languages, the concrete syntax code is mapped to directives of the interpreter. A parser generator creates a parser that triggers instructions in a programming language. In all approaches, a programming language executes the DSL code and is used as the target of the transformations. This programming language is called the host language.

  index | contents | previous | next