Jump to: navigation, search

MDT/OCL/MDT-OCL 3.0.0 Migration Guide

< MDT‎ | OCL

CST changes

The CST forms a largely internal API, so OCL applications should be unaffected by changes.

Implementers of derived languages may notice a number of simplifications and enhancements.

ClassifierContextDecl.invOrDefCS and InvOrDefCS.invOrDefCS

InvOrDefCSis now maintained as an ClassifierContextDecl.constraints array rather than a reverse ordered linked list.

Simplify your code.


This class no longer exists.

"A::b" is now parsed as a PropertyCallExpCS, allowing a trailing @pre.

Change code that disambiguated a PropertyCallExpCS from an EnumLiteralExpCS to disambiguate an EnumLiteralExpCS from a PropertyCallExpCS.


This is a new field to support qualified names. It is also used by static calls.

Change old code that detected an anomalous PathNameCS as the FeatureCallExpCS.source to use the FeatureCallExpCS.pathNameCS.

Write new coded to support qualified names.

IsMarkedPreCS and FeatureCallExpCS.isMarkedPreCS

@pre is now parsed to a null/non-null IsMarkedPreCS, avoiding creating objects for the predominant usage of no @pre.

Change any access to test for isMarkedPreCS.isPre() to test for isMarkedPreCS != null. (Failure to change this will give an NPE).

Any usage of a non-null IsMarkedPreCS can be optimised to exploit it's @pre-always behaviour.


This new simpleNames field comprising a list of SimpleNameCS replaces the old sequenceOfNames field comprising a list of String. This allows the token context of each path element to be accesses by CST applications.

Change code to invoke SimpleNameCS.getValue() to obtain the old string.

Use the AbstractOCLAnalayzer.createSequenceOfNames() method to create a list of strings from the list of SimpleNameCS.

PropertyContextCS.initOrDerValueCS and InitOrDerValueCS.initOrDerValueCS

InitOrDerValueCS is now maintained as an PropertyContextCS.constraints array rather than a reverse ordered linked list.

Simplify your code.


This class no longer exists.

An oclIsInState call is now parsed as an ordinary operation call.

The AbstractOCLAnalyzer invokes oclIsInStateOperationCallExpCS().

Grammar changes

The grammar changes should be invisible to OCL users, except in so far as bugs are fixed.

Implementers of derived languages will find that a creaful review is needed to track the changes that align with the OCL specification. In particular the spelling change of the OclExpressionCS to oclExpressionCS will almost certainbly be required. Careful examination of an LPG report file will often reveal that old names are assumed to be non-terminals.

Complete OCL and Essential OCL

The Complete OCL grammar is defined by OCLParser.g, OCLLexer.g, OCLKWLexer.g.

The Essential OCL grammar is now defined by EssentialOCL.g, EssentialOCLLexer.g, EssentialOCLKWLexer.g.

In MDT/OCL 1.3 EssentialOCL.g included a number of Complete OCL facilities such as reserved words, ^ and ^^ message operators and @pre suffixes. These are not present in MDT/OCL 3.0.0.

OCL 2.1 alignment

The MDT/OCL 3.0.0 grammar has been changed to align as closely as possible with the OMG OCL 2.1 concrete syntax and to provide the basis for a comprehensive grammar submitted for incorporation in a future OCL specification via resolution of Issues ...

This alignment causes the following changes.


Production names now match the OCL 2.1 specification as a result the following nominally similar productions are very different.

MDT/OCL 1.3 production MDT/OCL 3.0.0 production
booleanLiteralExpCS BooleanLiteralExpCS
callExpCS CallExpCS
collectionLiteralExpCS CollectionLiteralExpCS
collectionRangeCS CollectionRangeCS
collectionTypeIdentifierCS CollectionTypeIdentifierCS
dotArrowExpCS ~ primaryExpCS
enumLiteralExpCS -
featureCallExpCS FeatureCallExpCS
ifExpCS IfExpCS
integerLiteralExpCS IntegerLiteralExpCS
invalidLiteralExpCS InvalidLiteralExpCS
iterateExpCS IterateExpCS
iteratorExpCS IteratorExpCS
letExpCS LetExpCS
literalExpCS LiteralExpCS
loopExpCS LoopExpCS
nullLiteralExpCS NullLiteralExpCS
oclExpCS ~ primaryExpCS
oclExpressionCS OclExpressionCS
oclMessageArgCS OclMessageArgCS
oclMessageArgumentsCS OclMessageArgumentsCS
primitiveLiteralExpCS PrimitiveLiteralExpCS
propertyCallExpCS PropertyCallExpCS
realLiteralExpCS RealLiteralExpCS
stringLiteralExpCS StringLiteralExpCS
tupleLiteralExpCS TupleLiteralExpCS
unlimitedNaturalLiteralExpCS UnlimitedNaturalLiteralExpCS
variableExpCS AssociationClassCallExpCS
variableCS VariableDeclarationCS
variableCS2 TupleLiteralPartCS
variableListCS variableDeclarationListCS
variableListCS2 TupleLiteralPartsCS


