Авторитетним посиланням на прагматичні проблеми, що стоять за реалізацією двигунів регулярних випромінювань, є серія з трьох дописів блогу від Расса Кокса . Як описано там, оскільки зворотні посилання роблять вашу мову нерегулярною, вони реалізуються за допомогою зворотного відстеження .
Шукаючі і дивлячісь, як і багато особливостей двигунів відповідності шаблонів регулярних виразів, не зовсім вписуються в парадигму вирішення питання про те, чи є рядок членом мови чи ні. Замість регексів ми зазвичай шукаємо підрядки у більшому рядку. "Збіги" - це підрядки, які є членами мови, а значення, що повертається, є початковою та кінцевою точками підрядки у більшому рядку.
Суть лукахедів та поглядів позаду - це не стільки в тому, щоб запровадити здатність відповідати нестандартним мовам, а скоріше налаштувати там, де движок повідомляє про початкову та кінцеву точки відповідних підрядків.
Я покладаюся на опис за адресою http://www.regular-expressions.info/lookaround.html . Двигуни регулярних виразів, що підтримують цю функцію (Perl, TCL, Python, Ruby, ...), схоже, базуються на зворотному відстеженні (тобто вони підтримують набагато більший набір мов, ніж просто звичайні мови). Вони, схоже, реалізують цю функцію як відносно "просте" розширення зворотного відстеження, а не намагаються побудувати справжні кінцеві автомати для виконання завдання.
Позитивний Lookahead
Синтаксис позитивного пошуку є (?=
регулярним вираженням)
. Так, наприклад, q(?=u)
матчі, q
лише якщо за ними дотримуються u
, але не відповідають u
. Я думаю, що вони реалізують це за допомогою варіації зворотного відстеження. Створіть FSM для виразу перед позитивним lookahead. Коли це збіг, згадайте, де він закінчився, і почніть новий FSM, який представляє вираз усередині позитивного пошуку. Якщо це збіги, то у вас є "відповідність", але матч "закінчується" безпосередньо перед позицією, де почався позитивний матч "лукахед".
Єдиною частиною цього, яка була б складною без зворотного відстеження, є те, що вам потрібно запам’ятати точку на вході, з якої починається пошук і перемістити вхідну стрічку назад у цю позицію після завершення матчу.
Негативний Lookahead
Синтаксис негативного пошуку є (?!
регулярним вираженням)
. Так, наприклад, q(?!u)
матчі, q
лише якщо за ним не дотримуються u
. Це може бути або q
наступним яким-небудь іншим символом, або а q
в самому кінці рядка. Я думаю, що це реалізується шляхом створення NFA для виразу lookahead, а потім успіху лише в тому випадку, якщо NFA не зможе відповідати наступній рядку.
Якщо ви хочете зробити це, не покладаючись на зворотний трекінг, ви можете заперечити NFA вираження lookahead, тоді ставитесь до нього так само, як ви ставитесь до позитивного lookahead.
Позитивний погляд
(?<=
)
(?=q)u
u
q
q
ннн
Ви можете реалізувати це без зворотного відстеження, взявши перетин "рядка, який закінчується регулярним виразом ", з будь-якою частиною регулярного виразу, що знаходиться перед оператором "заднім поглядом". Це буде непросто , хоча, тому що з переглядом тому регулярний вираз , можливо , доведеться шукати далі , ніж поточне початок введення.
Негативний огляд
Синтаксис негативного вигляду - це (?<!
регулярний вираз)
. Так, наприклад, (?<!q)u
сірники u
, але тільки якщо це не передує q
. Таким чином, це збігалося б з u
in umbrella
і u
in doubt
, але не з u
in quick
. Знову ж таки, це, здається, робиться шляхом обчислення довжини регулярних виразів , резервного копіювання багатьох символів, тестування на матч з регулярними виразками , але тепер не вдалося провести весь матч, якщо вигляд буде збігатися.
Ви можете реалізувати це без зворотного відстеження, зробивши заперечення регулярного вираження, а потім зробивши те саме, що і для позитивного погляду позаду.