Source-linked AI summary
MontiCore: a Framework for Compositional Development of Domain Specific Languages
Holger Krahn, Bernhard Rumpe, Stefan Völkel
TL;DR
DSL development must manage increasing complexity, evolution, reuse, and consistency across language artifacts. MontiCore addresses these issues with a concise grammar-based representation, graph-capable abstract syntax, and grammar inheritance and embedding for modular composition. The framework supports textual language and tool development and has been used for examples including UML/P and Java 5.
Problem
Increasingly complex DSLs are difficult to evolve, reuse, and keep consistent when concrete and abstract syntax and related artifacts must develop together.
Method
MontiCore uses one extended grammar format for concrete and abstract syntax, adds associations and inheritance for graph structures, and provides grammar inheritance and language embedding.
Results
MontiCore supports modular, compositional language development with embedding and language inheritance, and has been used for language definitions including UML/P and complete Java 5.
Takeaways & Limitations
Compositional engineering in MontiCore supports project-individual DSLs with corresponding tool support and controlled reuse of existing languages.
Takeaways & Limitations
Multiple grammar inheritance can produce name clashes, and combining conflicting super-productions is not always possible.
Abstract
from arXiv · showhide
Domain specific languages (DSLs) are increasingly used today. Coping with complex language definitions, evolving them in a structured way, and ensuring their error freeness are the main challenges of DSL design and implementation. The use of modular language definitions and composition operators are therefore inevitable in the independent development of language components. In this article, we discuss these arising issues by describing a framework for the compositional development of textual DSLs and their supporting tools. We use a redundance-free definition of a readable concrete syntax and a comprehensible abstract syntax as both representations significantly overlap in their structure. For enhancing the usability of the abstract syntax, we added concepts like associations and inheritance to a grammar- based definition in order to build up arbitrary graphs (as known from metamodeling). Two modularity concepts, grammar inheritance and embedding, are discussed. They permit compositional language definition and thus simplify the extension of languages based on already existing ones. We demonstrate that compositional engineering of new languages is a useful concept when project-individual DSLs with appropriate tool support are defined.
1 Introduction
DSLs help address the complexity and risks of software development, but their growing complexity makes evolution, reuse, and error freeness harder. MontiCore addresses these challenges through concise textual definitions, modularity mechanisms, and integrated tooling.
- DSLs are used to fit software development to specific domains and reduce the costs and risks of complex development.
- As DSLs become more complex, evolving them, ensuring error freeness, and reusing language components become harder.
- Separate concrete and abstract syntax definitions create redundancy, duplication, inconsistencies, and costly synchronized co-evolution across language modules.
- MontiCore uses an extended grammar format to define textual concrete and abstract syntax together, while supporting associations and inheritance for graph-based abstract syntax.
- MontiCore also supports modular tools, including model traversal, Eclipse editing features, error reporting, and command-line use for build scripts.
- Grammar inheritance supports incremental language changes, while compositional embedding combines language fragments into coherent languages.
2 Language definition using MontiCore
MontiCore uses an enriched grammar to define concrete and abstract syntax together, while extending grammar-based definitions with object-oriented features and associations for modular, graph-structured DSLs.
- Concrete and abstract syntax: MontiCore uses one enriched grammar to define both a language’s concrete textual syntax and its abstract syntax.The single-definition approach avoids consistency problems between separate syntax descriptions and aligns similar concrete and abstract elements by construction.
- Concrete and abstract syntax: The grammar format supports productions, alternatives, blocks, repetitions, cardinalities, named elements, token classes, and mappings to data types.Token classes can map strings to primitive or arbitrary Java-defined types, while named grammar elements become accessible in the abstract syntax.
- Concrete and abstract syntax: MontiCore flattens some grammar structures in the abstract syntax, so deeply nested blocks can lose ordering information that source positions help reconstruct.The approach represents alternatives such as B and C as attributes in a relatively flat class A; source positions preserve the order of occurrences in the text.
- Motivation for extensions: The framework’s advanced features address duplicated substructure and invariants that arise in language definitions by adding inheritance, interfaces, and associations.The ShopSystem example motivates these extensions because related productions can otherwise share structure without being related, while semantic constraints remain invisible in the class structure.
- Inheritance and interfaces: Inheritance and interfaces add object-oriented structure to abstract syntax, allowing subclasses to reuse inherited attributes and interfaces to represent alternatives without changing existing productions.The extends relation maps to class inheritance, and implements causes an interface-nonterminal to be realized as an alternative production.
- Associations: Associations extend the grammar-generated tree into an arbitrary graph with an embedded composition spanning tree, supporting direct links between related abstract-syntax objects.MontiCore establishes association links after parsing, enabling forward references and developer navigation through generated methods without distinguishing those links from parsing-established links.
3 Modularity concepts
MontiCore supports modular language development through grammar inheritance and language embedding, extending or combining independently developed languages while propagating modularity into abstract syntax and tooling.
- Modularity concepts: MontiCore uses grammar inheritance to extend existing languages by specifying differences, while embedding combines separately designed languages or language parts.These concepts also apply beyond concrete syntax to ASTs, context conditions, analysis, code generation, and tool infrastructure.
- Grammar inheritance: Grammar inheritance can reuse multiple grammars, allowing extensions such as SQL-select expressions inside a general-purpose language.The new grammar inherits productions from the GPL and SQL grammars rather than rebuilding both languages monolithically.
- Grammar inheritance: Inherited productions generate subtype AST classes, so algorithms written for the supergrammar can continue to process extended-language classes without complete reimplementation.This reuse can include complicated analyses such as symbol-table building, possibly after minor adaptation.
- Grammar inheritance: Multiple inheritance has a name-clash limitation: shared production names require a new production that is a subtype containing all inherited elements, which may be impossible for contradictory super-productions.MontiCore avoids explicit superclass-resolution strategies and instead advocates refactoring contradicting supergrammars.
- Language embedding: Language embedding marks external nonterminals as hooks where another grammar continues parsing, and MontiCore combines the independently derived parsers at runtime.The resulting grammar behaves as the union of the fragments, while the languages and their parsers, ASTs, and processing algorithms remain independently developable.
- Language embedding: Embedding and inheritance can be used in parallel because the two modularity concepts do not interfere with each other.This supports language combinations that require both reusable extensions and separately developed embedded languages.
4 Developing tools in a modular fashion using the DSLTool-framework
The DSLTool-framework extends MontiCore’s modular parsing approach to analysis and code generation, providing configurable infrastructure for processing abstract syntax and integrating language-specific tools.
- Framework scope: The DSLTool-framework supports modular generative and analytic tools that operate on DSL abstract syntax, complementing MontiCore’s modular parser and AST infrastructure.Its focus is compositional language engineering across parsing, analysis, and code generation.
- Architectural drivers and main features: The framework’s architectural drivers include decoupled algorithms, integration of languages and algorithms, flexible configuration, reusable APIs, and cross-platform execution.These drivers guided the framework’s supported functions.
- Architectural drivers and main features: The MontiCore grammar generator was created during bootstrapping and provided feedback on the DSLTool-framework design.The experience came from creating various DSL tools, especially the generator for the MontiCore grammar format.
- Framework architecture: DSLTool organizes input models as root objects, whose common DSLRoot type provides access to generators, file processing, status messages, ASTs, and symbol tables.RootFactory objects set up parsers and pretty printers, while Execution-Units encapsulate stateless algorithms operating on AST roots.
- Traversal: Model traversal follows the spanning composition tree through an adapted Visitor pattern implemented with Java Reflection, supporting dynamic extensibility from language embedding.Generated traverse(...) methods reduce the traversal slowdown to factor 4, compared with reported reductions of factor 18 to 256 for other non-invasive approaches.
- Eclipse: MontiCore can generate Eclipse plugins from a grammar plus a small editor description, while language embedding automatically produces tools supporting combined functionality.For inheritance, only the language delta and corresponding editor-functionality delta need to be specified or generated.
5 Related work
Related work spans textual language workbenches, parser and attribute-grammar systems, and frameworks supporting modular syntax or language extensions. MontiCore is distinguished by integrating concrete and abstract syntax with broader modularity across language-development artifacts.
- Textual language workbenches provide formalisms for specifying textual domain-specific languages, complementing graphical approaches.
- Grammar Deployment Kit supports parser-generator transformation and grammar adaptation, but not extensions such as inheritance or associations.
- MontiCore combines concrete and abstract syntax in a grammar-based representation, unlike approaches using separate descriptions or lacking strongly typed internal representations.
- TCSSL specifies a bidirectional mapping between textual representations and models, whereas MontiCore focuses on AST-based analysis, transformation, and code generation.
- Composable parsing approaches address modular syntax, while MontiCore integrates compositionality across concrete syntax, abstract syntax, and other language-development aspects.
- Attribute-grammar systems can modularize language development and represent references between AST nodes, comparable to MontiCore associations.
6 Conclusion
The paper presents MontiCore as a framework for modular, compositional development of textual languages. It combines concise syntax specification and graph-capable ASTs with grammar inheritance and language embedding, and reports use on examples including UML/P and Java 5.
- The work’s main results are modular and compositional language development through language embedding and language inheritance.
- MontiCore specifies concrete and abstract syntax in one concise grammar format, reducing redundancy between separate syntax descriptions.
- Associations and generated name-resolution support extend ASTs from trees to graphs with spanning trees.
- Grammar inheritance extends nonterminals while preserving the base grammar and generated code, whereas embedding fills explicit grammar holes with another language.
- MontiCore composes independently generated parsers, symbol tables, and infrastructure at configuration time, including when source code is unavailable.
- The framework has been used for toy examples and sophisticated language definitions including UML/P and complete Java 5.