2013-07-10 112 views
1

我不敢相信我是第一個問這個問題的人!當使用ANTLR4時,我需要訪問者遍歷分析樹並進行一些修改,所以我需要訪問每個樹節點中的子樹。這裏是我的Fortran語法的一個片段:如何通過訪問者訪問ANTLR4中的重複子樹?

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* 
    ; 

正如你所看到的,有在ifStatement重複子樹elseIfStatement。當我創建解析樹訪問者,我想訪問被解析的所有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*

回答

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上的適當量。

+0

巴特,感謝您的幫助!我遵循你的建議,並在'class IfMultipleStatementsContext'中得到了'public List elseIfStatement()'。我認爲ANTLR4不喜歡我以前的規則風格?無論如何我會報告這個問題。 –

+0

@LiDong,不客氣。 –

+0

我還有一個問題。由於我們已經標記了其他規則,如果我們有另一個規則包含'ifStatement',那麼我們該如何回到'ifMultipleStatements'或'ifSingleStatement'。我在IfStatementContext類中看不到它們。 –