Catatan: Setelah mencoba ini sendiri, saya segera menyadari kesalahan apa ini. Karenanya, saya sedikit memodifikasi aturan.
Fungsi minimum yang disyaratkan:
- Kelas karakter (
.
,\w
,\W
, dll) - Pengganda (
+
,*
, dan?
) - Grup tangkapan sederhana
Tantangan Anda adalah menerapkan PCRE dalam bahasa yang Anda pilih dengan ketentuan sebagai berikut:
- Anda tidak boleh menggunakan fasilitas RegEx asli bahasa Anda dengan cara apa pun . Anda juga tidak dapat menggunakan perpustakaan RegEx pihak ketiga.
- Entri Anda harus menerapkan sebanyak spesifikasi PCRE. mungkin.
Program Anda harus menerima sebagai input, 2 baris:
- ekspresi reguler
- input string untuk dicocokkan
Program Anda harus menunjukkan dalam outputnya:
- Apakah RegEx cocok di mana saja di string input
- Hasil dari setiap grup penangkap
Pemenang akan menjadi entri yang mengimplementasikan sebanyak mungkin spesifikasi. mungkin. Dalam hal seri, pemenang akan menjadi entri paling kreatif, seperti yang dinilai oleh saya.
Sunting: untuk memperjelas beberapa hal, berikut adalah beberapa contoh input dan output yang diharapkan:
- Memasukkan:
^ \ s * (\ w +) $ Halo
- Keluaran:
Cocok: ya Grup 1: 'halo'
- Memasukkan:
(\ w +) @ (\ w +) (?: \. com | \ .net) [email protected]
- Keluaran:
Cocok: ya Grup 1: 'sam' Grup 2: 'ujian'
code-challenge
regular-expression
Nathan Osman
sumber
sumber
Jawaban:
Python
Karena menerapkan PCRE penuh terlalu banyak, saya hanya mengimplementasikan sebagian yang penting saja.
Mendukung
|.\.\w\W\s+*()
. Input regexp harus benar.Contoh:
Bagaimana itu bekerja:
Untuk teori terperinci, baca Pengantar Teori Automata, Bahasa, dan Komputasi ini .
Idenya adalah untuk mengubah ekspresi reguler asli menjadi automata nondeterminist finite automata (NFA). Sebenarnya, ekspresi reguler PCRE setidaknya adalah tata bahasa bebas konteks yang kami perlukan push-down automata, tetapi kami akan membatasi diri kami untuk subset dari PCRE.
Automatas terbatas adalah grafik terarah di mana node dinyatakan, tepi adalah transisi dan setiap transisi memiliki input yang cocok. Awalnya Anda mulai dari simpul awal, yang telah ditentukan sebelumnya. Setiap kali Anda menerima input yang cocok dengan salah satu transisi Anda mengambil transisi itu ke keadaan baru. Jika Anda mencapai terminal node, itu disebut input diterima automata. Dalam kasus kami, input adalah fungsi yang cocok yang mengembalikan true.
Mereka disebut nondeterminist automata karena kadang-kadang ada lebih banyak transisi yang cocok yang dapat Anda ambil dari keadaan yang sama. Dalam implementasi saya semua transisi ke keadaan yang sama harus cocok dengan hal yang sama, jadi saya menyimpan fungsi yang cocok bersama-sama dengan negara tujuan (
states[dest][0]
).Kami mengubah regexp kami menjadi automata terbatas menggunakan blok bangunan. Blok penyusun memiliki simpul mulai (
first
) dan simpul akhir (last
) dan cocok dengan sesuatu dari teks (kemungkinan string kosong).Contoh paling sederhana termasuk
True
(first == last
)c == txt[pos]
(first == last
)(
pertama == terakhir`)Anda juga akan membutuhkan posisi baru di teks tempat untuk mencocokkan token berikutnya.
Contoh yang lebih rumit adalah (huruf besar berarti blok).
pencocokan B +:
pencocokan A | B | C:
Semua operator regexp dapat diubah seperti ini. Coba saja
*
.Bagian terakhir adalah mengurai regexp yang membutuhkan tata bahasa yang sangat sederhana:
Semoga menerapkan tata bahasa sederhana (saya pikir adalah LL (1), tetapi benar kalau saya salah) jauh lebih mudah daripada membangun NFA.
Setelah Anda memiliki NFA, Anda harus mundur hingga mencapai simpul terminal.
Kode sumber (atau di sini ):
sumber
(a+b)+
cocokabaabaaabaaaab
.