Concrete Syntax
ExpressionInOclCS
The ExpressionInOcl symbol has been added to setup the initial
environment of an expression.
ExpressionInOclCS ::= OclExpressionCS
Abstract syntax mapping
ExpressionInOclCS.ast : OclExpression
Synthesized attributes
ExpressionInOclCS.ast = OclExpressionCS.ast
Inherited attributes
The environment of the OCL expression must be defined, but what
exactly needs to be in the environment depends on the context of
the OCL expression. The following rule is therefore not complete. It
defines the env attribute by adding the self variable to an empty
environment, as well as a Namespace containing all elements visible
from self. (In Section 12.2, "The
ExpressionInOcl Type," the contextualClassifier will be
defined for the various places where an ocl expression may occur.) In
the context of a pre- or postcondition, the result variable as well as
variable definitions for any named operation parameters can be added in
a similar way.
OclExpressionCS.env =
ExpressionInOclCS.contextualClassifier.namespace.getEnvironmentWithParents()
.addElement ('self',
ExpressionInOclCS.contextualClassifier, true)
OclExpressionCS
An OclExpression has several production rules, one for each
subclass of OclExpression. Note that UnspecifiedValueExp is handled
explicitly in OclMessageArgCS, because that is the only place where it
is allowed.
OclExpressionCS ::= PropertyCallExpCS
OclExpressionCS ::= VariableExpCS
OclExpressionCS ::= LiteralExpCS
OclExpressionCS ::= LetExpCS
OclExpressionCS ::= OclMessageExpCS
OclExpressionCS ::= IfExpCS
Abstract syntax mapping
OclExpressionCS.ast : OclExpression
Synthesized attributes
- OclExpressionCS.ast = PropertyCallExpCS.ast
- OclExpressionCS.ast = VariableExpCS.ast
- OclExpressionCS.ast = LiteralExpCS.ast
- OclExpressionCS.ast = LetExpCS.ast
- OclExpressionCS.ast = OclMessageExpCS.ast
- OclExpressionCS.ast = IfExpCS.ast
Inherited attributes
- PropertyCallExpCS.env = OclExpressionCS.env
- VariableExpCS.env = OclExpressionCS.env
- LiteralExpCS.env = OclExpressionCS.env
- LetExpCS.env = OclExpressionCS.env
- OclMessageExpCS.env = OclExpressionCS.env
- IfExpCS.env = OclExpressionCS.env
Disambiguating rules
The disambiguating rules are defined in the children.
VariableExpCS
A variable expression is just a name that refers to a variable.
VariableExpCS ::= simpleNameCS
Abstract syntax mapping
VariableExpCS.ast : VariableExpression
Synthesized attributes
VariableExpCS.ast.referredVariable =
env.lookup(simpleNameCS.ast).referredElement.oclAsType(VariableDeclaration)
Inherited attributes
-- none
Disambiguating rules
- simpleName must be a name of a visible VariableDeclaration in the
current environment.
env.lookup (simpleNameCS.ast).referredElement.oclIsKindOf
(VariableDeclaration)
simpleNameCS
This production rule represents a single name. No special rules are
applicable. The exact syntax of a String is undefined in UML 1.4,
and remains undefined in OCL 2.0. The reason for this is
internationalization.
simpleNameCS ::= <String>
Abstract syntax mapping
simpleNameGr.ast : String
Synthesized attributes
simpleNameGr.ast = <String>
Inherited attributes
-- none
Disambiguating rules
-- none
pathNameCS
This rule represents a path name, which is held in its ast
as a
sequence of Strings.
pathNameCS ::= simpleNameCS ('::' pathNameCS )?
Abstract syntax mapping
pathNameCS.ast : Sequence(String)
Synthesized attributes
pathNameCS.ast =
Sequence{simpleNameCS.ast}->union(pathNameCS.ast)
Inherited attributes
-- none
Disambiguating rules
-- none
LiteralExpCS
This rule represents literal expressions.
-
LiteralExpCS ::= EnumLiteralExpCS
LiteralExpCS ::= CollectionLiteralExpCS
LiteralExpCS ::= TupleLiteralExpCS
LiteralExpCS ::= PrimitiveLiteralExpCS
Abstract syntax mapping
LiteralExpCS.ast : LiteralExp
Synthesized attributes
-
LiteralExpCS.ast = EnumLiteralExpCS.ast
LiteralExpCS.ast = CollectionLiteralExpCS.ast
LiteralExpCS.ast = TupleLiteralExpCS.ast
LiteralExpCS.ast = PrimitiveLiteralExpCS.ast
Inherited attributes
EnumLiteralExpCS.env = LiteralExpCS.env
CollectionLiteralExpCS.env = LiteralExpCS.env
TupleLiteralExpCS.env = LiteralExpCS.env
PrimitiveLiteralExpCS.env = LiteralExpCS.env
Disambiguating rules
-- none
EnumLiteralExpCS
The rule represents Enumeration Literal expressions.
EnumLiteralExpCS ::= pathNameCS '::' simpleNameCS
Abstract syntax mapping
EnumLiteralExpCS.ast : EnumLiteralExp
Synthesized attributes
EnumLiteralExpCS.ast.type =
env.lookupPathName
(pathNameCS.ast).referredElement.oclAsType
(Classifier)
EnumLiteralExpCS.ast.referredEnumLiteral =
EnumLiteralExpCS.ast.type.oclAsType
(Enumeration).literal->
select (l | l.name =
simpleNameCS.ast )->any(true)
Inherited attributes
-- none
Disambiguating rules
- The specified name must indeed reference an
enumeration:
not EnumLiteralExpCS.ast.type.oclIsUndefined() and
EnumLiteralExpCS.ast.type.oclIsKindOf (Enumeration)
CollectionLiteralExpCS
This rule represents a collection literal expression.
CollectionLiteralExpCS ::= CollectionTypeIdentifierCS
`{` CollectionLiteralPartsCS? `}'
Abstract syntax mapping
CollectionLiteralExpCS.ast : CollectionLiteralExp
Synthesized attributes
CollectionLiteralExpCS.ast.parts =
CollectionLiteralPartsCS.ast
CollectionLiteralExpCS.ast.kind = CollectionTypeIdentifierCS.ast
Inherited attributes
CollectionTypeIdentifierCS.env = CollectionLiteralExpCS.env
CollectionLiteralPartsCS.env = CollectionLiteralExpCS.env
Disambiguating rules
- In a literal the collectiuon type may not be
Collection
CollectionTypeIdentifierCS.ast <> 'Collection'
CollectionTypeIdentifierCS
This rule represent the type indentifier in a collection
literal
expression. The Collection type is an abstract type on M1 level, so it
has no corresponding literals.
-
CollectionTypeIdentifierCS ::= 'Set'
CollectionTypeIdentifierCS ::= 'Bag'
CollectionTypeIdentifierCS ::= 'Sequence'
CollectionTypeIdentifierCS ::= 'Collection'
CollectionTypeIdentifierCS ::= 'OrderedSet'
Abstract syntax mapping
CollectionTypeIdentifierCS.ast : CollectionKind
Synthesized attributes
CollectionTypeIdentifierCS.ast = CollectionKind::Set
CollectionTypeIdentifierCS.ast = CollectionKind::Bag
CollectionTypeIdentifierCS.ast = CollectionKind::Sequence
CollectionTypeIdentifierCS.ast = CollectionKind::Collection
CollectionTypeIdentifierCS.ast = CollectionKind::OrderedSet
Inherited attributes
-- none
Disambiguating rules
-- none
CollectionLiteralPartsCS
This production rule describes a sequence of items that are
the
contents of a collection literal.
CollectionLiteralPartsCS[1] = CollectionLiteralPartCS
( ',' CollectionLiteralPartsCS[2] )?
Abstract syntax mapping
CollectionLiteralPartsCS[1].ast :
Sequence(CollectionLiteralPart)
Synthesized attributes
CollectionLiteralPartsCS[1].ast =
Sequence{CollectionLiteralPartCS.ast}->union(CollectionLiteralPartsCS[2].ast)
Inherited attributes
CollectionLiteralPartCS.env = CollectionLiteralPartsCS[1].env
CollectionLiteralPartSCS[2].env = CollectionLiteralPartsCS[1].env
Disambiguating rules
-- none
CollectionLiteralPartCS
-
CollectionLiteralPartCS ::= CollectionRangeCS
CollectionLiteralPartCS ::= OclExpressionCS
Abstract syntax mapping
CollectionLiteralPartCS.ast : CollectionLiteralPart
Synthesized attributes
-
CollectionLiteralPartCS.ast = CollectionRange.ast
CollectionLiteralPartCS.ast.oclIsKindOf(CollectionItem)
and
CollectionLiteralPartCS.ast.oclAsType(CollectionItem).OclExpression =
OclExpressionCS.ast
Inherited attributes
CollectionRangeCS.env = CollectionLiteralPartCS.env
OclExpressionCS.env = CollectionLiteralPartCS.env
Disambiguating rules
-- none
CollectionRangeCS
CollectionRangeCS ::= OclExpressionCS[1] '..'
OclExpressionCS[2]
Abstract syntax mapping
CollectionRangeCS.ast : CollectionRange
Synthesized attributes
CollectionRangeCS.ast.first = OclExpressionCS[1].ast
CollectionRangeCS.ast.last = OclExpressionCS[2].ast
Inherited attributes
OclExpressionCS[1].env = CollectionRangeCS.env
OclExpressionCS[2].env = CollectionRangeCS.env
Disambiguating rules
-- none
PrimitiveLiteralExpCS
This includes Real, Boolean, Integer and String literals.
Exprecially
String literals must take internationalisation into account and might
need to remain undefined in this specification.
PrimitiveLiteralExpCS ::= IntegerLiteralExpCS
PrimitiveLiteralExpCS ::= RealLiteralExpCS
PrimitiveLiteralExpCS ::= StringLiteralExpCS
PrimitiveLiteralExpCS ::= BooleanLiteralExpCS
Abstract syntax mapping
PrimitiveLiteralExpCS.ast : PrimitiveLiteralExp
Synthesized attributes
-
PrimitiveLiteralExpCS.ast = IntegerLiteralExpCS.ast
PrimitiveLiteralExpCS.ast = RealLiteralExpCS.ast
PrimitiveLiteralExpCS.ast = StringLiteralExpCS.ast
PrimitiveLiteralExpCS.ast = BooleanLiteralExpCS.ast
Inherited attributes
-- none
Disambiguating rules
-- none
TupleLiteralExpCS
This rule represents tuple literal expressions.
TupleLiteralExpCS ::= `Tuple' `{` variableDeclarationListCS `}'
Abstract syntax mapping
TupleLiteralExpCS.ast : TupleLiteralExp
Synthesized attributes
TupleLiteralExpCS.tuplePart = variableDeclarationListCS.ast
Inherited attributes
variableDeclarationListCS[1].env = TupleLiteralExpCS.env
Disambiguating rules
The initExpression and type of all VariableDeclarations must
exist.
TupleLiteralExpCS.tuplePart->forAll( varDecl |
varDecl.initExpression->notEmpty() and not
varDecl.type.oclIsUndefined() )
IntegerLiteralExpCS
This rule represents integer literal expressions.
IntegerLiteralExpCS ::= <String>
Abstract syntax mapping
IntegerLiteralExpCS.ast : IntegerLiteralExp
Synthesized attributes
IntegerLiteralExpCS.ast.integerSymbol =
<String>.toInteger()
Inherited attributes
-- none
Disambiguating rules
-- none
RealLiteralExpCS
This rule represents real literal expressions.
RealLiteralExpCS ::= <String>
Abstract syntax mapping
RealLiteralExpCS.ast : RealLiteralExp
Synthesized attributes
RealLiteralExpCS.ast.realSymbol = <String>.toReal()
Inherited attributes
-- none
Disambiguating rules
-- none
StringLiteralExpCS
This rule represents string literal expressions.
StringLiteralExpCS ::= ''' <String> '''
Abstract syntax mapping
StringLiteralExpCS.ast : StringLiteralExp
Synthesized attributes
StringLiteralExpCS.ast.symbol = <String>
Inherited attributes
-- none
Disambiguating rules
-- none
BooleanLiteralExpCS
This rule represents boolean literal expressions.
BooleanLiteralExpCS ::= 'true'
BooleanLiteralExpCS ::= 'false'
Abstract syntax mapping
BooleanLiteralExpCS.ast : BooleanLiteralExp
Synthesized attributes
-
BooleanLiteralExpCS.ast.booleanSymbol = true
BooleanLiteralExpCS.ast.booleanSymbol = false
Inherited attributes
-- none
Disambiguating rules
-- none
PropertyCallExpCS
This rule represents property call expressions.
-
PropertyCallExpCS ::= ModelPropertyCallExpCS
PropertyCallExpCS ::= LoopExpCS
Abstract syntax mapping
PropertyCallExpCS.ast : PropertyCallExp
Synthesized attributes
-
PropertyCallExpCS.ast = ModelPropertyCallCS.ast
PropertyCallExpCS.ast = LoopExpCS.ast
Inherited attributes
-
ModelPropertyCallCS.env = PropertyCallExpCS.env
- LoopExpCS.env = PropertyCallExpCS.env
Disambiguating rules
The disambiguating rules are defined in the children.
LoopExpCS
This rule represents loop expressions.
-
LoopExpCS ::= IteratorExpCS
LoopExpCS ::= IterateExpCS
Abstract syntax mapping
LoopExpCS.ast : LoopExp
Synthesized attributes
-
LoopExpCS.ast = IteratorExpCS.ast
LoopExpCS.ast = IterateExpCS.ast
Inherited attributes
IteratorExpCS.env = LoopExpCS.env
IterateExpCS.env = LoopExpCS.env
Disambiguating rules
-- none
IteratorExpCS
The first alternative is a straightforward Iterator expression,
with
optional iterator variable. The second and third alternatives are
so-called implicit collect iterators. B is for
operations and C for attributes, D for navigations and E for
associationclasses.
-
IteratorExpCS ::= OclExpressionCS[1] '->' simpleNameCS
'('
(VariableDeclarationCS[1],
(','
VariableDeclarationCS[2])? '|' )?
OclExpressionCS[2]
')'
IteratorExpCS ::= OclExpressionCS '.' simpleNameCS
'('argumentsCS?')'
IteratorExpCS ::= OclExpressionCS '.' simpleNameCS
IteratorExpCS ::= OclExpressionCS '.' simpleNameCS
('['
argumentsCS ']')?
IteratorExpCS ::= OclExpressionCS '.' simpleNameCS
('['
argumentsCS ']')?
Abstract syntax mapping
IteratorExpCS.ast : IteratorExp
Synthesized attributes
-- the ast needs to be determined bit by
bit, first the source
association of IteratorExp
[A] IteratorExpCS.ast.source = OclExpressionCS[1].ast
- next the iterator association of IteratorExp
-- when the variable declaration is present, its ast
is the iterator of
this iteratorExp
-- when the variable declaration is not present, the
iterator has a
default name and
-- type
-- In any case, the iterator does not have an init
expression
[A] IteratorExpCS.ast.iterators->at(1).name = if
VariableDeclarationCS[1]->isEmpty()
then ''
else
VariableDeclarationCS[1].ast.name
endif
[A] IteratorExpCS.ast.iterator->at(1).type =
if
VariableDeclarationCS[1]->isEmpty() or
(VariableDeclarationCS[1]->notEmpty() and
VariableDeclarationCS[1].ast.type.oclIsUndefined() )
then
OclExpressionCS[1].type.oclAsType (CollectionType).elementType
else
VariableDeclarationCS[1].ast.type
endif
-- The optional second iterator
[A] if VariableDeclarationCS[2]->isEmpty() then
IteratorExpCS.ast.iterators->size() = 1
else
IteratorExpCS.ast.iterators->at(2).name =
VariableDeclarationCS[2].ast.name
and
IteratorExpCS.ast.iterators->at(2).type =
if
VariableDeclarationCS[2]->isEmpty() or
(VariableDeclarationCS[2]->notEmpty() and
VariableDeclarationCS[2].ast.type.oclIsUndefined() )
then
OclExpressionCS[1].type.oclAsType
(CollectionType).elementType
else
VariableDeclarationCS[2].ast.type
endif
endif
[A] IteratorExpCS.ast.iterators->forAll(initExpression->isEmpty())
-- next the name attribute and body association of
the IteratorExp
[A] IteratorExpCS.ast.name = simpleNameCS.ast and
[A] IteratorExpCS.ast.body = OclExpressionCS[2].ast
-- Alternative B is an implicit collect of an
operation over a
collection
[B] IteratorExpCS.ast.iterator.type =
OclExpressionCS.ast.type.oclAsType (CollectionType).elementType
[B] IteratorExpCS.ast.source = OclExpressionCS.ast
[B] IteratorExpCS.ast.name = 'collect'
[B] -- the body of the implicit collect is the operation call referred
to by 'name'
IteratorExpCS.ast.body.oclIsKindOf
(OperationCallExp) and
let body : OperationCallExp =
IteratorExpCS.ast.body.oclAsType(OperationCallExp)
in
body.arguments = argumentsCS.ast
and
body.source.oclIsKindOf(VariableExp)
and
body.source.oclAsType (VariableExp).referredVariable
=
IteratorExpCS.ast.iterator
and
body.referredOperation =
OclExpressionCS.ast.type.oclAsType (CollectionType ).elementType
.lookupOperation( simpleNameCS.ast,
if (argumentsCS->notEmpty())
then arguments.ast->collect(type)
else Sequence{} endif)
-- Alternative C/D is an implicit collect of an
association or
attribute over a collection
[C, D] IteratorExpCS.ast.iterator.type =
OclExpressionCS.ast.type.oclAsType
(CollectionType).elementType
[C, D] IteratorExpCS.ast.source = OclExpressionCS.ast
[C, D] IteratorExpCS.ast.name = 'collect'
[C] -- the body of the implicit collect is the
attribute referred to by
'name'
let refAtt : Attribute =
OclExpressionCS.ast.type.oclAsType
(CollectionType).
elementType.lookupAttribute( simpleNameCS.ast),
in
IteratorExpCS.ast.body.oclIsKindOf (AttributeCallExp) and
let body : AttributeCallExp =
IteratorExpCS.ast.body.oclAsType(AttributeCallExp)
in
body.source.oclIsKindOf(VariableExp)
and
body.source.oclAsType (VariableExp).referredVariable =
IteratorExpCS.ast.iterator
and
body.referredAttribute = refAtt
[D] -- the body of the implicit collect is the navigation call referred
to by 'name'
let refNav : AssociationEnd =
OclExpressionCS.ast.type.oclAsType
(CollectionType).
elementType.lookupAssociationEnd(simpleNameCS.ast)
in
IteratorExpCS.ast.body.oclIsKindOf
(AssociationEndCallExp) and
let body : AssociationEndCallExp =
IteratorExpCS.ast.body.oclAsType(AssociationEndCallExp)
in
body.source.oclIsKindOf(VariableExp)
and
body.source.oclAsType
(VariableExp).referredVariable =
IteratorExpCS.ast.iterator
and
body.referredAssociationEnd =
refNav
and
body.ast.qualifiers =
argumentsCS.ast
[E] -- the body of the implicit collect is the navigation to the
association class
-- referred to by 'name'
let refClass : AssociationClass =
OclExpressionCS.ast.type.oclAsType (CollectionType).
elementType.lookupAssociationClass(simpleNameCS.ast)
in
IteratorExpCS.ast.body.oclIsKindOf (AssociationClassCallExp) and
let body : AssociationClassCallExp =
IteratorExpCS.ast.body.oclAsType(AssociationClassCallExp)
in
body.source.oclIsKindOf(VariableExp)
and
body.source.oclAsType
(VariableExp).referredVariable =
IteratorExpCS.ast.iterator
and
body.referredAssociationClass =
refNav
and
body.ast.qualifiers =
argumentsCS.ast
Inherited attributes
[A] OclExpressionCS[1].env = IteratorExpCS.env
[A] VariableDeclarationCS.env = IteratorExpCS.env
-- inside an iterator expression the body is
evaluated with a new
environment that
-- includes the iterator variable.
[A] OclExpressionCS[2].env =
IteratorExpCS.env.nestedEnvironment().addElement(VariableDeclarationCS.ast.varName,
VariableDeclarationCS.ast,
true)
[B] OclExpressionCS.env = IteratorExpCS.env
[B] argumentsCS.env = IteratorExpCS.env
[C] OclExpressionCS.env = IteratorExpCS.env
[D] OclExpressionCS.env = IteratorExpCS.env
Disambiguating rules
[1] [A] When the variable declaration is present, it may not
have
an init expression.
VariableDeclarationCS->notEmpty() implies
VariableDeclarationCS.ast.initExpression->isEmpty()
[2] [B] The source must be of a collection type.
OclExpressionCS.ast.type.oclIsKindOf(CollectionType)
[3] [C] The source must be of a collection type.
OclExpressionCS.ast.type.oclIsKindOf(CollectionType)
[4] [C] The referred attribute must be present.
refAtt->notEmpty()
[5] [D] The referred navifation must be present.
refNav->notEmpty()
IterateExpCS
IterateExpCS ::= OclExpressionCS[1] '->' 'iterate'
'(' (VariableDeclarationCS[1] ';')?
VariableDeclarationCS[2] '|'
OclExpressionCS[2]
')'
Abstract syntax mapping
IterateExpCS.ast : IterateExp
Synthesized attributes
-- the ast needs to be determined bit by bit, first the
source
association of IterateExp
IterateExpCS.ast.source = OclExpressionCS[1].ast
-- next the iterator association of IterateExp
-- when the first variable declaration is present, its ast is the
iterator of this
-- iterateExp, when the variable declaration is not present, the
iterator has a default
-- name and type,
-- in any case, the iterator has an empty init expression.
IterateExpCS.ast.iterator.name = if
VariableDeclarationCS[1]->isEmpty() then ''
else VariableDeclarationCS[1].ast.name
endif
IterateExpCS.ast.iterator.type =
if VariableDeclarationCS[1]->isEmpty() or
(VariableDeclarationCS[1]->notEmpty() and
VariableDeclarationCS[1].ast.type.oclIsUndefined() )
then
OclExpressionCS[1].type.oclAsType
(CollectionType).elementType
else
VariableDeclarationCS[1].ast.type
endif
IterateExpCS.ast.iterator.initExpression->isEmpty()
-- next the name attribute and body and result association of the
IterateExp
IterateExpCS.ast.result = VariableDeclarationCS[2].ast
IterateExpCS.ast.name = 'iterate'
IterateExpCS.ast.body = OclExpressionCS[2].ast
Inherited attributes
OclExpressionCS[1].env = IteratorExpCS.env
VariableDeclarationCS[1].env = IteratorExpCS.env
VariableDeclarationCS[2].env = IteratorExpCS.env
-- Inside an iterate expression the body is evaluated with a new
environment that includes
-- the iterator variable and the result variable.
OclExpressionCS[2].env =
IteratorExpCS.env.nestedEnvironment().addElement
(VariableDeclarationCS[1].ast.varName,
VariableDeclarationCS[1].ast,
true).addElement
(VariableDeclarationCS[2].ast.varName,
VariableDeclarationCS[2].ast,
true)
Disambiguating rules
- A result variable declaration must have a type and
an
initial
value
not VariableDeclarationCS[2].ast.type.oclIsUndefined()
VariableDeclarationCS[2].ast.initExpression->notEmpty()
- When the first variable declaration is present, it may not have
an
init expression.
VariableDeclarationCS[1]->notEmpty() implies
VariableDeclarationCS[1].ast.initExpression->isEmpty()
VariableDeclarationCS
In the variable declaration, the type and init expression are
optional.
When these are required, this is defined in the production rule where
the variable declaration is used.
VariableDeclarationCS ::= simpleNameCS (':' typeCS)?
( '=' OclExpressionCS )?
Abstract syntax mapping
VariableDeclarationCS.ast : VariableDeclaration
Synthesised attributes
VariableDeclarationCS.ast.name = simpleNameCS.ast
VariableDeclarationCS.ast.initExpression = OclExpressionCS.ast
-- A well-formed VariableDeclaration must have a type according to the
abstract syntax.
-- The value OclUndefined is used when no type has been given in the
concrete syntax.
-- Production rules that use this need to check on this type.
VariableDeclarationCS.ast.type = if
typeCS->notEmpty() then
typeCS.ast
else
OclUndefined
endif
Inherited attributes
OclExpressionCS.env = VariableDeclarationCS.env
typeCS.env = VariableDeclarationCS.env
Disambiguating rules
-- none
TypeCS
A typename is either a Classifier, or a collection of some type.
-
typeCS ::= pathNameCS
typeCS ::= collectionTypeCS
typeCS ::= tupleTypeCS
Abstract syntax mapping
typeCS.ast : Classifier
Synthesised attributes
typeCS.ast
=typeCS.env.lookupPathName(pathNameCS.ast).referredElement.oclAsType(Classifier)
typeCS.ast = CollectionTypeCS.ast
typeCS.ast = tupleTypeCS.ast
Inherited attributes
-
collectionTypeCS.env = typeCS.env
tupleTypeCS.env = typeCS.env
Disambiguating rules
[1] [A] pathName must be a name of a Classifier in current
environment.
typeCS.env.lookupPathName(pathNameCS.ast).referredElement.oclIsKindOf
(Classifier)
collectionTypeCS
A typename is either a Classifier, or a collection of some type.
collectionTypeCS ::= collectionTypeIdentifierCS '(' typeCS ')'
Abstract syntax mapping
typeCS.ast : CollectionType
Synthesised attributes
collectionTypeCS.ast.elementType = typeCS.ast
-- We know that the 'ast' is a collectiontype, all we need to state now
is which
-- specific collection type it is.
kind = CollectionKind::Set implies
collectionTypeCS.ast.oclIsKindOf (SetType )
kind = CollectionKind::Sequence implies
collectionTypeCS.ast.oclIsKindOf (SequenceType)
kind = CollectionKind::Bag implies collectionTypeCS.ast.oclIsKindOf
(BagType )
kind = CollectionKind::Collection implies
collectionTypeCS.ast.oclIsKindOf
(CollectionType)
kind = CollectionKind::OrderedSet implies
collectionTypeCS.ast.oclIsKindOf
(OrderedSetType)
Inherited attributes
typeCS.env =
collectionTypeCS.env
Disambiguating rules
-- none
tupleTypeCS
This represents a tuple type declaration.
tupleTypeCS ::= 'Tuple' '(' variableDeclarationListCS? ')'
Abstract syntax mapping
typeCS.ast : TupleType
Synthesised attributes
typeCS.ast = TupleType::make(
variableDeclarationListCS->collect( v
| v.asAttribute() ))
Inherited attributes
variableDeclarationListCS.env = tupleTypeCS.env
Disambiguating rules
- Of all VariableDeclarations the initExpression
must be
empty
and the type must exist.
variableDeclarationListCS.ast->forAll( varDecl |
varDecl.initExpression->notEmpty() and varDecl.type->notEmpty() )
variableDeclarationListCS
This production rule represents the formal parameters of a
tuple or
attribute definition.
variableDeclarationListCS[1] = VariableDeclarationCS
(','variableDeclarationListCS[2] )?
Abstract syntax mapping
variableDeclarationListCS[1].ast : Sequence(
VariableDeclaration )
Synthesized attributes
variableDeclarationListCS[1].ast =
Sequence{VariableDeclarationCS.ast}
->union(variableDeclarationListCS[2].ast)
Inherited attributes
VariableDeclarationCS.env = variableDeclarationListCS[1].env
variableDeclarationListCS[2].env = variableDeclarationListCS[1].env
Disambiguating rules
-- none
ModelPropertyCallExpCS
A ModelPropertCall expression may have three different productions.
Which one is chosen depends on the disambiguating rules defined in each
of the alternatives.
-
ModelPropertyCallExpCS ::= OperationCallExpCS
-
ModelPropertyCallExpCS ::= AttributeCallExpCS
-
ModelPropertyCallExpCS ::= NavigationCallExpCS
Abstract syntax mapping
ModelPropertyCallExpCS.ast : ModelPropertyCallExp
Synthesised attributes
The value of this production is the value of its child production.
-
ModelPropertyCallExpCS.ast = OperationCallExpCS.ast
ModelPropertyCallExpCS.ast = AttributeCallExpCS.ast
ModelPropertyCallExpCS.ast = NavigationCallExpCS.ast
Inherited attributes
-
OperationCallExpCS.env = ModelPropertyCallExpCS.env
AttributeCallExpCS.env = ModelPropertyCallExpCS.env
NavigationCallExpCS.env = ModelPropertyCallExpCS.env
Disambiguating rules
These are defined in the children.
OperationCallExpCS
An operation call has many different forms. A is used for
infix, B for
using an object as an implicit collection. C is a straightforward
operation call, while D has an implicit source
expression. E and F are like C and D, with the @pre addition. G covers
the class operation call. Rule H is for unary prefix
expressions.
OperationCallExpCS ::= OclExpressionCS[1]
simpleNameCS OclExpressionCS[2]
OperationCallExpCS
::= OclExpressionCS '->' simpleNameCS
'('
argumentsCS? ')'
OperationCallExpCS ::=
OclExpressionCS '.' simpleNameCS
'(' argumentsCS? ')'
OperationCallExpCS ::=
simpleNameCS '(' argumentsCS? ')'
OperationCallExpCS ::= OclExpressionCS '.' simpleNameCS
isMarkedPreCS '(' argumentsCS? ')'
OperationCallExpCS
::= simpleNameCS isMarkedPreCS '('
argumentsCS?
')'
OperationCallExpCS ::= pathNameCS '(' argumentsCS? ')'
OperationCallExpCS ::= simpleNameCS OclExpressionCS
Abstract syntax mapping
OperationCallExpCS.ast : OperationCallExp
Synthesised attributes
-- this rule is for binary operators as
'+', '-', '*' etc. It has only
one argument.
[A] OperationCallExpCS.ast.arguments = Sequence{OclExpression2[2].ast}
OperationCallExpCS.ast.source =
OclExpressionCS[1].ast
OperationCallExpCS.ast.referredOperation =
OclExpressionCS.ast.type.lookupOperation (
simpleNameCS.ast,
Sequence{OclExpression[2].ast.type} )
-- The source is either a collection or a single
object used as a
collection.
[B] OperationCallExpCS.ast.arguments = argumentsCS.ast
-- if the OclExpressionCS is a collectiontype, then
the source is this
OclExpressionCS.
-- Otherwise, the source must be build up by
defining a singleton set
containing
-- the OclExpressionCS. This is done though
inserting a call to the
standard
-- operation "asSet()"
OperationCallExpCS.ast.source =
if
OclExpressionCS.ast.type.oclIsKindOf(CollectionType)
then
OclExpressionCS.ast
else
OclExpressionCS.ast.withAsSet()
endif
---- The referred operation:
OperationCallExpCS.ast.referredOperation =
if
OclExpressionCS.ast.type.oclIsKindOf (CollectionType)
then -- this
is a collection operation called on a collection
OclExpressionCS.ast.type.lookupOperation
(simpleNameCS.ast,
if (argumentsCS->notEmpty())
then
argumentsCS.ast->collect(type)
else Sequence{} endif )
else
-- this is a set operation called on an object =>
implicit Set with
one element
SetType.allInstances()->any (st |
st.elementType =
OclExpressionCS.ast.type).lookupOperation (
simpleNameCS.ast,
if
(argumentsCS->notEmpty())
then
argumentsCS.ast->collect(type)
else
Sequence{} endif )
endif
[C] OperationCallExpCS.ast.referredOperation =
OclExpressionCS.ast.type.lookupOperation (simpleNameCS.ast,
if
argumentsCS->notEmpty()
then
arguments.ast->collect(type)
else
Sequence{} endif)
OperationCallExpCS.ast.arguments = argumentsCS.ast
OperationCallExpCS.ast.source =
OclExpressionCS.ast
[D] OperationCallExpCS.ast.arguments = argumentsCS.ast and
OperationCallExpCS.ast.referredOperation =
env.lookupImplicitOperation(simpleName.ast,
if
argumentsCS->notEmpty()
then
arguments.ast->collect(type)
else
Sequence{} endif)
OperationCallExpCS.ast.source =
env.lookupImplicitSourceForOperation(
simpleName.ast,
if
argumentsCS->notEmpty()
then
arguments.ast->collect(type)
else
Sequence{} endif)
[E] -- incorporate the isPre() operation.
OperationCallExpCS.ast.referredOperation =
OclExpressionCS.ast.type.lookupOperation (simpleNameCS.ast,
if argumentsCS->notEmpty()
then arguments.ast->collect(type)
else Sequence{} endif)
OperationCallExpCS.ast.arguments = argumentsCS.ast
OperationCallExpCS.ast.source =
OclExpressionCS.ast.withAtPre()
[F] -- incorporate atPre() operation with the implicit source
OperationCallExpCS.ast.arguments = argumentsCS.ast
and
OperationCallExpCS.ast.referredOperation =
env.lookupImplicitOperation(simpleName.ast,
if argumentsCS->notEmpty()
then arguments.ast->collect(type)
else Sequence{} endif)
)
OperationCallExpCS.ast.source =
env.lookupImplicitSourceForOperation(simpleName.ast,
if argumentsCS->notEmpty()
then arguments.ast->collect(type)
else Sequence{} endif)
).withAtPre()
[G] OperationCallExpCS.ast.arguments = argumentsCS.ast and
OperationCallExpCS.ast.referredOperation =
env.lookupPathName(pathName.ast,
if argumentsCS->notEmpty()
then arguments.ast->collect(type)
else Sequence{} endif)
OperationCallExpCS.ast.source->isEmpty()
-- this rule is for unary operators as '-' and 'not' etc. It has no
argument.
[H] OperationCallExpCS.ast.arguments->isEmpty()
OperationCallExpCS.ast.source = OclExpressionCS.ast
OperationCallExpCS.ast.referredOperation =
OclExpressionCS.ast.type.lookupOperation (
simpleNameCS.ast,
Sequence{} )
Inherited attributes
[A] OclExpressionCS[1].env = OperationCallExpCS.env
[A] OclExpressionCS[2].env = OperationCallExpCS.env
[B] OclExpressionCS.env = OperationCallExpCS.env
[B] argumentsCS.env = OperationCallExpCS.env
[C] OclExpressionCS.env = OperationCallExpCS.env
[C] argumentsCS.env = OperationCallExpCS.env
[D] argumentsCS.env = OperationCallExpCS.env
[E] OclExpressionCS.env = OperationCallExpCS.env
[E] argumentsCS.env = OperationCallExpCS.env
[F] argumentsCS.env = OperationCallExpCS.env
Disambiguating rules
[1] [A] The name of the referred Operation must be an operator
Set{'+','-','*','/','and','or','xor','=','<=','>=','<','>'}->includes(simpleNameCS.ast)
[2] [A,B,C,D,E,F] The referred Operation must be defined for the type
of source
not OperationCallExpCS.ast.referredOperation.oclIsUndefined()
[3] [C] The name of the referred Operation cannot be an operator.
Set{'+','-','*','/','and','or','xor','=','<=','>=','<','>'}->excludes(simpleNameCS.ast)
AttributeCallExpCS
This production rule results in an AttributeCallExp. In
production [A]
the source is explicit, while production [B] is used for an implicit
source. Alternative C covers the use of a classifier
scoped attribute.
-
AttributeCallExpCS ::= OclExpressionCS '.'
simpleNameCS
isMarkedPreCS?
AttributeCallExpCS ::= simpleNameCS isMarkedPreCS?
AttributeCallExpCS ::= pathNameCS
A
bstract syntax mapping
AttributeCallExpCS.ast : AttributeCallExp
Synthesised attributes
[A] AttributeCallExpCS.ast.referredAttribute =
OclExpressionCS.ast.type.lookupAttribute(simpleNameCS.ast)
[A] AttributeCallExpCS.ast.source = if isMarkedPreCS->isEmpty()
then OclExpressionCS.ast
else
OclExpressionCS.ast.withAtPre()
endif
[B] AttributeCallExpCS.ast.referredAttribute =
env.lookupImplicitAttribute(simpleNameCS.ast)
[B] AttributeCallExpCS.ast.source =
if isMarkedPreCS->isEmpty()
then
env.findImplicitSourceForAttribute(simpleNameCS.ast)
else
env.findImplicitSourceForAttribute(simpleNameCS.ast).withAtPre()
endif
[C] AttributeCallExpCS.ast.referredAttribute =
env.lookupPathName(pathNameCS.ast).oclAsType(Attribute)
Inherited attributes
[A] OclExpressionCS.env = AttributeCallExpCS.env
Disambiguating rules
[1] [A, B] 'simpleName' is name of an Attribute of the type of
source or if source is empty the name of an attribute of 'self' or any
of the iterator variables in (nested) scope. In OCL:
not AttributeCallExpCS.ast.referredAttribute.oclIsUndefined()
[2] [C] The pathName refers to a class attribute.
env.lookupPathName(pathNameCS.ast).oclIsKindOf(Attribute)
and
AttributeCallExpCS.ast.referredAttribute.ownerscope =
ScopeKind::instance
NavigationCallExpCS
This production rule represents a navigation call expression.
-
NavigationCallExpCS ::= AssociationEndCallExpCS
NavigationCallExpCS ::= AssociationClassCallExpCS
Abstract syntax mapping
NavigationCallExpCS.ast : NavigationCallExp
Synthesised attributes
The value of this production is the value of its child production.
NavigationCallExpCS.ast = AssociationEndCallExpCS.ast
NavigationCallExpCS.ast = AssociationClassCallExpCS.ast
Inherited attributes
-
AssociationEndCallExpCS.env =
NavigationCallExpCS.env
AssociationClassCallExpCS.env =
NavigationCallExpCS.env
Disambiguating rules
These are defined in the children.
AssociationEndCallExpCS
This production rule represents a navigation through an association
end. Rule A is the default, rule B is used with an implicit source,
while rule C is used with qualifiers.
AssociationEndCallExpCS ::= OclExpressionCS '.' simpleNameCS ('['
argumentsCS ']')? isMarkedPreCS?
AssociationEndCallExpCS ::= simpleNameCS ('[' argumentsCS ']')?
isMarkedPreCS?
Abstract syntax mapping
AssociationEndCallExpCS.ast : AssociationEndCallExp
Synthesised attributes
[A] AssociationEndCallExpCS.ast.referredAssociationEnd =
OclExpressionCS.ast.type.lookupAssociationEnd(simpleNameCS.ast)
AssociationEndCallExpCS.ast.source = if
isMarkedPreCS->isEmpty()
then
OclExpressionCS.ast
else
OclExpressionCS.ast.withAtPre()
endif
[A] AssociationEndCallExpCS.ast.qualifiers = argumentsCS.ast
[B] AssociationEndCallExpCS.ast.referredAssociationEnd =
env.lookupImplicitAssociationEnd(simpleNameCS.ast)
AssociationEndCallExpCS.ast.source =
if
isMarkedPreCS->isEmpty()
then
env.findImplicitSourceForAssociationEnd(simpleNameCS.ast)
else
env.findImplicitSourceForAssociationEnd(simpleNameCS.ast).withAtPre()
endif
[B] AssociationEndCallExpCS.ast.qualifiers = argumentsCS.ast
Inherited attributes
[A] OclExpressionCS.env = AssociationEndCallExpCS.env
[A, B] argumentsCS.env = AssociationEndCallExpCS.env
Disambiguating rules
[1] [A,B] 'simpleName' is name of an AssociationEnd of the type
of
source or if source is empty the name of an Associatio-
nEnd of 'self' or any of the iterator variables in (nested) scope. In
OCL:
not
AssociationEndCallExpCS.ast.referredAssociationEnd.oclIsUndefined()
AssociationClassCallExpCS
This production rule represents a navigation to an association class.
[A] AssociationClassCallExpCS ::= OclExpressionCS '.' simpleNameCS
('[' argumentsCS ']')? isMarkedPreCS?
[B] AssociationClassCallExpCS ::= simpleNameCS
('[' argumentsCS ']')? isMarkedPreCS?
Abstract syntax mapping
AssociationClassCallExpCS.ast : AssociationClassCallExp
Synthesised attributes
[A] AssociationClassCallExpCS.ast.referredAssociationClass =
OclExpressionCS.ast.type.lookupAssociationClass(simpleNameCS.ast)
AssociationClassCallExpCS.ast.source = if
isMarkedPreCS->isEmpty()
then
OclExpressionCS.ast
else
OclExpressionCS.ast.withAtPre()
endif
[A] AssociationClassCallExpCS.ast.qualifiers = argumentsCS.ast
[B] AssociationClassCallExpCS.ast.referredAssociationClass =
env.lookupImplicitAssociationClass(simpleNameCS.ast)
AssociationClassCallExpCS.ast.source =
if
isMarkedPreCS->isEmpty()
then
env.findImplicitSourceForAssociationClass(simpleNameCS.ast)
else
env.findImplicitSourceForAssociationClass(simpleNameCS.ast).withAtPre()
endif
[B] AssociationClassCallExpCS.ast.qualifiers = argumentsCS.ast
Inherited attributes
[A] OclExpressionCS.env = AssociationClassCallExpCS.env
[A, B] argumentsCS.env = AssociationClassCallExpCS.env
Disambiguating rules
[1] 'simpleName' is name of an AssociationClass of the type of
source.
not
AssociationClassCallExpCS.ast.referredAssociationClass.oclIsUndefined()
isMarkedPreCS
This production rule represents the marking @pre in an
ocl expression.
isMarkedPreCS ::= '@' 'pre'
Abstract syntax mapping
isMarkedPreCS.ast : Boolean
Synthesised attributes
self.ast = true
Inherited attributes
-- none
Disambiguating rules
-- none
argumentsCS
This production rule represents a sequence of arguments.
argumentsCS[1] ::= OclExpressionCS ( ',' argumentsCS[2] )?
Abstract syntax mapping
argumentsCS[1].ast : Sequence(OclExpression)
Synthesised attributes
argumentsCS[1].ast =
Sequence{OclExpressionCS.ast}->union(argumentsCS[2].ast)
Inherited attributes
OclExpressionCS.env = argumentsCS[1].env
argumentsCS[2].env = argumentsCS[1].env
Disambiguating rules
-- none
LetExpCS
This production rule represents a let expression. The LetExpSubCS
nonterminal has the purpose of allowing directly nested let expressions
with the shorthand syntax, i.e. ending with one
'in' keyword.
LetExpCS ::= 'let' VariableDeclarationCS
LetExpSubCS
Abstract syntax mapping
LetExpCS.ast : LetExp
Synthesised attributes
LetExpCS.ast.variable = VariableDeclarationCS.ast
LetExpCS.ast.in = LetExpSubCS.ast
Inherited attributes
LetExpSubCS.env = LetExpCS.env.nestedEnvironment().addElement(
VariableDeclarationCS.ast.varName,
VariableDeclarationCS.ast,
false)
Disambiguating rules
[1] The variable name must be unique in the current scope
LetExpCS.env.lookup
(VariableDeclarationCS.ast.varName).oclIsUndefined()
[2] A variable declaration inside a let must have a declared
type and
an initial value.
not VariableDeclarationCS.ast.type.oclIsUndefined() and
VariableDeclarationCS.ast.initExpression->notEmpty()
LetExpSubCS
[A] LetExpSubCS[1] ::= ',' VariableDeclarationCS
LetExpSubCS[2]
[B] LetExpSubCS ::= 'in' OclExpressionCS
Abstract syntax mapping
LetExpSubCS.ast : OclExpression
Synthesised attributes
[A] LetExpSubCS[1].ast.oclAsType(LetExp).variable =
VariableDeclarationCS.ast
[A] LetExpSubCS[1].ast.oclAsType(LetExp).OClExpression =
LetExpSubCS[2].ast
[B] LetExpSubCS.ast = OclExpressionCS.ast
Inherited attributes
[A] VariableDeclarationCS.env = LetExpSubCS[1].env
[A] LetExpSubCS[2].env =
LetExpSubCS[1].env.nestedEnvironment().addElement(
VariableDeclarationCS.ast.varName,
VariableDeclarationCS.ast,
false)
[B] OClExpressionCS.env = LetExpSubCS.env
Disambiguating rules
[A] The variable name must be unique in the current scope
LetExpSubCS[1].env.lookup
(VariableDeclarationCS.ast.varName).oclIsUndefined()
[A] A variable declaration inside a let must have a declared type and
an initial value.
not
VariableDeclarationCS.ast.type.oclIsUndefined() and
VariableDeclarationCS.ast.initExpression->notEmpty()
OclMessageExpCS
The message Name must either be the name of a Signal, or the
name of an
Operation belonging to the target object(s).
[A] OclMessageExpCS ::= OclExpressionCS '^^'
simpleNameCS '(' OclMessageArgumentsCS? ')'
[B] OclMessageExpCS ::= OclExpressionCS '^'
simpleNameCS '(' OclMessageArgumentsCS? ')'
Abstract syntax mapping
[A] OclMessageExpCS.ast : OclMessageExp
[B] OclMessageExpCS.ast : OclMessageExp
Synthesised attributes
[A] OclMessageExpCS.ast.target = OclExpressionCS.ast
[A] OclMessageExpCS.ast.arguments = OclMessageArgumentsCS.ast
-- first, find the sequence of types of the
operation/signal parameters
[A] let params : Sequence(Classifier) =
OclMessageArguments.ast->collect(messArg |
messArg.getType() ),
-- try to find either the called operation or the
sent signal
[A] operation : Operation = OclMessageExpCS.ast.target.type.
lookupOperation(simpleNameCS.ast,
params),
signal : Signal = OclMessageExpCS.ast.target.type.
lookupSignal(simpleNameCS.ast, params)
in
OclMessageExpCS.ast.calledOperation = if
operation->isEmpty()
then OclUndefined
else = operation
endif
OclMessageExpCS.ast.sentSignal = if
signal->isEmpty()
then OclUndefined
else signal
endif
[B]
-- OclExpression^simpleNameCS(OclMessageArguments)
is identical to
--
OclExpression^^simpleNameCS(OclMessageArguments)->size() = 1
-- actual mapping: straigthforward, TBD...
Inherited attributes
OclExpressionCS.env = OclMessageExpCS.env
OclMessageArgumentsCS.env = OclMessageExpCS.env
Disambiguating rules
-- none
OclMessageArgumentsCS
OclMessageArgumentsCS[1] ::= OclMessageArgCS
( ',' OclMessageArgumentsCS[2] )?
Abstract syntax mapping
OclMessageArgumentsCS[1].ast : Sequence(OclMessageArg)
Synthesised attributes
OclMessageArgumentsCS[1].ast =
Sequence{OclMessageArgCS.ast}->union(OclMessageArgumentsCS[2].ast)
Inherited attributes
OclMessageArgCS.env = OclMessageArgumentsCS[1].env
OclMessageArgumentsCS[2].env = OclMessageArgumentsCS[1].env
Disambiguating rules
-- none
OclMessageArgCS
[A] OclMessageArgCS ::= '?' (':' typeCS)?
[B] OclMessageArgCS ::= OclExpressionCS
Abstract syntax mapping
OclMessageArgCS.ast : OclMessageArg
Synthesised attributes
[A] OclMessageArgCS.ast.expression->isEmpty()
[A] OclMessageArgCS.ast.unspecified->notEmpty()
[A] OclMessageArgCS.ast.type = typeCS.ast
[B] OclMessageArgCS.ast.unspecified->isEmpty()
[B] OclMessageArgCS.ast.expression = OclExpressionCS.ast
Inherited attributes
OclExpressionCS.env = OclMessageArgCS.env
Disambiguating rules
-- none
IfExpCS
IfExpCS ::= 'if' OclExpression[1]
'then' OclExpression[2]
'else' OclExpression[3]
'endif'
Abstract syntax mapping
IfExpCS.ast : IfExp
Synthesised attributes
IfExpCS.ast.condition = OclExpression[1].ast
IfExpCS.ast.thenExpression = OclExpression[2].ast
IfExpCS.ast.elseExpression = OclExpression[3].ast
Inherited attributes
OclExpression[1].env = IfExpCS.env
OclExpression[2].env = IfExpCS.env
OclExpression[3].env = IfExpCS.env
Disambiguating rules
-- none
Comments
It is possible to include comments anywhere in a text composed
according to the above concrete syntax. There will be no mapping of any
comments to the abstract syntax. Comments are simply
skipped when the text is being parsed. There are two forms of comments,
a line comment and a paragraph comment. The line
comment starts with the string `--' and ends with the next newline. The
paragraph comment starts with the string
`/*', and ends with the string `*/'. Paragraph comments may be nested.
Operator Precedence
In the grammar, the precedence of the operators from highest to lowest
is as follows:
-
@pre
-
dot and arrow operations: `.' and `->'
-
unary `not' and unary minus `-'
-
`*' and `/'
-
`+' and binary `-'
-
`if-then-else-endif'
-
`<', `>', `<=', `>='
-
`=', `<>'
-
`and', `or' and `xor'
-
`implies'
Parentheses `(' and `)' can be used to change precedence.