Referensi otoritatif tentang masalah pragmatis di balik penerapan mesin regex adalah serangkaian tiga posting blog oleh Russ Cox . Seperti yang dijelaskan di sana, karena backreferences membuat bahasa Anda tidak biasa, mereka diimplementasikan menggunakan backtracking .
Mencari dan melihat ke belakang, seperti banyak fitur dari mesin pencocokan pola regex, tidak cukup cocok dengan paradigma memutuskan apakah string adalah anggota suatu bahasa atau tidak. Alih-alih dengan regex kita biasanya mencari substring dalam string yang lebih besar. "Match" adalah substring yang merupakan anggota bahasa, dan nilai kembali adalah titik awal dan akhir substring dalam string yang lebih besar.
Titik lookaheads dan lookbehinds bukanlah untuk memperkenalkan kemampuan untuk mencocokkan bahasa yang tidak biasa, melainkan untuk menyesuaikan di mana mesin melaporkan titik awal dan akhir dari substring yang cocok.
Saya mengandalkan deskripsi di http : //www . regular-expressions.info/lookaround.html . Mesin regex yang mendukung fitur ini (Perl, TCL, Python, Ruby, ...) semua tampaknya didasarkan pada pengulangan (yaitu, mereka mendukung serangkaian bahasa yang jauh lebih besar daripada hanya bahasa biasa). Mereka tampaknya menerapkan fitur ini sebagai perpanjangan backtracking yang relatif "sederhana", daripada mencoba untuk membangun automata terbatas nyata untuk melakukan tugas.
Penampilan positif
Sintaks untuk lookahead positif adalah (?=
regex)
. Jadi misalnya q(?=u)
cocok q
hanya jika diikuti oleh u
, tetapi tidak cocok dengan u
. Saya membayangkan mereka menerapkan ini dengan variasi pada backtracking. Buat FSM untuk ekspresi sebelum tampilan positif. Ketika yang cocok ingat di mana itu berakhir dan mulai FSM baru yang mewakili ekspresi di dalam lookahead positif. Jika itu cocok maka Anda memiliki "pertandingan", tetapi pertandingan "berakhir" tepat sebelum posisi di mana pertandingan pencarian kepala positif dimulai.
Satu-satunya bagian dari ini yang akan sulit tanpa mundur adalah bahwa Anda perlu mengingat titik di input di mana lookahead dimulai dan pindahkan tape input Anda kembali ke posisi ini setelah Anda selesai dengan pertandingan.
Lookahead negatif
Sintaks untuk lookahead negatif adalah (?!
regex)
. Jadi misalnya q(?!u)
cocok q
hanya jika tidak diikuti oleh u
. Ini bisa berupa q
diikuti oleh beberapa karakter lain, atau q
di akhir string. Saya membayangkan ini diimplementasikan dengan membuat NFA untuk ekspresi lookahead, kemudian berhasil hanya jika NFA gagal mencocokkan string berikutnya.
Jika Anda ingin melakukannya tanpa mengandalkan kemunduran, Anda bisa meniadakan NFA dari ekspresi lookahead, lalu perlakukan seperti cara Anda memperlakukan lookahead positif.
Terlihat Positif di Belakang
(?<=
)
(?=q)u
u
q
q
nnn
Anda mungkin dapat mengimplementasikan ini tanpa mundur dengan mengambil persimpangan "string yang berakhir dengan regex " dengan bagian regex apa pun yang datang sebelum operator yang melihat ke belakang. Ini akan menjadi meskipun rumit, karena lookbehind regex mungkin perlu melihat kembali lebih jauh dari awal saat input.
Terlihat Negatif di belakang
Sintaks untuk tampilan negatif di belakang adalah (?<!
regex)
. Jadi, misalnya, (?<!q)u
cocok u
, tetapi hanya jika tidak didahului oleh q
. Jadi itu akan cocok dengan u
in umbrella
dan u
in doubt
, tetapi tidak u
in quick
. Sekali lagi, ini tampaknya dilakukan dengan menghitung panjang regex , mendukung banyak karakter, menguji pertandingan dengan regex , tetapi sekarang gagal seluruh pertandingan jika tampilan di belakang cocok.
Anda mungkin dapat menerapkan ini tanpa mundur dengan mengambil negasi regex dan kemudian melakukan hal yang sama seperti yang Anda lakukan untuk tampilan positif.