Saya sedang mengerjakan parser untuk bahasa gaya-C, dan untuk parser itu saya perlu ekspresi reguler yang cocok dengan gaya-C / ** / komentar. Sekarang, saya telah menemukan ungkapan ini di web:
/\*([^\*]*\*+[^\*/])*([^\*]*\*+|[^\*]*\*/
Namun, seperti yang Anda lihat, ini adalah ekspresi yang agak berantakan, dan saya tidak tahu apakah itu benar-benar cocok dengan apa yang saya inginkan.
Adakah cara yang berbeda untuk (secara ketat) mendefinisikan ekspresi reguler yang mudah diperiksa dengan tangan bahwa mereka benar-benar benar, dan kemudian dapat dikonversi ('dapat dikompilasi') ke ekspresi reguler di atas?
compilers
parsers
regular-languages
Alex ten Brink
sumber
sumber
(!\*)
dimaksudkan? Maksud Anda notasi yang lebih umum[^*]
? Dan apa(!*|!/)
?Jawaban:
Saya dapat memikirkan empat cara:
Tentukan automaton untuk bahasa yang Anda minati. Konversi ekspresi reguler menjadi automaton (menggunakan turunan Brzozowski). Periksa apakah kedua automata menerima bahasa yang sama (tentukan dan perkecil atau gunakan argumen bisimulasi).
Tulis banyak kasus uji dan terapkan ekspresi reguler Anda ke sana.
Ubah otomat yang didefinisikan dalam poin 1 ke ekspresi reguler, menggunakan teknik standar.
Kombinasi di atas.
sumber
Jika Anda ingin memastikan bahwa Anda menguraikan komentar C, Anda harus berhadapan dengan model Anda dengan spesifikasi C. C99 §6.4.9 mendefinisikan sintaks komentar sebagai berikut:
Ini adalah prosa bahasa Inggris, bukan definisi formal, tetapi ada interpretasi yang cukup jelas dalam hal robot hingga nondeterministic finite (NFA) yang menggunakan komentar:
/
diikuti oleh*
memasuki kondisi komentar di-multiline, dan/
diikuti oleh/
memasuki kondisi komentar di-baris-tunggal.*
diikuti oleh/
memasuki status post-comment.Perhatikan bahwa untuk mengetahui apakah kondisi awal berlaku, Anda harus melakukan sedikit lebih banyak analisis untuk mendeteksi string dan karakter literal.
Setelah memiliki NFA, Anda dapat menggunakan teknik standar untuk membangun ekspresi reguler (Saya tidak melihatnya di artikel Wikipedia, tetapi harus dibahas dalam buku teks).
Jika Anda sudah memiliki ekspresi reguler dan ingin mengujinya, Anda dapat membandingkan bahasa yang dihasilkan dengan yang dari NFA yang disimpulkan dari spesifikasi bahasa: kesetaraan bahasa biasa dapat ditentukan. Salah satu cara untuk memutuskan kesetaraan adalah dengan membangun otomat deterministik minimal untuk masing-masing; jika bahasanya setara, DFA minimal adalah isomorfik.
sumber
Jika Anda menulis parser, hal-hal semacam ini ditangani oleh penganalisa leksikal. Dan di sana Anda dapat mengekspresikan ini dengan ekspresi reguler, atau (seperti
flex
contoh yang saya lihat tunjukkan) "lepas ke bahasa yang mendasarinya" dan selesaikan pekerjaan di sana. Yaitu, melihat/*
hanya melompat ke depan sampai Anda menemukan*/
(DFA untuk ini mudah untuk membangun, dan dari sana sebuah fragmen C mudah untuk ditulis).sumber