Keuntungan Antlr (dibandingkan katakanlah, lex / yacc / bison) [ditutup]

143

Saya telah menggunakan lex dan yacc (biasanya bison) di masa lalu untuk berbagai proyek, biasanya penerjemah (seperti subset dari EDIF yang dialirkan ke aplikasi EDA). Selain itu, saya harus mendukung kode berdasarkan tata bahasa lex / yacc sejak dekade yang lalu. Jadi saya tahu jalan saya di sekitar alat, meskipun saya bukan ahli.

Saya telah melihat komentar positif tentang Antlr di berbagai forum di masa lalu, dan saya ingin tahu apa yang mungkin saya lewatkan. Jadi, jika Anda telah menggunakan keduanya, tolong katakan padaku apa yang lebih baik atau lebih maju di Antlr. Kendala saya saat ini adalah bahwa saya bekerja di toko C ++, dan produk apa pun yang kami kirimkan tidak akan menyertakan Java, sehingga parser yang dihasilkan harus mengikuti aturan itu.

Don Wakefield
sumber

Jawaban:

145

Pembaruan / peringatan: Jawaban ini mungkin kedaluwarsa!


Satu perbedaan utama adalah bahwa ANTLR menghasilkan parser LL (*), sedangkan YACC dan Bison keduanya menghasilkan parser yang LALR. Ini adalah perbedaan penting untuk sejumlah aplikasi, operator yang paling jelas:

expr ::= expr '+' expr
       | expr '-' expr
       | '(' expr ')'
       | NUM ;

ANTLR sepenuhnya tidak mampu menangani tata bahasa apa adanya. Untuk menggunakan ANTLR (atau generator parser LL lainnya), Anda perlu mengubah tata bahasa ini menjadi sesuatu yang tidak rekursif kiri. Namun, Bison tidak memiliki masalah dengan tata bahasa bentuk ini. Anda perlu mendeklarasikan '+' dan '-' sebagai operator asosiatif kiri, tetapi itu tidak sepenuhnya diperlukan untuk rekursi kiri. Contoh yang lebih baik mungkin dikirim:

expr ::= expr '.' ID '(' actuals ')' ;

actuals ::= actuals ',' expr | expr ;

Perhatikan bahwa keduanya expr danactuals aturannya bersifat rekursif kiri. Ini menghasilkan AST yang jauh lebih efisien ketika tiba saatnya untuk pembuatan kode karena ia menghindari kebutuhan akan banyak register dan tumpahan yang tidak perlu (pohon yang condong ke kiri dapat runtuh sedangkan pohon yang condong ke kanan tidak bisa).

Dalam hal selera pribadi, saya pikir bahwa tata bahasa LALR jauh lebih mudah untuk dibangun dan di-debug. Kelemahannya adalah Anda harus berurusan dengan kesalahan yang agak samar seperti mengurangi-shift dan (mengurangi yang ditakuti) mengurangi-mengurangi. Ini adalah kesalahan yang ditangkap Bison saat membuat parser, sehingga tidak memengaruhi pengalaman pengguna akhir, tetapi ini dapat membuat proses pengembangan menjadi sedikit lebih menarik. ANTLR umumnya dianggap lebih mudah digunakan daripada YACC / Bison karena alasan ini.

Daniel Spiewak
sumber
2
Jadi keuntungan besar dari Antlr dalam persepsi Anda adalah bahwa ia menghasilkan lebih sedikit kesalahan seperti sr dan rr selama tahap konstruksi? Saya berharap saya akan mencobanya, tetapi mungkin akhirnya akan bertahan dengan apa yang saya tahu ...
Don Wakefield
1
Ya, cukup banyak. :-) Saya juga tidak setuju dengan pendapat umum bahwa ANTLR lebih mudah daripada Bison, jadi saya pikir saya akan setuju dengan keputusan Anda.
Daniel Spiewak
2
Apakah aturan 'aktual' memerlukan aturan kedua untuk menunjukkan bahwa 'expr' sederhana adalah aktual? Kalau tidak, penjelasan yang bagus.
Jonathan Leffler
8
Komentar lain yang saya temukan baru-baru ini, meskipun berumur satu dekade, membuat pengamatan yang masuk akal terhadap keluaran : compilers.iecc.com/comparch/article/98-11-040 : "ANTLR / PCCTS adalah LL yang membuat penulisan tata bahasa lebih sulit, tetapi kode yang dihasilkan dapat dibaca. Menjadi LALR (tentu saja Anda tahu itu) membuat penulisan tata bahasa lebih mudah, tetapi kode yang dihasilkan mungkin juga hieroglif. "
Don Wakefield
72
Saya baru saja menyelesaikan dukungan rekursi kiri langsung untuk ANTLR rilis berikutnya v3.4. Menangani aturan ekspresi LR dan hal-hal serupa seperti aturan deklarator C. :)
Terence Parr
117