Productions have been adjusted to match the OCL 2.1 presentation.

MDT/OCL 1.3 production MDT/OCL 3.0.0 production
attrOrNavCallExpCS AssociationClassCallExpCS
callExpCS CallExpCS
keywordOperationCallExpCS OperationCallExpCS
messageExpCS OclMessageExpCS
operationCallExpCS OperationCallExpCS
stateExpCS OperationCallExpCS

LPG v2 migration

The OCL parser is generated by the LALR Parser Generator (LPG), a SourceForge project, licensed under the EPL v1.0. In previous releases, LPG v1.x was used in two ways:

  • by MDT-OCL developers so that the OCL parser was generated providing the OCL grammars (in LPG v1.x format).
  • by MDT-OCL project itself so that the generated OCL parser relies on the LPG runtime.

In MDT-OCL 3.0.0 one of the main goals is migrating all grammars and parsing infrastructure so that they are based on the last version of LPG v2. To tackle this challenge, the OCL grammars and some OCL infrastructure will have to be changed so that:

  • the OCL grammars are adapted to the new LPG v2 parser generator (in LPG v2.x format).
  • the new OCL parser will rely on the improved LPG v2 runtime.

Regarding OCL extending languages such as QVTd or QVTo, an specific migration guide has been created which should aim them to accomodate their grammars so that they are suitable for the new LPG v2 parser generator:

  • Due to convention reasons, all the grammars which are thought to be extended/imported by others should be renamed so that they have a .gi file extension. For example, OCLParser.g includes/imports EssentialOCLParser.gi, and imports terminals from OCLLexer.gi which filters the keywords from OCLKWLexer.gi.
  • Changes to an arbitrary OCLKWLexer.g extender:
    • Replace the old KeywordTemplateD.g used template by the new KeywordTemplateF.gi
    • Replace the legacy $Include OCLKWLexer.g $End section, by the new %Import OCLKWLexer.gi %End one.
    • Replace any $ symbol which was used to mark a section, by the new the new % symbol, so that, for instance, $Define...$End section turns into %Define...%End
  • Changes to an arbitrary OCLLexer.g extender:
    • Replace the old LexerTemplateD.g used template by the new LexerTemplateF.gi
    • Replace the legacy $Include LexerBasicMap.g $End section, by the new %Import exerBasicMapF.gi %End one.
    • Replace any $ symbol which was used to mark a section, by the new the new % symbol, so that, for instance, $Define...$End section turns into %Define...%End
  • Changes to an arbitrary OCLParser.g extender:
    • Replace the legacy $Import OCLParser.g $End section, by the new %Import OCLParser.gi %End one.
    • Replace any $ symbol which was used to mark a section, by the new the new % symbol, so that, for instance, $Globals...$End section turns into %Global...%End
    • Replace any $empty appearance by %empty.
    • Replace any $BeginJava and $EndJava macro use, by $EndCode and %EndCode.
    • If overriden, Replace the $lex_stream_class/.SomeLexerClass./ macro use, by $super_lexer_class/.SomeLexerClass./
    • The use of getIToken and getTokenText is deprecated now. So it's recommended to do the following in the action-blocks:
  - Replace $getSym(i) by getRhsSym(i)
  - Replace getTokenText($getToken(i)) by getRhsTokenText(i)
  - Replace getIToken($getToken(i)) by getRhsIToken(i)
  - Replace the remaining $getToken(i) by getRhsTokenIndex(i)
  • Apart from that. The generated Lexer and Parser don't inherit from LexStream and PrsStream anymore. Instead, an instance of them are contained by the generated Lexer and Parser, respectively. In consequence, indoer to invoke any function related the LexStream or PrsStream via the Lexer or the Parser, the client should firstly access to them doing getILexStream() or getIPrsStream(), respectively.