TL; DR regex
s зворотний трек. token
s ні. Ось чому ваш шаблон не відповідає. Ця відповідь зосереджена на тому, щоб пояснити це та як тривільно виправити свою граматику. Однак вам, ймовірно, слід переписати його або використати існуючий аналізатор, що саме ви повинні обов'язково зробити, якщо ви просто хочете проаналізувати TSV, а не дізнатися про регексери raku.
Фундаментальне непорозуміння?
Я думаю, що я нерозумію щось принципове щодо виразів у раку.
(Якщо ви вже знаєте, термін "регулярні вирази" є дуже неоднозначним, спробуйте пропустити цей розділ.)
Одне фундаментальне, що ви можете нерозуміти - це значення слова "регулярні виразки". Ось деякі популярні значення, які народ вважає:
Формальні регулярні вирази.
Регекси Perl.
Регулярні регулярні вирази (PCRE), сумісні з Perl.
Текстовий шаблон, що відповідає виразам під назвою "регулярні виразки", схожий на будь-яке з перерахованих вище і робить щось подібне.
Жодне з цих значень не сумісне між собою.
Хоча регулярні виразки Perl є семантично набором формальних регулярних виразів, вони набагато корисніші в багатьох відношеннях, але також більш вразливі до патологічного зворотного відстеження .
Хоча регулярні вирази, сумісні з Perl, сумісні з Perl в тому сенсі, що вони спочатку були такими ж, як і стандартні регексели Perl наприкінці 90-х, і в тому сенсі, що Perl підтримує підключаються двигуни регулярного виразів, включаючи двигун PCRE, синтаксис регулярного вираження PCRE не ідентичний стандартному Регекс Perl, який за замовчуванням використовувався Perl у 2020 році.
І хоча вирази тексту, що відповідають тексту, під назвою "регулярні вирази", як правило, схожі на один одного, і всі вони відповідають тексту, існує кілька десятків, можливо сотень, варіацій синтаксису і навіть у семантиці для одного і того ж синтаксису.
Висловлювання тексту тексту Раку, як правило, називають або "правилами", або "регулярними виразами". Використання терміна "регулярні вирази" передає той факт, що вони виглядають дещо як інші регекси (хоча синтаксис був очищений). Термін "правила" повідомляє той факт, що вони є частиною набагато більш широкого набору функцій та інструментів, які масштабуються до розбору (і далі).
Швидке виправлення
З урахуванням зазначених вище фундаментального аспекту слова «регулярні вирази» з шляху, тепер я можу звернутися до фундаментального аспекту вашого «регулярні вирази» 's поведінка .
Якщо ми переключимо три зразки у вашій граматиці для 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
зворотний трек, тоді як 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'
само, як це тимчасово робилося під час обробки регексу в попередньому рядку. Але, оскільки шаблон задекларований як token
, двигун правил (він же «движок-генекс») не відхиляє , тому загальна відповідність не вдається.
Ось що відбувається у вашому ОП.
Правильне виправлення
Краще рішення в цілому - відучити себе від того, щоб поводитись із зворотним відслідковуванням, оскільки це може бути повільним і навіть катастрофічно повільним (невідрізним від висячої програми), коли використовується для зіставлення проти зловмисно сконструйованого рядка або одного з випадково невдалим поєднанням символів.
Іноді regex
s доречні. Наприклад, якщо ви пишете одноразовий і регулярний вираз виконує роботу, то ви закінчили. Це добре. Це частина причини, що / ... /
синтаксис у raku оголошує шаблон зворотного відстеження, як і він regex
. (З іншого боку, ви можете написати , / :r ... /
якщо ви хочете перейти на Храпова - «тріскачка» означає протилежне «BackTrack», тому :r
перемикається регулярний вираз для token
семантики.)
Іноді зворотний трек все ще грає роль у контексті розбору. Наприклад, хоча граматика для raku, як правило, відхиляється від зворотного відстеження, а замість цього має сотні rule
s і token
s, вона все ж має 3 regex
s.
Я підтримав відповідь @ user0721090601 ++, тому що це корисно. Він також стосується декількох речей, які мені відразу здалися ідіоматичними у вашому коді, і, що важливо, дотримуються token
s. Це може бути відповідь, яку ви віддаєте перевагу, яка буде класною.
Nil
. Це досить безплідно, що стосується відгуків, правда? Для налагодження завантажте командний файл, якщо ви ще цього не зробили, та / або див. Як можна покращити звітність про помилки у граматиках? . Ви отрималиNil
Тому що ваш шаблон передбачається відстеження семантики. Дивіться мою відповідь з цього приводу. Рекомендую відмовитися від зворотного огляду. Дивіться відповідь @ user0721090601 про це. Про повну практичність та швидкість дивіться відповідь JJ. Також вступна загальна відповідь на "Я хочу розібрати X з Раку. Чи хтось може допомогти?" .