【问题标题】:PEG.js Get any text between ( and );PEG.js 获取 ( 和 ) 之间的任何文本;
【发布时间】:2017-01-28 23:24:24
【问题描述】:

我正在尝试在最后用分号捕获括号之间的一些文本。

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

我试过了:

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

但似乎 (.*) 将包括最后一个 );前 ”);”确实,我得到了错误:

预期的“);”或找到输入结尾以外的任何字符

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

这个正则表达式 \((.*)\); 可以满足我的要求,但我如何在 PEG.js 中做到这一点?我不想在结果中包含外括号和分号。

如果您知道自己在做什么,这似乎应该很容易=P

【问题讨论】:

  • 我有。找不到我要找的东西。又或许我没看懂。如果您知道文档中的哪个位置,如果您能告诉我在哪里,将不胜感激。

标签: javascript regex peg pegjs


【解决方案1】:

所以,关键是 PEG 是确定性的,而正则表达式不是。因此,一旦 PEG 接受了一些输入,它就不会回溯。然后我们可以模拟你想要的语义。既然您说正则表达式 \((.*)\); 可以满足您的要求,我们可能会将其转换为 PEG。

这个正则表达式有什么作用?它消耗所有字符直到输入结束,然后继续回溯,直到它看到);,即,它消耗最后一个可能的);

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

所以,一个解决方案是:

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

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

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

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

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

然后,此 PEG 再现了您建议的正则表达式的行为。

【讨论】:

  • 很好,它有效!我也学到了一些东西 =) 非常感谢!
  • 请注意,如果您在更大的语法上使用它,您可能应该添加另一种前瞻来限制检查。上面的代码假设您想要输入的最后一个 );,如果您想匹配 超出 Text 的内容,这可能不是所需的行为。
  • 我会读取这种多行的文件,但也许我可以在语法中添加一个 \n 来考虑这一点?
  • 我无法理解HaveTerminatorAhead 的工作原理。你能尝试用其他方式解释吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-11
  • 2016-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-30
相关资源
最近更新 更多