Изучение 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
Начиная с минимальной грамматики, он показывает, как создать синтаксический анализатор, а затем через пару итераций добавляет немного функциональности. Этого было достаточно, чтобы вытащить меня из стартовых колодок.
Цитрус - более легкая альтернатива верхушке дерева: 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 в целом. Это помогло заполнить многие пробелы в документации.