Какой лучший способ быть свободным в пробелах в грамматике perl6? - PullRequest
11 голосов
/ 08 июня 2019

Я хочу, чтобы грамматика была слабой, независимо от того, есть пробел или нет ... Я хочу соответствовать:

this                '   <foo>    <bar>    <baz>    '
and also this       '<foo><bar><baz>'

Это работает:

token TOP     { \s* <foo> \s* <bar> \s* <baz> \s* }

Но после прочтения всего о : sigspace, <. Ws> и rule Я могу представить, что есть способ сделать это без повторного * \ с. (а именно. Как мне сопоставить шестнадцатеричный массив в грамматике per6 )

Может, кто-нибудь подскажет, есть ли лучший способ сделать это в грамматике perl6?

NB. это не решается простым изменением декларатора token на rule - когда я пытаюсь использовать этот подход, я получаю либо соответствующий пробел или отсутствие пробела (но не * 1025) * оба ) в строке разбора.

1 Ответ

11 голосов
/ 08 июня 2019

Возможно, ваша проблема заключается в одном из этих трех правил "готчи":

  • Если вам нужно соответствие пробелов / границ токенов в начале правила , до первого первого атома Вы должны явно предоставить его (обычно с явным <.ws>).

  • Если вы хотите, чтобы границы пробелов и лексем соответствовали между каждым совпадением количественного атома (например, <foo>*), вы должны включает пробел между атомом и квантификатором (например, <foo> *).

  • Значение по умолчанию <ws> определяется как regex ws { <!ww> \s* }. Если вы хотите, чтобы rule s в определенной грамматике использовали другой шаблон, то определите свой собственный в этой грамматике. (Timotimo ++)

Подробнее об этом см. Мой обновленный ответ на Как мне сопоставить шестнадцатеричный массив в грамматике per6 .


Следующие четыре регулярных выражения соответствуют обеим строкам примера:

my \test-strings := '   <foo>    <bar>    <baz>    ', '<foo><bar><baz>';

my \test-regexes := token { \s*   '<foo>' \s* '<bar>' \s* '<baz>' \s* },
                    rule  { \s*   '<foo>' \s* '<bar>' \s* '<baz>' \s* },
                    rule  { \s*   '<foo>'     '<bar>'     '<baz>'     },
                    rule  { <.ws> '<foo>'     '<bar>'     '<baz>'     }

say (test-strings X~~ test-regexes).all ~~ Match # True
...