GenTL adopts the syntax for meta-variables and concrete syntax patterns from LogicAJ2.
MetaVariable := ?Name | ??Name CSP := ‘[[’ ... base language code with meta-variables... ‘]]’
GenTL supports self-defined logic predicates in the usual Prolog notation. Own
predicates can be defined based on a standard set of predefined predicates common
to logic programming languages. However, GenTL explicitly excludes predicates
that change the logic database. Only the most important predefined predicates are
described in the following.
For encapsulating concrete syntax patterns GenTL supports the predicate
described in detail in Section 4. Unification of two variables is denoted with the
PatternPredicate := MetaVariable is CSP Unification := MetaVariable = MetaVariable
If the arguments are different constants or variables bound to different constants,
unification fails. Otherwise the arguments are unified, that is, they are bound to
the same value. Note that, unlike an assignment, unification is symmetric. For
instance, the unification of a constant on the left-hand-side and a variable on the
const = ?var succeeds if the variable has the same value as the
constant or did not have a value before.
The predicate member(element, list) checks if an element is a member of a given
list. Elements can be removed from lists with delete( old list, element, new list).
A conditional transformation is a first-class language element in GenTL. Its syntax
is described below in EBNF notation. Non-terminal symbols are indicated by italics.
Terminal symbols are in sans serif font. Note that
* are the
usual symbols of the EBNF notation whereas
'' and '' are terminal symbols of GenTL:
CT := ct Name ( Arguments ) : Condition -> > Transformation . Arguments := [ MetaVariable [ , MetaVariable ]* ] Condition := PredicateInvocation | ! Condition // Negation | Condition , Condition // Conjunction | Condition ; Condition // Disjunction Transformation := Action [, Action]*
CTs are well-formed if and only if their transformation part only contains meta-variables that are also part of the condition. A condition is any logic expression that can be built by conjunction, disjunction and negation from the self-defined and predefined predicates. A transformation is a sequence of the following basic actions:
Action := skip | add Template before MetaVariable | add Template after MetaVariable | delete MetaVariable | replace MetaVariable with Template Template := [[..: base language code with meta-variables...]]
Compared to the basic CT concept, the syntax of transformations supports a higher level of abstraction. First, it enables use of concrete syntax patterns for specifying code to be generated. Second, it frees programmers from having to manage the creation of new unique element identities. Third, it allows for specifying relative locations of added elements with respect to existing ones. The first two feature free GenTL programmers from having to know the internal representation of a program. As a consequence, they cannot insert elements at a specific location by setting the respective arcs in the (unknown) AST. This explains the necessity of a syntax for specifying relative locations independent of the internal representation.
In order to support reuse, source code to be generated by transformations can be encapsulated into named and parameterized templates using generate declarations.This corresponds to the following refinement of the definition of templates:
Template := CSP | Generate Generate := generate Name ( Arguments ) CSP
The signature (name and arguments) defined by a generate declaration can be used like a concrete syntax pattern. It acts like a macro, propagating its arguments into the patten that it encapsulates. Transformations can be composed using AND- and OR-Sequences:
CTSEQ := ctseq Name ( Arguments ): SeqBody . SeqBody := CT Call | CT Call OR SeqBody | CT Call AND SeqBody CT Call := Name ( Arguments )