Я попросил treetop скомпилировать ваш язык в файл .rb. Это дало мне кое-что, чтобы покопаться:
$ 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 и соединение_object. Верхушка дерева при столкновении с левой рекурсией съедает стек до тех пор, пока его не стошнит У меня нет быстрого решения этой проблемы, но, по крайней мере, теперь у вас есть трассировка стека.
Кроме того, это не ваша непосредственная проблема, но определение digit
странно: оно может быть либо одной цифрой, либо множеством. Это заставляет digit*
или digit+
разрешать (предположительно) недопустимое целое число 1________2
.