Bagaimana komentar umumnya diperlakukan dalam bahasa pemrograman dan markup? Saya menulis parser untuk beberapa bahasa markup kustom dan ingin mengikuti prinsip paling tidak mengejutkan , jadi saya mencoba menentukan konvensi umum.
Misalnya, haruskah komentar yang tertanam di dalam token 'mengganggu' token atau tidak? Secara umum, adalah sesuatu seperti:
Sys/* comment */tem.out.println()
sah?
Juga, jika bahasanya peka terhadap baris baru, dan komentar menjangkau baris baru, haruskah baris baru dipertimbangkan atau tidak?
stuff stuff /* this is comment
this is still comment */more stuff
diperlakukan sebagai
stuff stuff more stuff
atau
stuff stuff
more stuff
?
Saya tahu apa yang dilakukan beberapa bahasa tertentu, saya juga tidak mencari pendapat, tetapi saya mencari apakah: apakah ada konsensus umum apa yang secara umum diharapkan oleh mark up sehubungan dengan token dan baris baru?
Konteks khusus saya adalah markup seperti wiki.
Jawaban:
Biasanya komentar dipindai (dan dibuang) sebagai bagian dari proses tokenization, tetapi sebelum diuraikan. Sebuah komentar berfungsi seperti pemisah token meskipun tidak ada spasi putih di sekitarnya.
Seperti yang Anda tunjukkan, spesifikasi C secara eksplisit menyatakan bahwa komentar diganti dengan spasi tunggal. Ini hanya spesifikasi-istilah, karena parser dunia nyata tidak akan benar-benar menggantikan apa pun, tetapi hanya akan memindai dan membuang komentar dengan cara yang sama seperti memindai dan membuang karakter spasi. Tapi itu menjelaskan dengan cara sederhana bahwa komentar memisahkan token dengan cara yang sama seperti ruang.
Isi komentar diabaikan, jadi linebreak di dalam komentar multiline tidak berpengaruh. Bahasa yang sensitif terhadap jeda baris (Python dan Visual Basic) biasanya tidak memiliki komentar multiline, tetapi JavaScript adalah satu pengecualian. Sebagai contoh:
Setara dengan
tidak
Komentar baris tunggal mempertahankan jeda baris, yaitu
setara dengan
tidak
Karena komentar dipindai tetapi tidak diuraikan, mereka cenderung tidak bersarang. Begitu
adalah kesalahan sintaksis, karena komentar dibuka oleh yang pertama
/*
dan ditutup oleh yang pertama*/
sumber
/* like this */
) dianggap sama dengan spasi kosong tunggal, dan komentar yang diakhiri EOL (// like this
) ke baris kosong.(define x #| this is #| a sub-comment |# the main comment |# 3) x
hasil3
.Untuk menjawab pertanyaan:
Saya akan mengatakan tidak ada yang akan mengharapkan komentar yang tertanam di dalam token menjadi sah.
Sebagai aturan umum, komentar harus diperlakukan sama dengan spasi putih. Setiap tempat yang akan valid untuk memiliki spasi putih juga harus diizinkan untuk memiliki komentar yang melekat. Satu-satunya pengecualian adalah string:
Akan sangat aneh untuk mendukung komentar di dalam string, dan akan membuat mereka bosan!
sumber
Hello /* world*/!
daripada menekan pembatas komentar. Juga, selamat datang di Programer!Dalam bahasa yang tidak sensitif spasi putih, karakter yang diabaikan (yaitu spasi putih atau yang merupakan bagian dari komentar) membatasi token.
Jadi misalnya
Sys tem
ada dua token, sedangkanSystem
satu. Kegunaan ini mungkin lebih jelas jika Anda membandingkannew Foo()
dannewFoo()
salah satunya akan membuat instanceFoo
sementara yang lain meneleponnewFoo
.Komentar dapat memainkan peran yang sama dengan menjalankan spasi putih, mis.
new/**/Foo()
Berfungsi sama dengannew Foo()
. Tentu saja ini bisa lebih kompleks, misalnyanew /**/ /**/ Foo()
atau yang lainnya.Secara teknis, seharusnya memungkinkan untuk memungkinkan komentar di dalam pengidentifikasi, tetapi saya ragu itu sangat praktis.
Sekarang, bagaimana dengan bahasa sensitif ruang-putih?
Python datang ke pikiran dan memiliki jawaban yang sangat sederhana: tidak ada komentar blok. Anda memulai komentar dengan
#
dan kemudian parser bekerja persis seolah-olah sisa baris tidak ada tetapi hanya baris baru.Berbeda dengan itu, giok memungkinkan untuk memblokir komentar , di mana blok berakhir ketika Anda kembali ke tingkat indentasi yang sama. Contoh:
Jadi di bidang ini, saya tidak akan mengatakan Anda bisa mengatakan bagaimana hal-hal biasanya ditangani. Apa yang tampaknya menjadi kesamaan, adalah bahwa komentar selalu berakhir dengan end-of-line, yang berarti bahwa semua komentar bertindak persis sama dengan baris baru.
sumber
Di masa lalu saya telah mengubah komentar menjadi token tunggal sebagai bagian dari analisis leksikal. Hal yang sama berlaku untuk string. Dari sana, hidup itu mudah.
Dalam kasus spesifik parser terakhir yang saya buat, aturan pelarian dilewatkan ke rutin parse tingkat atas. Aturan melarikan diri digunakan untuk menangani token seperti token komentar sejalan dengan tata bahasa inti. Secara umum, token ini dibuang.
Konsekuensi dari melakukannya dengan cara ini adalah bahwa contoh yang Anda posting dengan komentar di tengah pengenal, pengenal tidak akan menjadi pengidentifikasi tunggal - ini adalah perilaku yang diharapkan dalam semua bahasa (dari memori) yang telah saya kerjakan .
Kasus komentar dalam string harus ditangani secara implisit oleh analisis leksikal. Aturan untuk menangani string tidak memiliki minat pada komentar, dan dengan demikian komentar tersebut diperlakukan sebagai konten string. Hal yang sama berlaku untuk string (atau kutipan literal) dalam komentar - string adalah bagian dari komentar, yang secara eksplisit merupakan token tunggal; aturan untuk memproses komentar tidak tertarik pada string.
Saya harap masuk akal / membantu.
sumber
console.log(/*a comment containing "quotes" is possible*/ "and a string containing /*slash-star, star-slash*/ is possible")
, di mana ada kutipan dalam komentar dan sintaks komentar dalam sebuah string, bagaimana lexer tahu tokenize dengan benar? Bisakah Anda mengedit jawaban Anda, memberikan deskripsi umum tentang kasus-kasus itu?Itu tergantung pada tujuan apa yang dimiliki parser Anda. Jika Anda menulis parser untuk membangun pohon parse untuk dikompilasi daripada komentar tidak memiliki nilai semantik selain berpotensi memisahkan token (misalnya metode / komentar / (/ komentar /)). Dalam hal ini, itu diperlakukan seperti ruang.
Jika parser Anda adalah bagian dari transpiler yang menerjemahkan satu bahasa sumber ke bahasa sumber lain atau jika parser Anda adalah preprosesor yang mengambil unit kompilasi dalam bahasa sumber, mem-parsing-nya, memodifikasinya dan menulis versi yang diubah kembali dalam bahasa sumber yang sama, komentar seperti hal lain menjadi sangat penting.
Juga jika Anda memiliki informasi meta dalam komentar dan Anda terutama memperhatikan komentar seperti ketika membuat API-dokumentasi seperti JavaDoc, komentar tiba-tiba sangat penting.
Di sini komentar sering dilampirkan pada token itu sendiri. Jika Anda menemukan komentar, Anda melampirkannya sebagai komentar token. Karena token dapat memiliki beberapa token sebelum dan sesudah, itu lagi tujuan-tergantung bagaimana menangani komentar tersebut.
Gagasan membubuhi tanda non-komentar dengan memiliki komentar adalah untuk menghapus komentar dari tata bahasa sama sekali.
Setelah Anda memiliki pohon parse, AST mulai membongkar komentar yang mewakili setiap token dengan AST-Element-nya sendiri tetapi dilampirkan ke AST-Element lain di samping berisi-hubungan yang biasa. Ide yang bagus adalah memeriksa semua implementasi parser / AST untuk bahasa sumber yang tersedia di IDE open-source.
Salah satu implementasi yang sangat baik adalah infrastruktur kompiler Eclipse untuk bahasa Java. Mereka menyimpan komentar selama tokenization dan mewakili komentar dalam AST - sejauh yang saya ingat. Juga, implementasi parser / AST ini mempertahankan pemformatan.
sumber