Это одна из замечательных особенностей движка Oniguruma regexp, используемого в Ruby 1.9 - он обладает возможностями синтаксического анализатора и не ограничивается распознаванием обычных языков. Он имеет положительный и отрицательный взгляд / взгляд назад, который даже может использоваться для распознавания некоторых языков, которые не не зависят от контекста! В качестве примера возьмем следующее:
regexp = /\A(?<AB>a\g<AB>b|){0}(?=\g<AB>c)a*(?<BC>b\g<BC>c|){1}\Z/
Это регулярное выражение распознает такие строки, как «abc», «aabbcc», «aaabbbccc» и т. Д. - число «a», «b» и «c» должно быть одинаковым, иначе оно не будет совпадать.
(Одно ограничение: вы не можете использовать именованные группы во взглядах вперед и назад).
Хотя я и не заглянул под капот, Онигурума, похоже, имеет дело с именованными группами простым рекурсивным спуском, резервное копирование, когда что-то не совпадает. Я заметил, что он не может справиться с левой рекурсией. Например:
irb(main):013:0> regexp = /(?<A>\g<A>a|)/
SyntaxError: (irb):13: never ending recursion: /(?<A>\g<A>a|)/
from C:/Ruby192/bin/irb:12:in `<main>'
Я не очень хорошо помню свою теорию синтаксического анализа, но я думаю, что недетерминированный нисходящий синтаксический анализатор, подобный этому, должен быть способен анализировать любой контекстно-свободный язык. («Язык», а не «грамматика»; если ваша грамматика вышла из рекурсии, вам придется преобразовать ее в правую рекурсию.) Если это неверно, отредактируйте этот пост.