Derleyici Derleyici Yazma - Kullanım ve Özellikler Hakkında Bilgi


10

Bu, dil tasarımında kullanılan kavramları bir çerçeve şeklinde soyutlamayı amaçlayan Soyutlama Projesi'nin kardeş projesine odaklanan bir dizi sorunun bir parçasıdır. Kardeş proje, maçlarda kod enjeksiyonu kullanılmadan dilbilgisi dosyalarından bir ayrıştırıcı oluşturmayı amaçlayan OILexer olarak adlandırılır.

Bu sorularla ilişkili, yapısal yazmayla ilgili diğer bazı sayfalar burada görülebilir ve kullanım kolaylığı burada bulunabilir . Çerçeve ve gönderilecek uygun yerle ilgili bir soruşturmayla ilişkili meta-konu burada bulunabilir .

Belirli bir dilbilgisinden ayrıştırma ağacını ayıklamaya başlamak üzere olduğum noktaya geliyorum, ardından ileri yolları (ANTLR 4'ün LL (*) benzeri) ayırt etmek için DFA kullanan bir Yinelenen İniş ayrıştırıcısı izliyorum. içgörü kazanmak için açacağımı düşündüm.

Ayrıştırıcı derleyicide ne tür özellikler idealdir?

Şimdiye kadar neler uygulandığına dair kısa bir genel bakış:

  1. Şablonlar
  2. Belirli bir noktada neyin geçerli olduğunu bilerek, ileriye bakın.
  3. Değişmezleri kurallar dahilinde alarak ve hangi simgeden geldiklerine karar vererek 'Deliteralization' kuralını uygulayın.
  4. Belirsiz Otomata
  5. Deterministik Otomata
  6. Jeton tanıma için basit sözcüksel durum makinesi
  7. Jeton otomasyon yöntemleri:
    • Tara - yorumlar için yararlıdır: Yorum: = "/ *" Tara ("* /");
    • Çıkarma - Tanımlayıcılar için kullanışlıdır: Tanımlayıcı: = Çıkarma (IdentifierBody, Keywords);
      • Tanımlayıcının anahtar kelimeleri kabul etmediğinden emin olun.
    • Encode - Bir otomasyonu X serisi temel N geçiş sayısı olarak kodlar.
      • UnicodeEscape: = "\\ u" BaseEncode (IdentifierCharNoEscape, 16, 4);
        • Onaltılı 4 geçişli onaltılık bir unicode kaçış yapar. Bu ve: [0-9A-Fa-f] {4} arasındaki fark, Kodlama ile sonuçlanan otomasyonun, izin verilen onaltılık değerler kümesini IdentifierCharNoEscape kapsamıyla sınırlandırmasıdır. Bu yüzden \ u005c verirseniz, kodlama sürümü değeri kabul etmez. Bunun gibi şeylerin ciddi bir uyarısı var: Tutumlu kullanın. Ortaya çıkan otomasyon oldukça karmaşık olabilir.

Uygulanmayan şey CST üretimidir, bu çalışmayı elde etmek için Deterministik otomasyonları uygun bağlamı taşıyacak şekilde ayarlamam gerekir.

İlgilenenler için, T * y♯ projesinin orijinal formunun oldukça basılı bir resmini yükledim . Her dosya diğer her dosyaya bağlanmalı, onları takip etmek için bireysel kurallara bağlanmaya başladım, ancak çok uzun sürecekti (otomatikleştirmek daha kolay olurdu!)

Daha fazla içeriğe ihtiyaç duyulursa, lütfen buna göre gönderin.

Düzenleme 5-14-2013 : Belirli bir dilde durum makineleri için GraphViz grafikleri oluşturmak için kod yazdım. İşte AssemblyPart'ın bir GraphViz digrafisi . Dil açıklamasında bağlanan üyelerin göreli klasörlerinde bu kuralın digrafisi ile bir rulename.txt olmalıdır. Örneği yayınladığımdan beri bazı dil açıklamaları değişti, bunun nedeni gramerle ilgili şeyleri basitleştirmek. İşte ilginç bir grafik resmi .


8
Duvar metni. Bunu yanlış anlamayın, iyice açıklanmış bir sorunu takdir ediyorum. Bu durumda, biraz fazla ayrıntılıdır. Topladığımdan, bir dilbilgisi ayrıştırıcısına hangi özelliklerin dahil edilmesi gerektiğini veya sıfırdan başlamadan nasıl yapılacağını soruyorsunuz? Lütfen aşağıdaki soruları yanıtlamak için düzenleyin (yeniden yazmanız gerekmez, özetin sonuna ekleyin): Sorununuz nedir? Sorununuza olası çözümlerde hangi kısıtlamalara tabi olursunuz (hızlı olmalı, LL * vb. Olmalıdır)?
Neil

1
Özellik setiyle ilgili bilgi istiyorum. Odak kullanım kolaylığıdır. Zorluk, projeyi bilmeyen birisine, projeye ilişkin kavrayışa sahip olmalarıdır, böylece odaklanmaları konusunda bilgilendirilirler. 'Nasıl yapılır' diye sormuyorum, kullanılabilirlikle ilgili soruyorum. Sorunun nasıl düzeltileceğine dair öneriler takdir edilmektedir.
Allen Clark Copeland Jr

1
Bana göre, projenin ne hakkında olduğu belli değil. Örneğin, yacc günlerinden bu yana birçok ayrıştırıcı üreticisi gördük. OILexer'ınızda farklı olan nedir? Yeni nedir?
Ingo

1
Bu projenin amacı ayrıştırıcı üretimini basitleştirmektir. YACC / Bison ve FLEX / LEX'e benzer bir evet. En büyük fark, bu programlarda yer alan karmaşıklıktan kaçınmaktır. İşleri basit ve mesele haline getirmek ana hedeftir. Bu yüzden garip bölümlemeden yoksun bir format oluşturdum, ancak daha ziyade amaç onu düzenli programlamaya benzer hale getirmektir: sadece dil gelişimine özgü. Jetonlar adlarından sonra ': =' kullanılarak, kurallar adlarından sonra :: = kullanılarak tanımlanır. Şablonlar, kural sözdizimini paylaştıkları için argümanları için '<' ve '>' ifadelerini, ardından ":: =" kullanırlar.
Allen Clark Copeland Jr

3
Ayrıştırmadaki bu cehennem odağı yanlış yerleştirilmiş gibi görünüyor; bu iyi çözülmüş bir sorundur ve programlama dillerini işlemek için neye ihtiyaç duyduğunuzu göstermez. Google, "ayrıştırmadan sonra yaşam" konulu makalem için.
Ira Baxter

Yanıtlar:


5

Bu mükemmel bir soru.

Son zamanlarda birçok ayrıştırma üzerinde çalışıyorum ve IMHO bazı temel özellikler:

  • Programlı bir API - ideal olarak sadece bir kütüphaneyi içe aktararak bir programlama dilinde kullanılabilir. GUI veya BNF benzeri bir arayüze de sahip olabilir, ancak programlı olan anahtardır, çünkü takımınızı, IDE'nizi, statik analizinizi, testinizi, dil soyutlama tesislerinizi, programcı aşinalık, dokümantasyon oluşturucuyu, oluşturma sürecini, Ayrıca, öğrenme eğrisini önemli ölçüde azaltan küçük ayrıştırıcılarla etkileşimli olarak oynayabilirsiniz. Bu nedenler onu "önemli özellikler" listemin en üstüne yerleştiriyor.

  • @guysherman'ın belirttiği gibi hata raporlama Bir hata bulunduğunda, hatanın nerede olduğunu ve ne zaman meydana geldiğini bilmek istiyorum. Ne yazık ki, geri izleme devreye girdiğinde iyi hataların nasıl üretileceğini açıklamak için iyi kaynaklar bulamadım. (Not @ Sk-logic aşağıdaki yorum rağmen).

  • kısmi sonuçlar. Ayrıştırma başarısız olduğunda, girdinin hatanın konumundan önce olan kısmından başarıyla ayrıştırıldığını görmek istiyorum.

  • soyutlama. Asla yeterli fonksiyonda inşa edemezsiniz ve kullanıcının her zaman daha fazlasına ihtiyacı olacaktır, bu yüzden öndeki tüm olası fonksiyonları anlamaya çalışmak başarısızlığa mahkumdur. Şablonlarla kastettiğiniz bu mu?

  • 2'nize katılıyorum (ileriye dönük tahmin). İyi hata raporları oluşturmaya yardımcı olduğunu düşünüyorum. Başka bir şey için yararlı mı?

  • ayrıştırma gerçekleştiğinde bir ayrıştırma ağacı oluşturma desteği, belki de:

    • ağacın yapısının doğrudan dilbilgisine karşılık geldiği ve sonraki aşamaların hata raporlaması için düzen bilgisi içerdiği somut bir sözdizimi ağacı. Bu durumda, müşteri doğru ağaç yapısını elde etmek için hiçbir şey yapmak zorunda olmamalıdır - doğrudan dilbilgisine bağlı olmalıdır.
    • soyut bir sözdizimi ağacı. Bu durumda, kullanıcı tüm ayrıştırma ağaçlarıyla uğraşabilir
  • bir tür günlük kaydı. Bundan emin değilim; ayrıştırıcının denediği kuralların bir izini göstermek ya da (örneğin) HTML belgeleri oluşturmak için belirteçleri kullanmak istemeniz durumunda, boşluk veya yorumlar gibi önemsiz belirteçleri takip etmek olabilir.

  • bağlama duyarlı dillerle başa çıkma becerisi. Bunun ne kadar önemli olduğundan emin değilim - pratikte, bir dilin üst kümesini bağlamsız bir dilbilgisi ile ayrıştırmak, daha sonra ek geçişlerde içeriğe duyarlı kısıtlamaları kontrol etmek daha temiz görünüyor.

  • özel hata mesajları, böylece belirli durumlarda hata raporlarını ayarlamak ve belki daha hızlı bir şekilde sorunları anlamak ve gidermek.

Öte yandan, hata düzeltmeyi özellikle önemli bulmuyorum - ancak şu anki ilerleme konusunda güncel değilim. Fark ettiğim problemler, araçların sağladığı olası düzeltmelerin: 1) çok sayıda ve 2) yapılan gerçek hatalara karşılık gelmediği ve bu kadar da yararlı olmadığıdır. İnşallah bu durum düzelecektir (veya belki de zaten böyle olmuştur).