Perbedaan paling signifikan antara YACC / Bison dan ANTLR adalah jenis tata bahasa yang dapat diproses oleh alat ini. YACC / Bison menangani tata bahasa LALR, ANTLR menangani tata bahasa LL.

Seringkali, orang yang telah bekerja dengan tata bahasa LALR untuk waktu yang lama, akan merasa bekerja dengan tata bahasa LL lebih sulit dan sebaliknya. Itu tidak berarti bahwa tata bahasa atau alat secara inheren lebih sulit untuk dikerjakan. Alat mana yang Anda temukan lebih mudah digunakan sebagian besar akan terbiasa dengan jenis tata bahasa.

Sejauh keuntungan pergi, ada aspek di mana tata bahasa LALR memiliki keunggulan dibandingkan tata bahasa LL dan ada aspek lain di mana tata bahasa LL memiliki keunggulan dibandingkan tata bahasa LALR.

YACC / Bison menghasilkan parser yang digerakkan oleh tabel, yang berarti "logika pemrosesan" terkandung dalam data program parser, tidak begitu banyak dalam kode parser. Bayarannya adalah bahwa bahkan parser untuk bahasa yang sangat kompleks memiliki jejak kode yang relatif kecil. Ini lebih penting pada 1960-an dan 1970-an ketika perangkat keras sangat terbatas. Generator parser yang digerakkan oleh tabel kembali ke era ini dan jejak kode kecil adalah persyaratan utama saat itu.

ANTLR menghasilkan parser keturunan rekursif, yang berarti "logika pemrosesan" terkandung dalam kode parser, karena setiap aturan produksi tata bahasa diwakili oleh fungsi dalam kode parser. Hasilnya adalah bahwa lebih mudah untuk memahami apa yang dilakukan parser dengan membaca kodenya. Juga, parser keturunan rekursif biasanya lebih cepat daripada yang digerakkan oleh tabel. Namun, untuk bahasa yang sangat kompleks, jejak kode akan lebih besar. Ini adalah masalah di tahun 1960-an dan 1970-an. Saat itu, hanya bahasa yang relatif kecil seperti Pascal misalnya yang diimplementasikan dengan cara ini karena keterbatasan perangkat keras.

Parser yang dihasilkan ANTLR biasanya di sekitar 10.000 baris kode dan banyak lagi. Pengurai keturunan rekursif tulisan tangan sering berada di stadion baseball yang sama. Kompiler Oberon milik Wirth mungkin adalah yang paling ringkas dengan sekitar 4000 baris kode termasuk pembuatan kode, tetapi Oberon adalah bahasa yang sangat kompak dengan hanya sekitar 40 aturan produksi.

Seperti yang telah ditunjukkan oleh seseorang, nilai tambah besar untuk ANTLR adalah alat IDE grafis, yang disebut ANTLRworks. Ini adalah laboratorium desain tata bahasa dan bahasa yang lengkap. Ini memvisualisasikan aturan tata bahasa Anda saat Anda mengetiknya dan jika menemukan konflik, itu akan menunjukkan kepada Anda secara grafis apa konflik itu dan apa yang menyebabkannya. Ia bahkan dapat secara otomatis memperbaiki dan menyelesaikan konflik seperti rekursi kiri. Setelah Anda memiliki tata bahasa bebas konflik, Anda dapat membiarkan ANTLRworks mengurai file input bahasa Anda dan membangun parse tree dan AST untuk Anda dan memperlihatkan pohon tersebut secara grafis dalam IDE. Ini adalah keuntungan yang sangat besar karena dapat menghemat banyak waktu kerja: Anda akan menemukan kesalahan konseptual dalam desain bahasa Anda sebelum Anda mulai membuat kode! Saya belum menemukan alat semacam itu untuk tata bahasa LALR, sepertinya tidak ada alat seperti itu.

