Antlr'ın avantajları (diyelim ki lex / yacc / bison) [kapalı]


143

Geçmişte lex ve yacc (daha çok bizon) kullandım çeşitli projeler, genellikle çevirmenler (bir EDA uygulamasına aktarılan EDIF alt kümesi gibi). Ayrıca, onlarca yıl geriye giden lex / yacc dilbilgisi dayalı kodu desteklemek zorunda kaldı. Bu yüzden uzman olmamamıza rağmen araçların etrafında yolumu biliyorum.

Geçmişte çeşitli forumlarda Antlr hakkında olumlu yorumlar gördüm ve neyi kaçırdığımı merak ediyorum. Her ikisini de kullandıysanız, lütfen Antlr'da neyin daha iyi veya daha gelişmiş olduğunu söyleyin. Şu anki kısıtlarım bir C ++ mağazasında çalışmam ve gönderdiğimiz herhangi bir ürün Java içermeyecek, bu nedenle ortaya çıkan ayrıştırıcılar bu kurala uymak zorunda kalacak.

Yanıtlar:


145

Güncelleme / uyarı: Bu cevap güncel olmayabilir!


Önemli bir fark, ANTLR'nin bir LL (*) ayrıştırıcısı oluşturması, YACC ve Bison ise LALR olan ayrıştırıcıları üretmesidir. Bu, bir dizi uygulama için önemli bir ayrımdır, en belirgin olanı operatörlerdir:

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

ANTLR bu dilbilgisini olduğu gibi kullanamaz. ANTLR'yi (veya başka bir LL ayrıştırıcı oluşturucusunu) kullanmak için, bu dilbilgisini sol özyinelemeli olmayan bir şeye dönüştürmeniz gerekir. Ancak, Bison'un bu formdaki gramerlerle bir sorunu yoktur. Sol ilişkisel operatörler olarak '+' ve '-' bildirmeniz gerekir, ancak sol özyineleme için kesinlikle gerekli değildir. Daha iyi bir örnek gönderilebilir:

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

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

Bildirim her iki exprve actualskurallar sol özyinelemeli edilir. Bu, kod üretme zamanı geldiğinde çok daha verimli bir AST üretir, çünkü birden fazla kayıt ve gereksiz dökülme ihtiyacını ortadan kaldırır (sağa yaslanan ağaç çökebilirken sağa yaslanan ağaç yapamaz).

Kişisel zevk açısından, LALR dilbilgisi oluşturmak ve hata ayıklamak çok daha kolay. Dezavantajı, shift-reduce ve (dreaded) reduce-reduce gibi biraz şifreli hatalarla uğraşmanızdır. Bunlar, Bison'un ayrıştırıcıyı oluştururken yakaladığı hatalardır, bu nedenle son kullanıcı deneyimini etkilemez, ancak geliştirme sürecini biraz daha ilginç hale getirebilir. ANTLR'nin tam olarak bu nedenle YACC / Bison'dan daha kolay olduğu düşünülmektedir.


2
Yani Antlr'ın sizin algınızdaki büyük, muhtemelen tek, avantajı, inşaat aşamasında sr ve rr gibi daha az hata üretmesidir? Ben bir deneyeceğim bekliyoruz, ama muhtemelen bildiklerim ile yapışacak ...
Don Wakefield

1
Evet, işte bu kadar. :-) Ben de ANTLR'nin Bison'dan daha kolay olduğuna dair popüler düşünceye gerçekten katılmıyorum, bu yüzden kararınıza katılıyorum.
Daniel Spiewak

2
'Gerçekler' kuralı, basit bir 'ifade' ifadesinin gerçek olduğunu gösteren ikinci bir kurala mı ihtiyaç duyuyor? Aksi takdirde, güzel bir açıklama.
Jonathan Leffler

8
Son zamanlarda bulduğum bir başka yorum, on yıl eski olmasına rağmen, makul bir çıktı gözlemi yapıyor : compilers.iecc.com/comparch/article/98-11-040 : "ANTLR / PCCTS dilbilgisi yazmayı zorlaştıran LL'dir, ancak oluşturulan kod okunabilir. Yat LALR (tabii ki bunu biliyorsunuz) dilbilgisi yazmayı kolaylaştırıyor, ancak üretilen kod hiyeroglif de olabilir. "
Don Wakefield

