1

我不敢相信我是第一个问这个问题的人!使用 ANTLR4 时,我需要一个访问者遍历解析树并进行一些修改,因此我需要访问每个树节点内的子树​​。这是我的 Fortran 语法片段:

ifStatement
    : IF_KEYWORD expression
      ( ( THEN_KEYWORD
          executableStatement*
          elseIfStatement*  // <--- problem is here
          elseStatement?
          END_KEYWORD IF_KEYWORD
        ) | executableStatement )
    ;

elseIfStatement
    : ELSE_KEYWORD IF_KEYWORD expression THEN_KEYWORD executableStatement*
    ;

如您所见, 中存在重复子树elseIfStatementifStatement当我为解析树创建访问者时,我想访问所有elseIfStatement被解析的上下文:

public Void visitIfStatement(FortranParser.IfStatementContext ctx) {
    ...
    for (FortranParser.ElseIfStatementContext elsIf : ctx.elseIfStatement()) // ERROR!!!
        visitElseIfStatement(elseIf);
    ...
    return null;
}

ctx.elseIfStatement()只返回 as 的第一次出现elseIfStatement

if (a == 1) then
    a = 2
else if (b == 1) then |
    b = 3             | -> returned by ctx.elseIfStatement()
else if (c == 1) then \
    c = 4             \ -> ignored??
else
    d = 4
end if

那么如何访问所有elseIfStatement子树呢?这个问题适用于executableStatement*上面所有带有'*'的解析器规则模式。

4

1 回答 1

1

可能是一个错误,如果我删除| executableStatement替代方案,ctx.elseIfStatement() 确实会返回一个List<ElseIfStatementContext>. 您可能想报告它:https ://github.com/antlr/antlr4/issues

但是,正如您现在所做的那样,您将被迫进行一些null检查以查看哪些替代方案匹配。更好的方法是“标记”您的替代方案

ifStatement
 : IF_KEYWORD expression
   THEN_KEYWORD
   executableStatement* 
   elseIfStatement*  
   elseStatement? END_KEYWORD IF_KEYWORD     #ifMultipleStatements
 | IF_KEYWORD expression executableStatement #ifSingleStatement
 ;

这将生成以下内容:

public static class IfMultipleStatementsContext extends IfStatementContext {
    ...
    public List<ElseIfStatementContext> elseIfStatement() {
        return getRuleContexts(ElseIfStatementContext.class);
    }
    ...
}

即:它生成适量的ElseIfStatementContexts。

于 2013-07-10T07:32:18.407 回答