Belirsiz gramerler neden kötü?


30

2 veya daha fazla sol veya sağ türetme ağacı varsa, o zaman dilbilgisinin belirsiz olduğunu, ancak neden herkesin ondan kurtulmak istediğini bu kadar kötü anlayamadığımı anlıyorum.


1
İlgili ama aynı değil: softwareengineering.stackexchange.com/q/343872/206652 (feragatname: Kabul edilen cevabı yazdım)
marstato

Ayrıca bakınız: " Belirsiz bir gramer bulmak ".
Rob

1
Aslında kesin olmayan form pratik kullanımlar için daha iyidir, net olmayan form daha az sayıda ağaç kurarak daha az sayıda üretim kuralı kullanır (dolayısıyla verimli derleyicinin ayrıştırması daha az zaman alır). Çoğu araç, dilbilgisi dışında açıkça belirsizliği çözme yeteneği sağlar.
Grijesh Chauhan

3
"herkes ondan kurtulmak istiyor". Bu doğru değil. Ticari olarak alakalı dillerde, diller geliştikçe eklenen belirsizliği görmek yaygındır. Örneğin C ++ std::vector<std::vector<int>>, daha >>önce aralarında boşluk olması gereken, 2011'deki belirsizliği kasıtlı olarak ekledi . Temel görüş, bu dillerin satıcılardan çok daha fazla kullanıcısı olduğudur, bu nedenle kullanıcılar için küçük bir can sıkıntısını düzeltmek, uygulayıcılar tarafından yapılan çok fazla işi haklı çıkarmaktadır.
MSalters

Yanıtlar:


52

Aritmetik ifadeler için aşağıdaki gramerleri göz önünde bulundurun: Şu ifadeyi dikkate alın: Değeri nedir? İşte iki olası ayrıştırma ağacı:

XX+XXXXXX/Xvarconst
abc

(X - X) - X görüntü tanımını buraya girin

Soldaki birine göre, normal olan yorumlamalıyız. Sağdaki birine göre , muhtemelen amaçlanan şey bu değil, olarak yorumlamalıyız .abc(ab)ca(bc)=ab+c

Bir programı derlerken söz diziminin yorumlanmasının açık olmasını istiyoruz. Bunu uygulamanın en kolay yolu, net olmayan bir gramer kullanmaktır. Dilbilgisi belirsiz ise, operatör önceliği ve birliktelik gibi bağlayıcı kurallar sağlayabiliriz. Bu kurallar, dilbilgisini belirli bir şekilde açık hale getirerek aynı şekilde ifade edilebilir.


Ayrıştırma ağaçları, sözdizimi ağaç üreteci kullanılarak üretilir .


12
@HIRAKMONDAL Sözdiziminin belirsiz olması, gerçek bir sorun değildir. Sorun, iki farklı ayrıştırma ağacının farklı davranışlara sahip olmasıdır. Dilinizde belirsiz bir dilbilgisi varsa, ancak bir ifade için ayrıştırılan ağaçların hepsi anlamsal olarak eşdeğerse, o zaman sorun olmaz (örneğin, Yuval örneğini ele alın ve tek operatörünüzün bulunduğu durumu düşünün +).
Bakuriu

14
@Bakuriu Söylediğiniz doğru, ancak "anlamsal olarak eşdeğer" yüksek bir emirdir. Örneğin, kayan nokta aritmetiği aslında birleştirici değildir (bu nedenle iki "+" ağacı eşdeğer olmaz). Ek olarak, cevap aynı şekilde ortaya çıksa bile, tanımsız değerlendirme sırası, ifadelerin yan etkileri olabileceği dillerde çok önemlidir. Öyleyse söyledikleriniz teknik olarak doğrudur, ancak pratikte bir gramerin belirsizliğinin o gramerin kullanımıyla ilgili hiçbir yan etkisi olmaması çok olağandışı olacaktır.
Richard Rast

Günümüzde bazı diller, eklemelerde tamsayı taşması olup olmadığını kontrol eder, bu nedenle tamsayılar için bir + b + c bile değerlendirme sırasına bağlıdır.
gnasher729

