使用LPeg匹配Unicode标点

使用LPeg匹配Unicode标点,unicode,lua,lpeg,Unicode,Lua,Lpeg,我正在尝试创建一个LPeg模式,它将匹配UTF-8编码输入中的任何Unicode标点。我想到了赛琳娜·Unicode和LPeg的以下联姻: localunicode=require(“unicode”) 本地lpeg=需要(“lpeg”) 局部标点=lpeg.Cmt(lpeg.Cs(any*any^-3),函数(s,i,a) 本地匹配=unicode.utf8.match(a,“^%p”) 如果匹配==nil 返回错误 其他的 返回i+#匹配 结束 (完) 这似乎是可行的,但它将丢失由多个Un

我正在尝试创建一个LPeg模式,它将匹配UTF-8编码输入中的任何Unicode标点。我想到了赛琳娜·Unicode和LPeg的以下联姻:

localunicode=require(“unicode”)
本地lpeg=需要(“lpeg”)
局部标点=lpeg.Cmt(lpeg.Cs(any*any^-3),函数(s,i,a)
本地匹配=unicode.utf8.match(a,“^%p”)
如果匹配==nil
返回错误
其他的
返回i+#匹配
结束
(完)
这似乎是可行的,但它将丢失由多个Unicode代码点组合而成的标点字符(如果存在这样的字符),因为我只在前面读取了4个字节,这可能会破坏解析器的性能,而且库
匹配
函数将执行的操作尚未定义,当我给它输入一个包含矮小UTF-8字符的字符串时(尽管它现在似乎可以工作)


我想知道这是否是一种正确的方法,或者是否有更好的方法来实现我试图实现的目标。

中的示例显示了匹配UTF-8字符的正确方法。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
和Selene-Unicode
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
的预期一致:

给定函数获取整个主题作为参数,当前位置(匹配patt后),加上patt生成的任何捕获值。函数返回的第一个值定义了匹配的发生方式。如果调用返回一个号码,则匹配成功,返回的号码将成为新的当前位置


这意味着我们应该返回函数接收到的相同数字,即UTF-8字符后的位置。

这将有助于提供一个具体示例,说明它与预期结果不匹配的内容。它不会与我抛出的任何输入不匹配,我只是不相信这是正确的方法,我觉得我引入了一些微妙的错误,这些错误以后会咬到我;非常感谢。我觉得很愚蠢,因为我没有注意到LPeg主页上有一个直接的例子。