Masalah ini adalah analog yang tepat dari masalah pencocokan tanda kurung dalam ekspresi di mana beberapa tanda kurung tutup telah dihilangkan. Berikut sebuah "jika" (atau dalam tata bahasa perwakilan) adalah kurung buka dan "yang lain" ( ) adalah kurung tutup. (Dari urutan dan , Anda dapat memasukkan mekanis dengan menempatkan satu sebelum setiap dan satu di bagian paling akhir.) Karena lebih cocok dengan otak kurung saya, saya menulis seolah-olah itu adalah masalah yang dihadapi.ababcb
Resolusi tradisional "cocok terdekat" menjuntai-lain cocok masing-masing dekat dengan yang paling baru terbuka belum tertandingi. Itu berarti bahwa tidak pernah ada pembukaan yang tidak tertandingi (atau tutup, dalam hal ini) antara pembukaan yang cocok dan penutupan yang cocok.
Salah satu alternatif yang mungkin adalah untuk mencocokkan setiap penutupan dengan pembukaan awal yang layak dan tidak tertandingi. "Layak" di sini berarti bahwa open dapat dicocokkan tanpa melanggar sarang kurung (mis. Yang pertama in tidak mungkin cocok dengan yang terakhir ).( ) ( ) )(()())
Pencocokan ini harus dilakukan di luar-dalam, sehingga kecocokan untuk penutupan tidak dilakukan sampai semua pasangan penutup telah cocok. Fakta ini membuatnya tidak mungkin untuk menghasilkan parse dengan algoritma dibatasi-lookahead, karena parse harus bekerja ke dalam dari kedua ujungnya, setelah memecah string menjadi segmen yang benar-benar cocok (karena mereka secara efektif membatasi rentang pencocokan potensial).
Namun, fakta bahwa parser kiri-ke-kanan online tidak ada tidak menyiratkan bahwa tidak ada CFG yang jelas. (Jelas: bahasa palindromik harus diurai dari kedua ujung ke tengah, tetapi mudah untuk menulis tata bahasa yang tidak ambigu).
Untuk menghasilkan tata bahasa untuk masalah kurung "pertandingan terjauh", saya mengandalkan fakta bahwa open yang tidak cocok tidak dapat diikuti oleh open yang cocok. Jika ya, maka properti yang paling cocok tidak akan berlaku karena open yang tidak cocok bisa cocok dengan penutupan open yang cocok, jadi fakta bahwa itu tidak cocok akan melanggar properti yang paling cocok dengan pertandingan.
Jadi inilah tata bahasa yang agak kikuk:
SUMT→U|M→T|aUbT|aUbc|aMbU→aMbM|c→aT|ac
adalah simbol awal; M adalah pernyataan yang sepenuhnya cocok; U jelas merupakan pernyataan yang tidak cocok (yang berarti mereka memasukkan setidaknya satu yang tidak cocok , sehingga mereka tidak dapat kosong) dan T adalah "ekor" yang hanya terdiri dari huruf s yang tidak cocok. Fakta di atas tentang tak tertandingi terbuka dapat dibaca langsung dari tata bahasa: semua tak tertandingi membuka berasal dari T , sebuah T hanya dapat muncul pada akhir dari U , dan U hanya dapat diikuti oleh T .SMUaTaTTUUT
Kecanggungan datang dari mencegah dari mencocokkan string kosong. Itu mencegah banyak dari apa yang saya anggap ambiguitas palsu: Mereka palsu dalam arti bahwa pencocokan pembukaan dan penutupan adalah sama di semua parse alternatif. Jika U dibolehkan nullable, itu juga akan menghasilkan string yang sepenuhnya seimbang. Karena S , pada dasarnya, M ∗ U , yang mengarah ke ambiguitas di mana Anda dapat menganggap S yang sepenuhnya seimbang sebagai serangkaian M yang diikuti oleh U yang kosong , atau satu yang lebih sedikit M diikuti oleh U yang sepenuhnya seimbang .UUSM∗USMUMU
Mungkin ada solusi yang lebih baik daripada yang saya pilih. Tapi yang ini sepertinya berhasil, dan itu berfungsi baik dengan parser GLR Bison yang saya gunakan untuk mengujinya; parser itu mengeluhkan tentang ambigu ambigu kecuali Anda menulis kode tambahan untuk menangani ambiguitas, dan saya terlalu malas untuk melakukan itu. Saya mengujinya dengan string hingga 20 open + closes, dan tampaknya telah menghasilkan parse yang tidak ambigu untuk setiap urutan yang disatukan dengan benar, tanpa menghasilkan parses untuk urutan yang disarang secara salah.