Dalam proses menulis penerjemah dari satu bahasa musik ke yang lain (ABC ke Alda) sebagai alasan untuk mempelajari kemampuan Raku DSL, saya perhatikan bahwa sepertinya tidak ada cara untuk mengakhiri .parse
! Ini kode demo singkat saya:
#!/home/hsmyers/rakudo741/bin/perl6
use v6d;
# use Grammar::Debugger;
use Grammar::Tracer;
my $test-n01 = q:to/EOS/;
a b c d e f g
A B C D E F G
EOS
grammar test {
token TOP { <score>+ }
token score {
<.ws>?
[
| <uc>
| <lc>
]+
<.ws>?
}
token uc { <[A..G]> }
token lc { <[a..g]> }
}
test.parse($test-n01).say;
Dan itu adalah bagian terakhir dari tampilan Grammer :: Tracer yang menunjukkan masalah saya.
| score
| | uc
| | * MATCH "G"
| * MATCH "G\n"
| score
| * FAIL
* MATCH "a b c d e f g\nA B C D E F G\n"
「a b c d e f g
A B C D E F G
」
Pada baris kedua hingga terakhir, kata FAIL memberi tahu saya bahwa .parse run tidak memiliki cara untuk berhenti. Saya ingin tahu apakah ini benar? .Say menampilkan semuanya sebagaimana mestinya, jadi saya tidak jelas tentang seberapa nyata GAGAL itu? Pertanyaannya tetap, "Bagaimana cara saya menulis tata bahasa dengan benar yang mem-parsing beberapa baris tanpa kesalahan?"
Jawaban:
Ketika Anda menggunakan tata bahasa debugger, itu memungkinkan Anda melihat dengan tepat bagaimana mesin mengurai string - gagal adalah normal dan diharapkan. Dianggap, misalnya, cocok
a+b*
dengan stringaab
. Anda harus mendapatkan dua pertandingan untuk 'a', diikuti oleh gagal (karenab
tidaka
) tetapi kemudian akan mencoba lagib
dan berhasil mencocokkan.Ini mungkin lebih mudah dilihat jika Anda melakukan pergantian dengan
||
(yang memberlakukan perintah). Jika Anda memilikidan Anda parsing kalimat "Saya punya kiwi", Anda akan melihatnya pertandingan pertama "Saya punya", diikuti oleh dua gagal dengan "apel" dan "oranye", dan akhirnya cocok dengan "kiwi".
Sekarang mari kita lihat kasus Anda:
Kegagalan di sini adalah normal: pada titik tertentu kita akan kehabisan
<score>
token, sehingga kegagalan tidak bisa dihindari. Ketika itu terjadi, mesin tata bahasa dapat beralih ke apa pun yang muncul setelah<score>+
tata bahasa Anda. Karena tidak ada apa-apa, kegagalan itu sebenarnya menghasilkan kecocokan seluruh string (karenaTOP
cocok dengan implisit/^…$/
).Selain itu, Anda dapat mempertimbangkan untuk menulis ulang tata bahasa Anda dengan aturan yang menyisipkan <.ws> * secara otomatis (kecuali penting untuk hanya menjadi satu ruang saja):
Selanjutnya, IME, Anda mungkin ingin juga ingin menambahkan token proto untuk uc / lc, karena ketika Anda memilikinya
[ <foo> | <bar> ]
Anda akan selalu memiliki salah satu dari mereka yang tidak terdefinisi yang dapat membuat memprosesnya dalam kelas tindakan agak mengganggu. Kamu bisa mencoba:$<letter>
akan selalu didefinisikan dengan cara ini.sumber
<.ws>*
secara otomatis". Pertimbangkan untuk meninjau Apa cara terbaik untuk lalai di ruang putih dalam tata bahasa Raku? dan Bagaimana cara mencocokkan heks array dalam tata bahasa perl6 dan Kapan ruang putih benar-benar penting dalam tata bahasa Raku? .proto
tidak terlalu sulit dan begitu Anda memahami itu membuat hidup Anda jauh lebih mudah.