72
ANTLR sonraki sürüm v3.4 için hemen sol özyineleme desteğini tamamladım. LR ifade kurallarını ve C bildirim kuralları gibi benzer şeyleri işler. :)
Terence Parr

117

YACC / Bison ve ANTLR arasındaki en önemli fark, bu araçların işleyebileceği dilbilgisi türüdür. YACC / Bizon LALR dilbilgisi tanıtıcısı, ANTLR LL dilbilgisi tanıtıcısı.

Çoğu zaman, LALR gramerleriyle uzun süredir çalışan insanlar, LL gramerleriyle çalışmayı daha zor ve tam tersini bulacaklardır. Bu, gramerlerin veya araçların çalışılması doğal olarak daha zor olduğu anlamına gelmez. Hangi aracı daha kolay bulacağınız çoğunlukla gramer türüne aşina olacaktır.

Avantajlara gelince, LALR gramerlerinin LL gramerlerine göre avantajları olduğu yönler vardır ve LL gramerlerinin LALR gramerlerine göre avantajları olduğu diğer hususlar da vardır.

YACC / Bison tablo tabanlı ayrıştırıcılar oluşturur, yani "işleme mantığı" ayrıştırıcı kodunda değil, ayrıştırıcı programının verilerinde bulunur. Ödeme, çok karmaşık bir dil için bir ayrıştırıcının bile nispeten küçük bir kod ayak izine sahip olmasıdır. Bu, donanımın çok sınırlı olduğu 1960'larda ve 1970'lerde daha önemliydi. Tablo güdümlü ayrıştırıcı jeneratörler bu döneme geri döner ve o zamanlar küçük kod ayak izi temel bir gereklilikti.

ANTLR, özyinelemeli iniş ayrıştırıcıları üretir; bu, dilbilgisinin her üretim kuralı ayrıştırıcının kodundaki bir işlevle temsil edildiğinden, ayrıştırıcının kodunda "işleme mantığı" nın bulunduğu anlamına gelir. Ödeme, ayrıştırıcının kodunu okuyarak ne yaptığını anlamanın daha kolay olmasıdır. Ayrıca, özyinelemeli iniş ayrıştırıcıları tipik olarak tablo ile çalışanlardan daha hızlıdır. Ancak, çok karmaşık diller için, kod ayak izi daha büyük olacaktır. Bu 1960 ve 1970'lerde bir sorundu. O zamanlar, örneğin Pascal gibi nispeten küçük diller, donanım sınırlamaları nedeniyle bu şekilde uygulandı.

ANTLR tarafından üretilen ayrıştırıcılar tipik olarak 10.000 kod satırı ve daha fazlası civarındadır. El yazısı özyinelemeli iniş ayrıştırıcılar genellikle aynı balo parkındadır. Wirth'in Oberon derleyicisi belki de kod üretimi de dahil olmak üzere yaklaşık 4000 satır kod içeren en kompakt olanıdır, ancak Oberon sadece yaklaşık 40 üretim kuralına sahip çok kompakt bir dildir.

Birisinin işaret ettiği gibi, ANTLR için büyük bir artı, ANTLRworks adı verilen grafiksel IDE aracıdır. Tam bir dilbilgisi ve dil tasarım laboratuvarıdır. Siz yazarken dilbilgisi kurallarınızı görselleştirir ve herhangi bir çakışma bulursa, size grafiksel olarak çatışmanın ne olduğunu ve neye neden olduğunu gösterir. Sol özyineleme gibi çakışmaları otomatik olarak yeniden düzenleyebilir ve çözebilir. Çakışmasız bir dilbilgisine sahip olduğunuzda, ANTLRworks'ün dilinizin bir giriş dosyasını ayrıştırmasına ve sizin için bir ayrıştırma ağacı ve AST oluşturmasına ve ağacı IDE'de grafik olarak göstermesine izin verebilirsiniz. Bu çok büyük bir avantajdır, çünkü saatlerce çalışmanızı kurtarabilir: Kodlamaya başlamadan önce dil tasarımınızda kavramsal hatalar bulacaksınız! LALR gramerleri için böyle bir araç bulamadım, öyle bir araç yok gibi görünüyor.

