Соответствие пунктуации Юникода с использованием 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.