使用 lpeg 只在单词边界上捕获
我一直在开发一款使用 LPEG 实现语法高亮支持的 文本编辑器。让事情正常运行非常简单,但我仅完成了最小的要求。
我定义了一堆类似这样的模式:
-- 关键词
local keyword = C(
P"auto" +
P"break" +
P"case" +
P"char" +
P"int"
-- more ..
) / function() add_syntax( RED, ... )
这可以正确处理输入,但不幸的是匹配了太多。例如 int 在 printf 的中间匹配,这是可以预料的,因为我使用 " P" 进行文字匹配。
显然,要执行“正常”高亮,我需要匹配在单词边界上,使得 "int" 匹配 "int",但不匹配 "printf","vsprintf" 等等。
我尝试使用这个来限制匹配仅出现在 " <[{ \n" 后面,但这并没有达到我想要的效果:
-- 空格、换行、逗号、括号后跟关键字
S(" \n(<{,")^1 * P"auto" +
我是否错过了一个简单而明显的解决方案来匹配仅在字符或其他类似 C 代码中预期的字符的空格或字符中包围关键字/令牌?我需要捕获记号以便可以突出显示它,但除此之外我并不固执于任何特定的方法。
例如, 这些应该匹配:
int foo;
void(int argc,std::list<int,int> ) { .. };
但这不应该:
fprintf(stderr, "blah. patterns are hard\n");
LPeg 的构造 -pattern (或者,在下面的例子中更具体地说的是 -idchar )很好地确保了当前匹配不会被 pattern (也就是 idchar )所跟随。幸运的是,这对于在输入的结尾处匹配空字符串也有效,因此我们不需要特别处理这种情况。为了确保匹配不被先导的模式所匹配,LPeg 提供了 lpeg.B(pattern) 。不幸的是,这需要匹配固定长度字符串的模式,因此无法在输入的开头工作。为了解决这个问题,下面的代码分别尝试在输入开头时不使用 lpeg.B() 进行匹配,然后在后续字符串中检查后缀和前缀的模式:
local L = require( "lpeg" )
local function decorate( word )
-- 在 UNIX 终端上进行高亮显示
return "\27[32;1m"..word.."\27[0m"
end
-- 匹配可能是标识符的字符
local idchar = L.R( "az", "AZ", "09" ) + L.P"_"
-- 要进行高亮显示的关键字列表
local keywords = L.C( L.P"in" +
L.P"for" )
local function highlight( s )
local p = L.P{
(L.V"nosuffix" + "") * (L.V"exactmatch" + 1)^0,
nosuffix = (keywords / decorate) * -idchar,
exactmatch = L.B( 1 - idchar ) * L.V"nosuffix",
}
return L.match( L.Cs( p ), s )
end
-- 测试:
print( highlight"" )
print( highlight"hello world" )
print( highlight"in 0in int for xfor for_ |for| in" )
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

我认为您应该否定与文档中的示例类似的匹配模式:
local t = lpeg.locale() function atwordboundary (p) return lpeg.P{ [1] = p + t.alpha^0 * (1 - t.alpha)^1 * lpeg.V(1) } end此SO答案也讨论了类似的解决方案,可能会引起您的兴趣。
还有另一个编辑器组件使用LPeg进行语法高亮的解析,因此您可能想查看他们如何处理此问题(或者如果适用于您的设计,请使用他们的词法分析器)。