Я пытаюсь написать грамматику для чего-то вроде списка содержимого книги,
который я могу упростить до следующего:
Учитывая
input = [[
* A
** B
*** C
** D
*** E
* F
]]
Тогда на выходе должна быть эта таблица:
{ "A" { "B", { "C" }, "D", { "E" } } "F" }
Следующая попытка недействительна (с более чем несколькими проблемами), но я предоставил ее, чтобы дать приблизительное представление о моем мышлении.
local C, Cb, Cc, Cg, Cmt, Ct, P, R, V = lpeg.C, lpeg.Cb, lpeg.Cc, lpeg.Cg, lpeg.Cmt, lpeg.Ct, lpeg.P, lpeg.R, lpeg.V
function is_child(str, i, depth, new_depth)
return new_depth > depth
end
grammar = P {
'Begin';
Begin = Cg(Cc(0), 'depth') * V'Array',
Array = Ct(V'Element'^0),
Element = V'IsChild' * V'Array' + V'Letter',
IsChild = Cmt(Cb('depth') * Cg(V'Depth', 'new_depth'), is_child),
Depth = P'*'^1 / string.len,
Letter = P' ' * C(R'AZ') * P'\n',
}
Моя идея заключается в том, что я должен сохранить некоторое состояние depth
(инициализированное нулем), чтобы определить, представляет ли следующая строка ввода дочерний или дочерний узел. Таким образом, правило IsChild
будет сравнивать новую глубину со старой и принимать решение.
Но это примерно столько, сколько я получил. Мне не понятно, как бы я правильно обновил состояние глубины с depth
до new_depth
. Глубина может увеличиваться только на единицу, но может уменьшаться на любую величину (например, E -> F падает на 2). Также существует проблема, заключающаяся в том, что Cg
для хранения new_depth
не возвращает никакого значения (если только оно не заключено в Ct
, что здесь неуместно).
Итак, с высокой вероятностью я считаю, что это неправильный подход. Возможно, кто-то с большим опытом работы с lpeg мог бы предложить некоторую помощь, чтобы вернуть приведенную выше таблицу вывода.