3
Daha da kötüsü, bazı durumlarda dilbilgisi alternatif anlamı elde etmek için hiçbir yol sağlamamaktadır. Sorgu dillerinde bunu gördüm, kaçış dilbilgisi seçiminin (örneğin kaçış için özel karakterin iki katı olduğu) bazı sorgulamaları ifade etmeyi imkansız hale getirir.
Monica

12

Mevcut diğer cevapların aksine [ 1 , 2 ], belirsiz gramerlerin faydalı olduğu bir uygulama alanı vardır . Doğal dil işleme alanında (NLP), doğal dili (NL) resmi dilbilgileriyle ayrıştırmak istediğinizde, NL'nin farklı seviyelerde doğası gereği belirsiz olma problemi vardır [Koh18, ch. 6.4]:

  • Sözdizimsel uyumluluk:

    Peter kırmızı spor arabadaki adamı kovaladı.

    Peter veya kırmızı spor arabadaki adam mıydı?

  • Anlamsal uyumluluk:

    Peter bankaya gitti

    Oturmak için bir banka mı yoksa para çekecek bir banka mı?

  • Pragmatik ambuite:

    İki adam iki çanta taşıdı

    Çantaları birlikte mi taşıdılar ya da her biri iki çanta mı taşıdı?

NLP için farklı yaklaşımlar, genel olarak ve özellikle de bu amaçlara yönelik işlemlerle farklı şekilde ilgilenir. Örneğin, boru hattınız aşağıdaki gibi görünebilir:

  1. Belirsiz dilbilgisi ile NL ayrıştırma
  2. Ortaya çıkan her AST için: belirsiz anlamsal anlamlar üretmek ve adım 1'den itibaren imkansız sözdizimsel belirsizlikleri dışlamak için model oluşturmayı çalıştırın.
  3. Sonuçta ortaya çıkan her model için: önbelleğinize kaydedin.

Bu cümleyi her cümle için yapıyorsun. Ne kadar çok metin, örneğin, işlediğiniz kitaptan, daha önceki cümlelere göre 3. adıma kadar süren imkansız gereksiz modelleri daha fazla ekarte edebilirsiniz.

Programlama dilinin aksine, her NL cümlesinin kesin bir semantik olması gerekliliğini ortadan kaldırabiliriz. Bunun yerine, daha büyük metinleri ayrıştırma sırasında birden fazla olası anlamsal modelin kaydını tutabiliriz. Bir süre sonra, daha sonra elde edilen görüşler önceki belirsizlikleri dışlamamıza yardımcı olur.

Belirsiz dilbilgisi için birden fazla türev çıktısı alabilmeniz için ellerinizi kirletmek istiyorsanız, Dilbilgisel Çerçeveye bir göz atın . Ayrıca, [Koh18, ch. 5] yukarıdaki boru hattımla benzer bir şey gösteren bir tanıtımı var. [Koh18] ders notları olduğundan, ders notları olmadan ders notlarını tek başına anlamak o kadar kolay olmayabilir.


Referanslar

[Koh18]: Michael Kohlhase. "Mantık Tabanlı Doğal Dil İşleme. Kış Dönemi 2018/19. Ders Notları." URL: https://kwarc.info/teaching/LBS/notes.pdf . Kurs tanımının URL'si: https://kwarc.info/courses/lbs/ (Almanca)

[Koh18, ch. 5]: [Koh18] 'de "Bölümlerin Uygulanması: Dilbilgisi ve Mantıksal Çerçeveler" başlıklı 5. Bölüme bakınız.

[Koh18, ch. 6.4] Bkz. Bölüm 6.4, [Koh18] 'de "Belirsizliğin Hesaplamalı Rolü".


Bir ton teşekkürler .. Aynı şüphe vardı ve sen onu temizledin .. :)
HIRAK MONDAL

1
Bufalo
buffalodaki

“Buna zıt olarak” yazıyorsunuz ama ben buna cevabımın cevabının diğer tarafı olarak adlandırıyorum. Belirsiz dilbilgileriyle doğal dilleri ayrıştırmak o kadar zordur ki, geleneksel ayrıştırıcılar bunu yapamaz!
Davislor

