Я пытаюсь научить себя грамматическому генератору 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 (). Я понятия не имею, почему это так.
Я все еще ищу больше информации о верхушке дерева.