Защита от сопоставления с бесконечным семейством шаблонов в Raku

#grammar #raku

#грамматика #raku

Вопрос:

Я пытаюсь избежать сопоставления пробелов в конце строки, при этом все еще сопоставляя пробелы в середине слов.

Вот пример регулярного выражения, которое соответствует символам подчеркивания внутри x , но не соответствует трем завершающим символам подчеркивания.

 say 'x_x___x________' ~~ /
[
| 'x'
| '_' <!before [
        | $ 
        | '_' <?before

gt;
| '_' <?before ['_' <?before


gt;]>
| '_' <?before ['_' <?before ['_' <?before


gt;]>]>
# ...
]>
]
/;

Есть ли способ построить остальную часть шаблона, подразумеваемого ... ?

Комментарии:

1. Вероятно, самый простой способ избежать сопоставления пробелов в конце строки, но сопоставлять их где-либо еще — это делать это совсем по-другому:: s <!before $> Это соответствует всем разделам пробелов, если оно не находится прямо перед концом строки

Ответ №1:

Немного сложно понять, о чем вы просите.


Возможно, вы ищете что-то такое простое, как это:

 say 'x_x___x________' ~~ / 'x'  % '_' ** 1..3 /
# 「x_x___x」
 

или

 say 'x_x___x________' ~~ / 'x'  % '_' ** 1..2 /
# 「x_x」
 

или

 say 'x_x___x________' ~~ / 'x'  % '_'  /
# 「x_x___x」
 

Комментарии:

1. Я вижу, что @brad (?) ответил на ваш актуальный вопрос — вот ссылка на модифицированный квантификатор для разделителей в документе [ docs.raku.org/language/regexes#Modified_quantifier :_%,_%%]

2. По сути, это решение, на котором я остановился : / ['x' ] % '_' / . Однако я думаю, что в конечном итоге я ищу способ сопоставления произвольно длинных потоков, которые заканчиваются известным шаблоном. Я попытаюсь немного прояснить вопрос.

Ответ №2:

Я бы предложил использовать захват …, таким образом:

 'x_x___x________' ~~ /(.*?) _* $/; 
say $0;     #「x_x___x」
 

(Что? модификатор делает * ‘нежадным’.)
Пожалуйста, дайте мне знать, если я пропустил главное!

Комментарии:

1. или, более компактно, say ('x_x___x________' ~~ /(.*?) _* $/)[0];

Ответ №3:

избегайте сопоставления пробелов в конце строки, сохраняя при этом соответствие пробелов в середине слов

Согласно ответу Брэда и вашему комментарию к нему, что-то вроде этого:

 / w  % s  /
 

то, что я ищу, — это способ сопоставления произвольно длинных потоков, которые заканчиваются известным шаблоном

Согласно комментарию @user0721090601 к вашему вопросу и в качестве варианта ответа @p6steve, что-то вроде этого:

 / w  % s  )> s* $ /
 

<a rel=»noreferrer noopener nofollow» href=»https://docs.raku.org/language/regexes#index-entry-regex_-Capture_markers:_» rel=»nofollow noreferrer»>Маркер )> захвата отмечает, где захват должен заканчиваться.

Вы можете использовать произвольные шаблоны слева и справа от этого маркера.

бесконечное семейство <!before> шаблонов

Обобщая на бесконечное семейство шаблонов любого типа, независимо от того, имеют они нулевую ширину или нет, наиболее естественным решением в регулярном выражении является итерация с использованием любого из стандартных кванторов с открытым концом. Например, s для одного или нескольких пробелов.[1] [2]

Есть ли способ построить остальную часть шаблона, подразумеваемого ... ?

Я обобщу это так: «Есть ли в регулярном выражении Raku способ сопоставить некоторый произвольный шаблон, который теоретически может быть распознан компьютерной программой?»

Ответ всегда «Да»:

  • Хотя правила / регулярные выражения Raku могут выглядеть как традиционные регулярные выражения, на самом деле они являются произвольными функциями, встроенными в произвольную программу, над которой вы в конечном итоге имеете полный контроль.
  • Правила имеют произвольный доступ для чтения к состоянию захвата.[3]
  • Правила могут выполнять произвольное полное вычисление по Тьюрингу.[4]
  • Набор правил / регулярных выражений может произвольно использовать входные данные и управлять состоянием синтаксического анализа / сопоставления, т. Е. Может реализовать любой синтаксический анализатор.

Короче говоря, если он может быть сопоставлен / проанализирован любой программой, написанной на любом языке программирования, он может быть сопоставлен / проанализирован с использованием правил / регулярных выражений Raku.

Сноски

[1] Если вы используете квантификатор с открытым концом, вам нужно убедиться, что каждая итерация / рекурсия сопоставления либо использует хотя бы один символ, либо завершается ошибкой, чтобы избежать бесконечного цикла. Например, * квантификатор будет успешным, даже если шаблон, который он определяет, не соответствует, поэтому будьте осторожны, чтобы это не привело к бесконечному циклу.

[2] Учитывая то, как вы написали свой пример, возможно, вам интересна рекурсия, а не итерация. Достаточно сказать, что это тоже легко сделать.[1]

[3] В правилах Raku захваты образуют иерархию. Есть две специальные переменные, которые отслеживают состояние захвата двух ключевых уровней этой иерархии:

  • является состоянием захвата самого внутреннего охватывающего общего захвата. Думайте об этом как о чем-то аналогичном возвращаемому значению, создаваемому текущим вызовом функции в стеке вызовов функций.
  • $/ является состоянием захвата самого внутреннего охватывающего захвата. Думайте об этом как о чем-то аналогичном значению, создаваемому определенным блоком кода внутри функции.

Например:

 '123' ~~ / 1* ( 2* { print "$¢ $/" } ) 3* { print "$¢ $/" } / ; # 1 2123 123
 
  • В целом / ... / аналогично обычному вызову функции. Первый 1 и первый 123 из выходных данных показывают, что было захвачено этим общим регулярным выражением.
  • ( ... ) Настраивает внутренний захват для части регулярного выражения. 2* { print "$¢ $/" } Внутри него аналогично блоку кода. 2 Показывает, что он захватил.
  • Финал 123 показывает, что на верхнем уровне регулярного $/ выражения и имеют одинаковое значение.

[4] Например, код в сноске 3 выше включает произвольный код внутри { ... } блоков. В более общем плане:

  • Правила могут вызываться рекурсивно;
  • Правила могут иметь полные подписи и передавать аргументы;
  • Правила могут содержать произвольный код;
  • Правила могут использовать множественную семантику отправки для разрешения. Примечательно, что это может включать разрешение на основе наибольшей длины совпадения.

Ответ №4:

Мне интересно trim() , могут ли процедуры Raku соответствовать вашим целям, например: .trim , .trim-trailing или даже .trim-leading . В Raku REPL:

 > say 'x x  x   ' ~~ m:g/ 'x'   s* /;    
(「x 」 「x  」 「x   」)    

> say 'x x  x   '.trim-trailing ~~ m:g/ 'x'   s* /;    
(「x 」 「x  」 「x」)
 

HTH.

https://docs.raku.org/routine/trim https://docs.raku.org/routine/trim-trailing https://docs.raku.org/routine/trim-leading