2

问题

乍一看,如果没有一些严重的错误,宏就无法正确嵌套。

主要问题是从数据对象中检索宏的值会将这个值嵌套到一个列表中:

a[X] -> $X {% id %}
main -> a["test"] {% id %}

Parse results:
[ [ 'test' ] ]

预期的结果是[ 'test' ]

一个快速的解决方法是返回 data[0][0],但这还不够,因为结果会嵌套在宏的每一层:

a[X] -> b[$X] {% id %}
b[X] -> $X {% id %}
main -> a["test"] {% id %}

Parse results:
[ [ [ 'x' ] ] ]

为了修复我们可以data => data[0][0]用于每个宏的错误。然而,这绝对是丑陋的。

真正的解决方法是使用动态范围。由于我们不能(据我所知)创建没有参数的宏,让我们使用无用的参数:

a[X] -> b["_"] {% id %}
b[_] -> $X {% id %}
main -> a["test"] {% id %}

Parse results:
[ [ 'test' ] ]

这停止了​​之前发生的嵌套地狱——我们可以通过 500 个子宏并且仍然得到相同的结果。但是我们仍然需要为最终的 sub-macro 放置 data[0][0] b,这会阻止我们b单独使用宏 - 我们必须使用a它才能工作。

我们正在寻找一种解决方案: - 允许单独使用最后一个宏 - 避免使用 data => data[0][0]

4

2 回答 2

0

解决方案

为避免此问题,最佳解决方案如下:

a[X] -> b[$X] {% id %}
b[X] -> c[$X] {% id %}
c[X] -> $X {% data => data[0].join('') %}

main -> a["test"] {% id %}

Parse results:
[ 'test' ]

解释

问题是,当最后一个子宏得到结果的时候,由于nearley默认把所有的东西都当作一个数组,结果嵌套到一个数组中,那么每一层都做同样的事情。在数组上使用 join 方法使其成为字符串 - 每个宏将停止将其放入数组中。

于 2018-10-30T05:58:06.733 回答
0

您必须考虑哪个宏或非终端负责构建数据和展平数组,以及它在哪里适合。

就个人而言,我喜欢将与宏相关的常规后处理保留在宏内部,并且我在负责执行此操作的非终端(或宏)内部进一步进行结构化(如展平数组)。

例子

withCurlyBrackets[X] -> "{" $X "}" {% d => d[1] %}
withSquareBrackets[X] -> "[" $X "]" {% d => d[1] %}
withRoundBrackets[X] -> "(" $X ")" {% d => d[1] %}

test -> withRoundBrackets[withSquareBrackets[withCurlyBrackets["test"]]] {% id => ({ value: id.flat(Infinity).join('') }) %}

// Parse results for '([{test}])': [ { value: 'test' } ]
于 2019-11-07T09:13:44.007 回答