9.3.25 IteratorExpCS
第一个选择是一个直接的迭代器表达式,使用一个可选的迭代器变量。第二和第三种选择是所谓的隐式collect迭代器。B用于操作,C用于属性,D用于导航,E用于关联类。
[A] IteratorExpCS ::= OclExpressionCS[1] ‘->’ simpleNameCS
‘(‘ (VariableDeclarationCS[1], (‘,’ VariableDeclarationCS[2])? ‘|’ )?
OclExpressionCS[2]
‘)’
[B] IteratorExpCS ::= OclExpressionCS ‘.’ simpleNameCS ‘(‘argumentsCS?’)’
[C] IteratorExpCS ::= OclExpressionCS ‘.’ simpleNameCS
[D] IteratorExpCS ::= OclExpressionCS ‘.’ simpleNameCS (‘[‘ argumentsCS ‘]’)?
[E] IteratorExpCS ::= OclExpressionCS ‘.’ simpleNameCS (‘[‘ argumentsCS ‘]’)?
抽象语法映射
IteratorExpCS.ast : IteratorExp
合成的属性
--ast需要逐位判断,首先是迭代器表达式的源关联
[A] IteratorExpCS.ast.source = OclExpressionCS[1].ast
-- 接下来是迭代器表达式的迭代器关联。当存在变量声明时,它的ast是这个迭代器表达式的迭代器;
-- 当变量声明不存在时,迭代器有一个缺省名称和类型。不管哪种情况,迭代器都不能有初始化表达式
[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
-- 可选的第二个迭代器
[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())
-- 接下来是迭代器表达式的名称属性和body关联
[A] IteratorExpCS.ast.name = simpleNameCS.ast and
[A] IteratorExpCS.ast.body = OclExpressionCS[2].ast
-- 选择B 是一个集合上的隐式collect操作
[B] IteratorExpCS.ast.iterator.type = OclExpressionCS.ast.type.oclAsType (CollectionType).elementType
[B] IteratorExpCS.ast.source = OclExpressionCS.ast
[B] IteratorExpCS.ast.name = 'collect'
[B] -- 隐式collect的body是通过‘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)
-- 选择C/D是一个集合上隐式的关联或属性的collect
[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] -- 隐式collect的body是‘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] -- 隐式collect的body是‘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] -- 隐式collect的body是‘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
继承的属性
[A] OclExpressionCS[1].env = IteratorExpCS.env
[A] VariableDeclarationCS.env = IteratorExpCS.env
-- 在迭代器表达式中,body在一个包含迭代器变量在内的新环境中被计算
[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
歧义消除规则
[1][A] 当存在变量声明时,不能有初始化表达式。
VariableDeclarationCS->notEmpty() implies VariableDeclarationCS.ast.initExpression->isEmpty()
[2][B] 源必须是一个集合类型。
OclExpressionCS.ast.type.oclIsKindOf(CollectionType)
[3][C] 源必须是一个集合类型。
OclExpressionCS.ast.type.oclIsKindOf(CollectionType)
[4][C] 引用的属性必须存在。
refAtt->notEmpty()
[5][D] 引用的导航必须存在。
refNav->notEmpty()