Nearley解析器如何无歧义返回不定数量匹配?附量词含义问询
Nearley解析器歧义问题解决与语法量词说明
问题背景与现状
我正在开发一款用于发布分支型冒险故事的软件,计划用Nearley替换自研的JavaScript解析器。目前编写的Nearley语法如下:
main->(excludebrackets link:+ excludebrackets):+ link->"[LINK:"i excludebrackets "|" excludebrackets "]" {% (d) => {return'<a href ="func__' + d[3][0].join("") + '()>'+d[1][0].join("")+"</a>"}%} excludebrackets->[^\[\]]:+ | null
单个链接标记[LINK: shoot | shoot_dragon]可被正确转换为<a href ="func__shoot_dragon()>shoot</a>,但处理包含多个链接的文本时,解析器出现歧义并返回多个结果,需要实现无歧义的不定数量匹配。
歧义解决方法
问题根源在于main规则的嵌套重复结构(excludebrackets link:+ excludebrackets):+——这种写法会让解析器对“普通文本+链接”的组合产生多种拆分逻辑(比如将多个链接归为一组或拆分为多组),进而引发歧义。
调整后的无歧义语法如下:
main -> (excludebrackets | link):* link -> "[LINK:"i excludebrackets "|" excludebrackets "]" {% (d) => {return '<a href="func__' + d[3][0].join('') + '()">' + d[1][0].join('') + '</a>'} %} excludebrackets -> [^\[\]]:+
关键修改点:
- 将
main规则改为(excludebrackets | link):*,表示零个或多个“普通文本段”或“链接”的交替序列,彻底避免嵌套重复带来的拆分歧义 - 移除
excludebrackets的null选项,因为main的:*已经覆盖了空输入场景,null选项会导致解析器匹配空文本段,额外增加歧义风险
语法量词含义说明
Nearley中的:*、:+、:?是用于规则重复匹配的量词,具体含义:
:+:匹配前置规则1次或多次,必须至少出现1次。例如link:+表示当前位置至少存在一个链接:*:匹配前置规则0次或多次,可以完全不出现。例如(excludebrackets | link):*允许文本全为普通内容、全为链接,或是两者混合:?:匹配前置规则0次或1次,即该规则是可选的。例如若有规则foo -> bar:? baz,则bar可以出现1次,也可以完全不出现,仅保留baz
内容的提问来源于stack exchange,提问作者user1833028
相关产品推荐
相关产品推荐

