Изучение Treetop

Я пытаюсь научиться самому генератору грамматики Ruby's Treetop. Я нахожу, что не только документация крайне "скудна" для "лучшего", но и не так интуитивно, как я надеялся.

На высоком уровне, я бы действительно хотел получить лучший учебник, чем документация на месте или видео, если оно есть.

На более низком уровне, вот грамматика, которую я не могу заставить работать вообще:

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

Когда я загружаю его и запускаю некоторые утверждения в очень простом тестовом объекте, я нахожу:

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

Работает нормально, пока

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

выдает ошибку: NoMethodError: закрытый метод `eval'вызван для #

Если я переверну целое число и число с плавающей запятой в описании, то и целые числа, и число с плавающей запятой выдаст мне эту ошибку Я думаю, что это может быть связано с ограниченным прогнозом, но я не могу найти какую-либо информацию в любом из документов, чтобы даже охватить идею оценки в контексте "или"

Немного больше информации, которая может помочь. Вот информация о pp для обоих этих блоков parse().

Поплавок:

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"

Целое число... обратите внимание, что, похоже, оно определено как правило целых чисел, но не перехватило метод eval():

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

Обновить:

Моя конкретная проблема работает, но я понятия не имею, почему:

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

Это не имеет смысла с имеющимися документами, но только удаление лишних скобок сделало совпадение, включающее класс Integer1, а также Integer0. Integer1, по-видимому, является классом, содержащим метод eval(). Я понятия не имею, почему это так.

Я все еще ищу больше информации о верхушке дерева.

8 ответов

Решение

К сожалению, документация Treetop отстой. Много. И примеры на сайте не помогают. Я обнаружил, что dzone имеет довольно большую коллекцию древовидных грамматик:

Treetop грамматики

Вы могли бы оценить хороший, простой учебник Пола Батти на Начало работы с Treetop

Начиная с минимальной грамматики, он показывает, как создать синтаксический анализатор, а затем через пару итераций добавляет немного функциональности. Этого было достаточно, чтобы вытащить меня из стартовых колодок.

Цитрус - более легкая альтернатива верхушке дерева: http://github.com/mjijackson/citrus

Роланд Свинглер выступил с презентацией по Treetop для LRUG: http://skillsmatter.com/podcast/ajax-ria/treetop которую я нашел полезным для начала.

Пару лет назад я следовал этому вводному туториалу Treetop, чтобы понять основы Treetop.

А затем краткое введение в написание синтаксического анализатора с Treetop, которое мне пригодилось, потому что в нем объяснялось, как сопоставить узлы синтаксического дерева с экземплярами класса ruby.

Я только начал экспериментировать с TreeTop.

Я пробовал переодевание

 rule num
      (float / integer)
 end

в

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

И это похоже на работу.

Это ошибка. Ненужные скобки вокруг правила для целого числа приводят к тому, что конструкция дополнительного модуля содержит определение eval, и этот модуль не смешивается с узлом, поэтому "eval" недоступен. Это ясно видно, если сравнивать код Ruby (сгенерированный с помощью команды tt) для версий с дополнительными скобками и без них.

Документы Treetop, похоже, предполагают, что вы уже знаете достаточно много о разборе грамматик выражений (PEG). Treetop полностью основан на PEG. Хотя PEG больше, чем просто Treetop, то есть они используются и в других библиотеках синтаксического анализа. Изучая Treetop, я обнаружил, что очень полезно изучать PEG в целом. Это помогло заполнить многие пробелы в документации.

Другие вопросы по тегам