Соответствие пунктуации Юникода с использованием LPeg

Я пытаюсь создать шаблон LPeg, который бы соответствовал любой пунктуации Unicode внутри кодированного ввода UTF-8. Я придумал следующий брак Селены Юникод и LPeg:

local unicode     = require("unicode")
local lpeg        = require("lpeg")
local punctuation = lpeg.Cmt(lpeg.Cs(any * any^-3), function(s,i,a)
  local match = unicode.utf8.match(a, "^%p")
  if match == nil
    return false
  else
    return i+#match
  end
end)

Это, кажется, работает, но оно пропустит знаки препинания, которые являются комбинацией нескольких кодовых точек Unicode (если такие символы существуют), так как я читаю только 4 байта вперед, это, вероятно, убивает производительность анализатора, и это не определено, что библиотека match Функция будет делать, когда я передаю ей строку, содержащую символ runt UTF-8 (хотя теперь она работает).

Я хотел бы знать, является ли это правильным подходом или есть лучший способ достичь того, чего я пытаюсь достичь.

1 ответ

Решение

Правильный способ сопоставления символов UTF-8 показан в примере на домашней странице LPeg. Первый байт символа UTF-8 определяет, сколько еще байтов является его частью:

local cont = lpeg.R("\128\191") -- continuation byte

local utf8 = lpeg.R("\0\127")
           + lpeg.R("\194\223") * cont
           + lpeg.R("\224\239") * cont * cont
           + lpeg.R("\240\244") * cont * cont * cont

Опираясь на это utf8 шаблон, который мы можем использовать lpeg.Cmt и Селена Юникод match Функция вроде как вы предложили:

local punctuation = lpeg.Cmt(lpeg.C(utf8), function (s, i, c)
    if unicode.utf8.match(c, "%p") then
        return i
    end
end)

Обратите внимание, что мы вернемся iэто в соответствии с чем Cmt надеется:

Данная функция получает в качестве аргументов весь предмет, текущую позицию (после совпадения патта), а также любые значения захвата, полученные паттом. Первое значение, возвращаемое функцией, определяет, как происходит совпадение. Если вызов возвращает номер, совпадение успешно, и возвращенный номер становится новой текущей позицией.

Это означает, что мы должны вернуть то же число, которое получает функция, то есть позицию сразу после символа UTF-8.

Другие вопросы по тегам