乍看之下,如果没有一些严重的错误,就无法正确地嵌套宏。
主要问题是从数据对象中检索宏的值会将其嵌套在列表中:
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个子宏,而仍然得到相同的结果。但是我们仍然需要将data [0] [0]放在最后一个子宏b
中,这使我们无法单独使用b
宏-我们必须使用{{1} }。
我们正在寻找以下解决方案: -允许自己使用最后一个宏 -避免使用data => data [0] [0]
答案 0 :(得分:0)
为避免此问题,最佳解决方案是:
a
a[X] -> b[$X] {% id %}
b[X] -> c[$X] {% id %}
c[X] -> $X {% data => data[0].join('') %}
main -> a["test"] {% id %}
问题在于,当最后一个子宏得到结果时,由于Nearley默认情况下将所有内容都视为数组,因此结果嵌套在数组中,然后每一层都执行相同的操作。在数组上使用join方法使它成为一个字符串-每个宏都会停止将其放入数组中。
答案 1 :(得分: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' } ]