Откат балансирующей группы в жадном повторении может вызвать дисбаланс?

Как обобщенный пример для этого вопроса, я намерен сопоставить некоторое количество a ', затем равное число b', плюс еще один b.

Изучите два шаблона, представленные в этом фрагменте (также на ideone.com):

var r1 = new Regex(@"(?xn)
   (?<A> a)+   (?<B-A> b)+    (?(A)(?!))   b
");
var r2 = new Regex(@"(?xn)
   (?<A> a)+   (?<B-A> b)+?   (?(A)(?!))   b
");

Console.WriteLine(r1.Match("aaabbb"));
// aaabbb

Console.WriteLine(r2.Match("aaabbb"));
// aabbb

Обратите внимание, что разница в совпадении двух шаблонов. r1, который использует жадное повторение в конструкции балансировочной группы, соответствует 3 a и 3 b 's, что НЕ предназначено. r2, который использует неохотное повторение, дает мне 2 a и 3 b 's, что и есть.

Единственное, что я могу объяснить, это то, что когда (?<B-A> b)+ обращается к одному меньше b, он появляется из стека b, но НЕ отбрасывает то, что было соответствующим образом вытолкнуто из стека a. Таким образом, хотя один менее b теперь сопоставляется из-за обратного отслеживания, стек a остается пустым. Это единственный способ объяснить, как r1 может соответствовать aaabbb.

Обратите внимание, что использование неохотой +? в r2 не вызывает этой проблемы. То, как я это вижу, это потому, что в отличие от жадного повторения, неохотное повторение не должно "отменить ущерб" стеку a, так сказать. Напротив, жадное повторение вызывает как можно больший "ущерб", но откат не позволяет "оставить вещи такими, какие они есть" в стеке a.

Это правильный анализ того, что произошло? И если да, то это поведение по дизайну? Потому что то, что в основном выглядит для меня, это то, что откат балансирующей группы в жадном повторении может привести к дисбалансу, и, таким образом, это потенциально может быть отнесено к категории ошибок (или, по крайней мере, несколько удивительного поведения, которое неадекватно документировано).

Ответ 1

Это bug в моно.

Причина, по которой люди получают .NET-подобный Environment.Version в IdeOne, - это требование Mono обратной совместимости с .NET, включая совместимость с приложениями, принимающими решения на основе версии фреймворка.