Soru şablonunu, 'Şablonlar' yazan madde işaretine PrecedenceHelper'a bir bağlantı ekleyecek şekilde düzenledim. Parametre dizisi gruplarına izin verir, bu nedenle dört parametreniz varsa, her parametre dizisi varsa, şablon dörtlü argüman kümelerinde kullanılmalıdır.
Allen Clark Copeland Jr

CST'yi inşa etmenizin ana nedeni, ayrıştırılan dosyanın genel düzeni. Belgeyi yeniden yazdırmak istiyorsanız , en iyi bahsiniz bir CST kullanmaktır, çünkü AST'leri adlarıyla bir CST'nin tutacağı garip aralığı işlemek için bilgi eksikliği anlamına gelir. İyi bir CST ise bir CST'yi dönüştürmek genellikle oldukça kolaydır.
Allen Clark Copeland Jr

Kullanıma hazır yerleşik işlevler konusunda soruyu tekrar düzenledim.
Allen Clark Copeland Jr

Bence şablonlar / işlevler hakkındaki düşüncemi ifade eden harika bir işe gitmedim: Demek istediğim, hiçbir zaman yeteri kadar sahip olamayacağınız için, bir sistemin bunları önceden bulmaya çalışmaması gerekir: kullanıcının yaratması gerekir Kendi.

