我无法相信我是第一个提出这个问题的人!使用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*
;
如您所见,elseIfStatement
中有重复的子树ifStatement
。当我为解析树创建访问者时,我想访问所有被解析的elseIfStatement
的上下文:
public Void visitIfStatement(FortranParser.IfStatementContext ctx) {
...
for (FortranParser.ElseIfStatementContext elsIf : ctx.elseIfStatement()) // ERROR!!!
visitElseIfStatement(elseIf);
...
return null;
}
但ctx.elseIfStatement()
仅返回第一次出现的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*
。
答案 0 :(得分:1)
可能是个错误,如果我移除了| executableStatement
替代方案,ctx.elseIfStatement()
会返回List<ElseIfStatementContext>
。您可能想要报告它:https://github.com/antlr/antlr4/issues
但是,正如您现在所做的那样,您将被迫进行一些null
检查以查看哪些替代方案匹配。一个更好的方法是"label" your alternatives:
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);
}
...
}
即:它会生成适当数量的ElseIfStatementContext
s。