Parsing 使用lpeg仅捕获单词边界
我一直在研究如何使用LPEG实现语法突出显示支持。启动和运行非常简单,但我只完成了最低要求 我已经定义了一系列这样的模式:Parsing 使用lpeg仅捕获单词边界,parsing,lua,lpeg,Parsing,Lua,Lpeg,我一直在研究如何使用LPEG实现语法突出显示支持。启动和运行非常简单,但我只完成了最低要求 我已经定义了一系列这样的模式: -- Keywords local keyword = C( P"auto" + P"break" + P"case" + P"char" + P"int" -- more .. ) / function() add_syntax( RED, ... ) 这可以正确地处理输入,但不幸的是匹配太多。例如 int >
-- Keywords
local keyword = C(
P"auto" +
P"break" +
P"case" +
P"char" +
P"int"
-- more ..
) / function() add_syntax( RED, ... )
这可以正确地处理输入,但不幸的是匹配太多。例如<代码> int >代码>匹配在<代码> Print F <代码>中,这是意料之中的,因为我使用了“<代码> p>代码>文字匹配。
显然,要执行“正确”的突出显示,我需要在单词边界上进行匹配,例如“int”匹配“int”,而不是“printf”、“vsprintf”等
我尝试使用此选项将匹配限制为仅出现在“
之后,我认为您应该否定匹配模式,类似于示例中的匹配模式:
如果我们只想在单词边界上查找模式,可以使用以下转换器:
这也讨论了一些类似的解决方案,因此可能会引起兴趣
还有一种方法使用LPeg进行语法分析,目的是突出显示语法,因此您可能希望了解它们是如何处理这一问题的(或者使用它们的lexer,如果它适用于您的设计)。LPeg结构-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" )
好的,更仔细地看一下,这种方法用于突出显示,但只处理后缀匹配。例如,“ending”与“end”不匹配,但“vend”匹配。我一直在要求,希望得到一个盘子上的答案,但你肯定超出了我的预期。接受了。非常感谢。
int foo;
void(int argc,std::list<int,int> ) { .. };
fprintf(stderr, "blah. patterns are hard\n");
local t = lpeg.locale()
function atwordboundary (p)
return lpeg.P{
[1] = p + t.alpha^0 * (1 - t.alpha)^1 * lpeg.V(1)
}
end
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" )