Saya sering mendengar klaim bahwa C ++ adalah bahasa yang peka konteks. Ambil contoh berikut:
a b(c);
Apakah ini definisi variabel atau deklarasi fungsi? Itu tergantung pada makna simbol c
. Jika c
adalah variabel , maka a b(c);
tentukan variabel bernama b
tipe a
. Langsung diinisialisasi dengan c
. Tetapi jika c
adalah tipe , maka a b(c);
mendeklarasikan fungsi bernama b
yang mengambil a c
dan mengembalikan a
.
Jika Anda mencari definisi bahasa bebas konteks, pada dasarnya ia akan memberi tahu Anda bahwa semua aturan tata bahasa harus memiliki sisi kiri yang terdiri dari tepat satu simbol non-terminal. Tata bahasa yang peka terhadap konteks, di sisi lain, memungkinkan deretan simbol terminal dan non-terminal yang sewenang-wenang di sisi kiri.
Menelusuri Lampiran A dari "Bahasa Pemrograman C ++", saya tidak dapat menemukan aturan tata bahasa tunggal yang memiliki hal lain selain simbol non-terminal tunggal di sisi kiri. Itu menyiratkan bahwa C ++ bebas konteks. (Tentu saja, setiap bahasa bebas konteks juga peka konteks dalam arti bahwa bahasa bebas konteks membentuk bagian dari bahasa peka konteks, tetapi bukan itu intinya.)
Jadi, apakah C ++ bebas konteks atau peka konteks?
sumber
Jawaban:
Di bawah ini adalah demonstrasi favorit saya (saat ini) tentang mengapa parsing C ++ (mungkin) Turing-complete , karena menunjukkan program yang secara sintaksis benar jika dan hanya jika bilangan bulat yang diberikan adalah prima.
Jadi saya menyatakan bahwa C ++ tidak bebas konteks atau peka konteks .
Jika Anda mengizinkan urutan simbol sewenang-wenang di kedua sisi dari produksi apa pun, Anda menghasilkan tata bahasa Tipe-0 ("tidak dibatasi") dalam hierarki Chomsky , yang lebih kuat daripada tata bahasa yang peka konteks; tata bahasa tanpa batas adalah Turing-complete. Tata bahasa konteks-sensitif (Tipe-1) memungkinkan banyak simbol konteks di sisi kiri produksi, tetapi konteks yang sama harus muncul di sisi kanan produksi (maka nama "konteks-sensitif"). [1] Tata bahasa yang peka terhadap konteks setara dengan mesin Turing yang dibatasi linier .
Dalam contoh program, perhitungan utama dapat dilakukan oleh mesin Turing yang dibatasi linier, sehingga tidak cukup membuktikan kesetaraan Turing, tetapi bagian yang penting adalah bahwa parser perlu melakukan perhitungan untuk melakukan analisis sintaksis. Itu bisa saja perhitungan yang dapat diekspresikan sebagai contoh template dan ada alasan untuk percaya bahwa contoh template C ++ adalah Turing-complete. Lihat, misalnya, makalah Todd L. Veldhuizen tahun 2003 .
Apapun, C ++ dapat diurai oleh komputer, jadi tentu saja dapat diurai oleh mesin Turing. Akibatnya, tata bahasa yang tidak terbatas bisa mengenalinya. Sebenarnya menulis tata bahasa seperti itu tidak praktis, itulah sebabnya standar tidak mencoba melakukannya. (Lihat di bawah.)
Masalah dengan "ambiguitas" ekspresi tertentu sebagian besar adalah ikan haring merah. Untuk mulai dengan, ambiguitas adalah fitur tata bahasa tertentu, bukan bahasa. Bahkan jika suatu bahasa dapat terbukti tidak memiliki tata bahasa yang jelas, jika itu dapat dikenali oleh tata bahasa bebas konteks, itu bebas konteks. Demikian pula, jika tidak dapat dikenali oleh tata bahasa bebas konteks tetapi bisa dikenali oleh tata bahasa yang peka konteks, itu peka konteks. Ambiguitas tidak relevan.
Tetapi dalam hal apa pun, seperti baris 21 (yaitu
auto b = foo<IsPrime<234799>>::typen<1>();
) dalam program di bawah ini, ekspresi tidak ambigu sama sekali; mereka hanya diuraikan secara berbeda tergantung pada konteks. Dalam ungkapan paling sederhana dari masalah ini, kategori sintaksis dari pengidentifikasi tertentu bergantung pada bagaimana mereka telah dinyatakan (misalnya, jenis dan fungsi), yang berarti bahwa bahasa formal harus mengenali fakta bahwa dua string panjang sewenang-wenang dalam program yang sama identik (deklarasi dan penggunaan). Ini dapat dimodelkan dengan tata bahasa "copy", yang merupakan tata bahasa yang mengakui dua salinan tepat berturut-turut dari kata yang sama. Sangat mudah untuk dibuktikan dengan lemma pemompaan bahwa bahasa ini tidak bebas konteks. Tata bahasa konteks-sensitif untuk bahasa ini dimungkinkan, dan tata bahasa Tipe-0 disediakan dalam jawaban untuk pertanyaan ini: https: // math .stackexchange.com / questions / 163830 / context-sensitive-grammar-for-the-copy-language .Jika seseorang mencoba untuk menulis tata bahasa konteks-sensitif (atau tidak dibatasi) untuk mem-parsing C ++, itu akan sangat mungkin mengisi alam semesta dengan coretan. Menulis mesin Turing untuk mem-parsing C ++ akan menjadi usaha yang sama mustahilnya. Bahkan menulis program C ++ sulit, dan sejauh yang saya tahu tidak ada yang terbukti benar. Inilah sebabnya mengapa standar tidak berusaha untuk menyediakan tata bahasa formal yang lengkap, dan mengapa ia memilih untuk menulis beberapa aturan parsing dalam bahasa Inggris teknis.
Apa yang tampak seperti tata bahasa formal dalam standar C ++ bukanlah definisi formal lengkap sintaks dari bahasa C ++. Itu bahkan bukan definisi formal lengkap dari bahasa setelah preprocessing, yang mungkin lebih mudah untuk diformalkan. (Namun itu bukan bahasa: bahasa C ++ seperti yang didefinisikan oleh standar termasuk preprosesor, dan operasi preprosesor dijelaskan secara algoritmik karena akan sangat sulit untuk dijelaskan dalam formalisme tata bahasa apa pun. Ini ada di bagian itu standar di mana dekomposisi leksikal dijelaskan, termasuk aturan di mana ia harus diterapkan lebih dari satu kali.)
Berbagai tata bahasa (dua tata bahasa yang tumpang tindih untuk analisis leksikal, satu yang terjadi sebelum preprocessing dan yang lainnya, jika perlu, sesudahnya, ditambah tata bahasa "sintaksis") dikumpulkan dalam Lampiran A, dengan catatan penting ini (penekanan ditambahkan):
Akhirnya, inilah program yang dijanjikan. Baris 21 secara sintaksis benar jika dan hanya jika N in
IsPrime<N>
adalah prima. Jika tidak,typen
merupakan bilangan bulat, bukan templat, sehinggatypen<1>()
diuraikan sebagai(typen<1)>()
yang secara sintaksis salah karena()
bukan ekspresi yang valid secara sintaksis.[1] Untuk membuatnya lebih teknis, setiap produksi dalam tata bahasa konteks-sensitif harus dalam bentuk:
αAβ → αγβ
di mana
A
non-terminal danα
,β
mungkin urutan kosong dari simbol tata bahasa, danγ
merupakan urutan tidak kosong. (Simbol tata bahasa dapat berupa terminal atau non-terminal).Ini dapat dibaca karena
A → γ
hanya dalam konteks[α, β]
. Dalam tata bahasa bebas konteks (Tipe 2),α
danβ
harus kosong.Ternyata Anda juga dapat membatasi tata bahasa dengan batasan "monoton", di mana setiap produksi harus dalam bentuk:
α → β
dimana|α| ≥ |β| > 0
(|α|
berarti "panjangα
")Mungkin untuk membuktikan bahwa rangkaian bahasa yang dikenali oleh tata bahasa monoton persis sama dengan rangkaian bahasa yang dikenali oleh tata bahasa konteks-sensitif, dan sering kali lebih mudah untuk mendasarkan bukti pada tata bahasa monoton. Akibatnya, cukup umum untuk melihat "konteks-sensitif" digunakan seolah-olah itu berarti "monoton".
sumber
0
dalam()
, untuk yang sederhana), tapi saya pikir ini lebih menarik dengan cara ini, karena itu menunjukkan bahwa Anda memerlukan contoh template bahkan untuk mengenali jika string adalah program C ++ yang benar secara sintaksis. Jika kedua cabang dikompilasi, maka saya harus bekerja lebih keras untuk membantah argumen bahwa perbedaannya adalah "semantik". Anehnya, walaupun saya sering ditantang untuk mendefinisikan "sintaksis", tidak ada yang pernah menawarkan definisi "semantik" selain "hal-hal yang saya pikir tidak sintaksis" :)Pertama, Anda benar diamati tidak ada konteks aturan sensitif dalam tata bahasa pada akhir C ++ standar, sehingga tata bahasa adalah bebas konteks.
Namun, tata bahasa itu tidak secara tepat menggambarkan bahasa C ++, karena ia menghasilkan program non-C ++ seperti
atau
Bahasa C ++ yang didefinisikan sebagai "himpunan program C ++ yang terbentuk dengan baik" tidak bebas konteks (dimungkinkan untuk menunjukkan bahwa hanya menuntut variabel yang akan dideklarasikan membuatnya demikian). Mengingat Anda secara teoritis dapat menulis program Turing-selesai dalam template dan membuat program salah berdasarkan hasil mereka, itu bahkan tidak peka konteks.
Sekarang, orang-orang (bodoh) (biasanya bukan ahli teori bahasa, tetapi perancang parser) biasanya menggunakan "tidak bebas konteks" dalam beberapa arti berikut
Tata bahasa di belakang standar tidak memenuhi kategori-kategori ini (yaitu ambigu, bukan LL (k) ...) sehingga tata bahasa C ++ "tidak bebas konteks" untuk mereka. Dan dalam arti tertentu, mereka benar sangat sulit untuk menghasilkan parser C ++ yang berfungsi.
Perhatikan bahwa properti yang digunakan di sini hanya terhubung dengan lemah ke bahasa bebas konteks - ambiguitas tidak ada hubungannya dengan sensitivitas konteks (pada kenyataannya, aturan konteks sensitif biasanya membantu menyamarkan produksi), dua lainnya hanyalah subset konteks -gratis bahasa. Dan parsing bahasa bebas konteks bukanlah proses linear (meskipun parsing deterministik adalah).
sumber
ambiguity doesn't have anything to do with context-sensitivity
Ini juga intuisi saya, jadi saya senang melihat seseorang (a) setuju, dan (b) menjelaskannya di tempat saya tidak bisa. Saya percaya itu mendiskualifikasi semua argumen yang didasarkan padaa b(c);
, dan sebagian memuaskan pertanyaan asli yang premisnya "sering terdengar" klaim sensitivitas konteks karena ambiguitas ... terutama ketika untuk tata bahasa sebenarnya tidak ada ambiguitas bahkan di MVP.Iya. Ungkapan berikut memiliki urutan operasi yang berbeda tergantung pada jenis konteks yang diselesaikan :
Sunting: Ketika urutan operasi aktual bervariasi, itu membuatnya sangat sulit untuk menggunakan kompiler "biasa" yang mem-parsing ke AST yang tidak didekorasi sebelum menghiasnya (menyebarkan informasi jenis). Hal-hal sensitif konteks lainnya yang disebutkan adalah "agak mudah" dibandingkan dengan ini (bukan berarti evaluasi templat sama sekali mudah).
Diikuti oleh:
sumber
Untuk menjawab pertanyaan Anda, Anda perlu membedakan dua pertanyaan yang berbeda.
Sintaks belaka dari hampir setiap bahasa pemrograman bebas konteks. Biasanya, ini diberikan sebagai bentuk diperpanjang Backus-Naur atau gramar bebas konteks.
Namun, bahkan jika suatu program sesuai dengan gramar bebas konteks yang ditentukan oleh bahasa pemrograman, itu tidak selalu merupakan program yang valid . Ada banyak poperties bebas-konteks yang harus dipenuhi oleh sebuah program agar menjadi program yang valid. Misalnya, properti yang paling sederhana adalah ruang lingkup variabel.
Untuk menyimpulkan, apakah C ++ bebas konteks tergantung pada pertanyaan yang Anda ajukan.
sumber
VARDECL : TYPENAME IDENTIFIER
, tetapi Anda tidak bisa memilikinya, karena Anda tidak bisa membedakan nama tipe dari pengidentifikasi lain di level CF. Contoh lain: pada level CF, Anda tidak dapat memutuskan apakah akan mema*b
- parsing sebagai deklarasi variabel (b
dari penunjuk tipe kea
) atau sebagai perkalian.Anda mungkin ingin melihat Desain & Evolusi C ++ , oleh Bjarne Stroustrup. Di dalamnya ia menggambarkan masalahnya mencoba menggunakan yacc (atau serupa) untuk mem-parsing versi awal C ++, dan berharap ia menggunakan keturunan rekursif sebagai gantinya.
sumber
Ya C ++ sensitif terhadap konteks, sangat sensitif terhadap konteks. Anda tidak dapat membangun pohon sintaks dengan hanya mengurai file menggunakan pengurai konteks bebas karena dalam beberapa kasus Anda perlu mengetahui simbol dari pengetahuan sebelumnya untuk memutuskan (mis. Membangun tabel simbol saat mengurai).
Contoh pertama:
Apakah ini ekspresi multiplikasi?
ATAU
Apakah ini deklarasi
B
variabel menjadi pointer tipeA
?Jika A adalah variabel, maka itu ekspresi, jika A adalah tipe, itu adalah deklarasi pointer.
Contoh kedua:
Apakah ini prototipe fungsi yang mengambil argumen
bar
tipe?ATAU
Apakah ini menyatakan variabel
B
tipeA
dan memanggil konstruktor A denganbar
konstanta sebagai penginisialisasi?Anda perlu tahu lagi apakah
bar
itu variabel atau tipe dari tabel simbol.Contoh ketiga:
Ini adalah kasus ketika membangun tabel simbol sementara parsing tidak membantu karena deklarasi x dan y muncul setelah definisi fungsi. Jadi, Anda perlu memindai definisi kelas terlebih dahulu, dan melihat definisi metode dalam pass kedua, untuk mengatakan x * y adalah ekspresi, dan bukan deklarasi pointer atau apa pun.
sumber
A B();
adalah deklarasi fungsi bahkan dalam definisi fungsi. Carilah parse paling menjengkelkan ...C ++ diuraikan dengan parser GLR. Itu berarti selama parsing kode sumber, parser mungkin menghadapi ambiguitas tetapi harus melanjutkan dan memutuskan aturan tata bahasa mana yang akan digunakan nanti .
lihat juga,
Mengapa C ++ tidak dapat diuraikan dengan parser LR (1)?
Ingat bahwa tata bahasa bebas konteks tidak dapat menggambarkan SEMUA aturan sintaksis bahasa pemrograman. Misalnya, Tata bahasa atribut digunakan untuk memeriksa validitas jenis ekspresi.
Anda tidak bisa mendeskripsikan aturan berikut dengan tata bahasa bebas konteks: Sisi Kanan dari tugas harus dari jenis yang sama dari sisi Kiri.
sumber
Saya punya perasaan bahwa ada beberapa kebingungan antara definisi formal "sensitif terhadap konteks" dan penggunaan "sensitif konteks" secara informal. Yang pertama memiliki makna yang jelas. Yang terakhir digunakan untuk mengatakan "Anda perlu konteks untuk menguraikan input".
Ini juga ditanyakan di sini: Konteks-sensitivitas vs Ambiguitas .
Berikut ini adalah tata bahasa bebas konteks:
Ini ambigu, jadi untuk mengurai input "x" Anda memerlukan beberapa konteks (atau hidup dengan ambiguitas, atau memancarkan "Peringatan: E8271 - Input ambigu di baris 115"). Tapi itu jelas bukan tata bahasa konteks-sensitif.
sumber
Tidak ada bahasa seperti Algol yang bebas konteks, karena mereka memiliki aturan yang membatasi ekspresi dan pernyataan yang dapat muncul pengidentifikasi berdasarkan jenisnya, dan karena tidak ada batasan jumlah pernyataan yang dapat terjadi antara deklarasi dan penggunaan.
Solusi yang biasa adalah dengan menulis parser bebas konteks yang benar-benar menerima superset dari program yang valid dan menempatkan bagian peka konteks dalam kode "semantik" ad hoc yang dilampirkan pada aturan.
C ++ melampaui ini, berkat sistem template Turing-complete. Lihat Pertanyaan Stack Overflow 794015 .
sumber
Benar :)
J. Stanley Warford. Sistem komputer . Halaman 341-346.
sumber
Kadang-kadang lebih buruk: Apa yang orang maksud ketika mereka mengatakan C ++ memiliki "tata bahasa yang tidak dapat ditentukan"?
sumber
Itu peka konteks, seperti
a b(c);
memiliki dua parses- deklarasi dan variabel yang valid. Ketika Anda mengatakan "Ifc
is a type", itu konteks, di sana, dan Anda telah menggambarkan dengan tepat bagaimana C ++ sensitif terhadapnya. Jika Anda tidak memiliki konteks "Apa ituc
?" Anda tidak dapat menguraikan ini dengan jelas.Di sini, konteksnya dinyatakan dalam pilihan token - parser membaca pengidentifikasi sebagai token nama ketik jika nama jenis. Ini adalah resolusi paling sederhana, dan menghindari banyak kerumitan menjadi peka konteks (dalam hal ini).
Sunting: Ada, tentu saja, lebih banyak masalah sensitivitas konteks, saya hanya berfokus pada yang Anda tunjukkan. Template sangat tidak menyenangkan untuk ini.
sumber
a<b<c>>d
kan? (Contoh Anda sebenarnya adalah karya klasik dari C , di mana itu adalah satu - satunya penghalang untuk bebas konteks.)Produksi dalam standar C ++ ditulis bebas konteks, tetapi seperti yang kita semua tahu tidak benar-benar mendefinisikan bahasa secara tepat. Beberapa dari apa yang kebanyakan orang lihat sebagai ambiguitas dalam bahasa saat ini dapat (saya percaya) diselesaikan dengan jelas dengan tata bahasa yang peka konteks.
Untuk contoh yang paling jelas, mari kita mempertimbangkan paling menjengkelkan Parse:
int f(X);
. JikaX
adalah nilai, maka ini mendefinisikanf
sebagai variabel yang akan diinisialisasi denganX
. JikaX
adalah tipe, itu didefinisikanf
sebagai fungsi yang mengambil parameter tipe tunggalX
.Melihat itu dari sudut pandang tata bahasa, kita bisa melihatnya seperti ini:
Tentu saja, untuk menjadi sepenuhnya benar kita perlu menambahkan beberapa "barang" tambahan untuk menjelaskan kemungkinan campur tangan deklarasi jenis lain (yaitu, A dan B keduanya harus benar-benar menjadi "deklarasi termasuk deklarasi X sebagai ..." , atau sesuatu pada urutan itu).
Ini masih agak berbeda dari CSG pada umumnya (atau setidaknya yang saya ingat dari mereka). Ini tergantung pada tabel simbol yang sedang dibangun - bagian yang secara khusus mengenali
X
sebagai jenis atau nilai, bukan hanya beberapa jenis pernyataan sebelumnya, tetapi jenis pernyataan yang benar untuk simbol / pengidentifikasi yang tepat.Karena itu, saya harus melakukan beberapa upaya untuk memastikan, tetapi tebakan langsung saya adalah bahwa ini tidak benar-benar memenuhi syarat sebagai CSG, setidaknya seperti istilah yang biasanya digunakan.
sumber
Kasus paling sederhana dari tata bahasa non-konteks bebas melibatkan parsing ekspresi yang melibatkan template.
Ini dapat diuraikan sebagai salah satu
Atau
Kedua AST hanya dapat disatukan dengan memeriksa deklarasi 'a' - AST sebelumnya jika 'a' adalah templat, atau yang kedua jika tidak.
sumber
<
harus menjadi braket jika bisa (mis., Mengikuti pengenal yang menamai templat). C ++ 11 menambahkan persyaratan bahwa>
dan karakter pertama>>
ditafsirkan sebagai kurung dekat jika penggunaan itu masuk akal. Ini memengaruhi penguraian dia<b>c>
manaa
templat tetapi tidak berpengaruha<b<c>
.a();
(yang merupakan salah satuexpr.call
atauexpr.type.conv
)Templat C ++ telah terbukti Turing Powerfull. Meskipun bukan referensi formal, berikut adalah tempat untuk melihat dalam hal ini:
http://cpptruths.blogspot.com/2005/11/c-templates-are-turing-complete.html
Saya akan berani menebak (setua bukti CACM folkoric dan singkat menunjukkan bahwa ALGOL di tahun 60-an tidak dapat diwakili oleh CFG) dan mengatakan bahwa C ++ karena itu tidak dapat dengan benar diurai hanya oleh CFG. CFG, dalam hubungannya dengan berbagai mekanisme TP baik dalam melewati pohon atau selama acara pengurangan - ini adalah cerita lain. Secara umum, karena Masalah Pemutusan, ada beberapa program C ++ yang tidak dapat ditunjukkan benar / salah tetapi tetap benar / salah.
{PS- Sebagai penulis Meta-S (disebutkan oleh beberapa orang di atas) - Saya dapat dengan yakin mengatakan bahwa Thothic tidak mati, juga tidak ada perangkat lunak yang tersedia secara gratis. Mungkin saya telah menuliskan versi tanggapan saya ini sehingga saya tidak bisa dihapus atau memilih ke -3.}
sumber
C ++ tidak bebas konteks. Saya mempelajarinya beberapa waktu lalu di kompiler kuliah. Pencarian cepat memberi tautan ini, di mana bagian "Sintaks atau semantik" menjelaskan mengapa C dan C ++ tidak bebas konteks:
Wikipedia Talk: Tata bahasa bebas konteks
Salam,
Ovan
sumber
Jelas, jika Anda menjawab pertanyaan itu kata demi kata, hampir semua bahasa dengan pengidentifikasi peka terhadap konteks.
Orang perlu tahu apakah pengenal adalah nama jenis (nama kelas, nama yang diperkenalkan oleh typedef, parameter templat nama samaran), nama templat atau nama lain untuk dapat dengan benar beberapa penggunaan pengidentifikasi. Contohnya:
adalah cast if
name
adalah nama jenis dan panggilan fungsi ifname
adalah nama fungsi. Kasus lain adalah apa yang disebut "parse paling menjengkelkan" di mana tidak mungkin untuk membedakan definisi variabel dan deklarasi fungsi (ada aturan yang mengatakan itu adalah deklarasi fungsi).Kesulitan itu telah memperkenalkan kebutuhan
typename
dantemplate
dengan nama-nama yang tergantung. Sisa dari C ++ tidak sensitif konteks sejauh yang saya tahu (yaitu mungkin untuk menulis tata bahasa bebas konteks untuk itu).sumber
Tautan yang benar adalah parsing enigines
Meta-S adalah milik perusahaan mati bernama Thothic. Saya dapat mengirim salinan gratis Meta-S kepada siapa pun yang tertarik dan saya telah menggunakannya dalam penelitian parsing. Harap perhatikan "tata bahasa pseudoknot" yang termasuk dalam folder contoh ditulis oleh non-bioinformatika, programmer amature dan pada dasarnya tidak berfungsi. Tata bahasa saya mengambil pendekatan yang berbeda dan bekerja dengan baik.
sumber
Masalah besar di sini adalah bahwa istilah "bebas konteks" dan "peka konteks" sedikit tidak intuitif dalam ilmu komputer. Untuk C ++, sensitivitas konteks terlihat sangat mirip dengan ambiguitas, tetapi itu tidak selalu benar dalam kasus umum.
Dalam C / ++, pernyataan if hanya dibolehkan di dalam tubuh fungsi. Itu tampaknya membuatnya sensitif terhadap konteks, bukan? Ya tidak. Tata bahasa bebas konteks sebenarnya tidak membutuhkan properti tempat Anda dapat mencabut beberapa baris kode dan menentukan apakah itu valid. Sebenarnya bukan itu arti bebas konteks. Ini benar-benar hanya label yang secara tidak langsung menyiratkan sesuatu yang terkait dengan seperti apa suaranya.
Sekarang, jika pernyataan di dalam fungsi tubuh diuraikan secara berbeda tergantung pada sesuatu yang didefinisikan di luar leluhur gramatikal langsung (misalnya apakah pengidentifikasi menggambarkan suatu jenis atau variabel), seperti dalam
a * b;
kasus, maka, pada kenyataannya, konteks-sensitif. Tidak ada ambiguitas aktual di sini; itu akan diurai sebagai deklarasi pointer jikaa
merupakan tipe dan perkalian sebaliknya.Menjadi peka konteks tidak selalu berarti "sulit untuk diuraikan". C sebenarnya tidak terlalu sulit karena
a * b;
"ambiguitas" yang terkenal itu dapat diselesaikan dengan tabel simbol yang mengandungtypedef
s yang ditemukan sebelumnya. Itu tidak memerlukan instantiasi template sewenang-wenang (yang telah terbukti Turing Lengkap) untuk menyelesaikan kasus seperti C ++ pada kesempatan tertentu. Sebenarnya tidak mungkin untuk menulis program C yang tidak akan dikompilasi dalam jumlah waktu yang terbatas walaupun ia memiliki sensitivitas konteks yang sama seperti yang dilakukan oleh C ++.Python (dan bahasa spasi-spasi sensitif lainnya) juga tergantung pada konteks, karena ia membutuhkan keadaan dalam lexer untuk menghasilkan token indent dan dedent, tetapi itu tidak membuat lebih sulit untuk diuraikan daripada tata bahasa LL-1 yang khas. Ini sebenarnya menggunakan parser-generator, yang merupakan bagian dari mengapa Python memiliki pesan kesalahan sintaksis yang tidak informatif. Penting juga untuk dicatat di sini bahwa tidak ada "ambiguitas" seperti
a * b;
masalah dalam Python, memberikan contoh konkret yang baik dari bahasa konteks-sensitif tanpa tata bahasa "ambigu" (seperti yang disebutkan dalam paragraf pertama).sumber
Jawaban ini mengatakan C ++ tidak bebas konteks ... ada implikasi (bukan oleh penjawab) yang tidak dapat diuraikan, dan jawabannya menawarkan contoh kode yang sulit yang menghasilkan program C ++ yang tidak valid jika konstanta tertentu bukan bilangan prima.
Seperti yang telah diamati orang lain, pertanyaan tentang apakah bahasa itu peka konteks / bebas berbeda dari pertanyaan yang sama tentang tata bahasa tertentu.
Untuk mengatur pertanyaan tentang parseabilitas untuk beristirahat, saya menawarkan bukti empiris bahwa ada tata bahasa bebas konteks untuk C ++, yang dapat digunakan untuk menghasilkan AST untuk parse bebas konteks dari teks sumber dengan sebenarnya menguraikannya dengan GLR yang ada alat berbasis -parser yang didorong oleh tata bahasa eksplisit.
Ya, itu berhasil dengan "menerima terlalu banyak"; tidak semua yang diterimanya adalah program C ++ yang valid, oleh karena itu diikuti dengan pemeriksaan tambahan (pemeriksaan jenis). Dan ya, pemeriksa tipe mungkin mengalami masalah komputasi. Dalam praktiknya alat tidak memiliki masalah ini; jika orang menulis program seperti itu, tidak ada yang mau dikompilasi. (Saya pikir standar sebenarnya membatasi jumlah perhitungan yang dapat Anda lakukan dengan membuka kerangka, jadi sebenarnya perhitungannya sebenarnya terbatas tetapi mungkin cukup besar).
Jika yang Anda maksud adalah, tentukan apakah program sumber adalah anggota dari set program sumber C ++ yang valid , maka saya akan setuju bahwa masalahnya jauh lebih sulit. Tapi itu tidak parsing itu masalahnya.
Alat ini mengatasi masalah ini dengan mengisolasi parsing dari jenis-memeriksa program parsing. (Di mana ada beberapa interpretasi dengan tidak adanya konteks, ia mencatat simpul ambiguitas di pohon parse dengan beberapa kemungkinan parse; pengecekan tipe memutuskan mana yang benar dan menghilangkan sub pohon yang tidak valid). Anda dapat melihat pohon parse (sebagian) dalam contoh di bawah ini; keseluruhan pohon terlalu besar untuk dapat dimasukkan dalam jawaban SO. Catatan Anda mendapatkan pohon parse apakah nilai 234797 atau 234799 digunakan.
Menjalankan nama / jenis penyelesai alat di atas AST dengan nilai asli 234799 berhasil. Dengan nilai 234797 pemecah nama gagal (seperti yang diharapkan) dengan pesan kesalahan, "typen bukan tipe." dan dengan demikian versi itu bukan program C ++ yang valid.
sumber