在不消耗结束匹配的情况下实现lpeg中的非贪婪搜索

这是从这个问题的评论中分离出来的。

据我所知,在PEG语法中,可以通过编写S <- E2 / E1 S(或者S = pattern E2如果可能或者pattern E1并继续S)来实现非贪婪搜索。

但是,我不想在最终模式中捕获E2 - 我想捕获_E2之前的内容。当尝试在LPEG中实现这一点时,我遇到了几个问题,包括将其构建到语法中时出现'空循环'错误。

我们应该如何在LPEG语法中实现以下搜索:[tag] foo [/tag],我们希望在结束标签之前捕获标签的内容(在示例中为'foo'),但我们希望在结束标签之前终止?从其他问题的评论中我了解到,这应该是可能的,但是我找不到LPEG中的示例。

这是测试语法的一部分

local tag_start = P"[tag]"
local tag_end = P"[/tag]"

G = P{'Pandoc',
  ...
  NotTag = #tag_end + P"1" * V"NotTag"^0;
  ...
  tag = tag_start * Ct(V"NotTag"^0) * tag_end;
}

原文链接 https://stackoverflow.com/questions/70763151

点赞
stackoverflow用户17237579
stackoverflow用户17237579

我又来了。我认为你需要更好地了解 LPeg 捕捉。表格捕捉(lpeg.Ct)是一种将你的捕捉收集到表格中的捕捉。由于“NotTag”规则中没有指定简单的捕捉(lpeg.C),所以最终的捕捉将变成一个空表格{}

再次建议你从lpeg.re开始,因为它更直观。

local re = require('lpeg.re')
local inspect = require('inspect')

local g = re.compile[=[--lpeg
  tag       <- tag_start {| {NotTag} |} tag_end
  NotTag    <- &tag_end / . NotTag

  tag_start <- '[tag]'
  tag_end   <- '[/tag]'
]=]

print(inspect(g:match('[tag] foo [/tag]')))
-- output: { " foo " }

此外,“S <- E2 / E1 S”并不等于“S <- E2 / E1 S*”,这两个是不等价的。


但是,如果我要执行相同的任务,我不会尝试使用非贪心匹配,因为非贪心匹配总是比贪心匹配更慢。

tag <- tag_start {| {( !tag_end . (!'[' .)* )*} |} tag_end

结合非预测和贪婪匹配就足够了。

2022-01-19 07:45:23