我一直在使用文本编辑器来实现语法突出显示支持。启动和运行是相当简单的,但我只完成了最低要求。
我定义了一系列这样的模式:
-- Keywords
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“之后,但这并没有达到我想要的效果:
-- space, newline, comma, brackets followed by the keyword
S(" \n(<{,")^1 * P"auto" + 这里是否有一个简单、明显的解决方案,只匹配被空格或C代码中所期望的其他字符包围的关键字/标记?我确实需要捕获的令牌,这样我就可以突出显示它,但否则我不会使用任何特定的方法。
例如,这些应与:
int foo;
void(int argc,std::list<int,int> ) { .. };但这不应:
fprintf(stderr, "blah. patterns are hard\n");发布于 2016-08-04 12:54:28
LPeg sure -pattern (或者更具体地说是下面的示例中的-idchar )很好地确保了当前匹配没有跟随pattern (即idchar)。幸运的是,这也适用于输入末尾的空字符串,因此我们不需要对此进行特殊处理。为了确保匹配之前没有模式,LPeg提供了lpeg.B(pattern)。不幸的是,这需要一个匹配固定长度字符串的模式,因此在输入开始时不能工作。要解决以下代码在返回到检查字符串其余部分的后缀和前缀的模式之前,分别尝试在输入开头不使用lpeg.B()进行匹配的问题:
local L = require( "lpeg" )
local function decorate( word )
-- highlighting in UNIX terminals
return "\27[32;1m"..word.."\27[0m"
end
-- matches characters that may be part of an identifier
local idchar = L.R( "az", "AZ", "09" ) + L.P"_"
-- list of keywords to be highlighted
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
-- tests:
print( highlight"" )
print( highlight"hello world" )
print( highlight"in 0in int for xfor for_ |for| in" )发布于 2016-08-01 04:21:29
我认为您应该否定匹配模式,就像在文档的示例中那样
如果我们只想在字界寻找一个模式,我们可以使用以下转换器:
local t = lpeg.locale()
function atwordboundary (p)
return lpeg.P{
[1] = p + t.alpha^0 * (1 - t.alpha)^1 * lpeg.V(1)
}
end这个所以回答还讨论了一些类似的解决方案,因此可能会引起人们的兴趣。
还有一些另一个编辑器组件使用LPeg进行语法高亮化的解析,所以您可能想看看他们是如何处理这个问题的(或者,如果对您的设计有用的话,也可以使用它们的词汇)。
https://stackoverflow.com/questions/38690698
复制相似问题