【问题标题】:Xtext grammar error "Decision can match input ... using multiple alternatives: 1, 3, 4, 5"Xtext 语法错误“Decision can match input ... using multiple alternatives: 1, 3, 4, 5”
【发布时间】:2013-12-29 23:47:30
【问题描述】:

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

总共有 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) 时,这是有效的,这意味着在第一个代码 sn-p 中没有其他情况:

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;

知道如何解决这个问题吗?希望您能帮助我,我将不胜感激!

这是我从代码 sn-p #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 ';'))

【问题讨论】:

    标签: parsing antlr grammar xtext


    【解决方案1】:

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

    (newParamA = ParamA)? & (newParamB = ParamB)? & (newParamC = ParamC)?
    

    (括号。为清楚起见添加)

    另请注意,避免关键字中的空格通常是个好主意。你应该更喜欢'paramA' '=' 而不是'paramA ='。这将大大改善词法分析器/解析器中的错误处理。

    【讨论】:

    • 感谢您的回复。实际上,我从您的方法 (A)? & (B)? & (C)?(简化)开始,但它允许我定义一个没有参数定义的组件。就我而言,我需要定义一个组件,该组件至少定义一个参数(A 或 B 或 C)。我怎么能存档呢?我试图解决这个问题的方法类似于 ((A) & (B)? & (C)?)) | ((A)? & (B) & (C)?) | ((A)? & (B)? & (C)),但它不起作用。
    • 现在我阅读了 Matthias 的答案,我认为您为我指明了正确的方向,但我仍然不知道从哪里开始。我接受了他的回答,因为它帮助我解决了问题。感谢您抽出宝贵时间并感谢您指出要避免在我的关键字中出现空格。 +1
    【解决方案2】:

    你想做的是这样的:

    你想要一个简单的语法(正如 Sebastian 所描述的那样):

    (newParamA = ParamA)? & (newParamB = ParamB)? & (newParamC = ParamC)?
    

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

    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);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-01-19
      • 1970-01-01
      • 2017-07-12
      • 2015-01-30
      • 2012-03-06
      • 2019-10-24
      • 1970-01-01
      • 2014-05-20
      • 2020-08-18
      相关资源
      最近更新 更多