Pergunta

Estou tentando me ensinar gerador de gramática Treetop de Ruby. Eu estou achando que não só é a documentação lamentavelmente escassa para o "melhor" lá fora, mas que não parecem funcionar tão intuitivamente como eu esperava.

Em um nível alto, eu realmente adoraria um tutorial melhor do que os docs no local ou o vídeo, se houver um.

Em um nível inferior, aqui está uma gramática eu não posso começar a trabalhar em tudo:

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

Quando eu carregá-lo e executar algumas afirmações em um objeto de teste muito simples, eu acho:

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

funciona bem, enquanto

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

levanta o erro: NoMethodError: método `eval privada' chamado para #

Se eu inverter inteiro e flutuar na descrição, ambos inteiros e carros alegóricos me dar esse erro. Eu acho que isso pode estar relacionado à antecipação limitado, mas não consigo encontrar qualquer informação em qualquer um dos documentos até mesmo cobrir a ideia de avaliar no "ou" contexto

Um pouco mais informação que pode ajudar. informações de aqui pp tanto para aqueles parse () blocos.

O float:

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"

O Integer ... nota que parece ter sido definida de seguir a regra número inteiro, mas não pegou o 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, ""

Update:

Eu tenho o meu especial de trabalho problema, mas não tenho idéia por que:

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

Isso não faz sentido com os documentos que estão presentes, mas apenas remover os parênteses adicionais fez o jogo incluir a classe Inteiro1, bem como Integer0. Inteiro1 é, aparentemente, a classe segurando o método eval (). Eu não tenho idéia por que este é o caso.

Eu ainda estou procurando mais informações sobre copa de árvore.

Foi útil?

Solução

Infelizmente, a documentação do Treetop suga. Muito. E os exemplos no site não são úteis. Descobri que dzone tem uma bela grande coleção de gramáticas copa de árvore:

Treetop gramáticas

Outras dicas

Você pode apreciar agradável de Paulo Battley, simples tutorial em Começando com Treetop

Começando com uma gramática mínima, ele mostra como criar um analisador e, em seguida, através de um par de iterações adiciona apenas um pouco de funcionalidade. Foi apenas o suficiente para me tirar os blocos de partida.

Roland Swingler fez uma apresentação sobre Treetop para LRUG: http://skillsmatter.com/podcast/ajax-ria/treetop que eu achei útil para começar.

Citrus é uma alternativa muito mais leves para copa: http://github.com/mjijackson/citrus

Eu segui este Treetop introdutória tutorial um par de anos atrás, para entender os conceitos básicos de copa de árvore.

E então Uma rápida introdução para escrevendo um analisador com Treetop , útil para mim porque ele explica como mapear os nós de árvore sintaxe para instâncias de classe rubi.

Eu apenas comecei a experimentar com TreeTop.

Eu tentei a mudança

 rule num
      (float / integer)
 end

para

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

E parece trabalho.

Os docs Copa parecem assumir que você já sabe uma quantidade razoável sobre gramática de análise sintática de expressão (PEG). Treetop é inteiramente baseado em PEG. PEGs são maiores do que apenas Treetop porém, ou seja, eles são usados ??em outras bibliotecas de análise também. Em aprender Copa da árvore, eu achei muito útil para estudar-se sobre PEGs em geral. Isso preenchimento ajudou em muitas das lacunas na documentação.

Este é um bug. Os parênteses desnecessários em torno da regra para um inteiro faz com que a construção de um módulo extra para conter a definição de eval, e este módulo não se misturam no nó, so 'eval' não está disponível. Você pode ver isso claramente se você comparar o código Ruby (gerado usando o comando tt) para as versões com e sem esses parênteses extras.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top