Ayrıştırıcılarını oluşturmak istemeyen, ancak bunları elle kodlayan kişiler için bile, ANTLRworks dil tasarımı / prototipleme için harika bir araçtır. Muhtemelen mevcut en iyi araç. Ne yazık ki, LALR ayrıştırıcıları oluşturmak istiyorsanız bu size yardımcı olmaz. ANTLRworks'ten yararlanmak için LALR'den LL'ye geçmek faydalı olabilir, ancak bazı insanlar için dilbilgisi türlerini değiştirmek çok acı verici bir deneyim olabilir. Başka bir deyişle: YMMV.


4
çünkü insanların hemen anlaşılmasını sağlayan farklı mekanizmaların arkasındaki tarihi açıklıyor
Haziran'da

35

ANTLR için birkaç avantaj:

  • ayrıştırıcıları çeşitli dillerde çıktılayabilir - oluşturulan ayrıştırıcıyı çalıştırmak için Java gerekmez.
  • Harika GUI dilbilgisi hata ayıklamasını kolaylaştırır (örneğin, oluşturulan AST'leri GUI'de doğru görebilirsiniz, ekstra bir araç gerekmez)
  • Oluşturulan kod aslında insan tarafından okunabilir (ANTLR'nin amaçlarından biridir) ve LL ayrıştırıcıları oluşturması kesinlikle bu konuda yardımcı olur.
  • terminallerin tanımı da bağlamsızdır ((f) lex'daki normal ifadenin aksine) - böylece, örneğin, düzgün kapatılmış parantezler içeren terminallerin tanımlanmasına izin verir

Benim .02 $


9

ANTRL bir diğer avantajı da kullanabilirsiniz olmasıdır ANTLRWorks benzer diğer jeneratörler için araçlar da orada olabilir gibi bu sıkı bir avantaj olduğunu söyleyemeyiz ancak.


9
  • Bison ve Flex daha az bellek kaplamasına neden olur, ancak grafiksel IDE'niz yoktur.
  • antlr daha fazla bellek kullanır, ancak grafiksel bir IDE olan antlrworks'ünüz vardır.

Bison / Flex bellek kullanımı tipik olarak bir mbayttır. Ayrıştırmak istediğiniz dosyadaki her jeton için 512 bayt bellek kullandığını varsayarak antlr ile karşılaştırın. 4 milyon jeton ve 32 bit sistemde sanal bellek yetersiz.

Ayrıştırmak istediğiniz dosya büyükse, antlr'ın belleği yetersiz olabilir, bu yüzden sadece bir yapılandırma dosyasını ayrıştırmak istiyorsanız, geçerli bir çözüm olacaktır. Aksi takdirde, çok fazla veri içeren bir dosyayı ayrıştırmak istiyorsanız Bison'u deneyin.


7
Merak ediyorum. Jeton başına 512 bayt bellek tüketimini açıklayan belgelere işaret edebilir misiniz? Bu tartışmayı gördüğümü hatırlamıyorum. Google anahtar kelime seçimim de bana memnuniyet vermiyor ...
Don Wakefield

2
Bir ayrıştırıcı oluştururken ayrıştırıcı üretecinin bellek ayak izinden mi bahsediyorsunuz, yoksa kaynak dil için girdi ayrıştırılırken oluşturulan ayrıştırıcının bellek ayak izinden mi bahsediyorsunuz? Bir dilbilgisinde milyonlarca jeton kesinlikle deli olur. Eğer böyle bir fikri ciddiye almaya çalışıyorsanız, zihinsel bir kurumda kilitli olmalısınız. Ayrıştırıcının kendisi için girdi dosyalarına gelince, bunların çok fazla sayıda jetonu olabileceği durumlar olabilir, ancak çoğu dil modülerdir, tüm girdiyi tek bir dosyada ayrıştırmazsınız, ayrı modüller daha küçüktür.
trijezdci
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.