TL; DR regex
s возврат. token
нет. Вот почему ваш шаблон не совпадает. Этот ответ сфокусирован на объяснении этого и на том, как легко исправить вашу грамматику. Однако вам, вероятно, следует переписать его или использовать существующий синтаксический анализатор, что вам определенно следует делать, если вы просто хотите анализировать TSV, а не узнавать о регулярных выражениях raku.
Фундаментальное недоразумение?
Я думаю, что я неправильно понимаю нечто фундаментальное в регулярных выражениях в raku.
(Если вы уже знаете, что термин "регулярные выражения" весьма неоднозначен, рассмотрите возможность пропуска этого раздела.)
Одна фундаментальная вещь, которую вы можете неправильно понять, это значение слова «регулярные выражения». Вот некоторые популярные значения, которые люди предполагают:
Формальные регулярные выражения.
Perl регулярные выражения
Совместимые с Perl регулярные выражения (PCRE).
Выражения соответствия шаблонам текста, называемые "регулярными выражениями", выглядят как любые из вышеперечисленных и выполняют нечто подобное.
Ни одно из этих значений не совместимо друг с другом.
Хотя регулярные выражения Perl семантически являются надмножеством формальных регулярных выражений, они гораздо более полезны во многих отношениях, но также более уязвимы для патологического возврата .
Хотя регулярные выражения, совместимые с Perl, совместимы с Perl в том смысле, что изначально они были такими же, как стандартные регулярные выражения Perl в конце 1990-х годов, и в том смысле, что Perl поддерживает подключаемые механизмы регулярных выражений, включая механизм PCRE, синтаксис регулярных выражений PCRE не идентичен стандартному. Регулярное выражение Perl используется по умолчанию Perl в 2020 году.
И хотя выражения сопоставления с текстовым шаблоном, называемые "регулярными выражениями", как правило, похожи друг на друга и сопоставляют весь текст, существуют десятки, а может быть, сотни вариантов синтаксиса и даже семантики для одного и того же синтаксиса.
Выражения соответствия шаблону текста Raku обычно называются либо «правилами», либо «регулярными выражениями». Использование термина «регулярные выражения» передает тот факт, что они похожи на другие регулярные выражения (хотя синтаксис был очищен). Термин «правила» передает тот факт, что они являются частью гораздо более широкого набора функций и инструментов, которые расширяются до синтаксического анализа (и далее).
Быстрое решение
С учетом вышеупомянутого фундаментального аспекта слова «регулярные выражения» я могу теперь обратиться к фундаментальному аспекту поведения вашего «регулярного выражения» .
Если мы переключим три шаблона в вашей грамматике для token
декларатора на regex
декларатор, ваша грамматика будет работать так, как вы хотели:
grammar Parser {
regex TOP { <headerRow><valueRow>+ }
regex headerRow { [\s*<header>]+\n }
token header { \S+ }
regex valueRow { [\s*<value>]+\n? }
token value { \S+ }
}
Единственное различие между a token
и a regex
состоит в том, что regex
отступает, а a token
нет. Таким образом:
say 'ab' ~~ regex { [ \s* a ]+ b } # 「ab」
say 'ab' ~~ token { [ \s* a ]+ b } # 「ab」
say 'ab' ~~ regex { [ \s* \S ]+ b } # 「ab」
say 'ab' ~~ token { [ \s* \S ]+ b } # Nil
Во время обработки последнего шаблона (который может быть и часто называется «регулярное выражение», но фактическим декларатором которого token
не является regex
), он \S
будет проглатывать 'b'
, как это было временно во время обработки регулярного выражения в предыдущей строке. Но поскольку шаблон объявлен как a token
, механизм правил (иначе называемый «механизм регулярных выражений») не возвращается , поэтому общее сопоставление не выполняется.
Вот что происходит в вашем ОП.
Правильное решение
Лучшее решение в целом отучить себя от предполагая обратного прослеживания поведения, потому что это может быть медленными и даже катастрофический медленно (неотличимо от программы повешения) при использовании в согласовании против злонамеренно построенной строки или один с случайно неудачной комбинацией символов.
Иногда regex
с уместны. Например, если вы пишете одноразовый код, и регулярное выражение выполняет свою работу, то все готово. Хорошо. Это / ... /
одна из причин того, что синтаксис в raku объявляет шаблон возврата, как regex
. (Опять же, вы можете написать, / :r ... /
если хотите включить храповик - «храповик» означает противоположность «возврата», поэтому :r
переключает регулярное выражение в token
семантику.)
Иногда обратное отслеживание все еще играет роль в контексте анализа. Например, в то время как грамматика для raku обычно избегает обратного отслеживания и вместо этого имеет сотни rule
s и token
s, тем не менее, у нее все еще есть 3 regex
s.
Я проголосовал за ответ @ user0721090601 ++, потому что он полезен. Он также затрагивает несколько вещей, которые мне сразу показались нелогичными в вашем коде, и, что важно, прилипает к token
s. Это может быть ответ, который вы предпочитаете, который будет крутым.
Nil
, Это довольно бесплодно, что касается обратной связи, верно? Для отладки загрузите commaide, если вы еще этого не сделали, и / или посмотрите, как можно улучшить отчетность об ошибках в грамматиках? , Вы получили,Nil
потому что ваш шаблон принял семантику возврата. Смотрите мой ответ об этом. Я рекомендую вам отказаться от отслеживания. Смотрите ответ @ user0721090601 об этом. Для практичности и скорости, смотрите ответ JJ. Кроме того, вводный общий ответ на «Я хочу разобрать X с Раку. Кто-нибудь может помочь?» ,