Почему некоторые замены LPeg не отображаются, когда в сценарии LPeg много уровней захвата? - PullRequest
0 голосов
/ 24 марта 2020

Я новичок в StackOverflow и, в конце концов, задал этот вопрос после прочтения всего, что смог найти на Inte rnet о перехватах в LPeg. Я изучаю LPeg, и я успешно создал несколько программ, использующих захваты и подстановки текста, используя C и захваты Cs. Однако я понимаю, что все еще что-то ускользает от моего понимания, поскольку я не могу заставить следующую программу заменить таблицы и строки в таблицах.

Следующая программа показывает работу в процессе. Цель программы - прочитать файл, в котором хранится несколько таблиц, и извлечь отдельные таблицы, а также отдельные строки (в программе они называются TUPLES). Я включаю тестовый файл, чтобы проиллюстрировать проблему. Для любопытных, формат файла - это формат StarBase, разработанный Джоном Роллом.

local function mk_read_sbt ()
  local lpeg = require'lpeg'
  local C, Cs, Ct, P, S, match
    = lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.P, lpeg.S, lpeg.match

  local EOF = P(-1)
  local EOL = P'\n'
  local FF  = P'\f' -- In Linux with Emacs I use ^L in place of \f.
  local SEP = P','
  local SPC = P' '

  local TABLEITEM  = (1 - SPC - SEP - EOL - FF)
                     * (SPC^0 * (1 - SPC - SEP - EOL - FF))^0 
  local TABLEITEM0 = (SPC^0 * TABLEITEM * SPC^0)
                   + SPC^0
  local TABLETUPLE = C(TABLEITEM0 * (SEP * TABLEITEM0)^0) / "<%1>"
  local TABLE      = C((TABLETUPLE * EOL)^0 * TABLETUPLE^(-1)) / "[[%1]]\n"
  local FILE       = TABLE^-1 * (FF * TABLE^-1)^0 * EOF

  return {file=function (t1) return match(Cs(FILE),t1) end,
          tuple=function (t1) return match(TABLETUPLE,t1) end}
end
r1 = mk_read_sbt()

sbt1 = [[
id,name,diameter,height
--,----,--------,------
23,malus,0.153,2.20
54,acer,0.045,0.51
\f
id,cost
--,----
23,1.33
32,4.26
]]

I sh строк, которые будут выглядеть после подстановки,

>print(r1.tuple(sbt1))
<id,name,diameter,height>

К сожалению, это то, что я получаю, когда читаю весь файл, и отдельные строки не экранируются в скобках <>, как я ожидал. Подстановка применялась правильно к двум таблицам в файле, но подстановка TUPLE - нет.

>print(r1.file(sbt1))
[[id,name,diameter,height
--,----,--------,------
23,malus,0.153,2.20
54,acer,0.045,0.51
]]

[[
id,cost
--,----
23,1.33
32,4.26
]]

Проблема в том, что замены, похоже, относятся только к последнему уровню. Из того, что я прочитал, захват «C (...) / замена» должен накапливать все замены, сделанные в шаблоне, даже косвенно через другие правила, но это не так. Есть ли способ заставить накопления замещения на многих уровнях или это плоская система с потерями замещения с более низких уровней?

Спасибо за любые подсказки.

(Редактирование и очистка) Извините если это похоже на монолог, но я чувствую, что двигаюсь вперед, но мне хочется ехать в густом тумане. Поэтому следующий код работает, как я и ожидал, и похоже, что мне нужно каскадные захваты C вместо базовых c C захватов. Вот фрагмент кода, который работает нормально, и результат, который я получаю

local TABLETUPLE = C(TABLEITEM0 * (SEP * TABLEITEM0)^0) / "<%1>"
local TABLE      = Cs((TABLETUPLE * EOL)^0 * TABLETUPLE^(-1)) / "[[%1]]\n"
local FILE       = Cs(TABLE^-1 * (FF * TABLE^-1)^0 * EOF) / "FILE: %1"
return {file=function (t1) return match(FILE,t1) end,
        tuple=function (t1) return match(TABLETUPLE,t1) end}

И ожидаемый результат,

>print(r1.file(sbt1))
FILE: [[<id,name,diameter,height>
<--,----,--------,------>
<23,malus,0.153,2.20>
<54,acer,0.045,0.51>
<>]]

[[<>
<id,cost>
<--,---->
<23,1.33>
<32,4.26>
<>]]

Так что, похоже, я ответил на свой вопрос: Использование Cs захватывает везде вместо использования простых C захватов. Тем не менее я все еще мог бы использовать некоторые подсказки в логике c за этим поведением.

...