Overview

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.

Basic Structure

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.

IMPORT

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.

RULE

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 a
    
Also, there may be zero or more linking sub-parts, but only one each of the others.

PATTERN

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
    

TEMPLATE

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

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 ]*
    

Expressions

Expresions are either variable names, literals, function calls, path expressions, or expressions involving the usual mathematical operators:

  • string literals are surrounded by double-quotes with backslash being the escape character,
  • integer literals are a sequenec of one or more digits,
  • boolean literals are the keywords true and false (must be lower-case)
  • an object reference literal is a URI surrounded by angle-brackets,
  • a function call is a function name follow by its arguments (expressions) in brackets,
  • path expressions begin with a variable name and are followed by one or more period-feature or arrow-feature pairs. A period-feature pair means get the value of the specified feature (or invoke the specified method if it is suffixed with bracketed arguments for the object referenced by the previous path element. An arrow-feature pair means do the same for each element of the collection-valued object referenced by the previous path element. If a pair is suffixed by braces (curly brackets), then the result is a collection rather than being a set of results, one for each object.
def
    "string_"
    integer_
    true | false
    < uri_ >
    name_ ( expressions )
    variable_ [ ( . | -> ) feature_ ()? {}? ]+
    

Note, currently enums can only be written using object literals.

Rule extending and overriding

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_ ) ]*