如何允许 Xtext 语法中的多个元素只使用一次修饰符?

How to allow a modifier only once for multiple elements in Xtext Grammar?

我想创建以下 DSL

namespace x.y.z
system <NAME> {
    component A { ... }
    component B { ... }
    coordinator component C { ... }
    component D { ... }
}

所有 component 都具有相同的结构,除了只有一个需要 coordinator 修饰符。

现在我尝试了两种不同的语法:

System:
    'system' name=ValidID '{'
        (coordinatorComponent=CoordinatorComponent) & 
        (components+=NonCoordinatorComponent*) & 
        (constraints=ComponentConstraints)?
    '}'
;

ComponentConstraints:
    'constraints' '{}'
;

CoordinatorComponent:
    'coordinator' 'component' {Component}
;

NonCoordinatorComponent:
    'component' {Component};

Component:
    name=ValidID '{'
        features+=Feature*
    '}'
;

同款略有变化

CoordinatorComponent:
    'coordinator' {Component}
;

NonCoordinatorComponent:
    {Component};

Component:
    'component' name=ValidID '{'
        features+=Feature*
    '}'
;

第一个导致错误 rule ruleSystem failed predicate: {getUnorderedGroupHelper().canLeave(grammarAccess.getSystemAccess().getUnorderedGroup())}? 在编写 DSL(不是语法)时的编辑器。

第二个有效,但我仍然认为它很奇怪,因为它并没有真正使用 修饰符,而是一种全新的类型。有没有更好的方法来一般地定义 Component 并使用必须在 System 中恰好使用一次的修饰符?

使用解析器片段怎么样

System:
    'system' name=ValidID '{'
        ((coordinatorComponent=CoordinatorComponent) & 
        (components+=NonCoordinatorComponent*) & 
        (constraints=ComponentConstraints)?)
    '}'
;

ComponentConstraints:
    'constraints' '{}'
;

CoordinatorComponent:
    'coordinator' 'component' Component
;

NonCoordinatorComponent:
    'component' Component;

fragment Component:
    name=ValidID '{'
        features+=Feature*
    '}'
;