DeCaf中的ANTLR歧义-教授不确定错误在哪里

DeCaf中的ANTLR歧义-教授不确定错误在哪里,antlr,antlrworks,Antlr,Antlrworks,我正在为学校做一个项目,将BNF格式的Decaf规范转换为上下文无关语法,并在ANTLR中构建它。我已经做了几个星期了,当我陷入困境时,我会去找教授,但我最终遇到了他说不应该导致错误的东西。这是我语法中孤立的部分,expr是起点。在此之前,我有一个问题 在语法中,如果我的lexer规则出现在解析器规则之前,或者它们通过语法文件间歇性地混合在一起,这有关系吗 calloutarg: expr | STRING; expr: multexpr ((PLUS|MINUS) multe

我正在为学校做一个项目,将BNF格式的Decaf规范转换为上下文无关语法,并在ANTLR中构建它。我已经做了几个星期了,当我陷入困境时,我会去找教授,但我最终遇到了他说不应该导致错误的东西。这是我语法中孤立的部分,expr是起点。在此之前,我有一个问题

在语法中,如果我的lexer规则出现在解析器规则之前,或者它们通过语法文件间歇性地混合在一起,这有关系吗

calloutarg:         expr | STRING;
expr:  multexpr ((PLUS|MINUS) multexpr)* ;
multexpr : atom ((MULT|DIVISION) atom)*
;

atom : OPENPAR expr CLOSEPAR | ID ((OPENBRACKET expr CLOSEBRACKET)? | OPENPAR ((expr (COMMA)* )+)? CLOSEPAR)|
CALLOUT OPENPAR STRING (COMMA (calloutarg)+ COMMA)? CLOSEPAR | constant;
constant: INT | CHAR | boolconstant;
boolconstant: TRUE|FALSE;
这种难看的格式是因为他对调试的部分建议是采用单独的规则,并在模糊之处将其分解,以查看错误从何处开始。在本例中,它说问题出在长ID部分,Open括号和OPENPAR是原因。如果你有任何想法,我非常感激。谢谢你,很抱歉我发布的代码的格式太糟糕了

在语法中,如果我的lexer规则出现在解析器规则之前,这有关系吗

不,那没关系

问题在于,在您的
atom
规则中,ANTLR无法在这三种变体之间做出选择:

  • ID(…
  • ID[…
  • ID
  • 不必求助于(可能)回溯。您可以通过使用一些语法谓词(看起来像:
    (…)=>…
    )来解决它。语法谓词只不过是一个“前瞻”,如果这个“前瞻”成功,它会选择那个特定的路径

    您当前的
    atom
    规则可以重写如下:

    atom 
      :  OPENPAR expr CLOSEPAR
      |  ID OPENPAR ((expr (COMMA)* )+)? CLOSEPAR 
      |  ID OPENBRACKET expr CLOSEBRACKET
      |  ID
      |  CALLOUT OPENPAR STRING (COMMA (calloutarg)+ COMMA)? CLOSEPAR
      |  constant
      ;
    
    使用谓词时,它将如下所示:

    atom 
      :  OPENPAR expr CLOSEPAR
      |  (ID OPENPAR)=>     ID OPENPAR ((expr (COMMA)* )+)? CLOSEPAR 
      |  (ID OPENBRACKET)=> ID OPENBRACKET expr CLOSEBRACKET
      |  ID
      |  CALLOUT OPENPAR STRING (COMMA (calloutarg)+ COMMA)? CLOSEPAR
      |  constant
      ;
    
    这应该会起作用

    注意:不要使用ANTLRWorks来生成或测试解析器!它不能处理谓词(很好)。最好在命令行中执行

    另见:


    编辑

    让我们为
    atom
    规则从
    A
    F
    的六个不同“分支”贴上标签:

    atom                                                            // branch
      :  OPENPAR expr CLOSEPAR                                      //   A
      |  ID OPENBRACKET expr CLOSEBRACKET                           //   B
      |  ID OPENPAR ((expr COMMA*)+)? CLOSEPAR                      //   C
      |  ID                                                         //   D
      |  CALLOUT OPENPAR STRING (COMMA calloutarg+ COMMA)? CLOSEPAR //   E
      |  constant                                                   //   F
      ;
    
    现在,当(未来)解析器应该像这样处理输入时:

    ID OPENPAR expr CLOSEPAR
    
    ANTLR不知道解析器应该如何处理它。它可以用两种不同的方式进行解析:

  • 分支
    D
    后接分支
    A
  • 分支机构
    C
  • 这就是ANTLR所抱怨的歧义的根源。如果您要注释掉其中一个分支
    A
    C
    D
    ,错误就会消失

    希望有帮助

    在语法中,如果我的lexer规则出现在解析器规则之前,这有关系吗

    不,那没关系

    问题在于,在您的
    atom
    规则中,ANTLR无法在这三种变体之间做出选择:

  • ID(…
  • ID[…
  • ID
  • 不必求助于(可能)回溯。您可以通过使用一些语法谓词(看起来像:
    (…)=>…
    )来解决它。语法谓词只不过是一个“前瞻”,如果这个“前瞻”成功,它会选择那个特定的路径

    您当前的
    atom
    规则可以重写如下:

    atom 
      :  OPENPAR expr CLOSEPAR
      |  ID OPENPAR ((expr (COMMA)* )+)? CLOSEPAR 
      |  ID OPENBRACKET expr CLOSEBRACKET
      |  ID
      |  CALLOUT OPENPAR STRING (COMMA (calloutarg)+ COMMA)? CLOSEPAR
      |  constant
      ;
    
    使用谓词时,它将如下所示:

    atom 
      :  OPENPAR expr CLOSEPAR
      |  (ID OPENPAR)=>     ID OPENPAR ((expr (COMMA)* )+)? CLOSEPAR 
      |  (ID OPENBRACKET)=> ID OPENBRACKET expr CLOSEBRACKET
      |  ID
      |  CALLOUT OPENPAR STRING (COMMA (calloutarg)+ COMMA)? CLOSEPAR
      |  constant
      ;
    
    这应该会起作用

    注意:不要使用ANTLRWorks来生成或测试解析器!它不能处理谓词(很好)。最好在命令行中执行

    另见:


    编辑

    让我们为
    atom
    规则从
    A
    F
    的六个不同“分支”贴上标签:

    atom                                                            // branch
      :  OPENPAR expr CLOSEPAR                                      //   A
      |  ID OPENBRACKET expr CLOSEBRACKET                           //   B
      |  ID OPENPAR ((expr COMMA*)+)? CLOSEPAR                      //   C
      |  ID                                                         //   D
      |  CALLOUT OPENPAR STRING (COMMA calloutarg+ COMMA)? CLOSEPAR //   E
      |  constant                                                   //   F
      ;
    
    现在,当(未来)解析器应该像这样处理输入时:

    ID OPENPAR expr CLOSEPAR
    
    ANTLR不知道解析器应该如何处理它。它可以用两种不同的方式进行解析:

  • 分支
    D
    后接分支
    A
  • 分支机构
    C
  • 这就是ANTLR所抱怨的歧义的根源。如果您要注释掉其中一个分支
    A
    C
    D
    ,错误就会消失


    希望这能有所帮助。

    谢谢你的帮助!我有一个问题,为什么我的左保理不能处理ID | ID[| ID(问题?)@Nick,请查看我答案的编辑。谢谢你的帮助!我有一个问题,为什么我的左保理不能处理ID | ID[| ID(问题?@Nick,请查看我答案的编辑。