Racket and Xtext are both considered as language workbenches, but they are based on different concepts and workflows.
As an experienced Xtext user, I find it difficult to adapt my thought process to Racket.
In Xtext, the grammar of a language is converted into, or mapped to, a set of classes (also called a metamodel). Xtext also generates a parser that converts a source file into a set of instances of those classes. A scoping API allows to resolve named references, so that the result is an object graph (also called a model) rather than an abstract syntax tree (AST). Such a model can be queried, transformed, or fed into a template engine to generate code.
In Racket, the reader produces an AST in the form of a syntax object. However, most examples that I have found seem to make an ad-hoc use of this syntax object. Either they are toy languages that do not need a complete object graph, or they are too complex and it is difficult to infer a general methodology.
For my current language project, after struggling with syntax objects, I have created the equivalent of a metamodel using Racket structs. Then it was fairly easy to convert a syntax object into an object graph that I could manipulate as if it were a model in EMF. However, I feel like I am not using syntax objects the way they are intended to be.
Here are my questions:
- What tools or APIs are available to work on syntax objects and achieve a similar ease-of-use as a model-driven framework?
- Are there documents that describe a general language development methodology in Racket, that could be applied to non-trivial languages?
- Are there documents that explain the Racket way, compared to Xtext or any other model-driven language framework?
EDIT:
Based on the documentation for Metaprogramming helpers, syntax classes can be used to specify and compose syntax patterns, and attach attributes to their elements. They can achieve a similar purpose as the classes of a metamodel. However, as far as I can see, syntax classes are not classes, and syntax objects are not linked to syntax classes in a class-instance relationship. This has the following consequences:
- Syntax classes do not support inheritance directly, but we can achieve a similar effect with
~or*
and attribute declarations for subclasses. - Syntax classes do not come with accessors for their attributes: you have to call
syntax-parse
every time you want to read an attribute.
At this point, there are still two missing features that are not addressed in the documentation that I have found:
- Traversing a syntax tree from child to parent: how can I get a reference to the syntax object enclosing a given syntax object?
- Scoping: how can I define specific scoping rules for my language?
attribute
or, under#'
, dot-notation); Syntax Spec which is relatively new but may fit your ideal workflow more closely. – Tumer