2016-04-29 9 views
1

を扱うとき、私はシンプルなANTLR4文法をしました電話を切っ:ANTLR4がEOF

grammar Test; 
preprocessing_file: oneline+; 

oneline: IDENTIFIER? new_line; 

new_line: EOF|CRLF 
; 

WS: [ \t\f]+ -> channel(2); 

CRLF: '\r'? '\n'; 


IDENTIFIER: (NONDIGIT | DIGIT)+ 
; 
    fragment DIGIT: [0-9]; 
    fragment NONDIGIT: [_a-zA-Z] ; 

私はCRLFによって終了されていない最後の行を可能に改行ルールを使用する方法をテストしていました。私はANTLR v4.1とv4.5.3で文法をテストしました。

数行のテキストの入力ファイルでANTLR4がフリーズし、しばらくするとOutOfMemoryExceptionが発生しました。 ANTLR4が無限ループに入ったようです。 ANTLR4のバグですか?私は何か悪いことをしましたか?また、私がルールのEOFを削除しても、すべて正常に動作します。

答えて

2

で検証するために必要であれば、後の段階でNEW_LINEの存在を検証します。これがなければ、メインルールは決して終了しません。つまり、レクサーはルールによって首尾よく消費されたトークンをEOFで生成し続けます。

preprocessing_file: oneline+? EOF ; 
oneline: IDENTIFIER? new_line ; 
new_line: EOF|CRLF ; 
+0

Thxがない最後の行には一致しません。これは問題です。私は、レクサーがそれを消費し続けると無限に多くのEOFが生成される可能性があることを認識しませんでした。しかし、あなたが提案した解決策はうまくいかないでしょう。実際の原因は、 'oneline'ルールが1つのEOFと無期限に一致し、レクサーが無期限にポンピングを続けるということです。非貪欲な演算子、つまりoneline +?を使用する必要があります余分なEOFに加えて – JavaMan

+0

はい - 回答が更新されました。 – GRosenberg

0

EOF [ファイルの終わり]はnew_lineルールであってはなりません。ただ、

oneline: IDENTIFIER? new_line? 

oneline: IDENTIFIER? new_line 

を変更するだけで、メインのルールにEOFを追加する必要があり、すべての

+0

(1)なぜルールでEOFが許可されていないのですか?この文法でファイル (2)の終わりを明示的に一致させるために私たちのために作成されたものではありませんIDENTIFIERは何でも構いませんが、私の実際の文法は内容について非常に具体的であり、 new_lineはオプションではありません。とにかく、ANLTR4がハングして後でOutOfMemoryExceptionをスローする理由はありません – JavaMan

+0

私はそれが許されないと言っているわけではなく、そこに置く本当の理由はないということだけです。最後に根本的なルールを入れ、それが助けになるかどうかを見てみましょう。そうでなければ、別の間違いがなければなりません...私は文法では見ていません/文法全体ですか? – Divisadero

+0

はい文法全体、私は '文法xx'を除外しました。ライン。 (私はその行をインクルードするためにsrcを編集したばかりです)。そして、new_lineルールのEOFがなければ、ANTLR4は正しく動作しますが、末尾のCRLF – JavaMan