udacity treehouse tracks techdegree teamtreehouse programming plans learn curso courses code app ruby parsing grammar treetop

ruby - tracks - treehouse courses list



Aprendiendo Treetop (8)

Estoy tratando de enseñarme el generador de gramática Treetop de Ruby. Estoy descubriendo que no solo la documentación es escasamente escasa para el "mejor" que existe, sino que no parece funcionar tan intuitivamente como esperaba.

En un alto nivel, realmente me encantaría un tutorial mejor que los documentos in situ o el video, si es que hay alguno.

En un nivel inferior, aquí hay una gramática que no puedo poner en práctica:

grammar SimpleTest rule num (float / integer) end rule float ( (( ''+'' / ''-'')? plain_digits ''.'' plain_digits) / (( ''+'' / ''-'')? plain_digits (''E'' / ''e'') plain_digits ) / (( ''+'' / ''-'')? plain_digits ''.'') / (( ''+'' / ''-'')? ''.'' plain_digits) ) { def eval text_value.to_f end } end rule integer (( ''+'' / ''-'' )? plain_digits) { def eval text_value.to_i end } end rule plain_digits [0-9] [0-9]* end end

Cuando lo cargo y ejecuto algunas afirmaciones en un objeto de prueba muy simple, encuentro:

assert_equal @parser.parse(''3.14'').eval,3.14

Funciona bien, mientras

assert_equal @parser.parse(''3'').eval,3

plantea el error: NoMethodError: método privado `eval ''pidió #

Si invierto el entero y floto en la descripción, tanto los enteros como los flotantes me dan este error. Creo que esto puede estar relacionado con la búsqueda limitada, pero no puedo encontrar ninguna información en ninguno de los documentos ni siquiera para cubrir la idea de evaluar en el contexto "o"

Un poco más de información que puede ayudar. Aquí hay información de pp para ambos bloques de análisis ().

El flotador:

SyntaxNode+Float4+Float0 offset=0, "3.14" (eval,plain_digits): SyntaxNode offset=0, "" SyntaxNode+PlainDigits0 offset=0, "3": SyntaxNode offset=0, "3" SyntaxNode offset=1, "" SyntaxNode offset=1, "." SyntaxNode+PlainDigits0 offset=2, "14": SyntaxNode offset=2, "1" SyntaxNode offset=3, "4": SyntaxNode offset=3, "4"

El número entero ... tenga en cuenta que parece haberse definido para seguir la regla de enteros, pero no capturó el método eval ():

SyntaxNode+Integer0 offset=0, "3" (plain_digits): SyntaxNode offset=0, "" SyntaxNode+PlainDigits0 offset=0, "3": SyntaxNode offset=0, "3" SyntaxNode offset=1, ""

Actualizar:

Tengo mi problema particular funcionando, pero no tengo idea de por qué:

rule integer ( ''+'' / ''-'' )? plain_digits { def eval text_value.to_i end } end

Esto no tiene sentido con los documentos que están presentes, sino que simplemente quita los paréntesis adicionales que hacen que la coincidencia incluya la clase Integer1 así como Integer0. Integer1 es aparentemente la clase que contiene el método eval (). No tengo idea de por qué este es el caso.

Todavía estoy buscando más información sobre treetop.


Lamentablemente, la documentación de Treetop apesta. Mucho. Y los ejemplos en el sitio web no son útiles. Descubrí que dzone tiene una colección bastante grande de gramáticas en los árboles:

Gramáticas de los árboles


Acabo de comenzar a experimentar con TreeTop.

Probé el cambio

rule num (float / integer) end

a

rule num (float / integer) { def eval text_value.to_f end } end

Y parece funcionar.


Usted podría apreciar el sencillo y sencillo tutorial de Paul Battley en Primeros pasos con Treetop

Comenzando con una gramática mínima, muestra cómo crear un analizador y luego a través de un par de iteraciones agrega solo un poco de funcionalidad. Fue suficiente para sacarme de los puntos de partida.




Los documentos Treetop parecen suponer que ya sabes bastante sobre el análisis de gramáticas de expresión (PEG). Treetop se basa completamente en PEG. Sin embargo, los PEG son más grandes que Treetop, es decir, también se usan en otras bibliotecas de análisis. Al aprender Treetop, me pareció muy útil estudiar PEG en general. Eso ayudó a llenar muchos vacíos en la documentación.



Este es un error. Los paréntesis innecesarios alrededor de la regla para un entero hace que la construcción de un módulo adicional contenga la definición de eval, y este módulo no se mezcla en el nodo, por lo que ''eval'' no está disponible. Puede ver esto claramente si compara el código de Ruby (generado con el comando tt) para las versiones con y sin estos paréntesis adicionales.