0

根据关于lookarounds的regular-expressions.info,引擎在前瞻后后退:

让我们再看一下内部,以确保您了解前瞻的含义。让我们应用 q(?=u)i 退出。前瞻现在是积极的,然后是另一个令牌。同样,q 匹配 q,u 匹配 u。同样,来自前瞻的匹配必须被丢弃,因此引擎从字符串中的 i 退回到 u。前瞻成功,因此引擎继续执行 i。但我无法匹配你。所以这个匹配尝试失败了。所有剩余的尝试也都失败了,因为字符串中没有更多的 q。

然而,在 Peg.js 中,它看起来像引擎仍然通过了&or!这样实际上它不是与正则表达式相同意义上的前瞻,而是对消费的决定,并且没有后退,因此没有真正的前瞻.

是这样吗?

(如果是这样,那么某些解析甚至不可能,比如这个?)

4

1 回答 1

1

Lookahead 的工作方式类似于它在正则表达式引擎中的工作方式。

此查询无法匹配,因为下一个字母应该是'u',而不是'i'

word = 'q' &'u' 'i' 't'

此查询成功:

word = 'q' &'u' 'u' 'i' 't'

此查询成功:

word = 'q' 'u' 'i' 't'

至于您的示例,请尝试以下方法,您根本不需要使用前瞻:

expression
    = termPair ( _ delimiter _ termPair )*

termPair
    = term ('.' term)? ' ' term ('.' term)?

term "term"
    = $([a-z0-9]+)

delimiter "delimiter"
    = "."

_ "whitespace"
    = [ \t\n\r]+

编辑:根据下面的评论添加了另一个示例。

expression
    = first:term rest:delimTerm* { return [first].concat(rest); }

delimTerm
    = delimiter t:term { return t; }

term "term"
    = $((!delimiter [a-z0-9. ])+)

delimiter "delimiter"
    = _ "." _

_ "whitespace"
    = [ \t\n\r]+

编辑:添加了术语表达式的额外解释。

我将尝试稍微分解术语规则$((!delimiter [a-z0-9. ])+)

$()将内部的所有内容转换为单个文本节点,例如[].join('').

一个术语的单个“字符”是任何字符[a-z0-9. ],如果我们想简化它,我们可以.改为说。在匹配我们想要先行查找 a 的字符之前delimiter,如果我们找到 adelimiter我们停止匹配该字符。因为我们想要多个字符,所以我们多次使用+.

它认为以这种方式前进是 PEG 解析器中的一个常见习语。我从树顶文档中学到了匹配字符串的想法。

于 2018-10-19T19:06:28.183 回答