Пользовательские методы для узлов синтаксиса Treetop
У меня есть грамматика Treetop PEG, которая соответствует некоторым ключам. Я хочу посмотреть значения, связанные с этими ключами, в хэше, который я даю парсеру. Как я могу сделать так, чтобы синтаксические узлы имели доступ к методам или переменным из парсера?
Например, вот простая грамматика, которая находит одно слово и пытается найти его значение:
# var.treetop
grammar VarResolver
include VarLookup
rule variable
[a-zA-Z] [a-zA-Z0-9_]*
{
def value
p found:text_value
find_variable(text_value)
end
}
end
end
Вот тестовый файл, использующий его:
# test.rb
require 'treetop'
module VarLookup
def set_variables(variable_hash)
@vars = variable_hash
end
def find_variable(str)
@vars[str.to_sym]
end
end
Treetop.load('var.treetop')
@p = VarResolverParser.new
@p.set_variables name:'Phrogz'
p @p.parse('name').value
Запустив этот тест, я получаю вывод:
{:found=>"name"}
(eval):16:in `value': undefined method `find_variable'
for #<Treetop::Runtime::SyntaxNode:0x00007f88e091b340> (NoMethodError)
Как я могу сделать find_variable
доступны внутри value
метод? (В реальном синтаксическом анализаторе эти правила глубоко вложены и должны разрешать значение, не возвращая фактическое имя в начало дерева разбора. Я не могу просто вернуть text_value
и посмотреть его снаружи.)
1 ответ
Это существенный недостаток в дизайне Treetop.
Я (как сопровождающий) не хотел еще больше замедлять его, передавая еще один аргумент каждому синтаксическому узлу и нарушая любые написанные пользователем классы синтаксического узла. Эти конструкторы получают объект "input", Range, который выбирает часть этого ввода, и, необязательно, массив дочерних SyntaxNodes. Они должны были получить сам Parser вместо входных данных в качестве члена.
Поэтому вместо этого для собственного использования (несколько лет назад) я создал собственный прокси для "ввода" и прикрепил к нему свой контекст. Вы можете сойтись с чем-то похожим
https://github.com/cjheath/activefacts-cql/blob/master/lib/activefacts/cql/parser.rb#L203-L249