1
Bir yaklaşımı özellikle sonsuz geri izleme (Packrat) ile hata bildirimi için yararlı buldum: her üretim kuralı hata mesajları ("blah-blah-blah beklendiği gibi" şeklinde ifade edilir) ile açıklanır ve hata durumunda bu mesaj akışta aynı şekilde saklanır kaydedilmiş jetonlar olarak. Tüm hatalar kurtarılamazsa (akış sonuna ulaşmadan ayrıştırma sonlandırılır), en sağdaki hata mesajı (veya bu tür mesajların toplanması) en uygunudur. Yapılması en kolay şey bu, elbette daha fazla ek açıklama ile daha da rafine etmenin yolları var.
SK-mantığı

5

Dil tasarımında deneyimli değilim, ancak bir oyun motoru için IDE oluştururken ve IDE yaparken bir kez ayrıştırıcı yazmaya başladım.

Nihai son kullanıcılarınız için önemli olan bir şey, bence, mantıklı olan hata mesajlarıdır. Biliyorum, özellikle dünyayı parçalayan bir nokta değil, geriye doğru takip ederek, bunun temel sonuçlarından biri yanlış pozitiflerden kaçınabilmeniz gerektiğidir. Sahte pozitifler nereden geliyor? Ayrıştırıcıdan ilk hataya düşerler ve asla tam olarak iyileşmezler. C / C ++ bununla ünlüdür (yeni derleyiciler biraz daha akıllı olsa da).

Bunun yerine neye ihtiyacınız var? Bir noktada neyin geçerli olduğunu / neyin geçerli olmadığını bilmek yerine, neyin geçerli olmadığını ve geçerli olmasını sağlamak için minimum bir değişiklik yapmayı bilmeniz gerektiğini, böylece ilgili yanlış hatalar oluşturmadan ayrışmaya devam edebileceğinizi düşünüyorum. özyinelemeli inişinizin karışmasına. Bu bilgileri üretebilen bir ayrıştırıcı oluşturabilmek sadece size çok sağlam bir ayrıştırıcı sağlamakla kalmaz, aynı zamanda ayrıştırıcıyı tüketen yazılım için bazı harika özellikler de açar.

Bu durumda gerçekten zor ya da aptalca açık bir şey önerebileceğimin farkındayım. Bu aradığınız şey değilse, cevabımı mutlu bir şekilde silerim.


