我有一个包含各种类型的更改运算符的流氓语法:
syntax ChangeOperator
= entityOperator: EntityOperation op
| attributeOperator : AttributesOperations op
| relationOperator: RelationOperations op
| databaseOperator: DatabaseOperations op
;
我尝试根据更改运算符的类型(实体操作、属性操作等(执行不同的操作。我像这样遍历我的更改运算符:
for ( ChangeOperator op <- operators){
for(EvoQuery evo <- evoQueries){
transform(evo, op);
}
};
我定义了各种变换方法:
EvoQuery transform(EvoQuery q, EntityOperation op){ ... }
EvoQuery transform(EvoQuery q, AttributesOperations op) {...}
default EvoQuery transform(EvoQuery q, _) = q;
不幸的是,唯一被调用的"转换"版本是默认版本。
如何调整循环或签名以使它们根据替代方案的类型匹配?
形式参数中的模式与循环中的实际参数之间似乎存在类型不匹配(现在是ChangeOperator
,而不是某些操作(。将对transform
函数的调用更改为transform(evo, op.op)
,可能会给出预期的结果。
此外,两个for
循环可以组合成一个循环,如下所示:
for (ChangeOperator op <- operators, EvoQuery evo <- evoQueries) {
transform(evo, op);
};
transform
的前两个备选方案失败,因为 for 循环主体中op
参数的类型既不是实体操作也不是属性操作:它是ChangeOperator
。换句话说:具体的语法类型不是子类型,即使定义它们的规则只是一个"链规则"。
要匹配树中的某个级别,可以使用具体匹配或抽象匹配,如下所示:
在具体的语法中,我们解析一个带有单个孔的 ChangeOperator 代码段,并使用该模式与您作为第二个参数提供的解析树进行匹配:
EvoQuery transform(EvoQuery q, (ChangeOperator) `<EntityOperation op>`) { ... }
EvoQuery transform(EvoQuery q, (ChangeOperator) `<AttributesOperations op>`) {...}
在抽象表示法中,我们可以使用 ChangeOperator 的每个替代语法规则的名称标签来匹配替代。所以在这个例子中,我们使用抽象符号来匹配具体的解析树:
EvoQuery transform(EvoQuery q, entityOperator(EntityOperation op)) { ... }
EvoQuery transform(EvoQuery q, attributeOperator(AttributesOperations op)) {...}
PS:这个定义中有一个错误:
syntax ChangeOperator
= entityOperator: EntityOperation op
| attributeOperator : AttributesOperations op
| relationOperator: RelationOperations op
| databaseOperator: DatabaseOperations op
;
每个op
标签都应该不同,因为它们产生不同的类型:
syntax ChangeOperator
= entityOperator: EntityOperation eop
| attributeOperator : AttributesOperations aop
| relationOperator: RelationOperations rop
| databaseOperator: DatabaseOperations dop
;