あなたの言語を .rb ファイルにコンパイルするように treetop に依頼しました。それは私に掘り下げる何かを与えました:
$ tt -o /tmp/rip.rb /tmp/rip.treetop
次に、この小さなスタブを使用してループを再作成しました。
require 'treetop'
load '/tmp/rip.rb'
RipParser.new.parse('')
これはハングします。ほら、面白いじゃないですか!空の文字列は、質問の数十行の例と同じように動作を再現します。
ハングしている場所を見つけるために、Emacs キーボード マクロを使用して rip.rb を編集し、各メソッドのエントリにデバッグ ステートメントを追加しました。例えば:
def _nt_root
p [__LINE__, '_nt_root'] #DEBUG
start_index = index
これで、ループの範囲を確認できます。
[16, "root"]
[21, "_nt_root"]
[57, "_nt_statement"]
...
[3293, "_nt_eol"]
[3335, "_nt_semicolon"]
[3204, "_nt_comment"]
[57, "_nt_statement"]
[57, "_nt_statement"]
[57, "_nt_statement"]
...
そこからさらにデバッグすると、整数を空の文字列にすることが許可されていることがわかります。
rule integer
digit*
end
これにより、ステートメントを空の文字列にすることが間接的に許可され、トップレベルのルールstatement*
が空のステートメントを永久に消費することができます。に変更*
する+
とループは修正されますが、別の問題が明らかになります。
/tmp/rip.rb:777:in `_nt_object': stack level too deep (SystemStackError)
from /tmp/rip.rb:757:in `_nt_compound_object'
from /tmp/rip.rb:1726:in `_nt_range'
from /tmp/rip.rb:1671:in `_nt_special_literals'
from /tmp/rip.rb:825:in `_nt_literal_object'
from /tmp/rip.rb:787:in `_nt_object'
from /tmp/rip.rb:757:in `_nt_compound_object'
from /tmp/rip.rb:1726:in `_nt_range'
from /tmp/rip.rb:1671:in `_nt_special_literals'
... 3283 levels...
範囲は、special_literals、literal_object、object、および Compound_object を介して、間接的に左再帰です。Treetop は、左再帰に直面すると、吐くまでスタックを食べます。その問題を簡単に解決する方法はありませんが、少なくともスタック トレースを取得する必要があります。
また、これは差し迫った問題ではありませんが、 の定義digit
は奇妙です: 1 桁または複数のいずれかです。これにより、(おそらく) 不正な integer が発生しdigit*
たり、許可されたりします。digit+
1________2