Parsing Xtext语法错误“;决策可以匹配输入。。。使用多个备选方案:1、3、4、5“;

Parsing Xtext语法错误“;决策可以匹配输入。。。使用多个备选方案:1、3、4、5“;,parsing,antlr,grammar,xtext,Parsing,Antlr,Grammar,Xtext,我被我的xtext语法定义卡住了。基本上,我喜欢为一个组件定义多个参数。组件应至少包含一个参数定义paramA或paramB或paramC或(paramA和paramB)或(paramB和paramC)或(paramA和paramB) 从我的语法定义中可以看出,总共有6个案例: Component: 'Define available parameters:' ( (newParamA = ParamA | newParamB = ParamB | newParamC =

我被我的xtext语法定义卡住了。基本上,我喜欢为一个组件定义多个参数。组件应至少包含一个参数定义
paramA
paramB
paramC
或(
paramA
paramB
)或(
paramB
paramC
)或(
paramA
paramB

从我的语法定义中可以看出,总共有6个案例:

Component:
    'Define available parameters:' (
        (newParamA = ParamA | newParamB = ParamB | newParamC = ParamC)
        | (newParamA = ParamA & newParamB = ParamB)
        | (newParamA = ParamA & newParamC = ParamC)
        | (newParamB = ParamB & newParamC = ParamC)
        | (newParamA = ParamA & newParamB = ParamB & newParamC = ParamC)
    )
;

ParamA: ('paramA = ' paramA=Integer ';');
ParamB: ('paramB = ' paramB=Integer ';');
ParamC: ('paramC = ' paramC=Integer ';');

// Datatype
Integer returns ecore::EIntegerObject: '-'? INT;
以下是当我将语法简化为使用
(newParamA=ParamA | newParamB=ParamB | newParamC=ParamC)
时所起的作用,意思是在第一个代码段中没有其他情况:

Define available parameters:
    paramA = 1;
...
Define available parameters:
    paramB = 2;
...
Define available parameters:
    paramC = 3;
但我希望能够在我的dsl中定义多个可用参数,例如

Define available parameters:
    paramA = 1; paramB = 2;
...
Define available parameters:
    paramB = 2; paramC = 3;
...
Define available parameters:
    paramA = 1; paramB = 2; paramC = 3;
你知道如何解决这个问题吗?希望你能帮助我,我会感谢你的帮助

这是我从代码片段1生成语法时遇到的错误:

warning(200): ../my.packagename/src-gen/my/packagename/projectname/parser/antlr/internal/InternalMyDSL.g:722:1: Decision can match input such as "'paramC = ' '-' RULE_INT ';'" using multiple alternatives: 1, 3, 4, 5
As a result, alternative(s) 3,5,4 were disabled for that input
Semantic predicates were present but were hidden by actions.

...

4514 [main] ERROR enerator.CompositeGeneratorFragment  - java.io.FileNotFoundException: ..\my.packagename.ui\src-gen\my\packagename\projectname\ui\contentassist\antlr\internal\InternalMyDSLParser.java (The system cannot find the file specified)
org.eclipse.emf.common.util.WrappedException: java.io.FileNotFoundException: ..\my.packagename.ui\src-gen\my\packagename\projectname\ui\contentassist\antlr\internal\InternalMyDSLParser.java (The system cannot find the file specified)
    at org.eclipse.xtext.util.Files.readFileIntoString(Files.java:129)
    at org.eclipse.xtext.generator.parser.antlr.AbstractAntlrGeneratorFragment.simplifyUnorderedGroupPredicates(AbstractAntlrGeneratorFragment.java:130)
    at org.eclipse.xtext.generator.parser.antlr.AbstractAntlrGeneratorFragment.simplifyUnorderedGroupPredicatesIfRequired(AbstractAntlrGeneratorFragment.java:118)
    at org.eclipse.xtext.generator.parser.antlr.XtextAntlrUiGeneratorFragment.generate(XtextAntlrUiGeneratorFragment.java:86)
这里有一个我尝试过的解决方法(有效),但它不是一个解决方案,因为语言中的关键字正在更改以避免解析器错误:

('newParamA1 = ' paramA1=Integer ';')
| ('newParamB1 = ' paramB1=Integer ';')
| ('newParamC1 = ' paramC1=Integer ';')
| (('newParamA2 = ' paramA2=Integer ';') & ('newParamB2 = ' paramB2=Integer ';'))
| (('newParamA3 = ' paramA3=Integer ';') & ('newParamC2 = ' paramC2=Integer ';'))
| (('newParamB3 = ' paramB3=Integer ';') & ('newParamC3 = ' paramC3=Integer ';'))
| (('newParamA4 = ' paramA4=Integer ';') & ('newParamB4 = ' paramB4=Integer ';') & ('newParamC4 = ' paramC4=Integer ';'))

我认为您真正想要的是验证,确保至少在语义级别而不是语法级别给出一个参数。这将大大简化你的语法,例如你可以使用

(newParamA = ParamA)? & (newParamB = ParamB)? & (newParamC = ParamC)?
(为了清楚起见,添加了parenth)


还要注意的是,通常避免在关键字中使用空格是个好主意。您应该更喜欢
'paramA'='
而不是
'paramA='
。这将大大改进lexer/parser中的错误处理。

您要做的是:

class MyDSLValidator extends AbstractMyDSLValidator {
    @Check
    def void atLeastOneParameter(Component component) {
        if (component.newParamA == null && component.newParamB == null && component.newParamC == null) {
            error('requires at least one parameter definition', MyDSLPackage.Literals.COMPONENT__PARAMA);
        }
    }
}
您需要一个简单的语法(正如塞巴斯蒂安所描述的):

为了确保至少需要一个参数,您可以编写自己的验证器,如下所示:

class MyDSLValidator extends AbstractMyDSLValidator {
    @Check
    def void atLeastOneParameter(Component component) {
        if (component.newParamA == null && component.newParamB == null && component.newParamC == null) {
            error('requires at least one parameter definition', MyDSLPackage.Literals.COMPONENT__PARAMA);
        }
    }
}

谢谢你的回复。实际上,我是从你的方法开始的(B) ?&(C) ?(简化)但它允许我定义没有参数定义的组件。在我的例子中,我需要定义一个至少定义一个参数(a、B或C)的组件。我怎么能把它归档呢?我试图解决的问题与
((A)和(B)&(C)&(A)&(B)和(C);((A)&(B)和(C));((A)&(B)&(C)&(C))
类似。现在我读了Matthias的答案,我认为你为我指明了正确的方向,但我仍然不知道从哪里开始。我接受了他的回答,因为它帮助我解决了这个问题。感谢您抽出时间,感谢您指出避免在我的关键字中出现空格+1.