2

谁能提供一个清楚的解释和一些简单的例子来显示这个错误,显然与匹配时间捕获(Cmt)有关?

我不明白我能找到的唯一提及,即

http://lua-users.org/lists/lua-l/2013-06/msg00086.html

谢谢

4

1 回答 1

4

所以这个问题有点老了,但它是第一个搜索结果之一。互联网上关于此的内容并不多,而且可能不是很明显出了什么问题。

错误消息有点误导,但正在发生的事情 - 在正式的 PEG 术语中,至少据我了解 - 有一个重复运算符应用于解析表达式,它不会消耗任何输入。

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

我正在修补小玩具 BASIC-ish 语言,并且遇到了以下问题:

grammar = P{ "input",
  input = V"block"^0 * -1,
  block = V"expression"^0,
  -- (define expression here)
}

有了这个想法,根输入是一个可选的代码块,一个块是零个或多个表达式。这很简单,当然,我忽略了空格处理之类的东西。但是当你调用grammar:match("") 时会发生什么?

  1. 剩余的字符串:“”,在输入。看看它是否匹配一个块。
  2. 剩余字符串:“”,在块。看看它是否匹配一个表达式。
  3. 剩余字符串:“”,在表达式中。由于时间原因,假设它不匹配
  4. 剩余字符串:“”,在块。规则以零表达式结束,不消耗任何输入。
  5. 剩余的字符串:“”,在输入。消耗了一个块,检查是否有更多块匹配。
  6. 剩余字符串:“”,在块。看看它是否匹配一个表达式。

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

grammar = P{ "input", -- blocks can be empty, input contains one (empty or otherwise) block
  input = V"block" * -1,
  block = V"expression"^0,
  -- (define expression here)
}

或者:

grammar = P{ "input", -- blocks must be at least one expression, root can have one
  input = V"block"^0 * -1,
  block = V"expression"^1,
  -- (define expression here)
}

在第一种情况下,一个空字符串将匹配一个满足输入规则的块。在第二种情况下,空字符串将失败块,以零匹配块满足输入规则。

我还不需要使用 Cmt,但我相信旧版本的 LPeg 假设该函数要么失败要么消耗输入,即使 Cmt 调用中的规则可以匹配一个空字符串。最近的版本没有这个假设。

于 2016-11-13T04:16:12.923 回答