Parsing 使用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 >

我一直在研究如何使用LPEG实现语法突出显示支持。启动和运行非常简单,但我只完成了最低要求

我已经定义了一系列这样的模式:

 -- 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" )