2013-07-10 1 views
1

나는이 질문을하는 첫 번째 남자라고 믿을 수 없다! ANTLR4를 사용할 때 방문자가 파스 트리를 거쳐 일부 수정을해야하므로 각 트리 노드 내의 하위 트리에 액세스해야합니다. 당신이 볼 수 있듯이방문자를 통해 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을 반복한다 : 여기 내 포트란 문법의 조각입니다. 그래서

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 

:

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

그러나 ctx.elseIfStatement() 단지로 elseIfStatement의 첫 발생을 반환 : 나는 파스 트리에 대한 방문자를 만들 때, 나는 구문 분석 된 모든 elseIfStatement의 컨텍스트에 액세스하려면 elseIfStatement 하위 트리 모두에 액세스하는 방법? 그리고이 질문은 위의 executableStatement*으로 '*'가있는 모든 구문 분석기 규칙 패턴에 적용됩니다. 나는 | executableStatement 대안을 제거하면

답변

1

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의 적절한 양을 생성합니다.

+0

바트, 도와 줘서 고마워! 나는 당신의 충고를 따랐고,'class IfMultipleStatementsContext'에서'public List elseIfStatement()'를 얻었다. 나는 ANTLR4가 이전의 규칙 스타일을 좋아하지 않는다고 생각합니까? 어쨌든 나는이 문제를보고 할 것이다. –

+0

@ 리동, 천만에요. –

+0

다른 질문이 있습니다. 대체 규칙에 레이블을 붙 였기 때문에'ifStatement' 규칙을 포함하고 있다면'ifMultipleStatements' 또는'ifSingleStatement'에 어떻게 도달할까요? 나는'IfStatementContext' 클래스에서 그것들을 보지 못했습니다. –

관련 문제