Bu yapmayı planladığım şeylerden biri. Etki alanı hakkındaki bilgilerime yardımcı olmak için, bir arkadaşım, otomatikleştirmeyi asmak için elle gerçek bir ayrıştırıcı yazmayı önerdi. Oldukça hızlı bir şekilde fark ettiğim bir şey var: ayrıştırıcılar karmaşıktır ve elle yaptığımız ve süreci basitleştiren şeyler var. Kurallar ve Şablonlar aynı sözdizimini paylaşır; ancak Şablonlarda geçerli olan ancak kurallarda olmayan dil öğeleri vardır, bu görevi yerine getiren iç durumlar vardır. Bu da akla bir fikir getirdi: kurallar, alt kuralları paylaşmayı kolaylaştırmak için yol yardımlarını belirleyebilmelidir.
Allen Clark Copeland Jr

... bunun otomasyona geçmesi oldukça basit olmalı, ancak otomasyonların devlet tabanlı koşullara sahip olmasını gerektirecektir. Bunun üzerinde çalışacağım ve sana geri döneceğim. ANTLR, "T" * döngülerini işlemek için sonlu durum otomasyonlarını kullanır; burada, ayrıştırma işleminin çoğunu işlemek için kullanacağım, çünkü bir kuralda 800'den fazla varyasyon olduğunda indirimler durum olarak daha temiz olmalıdır (bu şişer) hızla / standart olarak spagetti kodu olarak.)
Allen Clark Copeland Jr

0

Dilbilgisinin "özyinelemeli kural bırakma" gibi kısıtlamaları olmamalıdır. Günümüzde yaygın olarak kullanılan araçların buna sahip olması ve sadece yacc'yi doğru yaptıktan yaklaşık 50 yıl sonra sadece LL dilbilgisini emmeyi anlayabilmeleri saçma .

Doğru özyineleme için bir örnek (yacc sözdizimi kullanılarak):

list: 
      elem                  { $$ = singleton($1); }
    | elem ',' list         { $$ = cons($1, $2);  }
    ;

Sol özyineleme için bir örnek (yacc synatx kullanarak):

funapp:
    term                    { $$ = $1; }
    | funapp term           { $$ = application($1, $2); }
    ;

Şimdi, bu başka bir şeye "yeniden düzenlenmiş" olabilir, ancak her iki durumda da, belirli bir özyineleme türü, yalnızca "doğru" yoldur, çünkü işlev uygulaması özyinelemeli olarak (örnek dilde) listeler sağ özyinelemelidir. .

Gelişmiş araçlardan, her şeyi aracın yeniden empoze ettiği sol / sağ özyinelemeden "refactor" yapmasını istemek yerine, bir şeyler yazmak için doğal yolu desteklemelerini bekleyebilirsiniz.


Evet, böyle keyfi kısıtlamalara sahip olmamak hoş bir şey. Bununla birlikte, bir tekrarlama işleci ile değiştirilemeyen sol özyineleme örneği nedir (normal ifadeler *veya +nicelleştiriciler gibi)? Bu alandaki bilgimin sınırlı olduğunu serbestçe itiraf ediyorum, ancak asla tekrarlamaya dönüştürülemeyen sol özyineleme kullanımıyla karşılaşmadım. Ve tekrarlama versiyonunu da daha net buldum (bu sadece kişisel tercih olmasına rağmen).

1
@MattFenwick Düzenlememe bakın. Sözdiziminin doğrudan sözdizimi ağacı oluşturmak için basit ve doğal anlamsal eylemlere (örneğin) nasıl yol açtığına dikkat edin. (Btw yacc mevcut değildir) tekrarı, ben sık sık vb boş bir liste, a tek, var olup olmadığını kontrol etmek gerekiyor galiba ile iken
Ingo

Cevap için teşekkürler. Ben bu örnekler yazmayı tercih ediyorum - Ben şimdi daha iyi anlıyorum list = sepBy1(',', elem)ve funapp = term{+}(ve tabii sepBy1ve +sol / sağ özyineleme açısından uygulanacağına dair ve standart sözdizimi ağaçları üretmek). Bu yüzden, sol ve sağ özyinelemenin kötü olduğunu düşünmüyorum, sadece düşük seviyeli olduklarını ve olayları daha net hale getirmek için mümkün olduğunda daha üst düzey bir soyutlama kullanmak istediğimi düşünüyorum. Tekrar teşekkürler!

1
@MattFenwick'e hoş geldiniz. Ama sonra belki bir zevk meselesi. Benim için, özyineleme (en azından hepsi doğal olarak özyinelemeli veya tamamen ilgisiz olan diller bağlamında) düşünmenin daha doğal yoludur. Ayrıca, bir ağaç özyinelemeli bir veri yapısıdır, bu nedenle özyinelemeyi simüle etmek için yinelemeye geri dönmeye gerek görmüyorum . Ancak, elbette, tercihler farklıdır.
Ingo
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.