1
@ComFreek Burada daha kesin olmalıyım. GF'ye kısa bir bakış (Link için teşekkürler!), Üç uzantıya sahip içeriksiz gramerleri okuduğunu gösterir (yeniden dağıtıma izin vermek gibi) ve olası tüm türevlerin bir listesini döndürür. Bunu yapmak için algoritmalar 50'li yıllardan beri var. Bununla birlikte, tamamen genel CFG'leri idare edebilmek, en kötü durumdaki çalışma sürenizi havaya uçurur ve uygulamada, GLL gibi genel bir çözümleyici kullanırken bile, yazılım mühendisleri, LL gramerleri gibi bir CFG alt kümesi kullanmaya çalışırlar. daha verimli bir şekilde ayrıştırılabilir.
Davislor

1
@ComFreek Bu nedenle, bilgisayarlar CFG ile başa çıkamazlar (doğal diller gerçekten bağlamsız ve gerçekte kullanışlı olmayan makine çevirisi tamamen farklı teknikler kullanıyor olsa da). Bu, çözümleyicinizin belirsizliği ele almasını gerektiriyorsa, onu daha verimli hale getirecek bazı kısayolları ortadan kaldırır.
Davislor

10

Belirsizliğin üstesinden gelmek için iyi tanımlanmış bir yol olsa bile (belirsiz ifadeler sözdizimi hatalarıdır), bu gramerler hala sorun yaratır. Belirsizliği bir gramerle tanıştırdığınız anda, bir ayrıştırıcı, aldığı ilk eşleşmenin kesin olduğundan emin olamaz. Herhangi bir belirsizliği ortadan kaldırmak için bir ifadeyi çözümlemek için diğer tüm yolları denemeye devam etmesi gerekir. LL (1) dili gibi basit bir şeyle de uğraşmazsınız, bu nedenle basit, küçük ve hızlı bir çözümleyici kullanamazsınız. Dilbilginizin birden çok yoldan okunabilen sembolleri vardır, bu nedenle çok fazla geri dönmeye hazır olmalısınız.

Bazı sınırlı alanlarda, bir ifadeyi ayrıştırmanın tüm olası yollarının eşdeğer olduğunu kanıtlamaktan kurtulabilirsiniz (örneğin, bir ilişkisel işlemi temsil ettikleri için). (a + b) + c = a + (b + c).


9

Anlamına IF a THEN IF b THEN x ELSE ygelir

IF a THEN
    IF b THEN
        x
    ELSE
        y

veya

IF a THEN
    IF b THEN x
ELSE
    y

? AKA sarkan başka bir sorun .


1
Belirsiz olmayan bir gramerin bile (Java, C, C ++, ...) bile insan bakış açısıyla belirgin (!) Belirsizliklere izin verdiğini gösteren iyi bir örnek. Her ne kadar resmi ve hesaplamalı olarak iyi olsak da, artık daha fazla UX / hatasız geliştirme sorunumuz var.
ComFreek

5

Örneğin C ++ 'daki en sinir bozucu ayrıştırmayı kullanın:

bar foo(foobar());

Bu fonksiyon bildirimi mi fooÇeşidi bar(foobar())(parametresi döndüren bir işlev işaretçi foobarya da bir değişken bildirimi) fooÇeşidi intvarsayılan başlatıldı ve başlatıldı foobar?

Parametre listesindeki ifade bir tür olarak yorumlanamadıkça, bu ilke olarak kabul edilerek derleyicilerde farklılaştırılır.

Böyle belirsiz bir ifade aldığınızda, derleyicide 2 seçenek vardır.

  1. ifadenin belirli bir türev olduğunu varsayalım ve diğer türevin ifade edilmesine izin vermek için dilbilgisine bir miktar ayırıcı ekleyin.

  2. hata oluştu ve her iki yoldan da ayrılmayı gerektiriyor

