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

ご覧のとおり、 には繰り返しサブツリー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*ます。

4

1 に答える 1

1

バグの可能性があります。代替を削除する| executableStatementと、. 報告することをお勧めします: https://github.com/antlr/antlr4/issuesctx.elseIfStatement() List<ElseIfStatementContext>

ただし、現在行っているように、どの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 に答える