Lpeg: Как контролировать глубину выходного дерева? - PullRequest
0 голосов
/ 18 марта 2019

Я пытаюсь написать грамматику для чего-то вроде списка содержимого книги, который я могу упростить до следующего:

Учитывая

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 мог бы предложить некоторую помощь, чтобы вернуть приведенную выше таблицу вывода.

...