Обучение верхушке дерева
Вопрос
Я пытаюсь научиться работать с генератором грамматики Treetop от Ruby.Я обнаружил, что документация не только крайне скудна для «лучшего» варианта, но и работает не так интуитивно, как я надеялся.
На высоком уровне мне бы очень хотелось, чтобы руководство было лучше, чем документация на сайте или видео, если оно есть.
На более низком уровне есть грамматика, с которой я вообще не могу работать:
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
выдает ошибку:НоМетодОшибка:частный метод `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().Я понятия не имею, почему это так.
Я все еще ищу дополнительную информацию о верхушке дерева.
Решение
К сожалению, документация Treetop отстойная.Много.И примеры на сайте бесполезны.Я обнаружил, что в dzone имеется довольно большая коллекция грамматик верхушек деревьев:
Другие советы
Возможно, вы оцените красивое и простое руководство Пола Бэттли по адресуНачало работы с Treetop
Начав с минимальной грамматики, он показывает, как создать парсер, а затем через пару итераций добавляет лишь немного функциональности.Этого было достаточно, чтобы вывести меня из стартовых блоков.
Роланд Свинглер провел презентацию Treetop для LRUG:http://skillsmatter.com/podcast/ajax-ria/treetopкоторые я нашел полезными для начала.
Цитрусовые — гораздо более легкая альтернатива верхушкам деревьев: http://github.com/mjijackson/citrus
я следил за этим Вводное руководство по верхушке дерева пару лет назад, чтобы понять основы Treetop.
А потом Краткое введение в написание парсера с помощью Treetop, полезен для меня, поскольку объясняет, как сопоставить узлы синтаксического дерева с экземплярами классов Ruby.
Я только начал экспериментировать с TreeTop.
Я попробовал изменить
rule num
(float / integer)
end
к
rule num
(float / integer)
{
def eval
text_value.to_f
end
}
end
И, кажется, это работает.
Документация Treetop, похоже, предполагает, что вы уже достаточно много знаете о анализ грамматики выражений (ПЭГ).Treetop полностью основан на PEG.Однако PEG больше, чем просто Treetop, т.е.они также используются в других библиотеках синтаксического анализа.При изучении Treetop мне было очень полезно изучить PEG в целом.Это помогло заполнить множество пробелов в документации.
Это ошибка.Ненужные круглые скобки вокруг правила для целого числа приводят к созданию дополнительного модуля, содержащего определение eval, и этот модуль не смешивается с узлом, поэтому «eval» недоступен.Вы можете ясно это увидеть, если сравните код Ruby (сгенерированный с помощью команды tt) для версий с этими дополнительными круглыми скобками и без них.