This document is intended to provide a quick, informal introduction to the Tefkat concrete syntax. It assumes a basic understanding of the ideas behind model transformation, as well as URIs, EMF, and simple grammar rules.
In the grammar fragments, we use a trailing underscore to indicate labels, while keywords and literals look like this: RULE and non-terminals look like this: expression.
Note, all Tefkat keywords must be in upper case except for the boolean literals true and false.
A transformation specification is normally stored in a single file with the suffix .qvt. This file starts with a line of the form:
def TRANSFORMATION name_ : source_ [, source_]* -> target_ [, target_]*
This provides a name for the transformation followed by (comma separated) names for each of the input (source) model instances and each of the output (target) model instances. The first source instance is used as the default context for FORALL and WHERE expressions, and the first target instance is used as the default context for MAKE and SET expressions.
This is followed by a series of import statements and rule and patterm definitions.
In order for the transformation engine (and also the parser) to be able to resolve class names, you must specify the set of models that define those types. This is done with an import statement which has the form:
def IMPORT uri
Generally, the uri will be of the form http://... or platform:/resource/... or file:/... and should resolve to an EMF ECore instance.
It is normal that you would include an import statement for each source model and each target model and for the tracking model (if you use one).
Note, if the Ecore model you are importing has been loaded as a plugin then you should use the URI to reference the model rather than a URL that points to the ECore file.
Rules are named and consist of a number of (optional) sub-parts: forall, where, make, set, and linking, and have the following form:
def RULE name_ FORALL class_ variable_ WHERE condition MAKE ( class_ variable_ FROM name_ ( expressions ) | template_name_ ( expressions ) ) SET path = expression LINKING tracking_ WITH name_ = expression ;
We have omitted fomally indicating where repeated elements may occur in the above for the sake of clarity. Each of the sub-parts forall, make, and set may contain repeated elements separated by commas. For example:
FORALL Person p, Account aAlso, there may be zero or more linking sub-parts, but only one each of the others.
Patterns are like rules, but can only match things so are limited to forall and where sub-parts. As well as being named, they also have one or more variables nominated as parameters.
def PATTERN name_ ( variables_ ) FORALL class_ variable_ WHERE condition
Templates are like rules, but can only create or set things so are limited to make, set, and linking sub-parts. As well as being named, they also have one or more variables nominated as parameters.
def TEMPLATE name_ ( variables_ ) MAKE class_ variable_ WHERE condition LINKING tracking_ WITH name_ = expression
Conditions take on the usual form of boolean-valued comparisons or pattern invocations linked together by ANDs, and ORs and optionally prefixed by NOT. Brackets are used to explicitly control precedence, but the usual rules apply. The keyword UNDEF is used to test for a null-valued feature.
def ( expression op expression | name_ ( expressions ) ) [(AND | OR) condition ]*
Expresions are either variable names, literals, function calls, path expressions, or expressions involving the usual mathematical operators:
def "string_" integer_ true | false < uri_ > name_ ( expressions ) variable_ [ ( . | -> ) feature_ ()? {}? ]+
Note, currently enums can only be written using object literals.
A rule can extend or override other rules, but it may not both extend and override the same rule.
def RULE name_ ( vars_ ) EXTENDS name_ ( vars_ ) [ , name_ ( vars_ ) ]* OVERRIDES name_ ( vars_ ) [ , name_ ( vars_ ) ]*