这是从对这个问题的评论中派生出来的。
正如我所理解的,在PEG语法中,可以通过编写S <- E2 / E1 S
(或者s=模式E2,如果可能的话,或者模式E1和连续的s(来实现非贪婪搜索。
然而,我不想在最终模式中捕获E2——我想捕获到E2。当我试图在LPEG中实现这一点时,我遇到了几个问题,包括在将其构建到语法中时出现的"规则中的空循环"错误。
我们将如何在LPEG语法中实现以下搜索:[tag] foo [/tag]
,其中我们希望在捕获表中捕获标记的内容(示例中为"o"(,但我们希望在结束标记之前终止?正如我从对另一个问题的评论中所理解的,这应该是可能的,但我在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;
}
又是我。我认为您需要更好地了解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
结合非谓词和贪婪匹配就足够了。