me preguntó copas de los árboles para compilar su idioma en un archivo .rb. Eso me dio algo para cavar en:
$ tt -o /tmp/rip.rb /tmp/rip.treetop
Luego utiliza este pequeño trozo de recrear el bucle:
require 'treetop'
load '/tmp/rip.rb'
RipParser.new.parse('')
Este cuelga. Ahora, ¡no es tan interesante! Una cadena vacía reproduce el comportamiento tan bien como el ejemplo de la docena o la línea en su pregunta.
para averiguar dónde está colgado, he usado una macro de teclado de Emacs para editar rip.rb, la adición de una declaración de depuración a la entrada de cada método. Por ejemplo:
def _nt_root
p [__LINE__, '_nt_root'] #DEBUG
start_index = index
Ahora podemos ver el alcance del bucle:
[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"]
...
Además depuración de allí revela que un número entero se le permite ser una cadena vacía:
rule integer
digit*
end
Esto permite indirectamente que una instrucción sea una cadena vacía, y la regla de nivel superior statement*
para consumir declaraciones vacías para siempre. Cambiando *
a +
fija el bucle, pero revela otro problema:
/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...
rango es de izquierda recursividad, de forma indirecta, a través de special_literals, literal_object, objeto y compound_object. Treetop, cuando se enfrenta con recursividad a la izquierda, se come hasta que vomita. No tengo una solución rápida para ese problema, pero al menos tienes un rastro de pila para ir desde ahora.
Además, este no es su problema inmediato, pero la definición de digit
es impar: puede ser de un dígito o múltiple. Esto causa digit*
o digit+
para permitir el (presumiblemente) número entero ilegal 1________2
.
Vi los primeros cinco o seis videos tutoriales, pero hasta ahora no he podido obtener una configuración de trabajo junto con. Tienes razón en que él no comienza demasiado rápido. Le daré a ANTLR otra oportunidad. – ravinggenius
@Raving, bueno, me gustó el aspecto de tu gramática 'treetop', y si querías programar en Ruby, entonces cambiar a ANTLR no ayudaría mucho. :) Solo pensé que su libro hizo un excelente trabajo al discutir cómo construir buenos analizadores, y ANTLR fue la herramienta que eligió usar. – sarnold