PEG.js获取(和)之间的任何文本;

时间:2016-09-20 21:44:29

标签: javascript regex peg pegjs

我试图在最后用分号的parathesis之间捕捉一些文本。

示例:(in here there can be 'anything' !"#¤);); any character is possible);

我试过这个:

Text
 = "(" text:(.*) ");" { return text.join(""); }

但似乎(。*)将包括最后一个);之前“);”我和我得到了错误:

  

预期“);”或任何字符,但发现输入结束

问题是文本可以包含“);”所以我想要最外面的);在行结束时做出决定。

这个正则表达式\((.*)\);做了我想要的,但我怎样才能在PEG.js中做同样的事情呢?我不想在结果中包含外括号和分号。

如果你知道你在做什么= P

,这似乎很容易

1 个答案:

答案 0 :(得分:5)

因此,重点是PEG是确定性的,而正则表达不是。因此,一旦接受了一些输入,PEG就不会回溯。然后我们可以模拟你想要的语义。既然你说正则表达式\((.*)\);做你想要的,我们可能会把它翻译成PEG。

这个正则表达式做了什么?它会消耗所有字符直到输入结束,然后保持回溯直到它看到);,即它消耗最后一个);

为了使用PEG工作,如果我们前面有);,我们可能会使用前瞻来继续消费。

所以,解决方案是:

Text
 = "(" text:TextUntilTerminator ");" { return text.join(""); }

TextUntilTerminator
 = x:(&HaveTerminatorAhead .)* { return x.map(y => y[1]) }

HaveTerminatorAhead
 = . (!");" .)* ");"

TextUntilTerminator非终端在HaveTerminatorAhead 匹配而不消费时消耗(前瞻,&符号)。然后它消耗一个单个字符。它会这样做,直到它知道我们已经到达输入的最终);

HaveTerminalAhead非终端很简单:它会验证前面是否有一个字符,如果有,则保证后面至少有一个);。我们还使用否定前瞻!来阻止我们看到的第一个);(避免使用它,这会重现原始问题)。

然后,这个PEG再现了你建议的正则表达式的行为。