0

そこで、私は Antlr v4 で実験を行っており、それがどのように機能するかを理解するために、いくつかの変わった文法を試しています。現在のテスト ケースは次のとおりです。

A、B、C、D の順に文字を並べた文法をお願いします。文字が繰り返されることがあります。また、文法をより面白くするために、A と B をグループ化し、C と D もグループ化します。したがって、次のような文字列は許容される文法です。

AAA

あいうえお

ACCCDD

しかし、うまくいっていません。起こっていることは、Antlr が私の文法に対してより良い終了規則を必要としているということだと思います。A と B を収集した後、C の存在が次のルールに進むことを意味することを認識していないようです。実際には機能していますが、エラーメッセージが表示され、結果の解析ツリーには、エラーメッセージを発行した場所に余分な要素が挿入されたように、null 要素が含まれているようです。

エラー メッセージの例を次に示します。

line 1:2 extraneous input 'C' expecting {'B', 'A'}

これは、入力「ABCD」に対して発生します。そのため、Antlr がそこにある C を見ると、何か奇妙なことが起こっています。解析ツリーの出力は次のとおりです。

'ABCD': (prog (aOrB (a A) (aOrB (b B) aOrB)) (cOrD (c C) (cOrD (d D) cOrD)) <EOF>)

最初の要素セットの最後に空の aOrB 要素があることがわかります。

何が起こっているのですか?エラーを発行して空の要素を追加するとき、Antlrはここで何を「考えている」のでしょうか? そして、どうすればこれを修正できますか?

わかりました、ここに悲惨な詳細があります。

私の文法:

grammar Abcd;

prog : aOrB cOrD EOF;
aOrB : ( a | b ) aOrB ;
a : 'A'+ ;
b : 'B'+ ;
cOrD : ( c | d ) cOrD ;
c : 'C'+ ;
d : 'D'+ ;

Javaでの私のテストプログラム:

  package antlrtests;

  import antlrtests.grammars.*;
  import org.antlr.v4.runtime.*;
  import org.antlr.v4.runtime.tree.*;

  class AbcdTest {
     private final String[] testVectors = {
        "A", "AABB", "B", "ABCD", "C", "D", };
     public void runTests() {
        for( String test : testVectors )
           simpleTest( test );
     }
     private void simpleTest( String test ) {
        ANTLRInputStream ains = new ANTLRInputStream( test );
        AbcdLexer wpl = new AbcdLexer( ains );
        CommonTokenStream tokens = new CommonTokenStream( wpl );
        AbcdParser wikiParser = new AbcdParser( tokens );
        ParseTree parseTree = wikiParser.prog();
        System.out.println( "'" + test + "': " + parseTree.toStringTree(
                wikiParser ) );
     }
  }

そして私のテストプログラムの出力。Antlr によって標準エラーに出力されるため、エラー メッセージが通常の出力と混同されていることに注意してください。

  run:
  line 1:1 no viable alternative at input '<EOF>'
  'A': (prog (aOrB (a A) aOrB) cOrD <EOF>)
  line 1:4 no viable alternative at input '<EOF>'
  'AABB': (prog (aOrB (a A A) (aOrB (b B B) aOrB)) cOrD <EOF>)
  'B': (prog (aOrB (b B) aOrB) cOrD <EOF>)
  line 1:1 no viable alternative at input '<EOF>'
  line 1:2 extraneous input 'C' expecting {'B', 'A'}
  line 1:4 no viable alternative at input '<EOF>'
  'ABCD': (prog (aOrB (a A) (aOrB (b B) aOrB)) (cOrD (c C) (cOrD (d D) cOrD)) <EOF>)
  line 1:0 no viable alternative at input 'C'
  line 1:1 no viable alternative at input '<EOF>'
  line 1:0 no viable alternative at input 'D'
  'C': (prog aOrB (cOrD (c C) cOrD) <EOF>)
  line 1:1 no viable alternative at input '<EOF>'
  'D': (prog aOrB (cOrD (d D) cOrD) <EOF>)
  BUILD SUCCESSFUL (total time: 0 seconds)

どんな助けでも大歓迎です。

4

2 に答える 2

0

これはあなたが求めているものではありませんか?

prog : 'A'* 'B'* 'C'* 'D'* EOF;

次の文法規則は無限に長い一連のAandBトークンに一致します。これは、末尾の再帰aOrB参照がオプションではないためです。StackOverflowExceptionあなたの文法は、入力が十分に多くのAおよび/または文字で始まっている場合はスローするか、Bそうでない場合は構文エラーが発生します。

aOrB : ( a | b ) aOrB ;

グループ化を維持したい場合は、代わりにこの文法を使用できます。aOrBとのcOrDルールだけを変更しました。ルールは一連のトークンにa一致するため、代わりに を使用します ( のインスタンスは 1 つだけ出現し、一連のトークン全体がその子になります)。AaOrBa?a*aA

grammar Abcd;

prog : aOrB cOrD EOF;
aOrB : a? b?;
a : 'A'+ ;
b : 'B'+ ;
cOrD : c? d?;
c : 'C'+ ;
d : 'D'+ ;

これは、同じ言語に一致する (ただし、異なる構文木を生成する) 別の文法で、*+、および?量指定子の他のオプションを示しています。この文法を使用することはお勧めしませんが、各選択肢が何をしているのかを理解し、上記の文法とまったく同じ入力に一致する理由を理解するために、非常に慎重に検討する必要があります。

grammar Abcd;

prog : aOrB cOrD? EOF;
aOrB : a* b;
a : 'A' ;
b : 'B'* ;
cOrD : (c d* | d+);
c : 'C'+ ;
d : 'D' ;
于 2013-05-03T02:23:49.323 に答える
0

aOrB ルールが a と b の順序を強制しないことに気付きましたか? 同様に、コード ルールも同様です。

于 2013-05-03T05:07:04.700 に答える