问题所在
乍一看,如果没有一些严重的bug,宏就不能正确地嵌套。
主要问题是从数据对象检索宏的值时,将该值嵌套到列表中:
a[X] -> $X {% id %}
main -> a["test"] {% id %}
Parse results:
[ [ 'test' ] ]预期的结果将是[ 'test' ]。
快速修复方法是返回数据,但这还不够,因为结果会嵌套到宏的每一层:
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个子宏,得到同样的结果。但是我们仍然需要为最终的子宏b放置数据,这就阻止了我们单独使用b宏--我们必须使用a才能工作。
我们正在寻找这样一种解决方案:-允许自行使用最后一个宏-避免使用数据=>数据
发布于 2018-10-30 05:58:06
解决方案
为了避免这个问题,最好的解决办法如下:
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方法使其成为一个字符串,每个宏都将停止将其放入数组中。
发布于 2019-11-07 09:13:44
您必须考虑哪个宏或nonTerminal负责构造数据和扁平数组,以及在什么地方适合这样做。
就我个人而言,我喜欢在宏中保留与宏相关的常规后处理,并且我会在链的更远的位置构造(比如扁平数组),在负责执行该操作的nonTerminal (或宏)中进行构造。
示例
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' } ]https://stackoverflow.com/questions/53058226
复制相似问题