Ответ 1
Это одна из удивительных вещей, связанных с движком Regexp Oniguruma, используемым в Ruby 1.9, - она обладает силе анализатора и не ограничивается распознаванием обычных языков. У этого есть положительный и отрицательный lookahead/lookbehind, который даже может быть использован для распознавания некоторых языков, которые не являются контекстуальными! В качестве примера возьмем следующее:
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" должно быть равно или оно не будет соответствовать.
(Одно ограничение: вы не можете использовать названные группы в lookahead и lookbehind.)
Хотя я havent заглянул под капот, Oniguruma, похоже, имеет дело с именованными группами простым рекурсивным спуском, создавая резервную копию, когда что-то не соответствует. Ive заметил, что он не может справиться с левой рекурсией. Например:
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>'
Я не очень хорошо помню мою теорию синтаксического анализа, но я думаю, что не детерминированный синтаксический анализатор сверху вниз должен иметь возможность анализировать любой контекстно-свободный язык. ( "язык", а не "грамматика", если ваша грамматика оставила рекурсию, вам придется преобразовать ее в правильную рекурсию.) Если это неверно, отредактируйте это сообщение.