Pregunta

Estoy tratando de enseñarme a mí mismo generador de gramática copa de árbol de Ruby. Estoy descubriendo que no sólo es la documentación lamentablemente escasa para el "mejor" uno por ahí, pero eso no parece trabajar como intuitivamente como yo esperaba.

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

En un nivel inferior, aquí está una gramática que no puedo ir a trabajar en absoluto:

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 cargo y ejecutar algunas afirmaciones en un objeto de prueba muy simple, me parece:

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

Funciona bien, mientras que

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

plantea el error: NoMethodError: eval método `privado' llamada de #

Si invierto número entero y flotar en la descripción, ambos enteros y flotadores me dan este error. Creo que esto puede estar relacionado con la búsqueda hacia delante limitado, pero no puedo encontrar ninguna información en cualquiera de los documentos a cubrir ni siquiera la idea de evaluar en el "o" contexto

Un poco más de información que puede ayudar. Aquí hay información pp tanto para los parse () bloques.

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 entero ... en cuenta que parece que se ha definido a seguir la regla número entero, pero no captó 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, ""

Actualización:

Yo tengo mi problema particular de trabajo, pero no tengo ni 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, pero sólo la eliminación de los paréntesis adicionales hechas partido incluyen la clase Entero1, así como Integer0. Entero1 es aparentemente la clase sosteniendo el método eval (). No tengo ni idea de por qué este es el caso.

Todavía estoy en busca de más información sobre las copas de los árboles.

¿Fue útil?

Solución

Por desgracia, la documentación de copa de árbol chupa. Mucho. Y los ejemplos de la página web no son útiles. Me encontré con que DZone tiene una muy gran colección de copas de los árboles gramáticas:

copa de árbol gramáticas

Otros consejos

Es posible apreciar buen tutorial de Pablo Battley, simple en Introducción a la copa de árbol

A partir de una gramática mínima, que muestra cómo crear un programa de análisis y luego a través de un par de iteraciones añade un poco de funcionalidad. Era justo lo suficiente para sacarme de la parrilla de salida.

Roland Swingler hizo una presentación sobre las copas de los LRUG: http://skillsmatter.com/podcast/ajax-ria/treetop que he encontrado útiles para empezar.

Los cítricos son una alternativa mucho más ligera en copa: http://github.com/mjijackson/citrus

copa de árbol introductoria tutorial hace un par de años para comprender los fundamentos de la copa del árbol.

Y a continuación, Una rápida introducción a escribir un analizador con copa de árbol , útil para mí, ya que explica cómo asignar los nodos del árbol de sintaxis al rubí instancias de la clase.

Acabo de empezar a experimentar con el de TreeTop.

He intentado cambiar el

 rule num
      (float / integer)
 end

a

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

Y parece que funciona.

Los documentos Cima del árbol parecen asumir que ya conoce bastante sobre análisis de la expresión de las gramáticas (PEG). Copas de los árboles se basa totalmente en los PEG. PEG son más grande que sólo copas de los árboles, sin embargo, es decir, que se utilizan en otras bibliotecas de análisis sintáctico también. En el aprendizaje de Cima del árbol, me pareció muy útil para estudiar hasta en los PEG en general. Eso ayudó a rellenar un montón de las lagunas en la documentación.

Esto es un error. Los paréntesis innecesarios alrededor de la regla para un entero hace que la construcción de un módulo adicional para contener la definición de eval, y este módulo no se mezclan en el nodo, por lo que 'eval' no está disponible. Esto se puede ver claramente si se compara el código Ruby (generado mediante el comando TT) para las versiones con y sin paréntesis, éstos adicional.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top