如何使用 PEGjs 进行验证,而不是解析?

3

我有以下的PEGjs产生式:

NameStartChar = ":" / [A-Z] / "_" / [a-z] / [\u00C0-\u00D6] / [\u00D8-\u00F6] / [\u00F8-\u02FF] / [\u0370-\u037D] /
                [\u037F-\u1FFF] / [\u200C-\u200D] / [\u2070-\u218F] / [\u2C00-\u2FEF] / [\u3001-\uD7FF] /
                [\uF900-\uFDCF] / [\uFDF0-\uFFFD] / [\uD800-\uDB7F][\uDC00-\uDFFF]

NameChar = NameStartChar / "-" / "." / [0-9] / "\u00B7" / [\u0300-\u036F] / [\u203F-\u2040]

Name = NameStartChar NameChar*

如果我的输入字符串与 Name 匹配,我希望得到true,否则返回false,我并不关心组件的解析。

然而,PEGjs在匹配失败时会抛出异常。

当然,我可以使用 try/catch 来处理,但我更希望避免这样做。我也想避免收集解析出来的组件(例如,当匹配 "abcd" 时,我不需要 ["a", ["b", "c", "d"]],我只需要 true)。

是否有一些隐藏的 PEGjs 功能可以解决这个问题?也许是巧妙的操作或组合子的创新用法?

或者,我应该使用完全不同的工具,而不是解析器生成器?如果是这样的话,有人知道我应该使用什么吗?

3个回答

4

我们可以使用 Name { return true } / { return false } 来获取一个表达式,如果规则匹配,则返回true。然后,我们可以添加!.来检查在true情况下是否到达输入的末尾,在false情况下使用.*跳到结尾。因此,我们得到:

ValidateName = Name !. { return true } / .* { return false }

0

你定义的名称语言对我来说似乎很规则,因此你可以使用正则表达式来实现它。 根据你使用的语言,你需要调用一个名为match或find的函数来测试你的输入。

记得加上行首和行尾锚点,以便匹配整个输入,例如:

^(:|[A-Z]|_|etc)(:|[A-Z]|_|etc|-|\.|[0-9]|etc)*$

是的,它肯定是可以的,但我想重用规范中现有的BNF而不是将它们翻译成正则表达式语法。 - Domenic
@Domenic,也许这个方法可行(免责声明,因为我几乎没有使用过PEG):添加一个规则TestName = Name / .*,并在/的两侧添加适当的语义动作。如果右侧不是Name,则应匹配任何内容。 - 1010

-1
ValidateName = Name { return true } / { return false }

如果您想在不通过子表达式推进解析器位置的情况下验证输入,可以使用&Name


这在 a! 上失败了,它应该返回 false 但是却抛出了一个错误。 - Domenic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接