Bahkan untuk orang-orang yang tidak ingin membuat parser mereka tetapi memberikan kode mereka, ANTLRworks adalah alat yang hebat untuk desain / prototipe bahasa. Sangat mungkin alat terbaik yang tersedia. Sayangnya, itu tidak membantu Anda jika Anda ingin membuat parser LALR. Beralih dari LALR ke LL hanya untuk memanfaatkan ANTLRwork mungkin bermanfaat, tetapi bagi sebagian orang, beralih jenis tata bahasa bisa menjadi pengalaman yang sangat menyakitkan. Dengan kata lain: YMMV.

trijezdci
sumber
4
menyukainya karena menjelaskan sejarah di balik mekanisme yang berbeda yang membuat orang mengerti dengan segera
zinking
35

Beberapa keuntungan untuk ANTLR:

  • dapat menampilkan parser dalam berbagai bahasa - Java tidak diperlukan untuk menjalankan parser yang dihasilkan.
  • GUI yang luar biasa memudahkan proses debug tata bahasa (mis. Anda dapat melihat hak AST yang dihasilkan di GUI, tidak perlu alat tambahan)
  • Kode yang dihasilkan sebenarnya dapat dibaca oleh manusia (ini adalah salah satu tujuan ANTLR) dan fakta bahwa ia menghasilkan parser LL pasti membantu dalam hal ini.
  • definisi terminal juga bebas konteks (bukan kebalikan dari regex di (f) lex) - sehingga memungkinkan, misalnya, definisi terminal yang mengandung tanda kurung tertutup dengan benar

$ 0,02 saya

Cristian Diaconescu
sumber
9

Keuntungan lain dari ANTRL adalah Anda dapat menggunakan ANTLRWORKS , meskipun saya tidak dapat mengatakan bahwa ini adalah keuntungan yang ketat, karena mungkin ada alat serupa untuk generator lain juga.

John dengan wafel
sumber
9
  • Bison dan Flex menghasilkan jejak memori yang lebih kecil, tetapi Anda tidak memiliki IDE grafis.
  • antlr menggunakan lebih banyak memori, tetapi Anda memiliki antlrworks, sebuah IDE grafis.

Penggunaan memori Bison / Flex biasanya sekitar satu mbyte atau lebih. Bandingkan dengan antlr - dengan asumsi ia menggunakan memori 512 byte untuk setiap token dalam file yang ingin Anda parse. 4 juta token dan Anda kehabisan memori virtual pada sistem 32-bit.

Jika file yang ingin Anda parse besar, antlr mungkin kehabisan memori, jadi jika Anda hanya ingin mem-parsing file konfigurasi, itu akan menjadi solusi yang layak. Kalau tidak, jika Anda ingin mem-parsing file dengan banyak data, coba Bison.

hanya aku
sumber
7
Saya penasaran. Bisakah Anda menunjukkan dokumentasi yang menjelaskan konsumsi 512 byte memori per token? Saya tidak ingat melihat diskusi itu. Pilihan kata kunci Google saya juga tidak memberi saya kepuasan ...
Don Wakefield
2
Apakah Anda berbicara tentang jejak memori generator parser saat membuat parser, atau apakah Anda berbicara tentang jejak memori parser yang dihasilkan saat mengurai input untuk bahasa sumber? Jutaan token dalam tata bahasa akan benar-benar gila. Anda harus dikurung di rumah sakit jiwa jika Anda serius mencoba menjual ide seperti itu. Adapun file input untuk parser itu sendiri, mungkin ada kasus-kasus di mana ini mungkin memiliki jumlah token yang sangat besar, tetapi sebagian besar bahasa bersifat modular, Anda tidak mem-parsing seluruh input dalam satu file, modul individual lebih kecil.
trijezdci