Lpeg "empty loop in rule" 错误

有人能提供一个清晰的解释和一些简单的例子,展示与匹配时间捕获(Cmt)相关的此错误吗?我不理解我能找到的唯一提到的内容,即 http://lua-users.org/lists/lua-l/2013-06/msg00086.html

谢谢

点赞
用户3448056
用户3448056

所以这个问题有点古老,但它是搜索结果中的一个。互联网上没有太多关于这个问题的信息,可能不是很明显有什么问题。

错误提示有点误导,但是发生了什么——在正式的 PEG 术语中,至少按照我的理解——是将一个可以消耗任何输入的解析表达式应用于重复操作符。

或者换句话说,LPeg 检测到可以匹配空字符串的循环,这将永远不会完成。有一个名为 LuLPeg 的纯 Lua 实现缺乏这个特定的检查。如果你执行你的语法,它很容易进入一个无限循环。

我正在尝试创建一个小的 BASIC-ish 语言,并在以下代码中遇到了问题:

grammar = P{ "input",
  input = V"block"^0 * -1,
  block = V"expression"^0,
  -- (在这里定义表达式)
}

根据这个想法,根输入是可选代码块,块是零或多个表达式。当然,这相当简化了,我省略了空格处理等内容。但是当你调用 grammar:match("") 时会发生什么?

  1. 剩余字符串: "",在输入处。看看它是否匹配一个块。
  2. 剩余字符串: "",在块区域。看看它是否匹配一个表达式。
  3. 剩余字符串: "",在表达式处。出于时间考虑,假设它不匹配
  4. 剩余字符串: "",在块里。规则用零个表达式结束,没有输入被消耗。
  5. 剩余字符串: "",在输入区域。一个块被消耗,检查是否有更多块与之匹配。
  6. 剩余字符串: "",在块区域。看看它是否匹配一个表达式。

以此类推。由于 V"block" 匹配空字符串,输入可以找到无限数量的块来满足 V"block"^0 规则。在这种情况下,有两个好的解决方案:将输入设置为最多一个块,或要求块为至少一个表达式,在可能存在块的地方将其设置为 ^0。所以要么:

grammar = P{ "input", -- 块可以为空,输入包含一个(空或非空)块
  input = V"block" * -1,
  block = V"expression"^0,
  -- (在这里定义表达式)
}

或者:

grammar = P{ "input", -- 必须至少有一个表达式的块,根可以有一个
  input = V"block"^0 * -1,
  block = V"expression"^1,
  -- (在这里定义表达式)
}

在第一种情况下,一个空字符串将匹配一个块,同时也符合输入规则。在第二种情况下,一个空字符串将会使块失败,在零个匹配块的情况下符合输入规则。

我还没有使用过 Cmt,但我相信发生的事情是 LPeg 的旧版本假定函数会失败或消耗输入,即使在 Cmt 调用内部的规则可以匹配一个空字符串的情况下也是如此。最新的版本没有这个假设。

2016-11-13 04:16:12