Использование вложенных макросов в Nearley вкладывает результат данных

Эта проблема

На первый взгляд, макросы не могут быть правильно вложены без серьезных ошибок.

Основная проблема заключается в том, что при получении значения макроса из объекта данных это значение вкладывается в список:

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

Parse results:
[ [ 'test' ] ]

Ожидаемый результат будет [ 'test' ],

Быстрое решение - вернуть данные [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 суб-макросов и все равно получить тот же результат. Но нам все еще нужно поместить данные [0] [0] для окончательного суб-макроса bи это мешает нам использовать b макрос сам по себе - мы должны использовать a чтобы это работало.

Мы ищем решение, которое: - позволяет использовать последний макрос сам по себе - избегает использования data => data[0][0]

1 ответ

Решение

Решение

Чтобы избежать проблемы, лучшим решением является следующее:

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 в массиве делает его строкой - и каждый макрос перестанет помещать его в массив.

Вы должны подумать о том, какой макрос или нетерминал отвечает за структурирование данных и сглаживание массивов и где это уместно.

Лично мне нравится поддерживать регулярную постобработку, относящуюся к макросу, внутри макроса, и я делаю структурирование (например, сглаживание массивов) дальше по цепочке, внутри нетерминала (или макроса), который отвечает только за это.

пример

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' } ]
Другие вопросы по тегам