Birincisi doğal olarak düşebilir, ikincisi derleyici programcısının belirsizliği bilmesini gerektirir.

Eğer bu belirsizlik belirlenmeden kalırsa, o belirsiz ifadenin farklı türevlerinde varsayılan 2 farklı derleyicinin olması mümkündür. Belirsiz nedenlerden dolayı kodun taşınabilir olmadığına liderlik etmek. Bu, insanların dil derlemede bir hata iken derleyicilerin birinde hata olduğunu varsaymalarına neden olur.


5

Bence bu soru, en iyi ihtimalle sadece sınır çizgisi doğru olan bir varsayım içeriyor.

Gerçek hayatta, (belirsiz) çok belirsiz olmadıkça, sadece belirsiz gramerlerle yaşamak oldukça yaygındır.

Örneğin, yacc (ya da bizon ya da byacc gibi) ile derlenmiş gramerlere bakarsanız, derlediğiniz zaman "N kaydırma / azaltma çakışması" hakkında oldukça az sayıda uyarı verdiğini göreceksiniz. Yacc bir kayma / azalma çatışması ile karşılaştığında, bu gramerde bir belirsizlik anlamına gelir.

Bir değişim / düşüş çatışması, ancak, genellikle oldukça küçük bir sorundur. Ayrıştırıcı üreteci, anlaşmazlığı azaltmak yerine "vardiya" lehine çözecektir. Dilbilgisi eğer istediğin buysa, gayet iyi (ve pratikte gayet iyi çalışıyor gibi görünüyor).

Bir kayma / azaltma çatışması tipik olarak bu genel siparişte ortaya çıkar (terminal olmayanlar için kapaklar ve terminaller için küçük harf):

A -> B | c
B -> a | c

Bir ile karşılaştığımızda cbelirsizlik vardır: cdoğrudan mı Ayoksa ayrıştırmalı mıyız yoksa Bsırayla Amı? Böyle bir durumda, yacc ve benzeri daha basit / daha kısa rotayı seçecek ve -> -> rotasına gitmek yerine cdoğrudan olarak ayrıştıracaktır . Bu yanlış olabilir, ancak öyleyse, muhtemelen dilbilginizde çok basit bir hataya sahip olduğunuz anlamına gelir ve seçeneğin kesinlikle bir olasılık olarak kabul edilmemesi gerekir .AcBAcA

Şimdi, aksine, daha çok şöyle bir şeyimiz olabilir:

A -> B | C
B -> a | c
C -> b | c

Şimdi bir karşı karşıya cgeldiğimizde, ca Bveya a gibi davranıp davranmama arasında bir çelişki var C. Otomatik bir çatışma çözme stratejisinin gerçekte ne istediğimizi seçmesi ihtimali çok daha az. Bunların hiçbiri "kayma" değildir - her ikisi de "azaltma" dır, bu nedenle bu bir "azaltma / azaltma çatışması" dır (bu sıkıntıya alışkın olanlar ve genel olarak bir kayma / azaltma çatışmasından çok daha büyük bir sorun olarak tanınırlar).

Her ne kadar, birisinin dilbilgisinde gerçekten belirsizliği memnuniyetle karşıladığını söyleyecek kadar ileri gideceğimden emin olmasam da, en azından bazı durumlarda hiç kimsenin bu konuda çok fazla umursayamayacağı kadar küçük. Özette tüm belirsizliği ortadan kaldırma fikrini beğenebilirler - ama bunu her zaman yapmak için yeterli değil. Örneğin, küçük bir belirsizlik içeren küçük, basit bir dilbilgisi, belirsizliği ortadan kaldıran daha büyük, daha karmaşık bir dilbilgisi için tercih edilebilir (özellikle dilbilgisinden gerçekte bir ayrıştırıcı üretme pratik alanına girdiğinizde ve belirsiz olanı bulduğunda) dilbilgisi, hedef makinenizde çalışmayacak bir ayrıştırıcı üretir).


dostum, keşke 5 ay önce vardiya düşürücü çatışmaların mükemmel bir açıklaması olsaydı! ^^; +1
HotelCalifornia
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.