Tarayıcısız ayrıştırma “Başka Sorunları Çözme” ile ne ilgisi var?


13

Sarkan başka problem hakkındaki Wikipedia makalesinden bu cümleyi anlamıyorum :

[Sarkan Başka problem] derleyici yapımında, özellikle de tarayıcısız ayrıştırmada ortaya çıkan bir sorundur.

Birisi bana tarayıcısız ayrıştırma tekniklerinin bu sorunu nasıl daha da kötüleştirebileceğini açıklayabilir mi? Bana öyle geliyor ki problem dilbilgisi ile ilgili - belirsiz olduğu için - ayrıştırma tekniği seçiminde değil. Neyi kaçırıyorum?


2
Düşünebildiğim tek şey, tarayıcısız bir ayrıştırıcının daha karmaşık bir dilbilgisine ihtiyaç duyması, belirsizliği çözmek için sezgisel tarama sağlamayı zorlaştırıyor.
Giorgio

3
@Robert Harvey: Mesele şu ki bu varsayım sözdizimi ağacına yansıtılmalıdır. Bir dilbilgisi dize için iki farklı sözdizimi ağacı türetmeye izin veriyorsa if a then if b then s1 else s2, dilbilgisi belirsizdir.
Giorgio

1
@RobertHarvey, dilleri tanımlamanın yaygın bir yolu bağlamsız bir dilbilgisi ve gerekirse dilbilgisini belirsizleştiren bir grup kural kullanmaktır.

2
Tüm tarayıcısız ayrıştırıcılar eşit yaratılmamıştır. Örneğin, PEG veya GLR için sarkan başka bir davranış her zaman öngörülebilir.
SK-logic

1
[Sarkan Else probleminin] tarayıcısız ayrıştırma ile bir ilgisi yoktur. [Sarkan Başka problem], LR (aşağıdan yukarıya) ayrıştırıcılarının kaydırma azaltma işlemleriyle ilgilidir. AFAIK
ddur

Yanıtlar:


6

En iyi tahminim Wikipedia makalesindeki cümlenin E. Visser çalışmasının yanlış anlaşılmasından kaynaklanmasıdır.

Tarayıcısız ayrıştırıcılar için dilbilgisi (yani, bir dili karakter dizileri olarak ayrı ayrı tanımlanmış jetonlarla birlikte bir dizi belirteç dizisi olarak bir karakter dizileri kümesi olarak tanımlayan dilbilgileri) çok fazla belirsizliğe sahip olma eğilimindedir. E. Visser kağıdı Tarayıcısız Genelleştirilmiş LR Ayrıştırıcılar (*) için Belirsizlik Filtreleri, belirsizlikleri çözmek için bir diğeri sarkan problemi çözmek için yararlı olan çeşitli mekanizmalar önerir. Ancak makale, "başka bir problemi sarkıyor" olarak adlandırılan kesin belirsizliğin tarayıcısız ayrıştırıcılarla (hatta mekanizmanın özellikle tarayıcısız ayrıştırıcılar için yararlı olduğunu) belirtmedi.

Başka bir belirsizlik çözümleme mekanizması (operatör önceliği ve önceliği) de dikkate alınan ayrıştırıcıların tarayıcısız doğası ile tamamen alakasız olduğu için örtük bir ifade önermediği gerçeği (örneğin, bu belirsizliklerin en uzun eşleşme kuralı tarafından ele alınırken, iç içe yerleştirmeden kaynaklanan düzenli gramerlerde bulunur).


(*) Muhtemelen E. Visser tarafından da, başka bir başvuru bile scannerless ayrıştırıcıları Vikipedi'ye tabanına olarak görev kağıdı Hangisi Scannerless Genelleştirilmiş-LR Ayrıştırma .


13

Sadece sorunu belirtmek için, Sarkan Else Sorunu, kod sözdizimi belirtiminde, belirsiz olabilen ifex ve els durumlarında belirsiz olabileceği bir belirsizliktir.

En basit ve klasik örnek:

if(conditionA)
if(conditionB)
   doFoo();
else
   doBar();

Bu ezbere dil şartname, özelliklerini bilmiyorum olanlara, belli değil ifalır else(ve bu özel kod parçacığı yarım düzine dilde geçerlidir, ancak her farklı performans gösterebilir).

Sarkan Else yapısı, tarayıcısız ayrıştırıcı uygulamaları için potansiyel bir sorun oluşturur, çünkü strateji, ayrıştırıcı tokenleştirmeye (derleme veya ara dilde derleme veya ara dilde özetleme) sahip olduğunu görene kadar her seferinde dosya akışını birer birer artırmaktır. . Bu, ayrıştırıcının minimum durumu korumasını sağlar; dosyaya ayrıştırıldığı jetonları yazmak için yeterli bilgiye sahip olduğunu düşündüğü anda bunu yapar. Bu, tarayıcısız bir ayrıştırıcının son hedefi; hızlı, basit, hafif derleme.

Noktalama işaretlerinden önce veya sonra yeni satırların ve boşlukların anlamsız olduğu varsayılarak (çoğu C stili dilinde olduğu gibi), bu ifade derleyiciye şu şekilde görünür:

if(conditionA)if(conditionB)doFoo();else doBar;

Bir bilgisayara mükemmel şekilde ayrıştırılabilir, bu yüzden görelim. Ben sahip olana kadar bir kerede bir karakter alıyorum:

if(conditionA)

Oh, bunun ne anlama geldiğini biliyorum (C # 'da), " pusheval yığını üzerine conditionA anlamına gelir ve daha brfalsesonra doğru değilse sonraki noktalı virgülden sonra ifadeye atlamaya çağırın ". Şu anda noktalı virgül görmüyorum, bu yüzden şimdilik bu talimattan sonra atlama uzaklığımı bir sonraki boşluğa ayarlayacağım ve noktalı virgül görene kadar daha fazla talimat ekledikçe bu ofseti artıracağım. Ayrıştırma devam ediyor ...

if(conditionB)

Tamam, bu benzer bir çift IL operasyonuna ayrılır ve az önce ayrıştırdığım talimattan hemen sonra gider. Noktalı virgül görmüyorum, bu yüzden önceki komutumun atlama ofsetini iki komutumun uzunluğuna (itme için ve diğeri mola için) kadar artıracağım ve aramaya devam edeceğim.

doFoo();

Tamam, bu kolay. Bu " calldoFoo". Ve bu gördüğüm noktalı virgül mü? Bu harika, çizginin sonu. Her iki bloğumun atlama ofsetlerini bu iki komutun uzunluğuna göre artıracağım ve umursadığımı unutacağım. Tamam, devam ediyorum ...

else

... Ah-oh. Göründüğü kadar basit değil. Tamam, sadece ne yaptığımı unuttum, ama bir elseşey zaten gördüğüm bir yerde koşullu bir mola ifadesi var, bu yüzden geri bakmama izin ver ... evet, işte, brfalsebazı "conditionB" yığın, her neyse. Tamam, şimdi bir breaksonraki ifade olarak koşulsuz ihtiyacım var . Bundan sonra gelecek olan ifade şimdi kesinlikle şartlı molamın hedefi, bu yüzden doğru yaptığımdan emin olacağım ve koyduğum koşulsuz molayı artıracağım. Devam ediyorum ...

doBar();

Bu kolay. " calldoBar". Noktalı virgül var ve hiç diş teli görmedim. Yani, koşulsuz breakne olursa olsun bir sonraki ifadeye atlamalı ve umursadığımı unutabilirim.


Peki, elimizde ne var ... (not: 10:00 PM ve bit ofsetlerini onaltılık biçime dönüştürmek veya bir fonksiyonun tüm IL kabuğunu bu komutlarla doldurmak gibi hissetmiyorum, bu yüzden bu sadece sahte IL normalde bayt uzaklığı olabilecek satır numaralarını kullanarak):

ldarg.1 //conditionA
brfalse <line 6> //jumps to "break"
ldarg.2 //conditionB
brfalse <line 7> //jumps to "call doBar"
call doFoo
break <line 8> //jumps beyond statement in scope
call doBar
<line 8 is here>

Aslında, bu doğru bir şekilde çalışır, EĞER kural (çoğu C tarzı dilde olduğu gibi) elseen yakın olan gider if. Yürütme iç içe geçmesini izlemeye yöneliktir, conditionA yanlışsa snippet'in geri kalanının tamamı atlanır:

if(conditionA)
    if(conditionB)
       doFoo();
    else
       doBar();

Dış bağlantılı mola çünkü ... ama, Serendipity tarafından yapar ififadesine atlar breaksonunda deyimi if tüm deyimi ötesinde yürütme işaretçi alır. Bu, gereksiz bir atlamadır ve bu örnek daha karmaşık olsaydı, bu şekilde ayrıştırılır ve belirtilirse artık çalışmayabilir.

Ayrıca, dil belirtimi sallantýdabir bu ne dese elseilk aittir ifve rahatsızlığı sonra yanlışsa rahatsızlığı doğrudur ancak conditionB sonra hiçbir şey aynen böyle olur iken Dobar, yürütülür?

if(conditionA)
    if(conditionB)
       doFoo();
else
   doBar();

Ayrıştırıcı, ilk ifvar olanı unutmuştu ve bu nedenle bu basit ayrıştırıcı algoritması, verimli kodun hiçbir şeyi söylemek için doğru kodu üretmeyecekti.

Şimdi, ayrıştırıcı daha uzun bir süre boyunca sahip olduğu ifs ve elses'leri hatırlayacak kadar akıllı olabilir , ancak dil özelliği elseiki ifs'nin birinciyle eşleşmesinden sonra bir tane söylerse if, bu ifs ile eşleşen elses ile ilgili bir soruna neden olur :

if(conditionA)
    if(conditionB)
       doFoo();
    else
       doBar();
else
    doBaz();

Ayrıştırıcı birinciyi, birinciyle elseeşleşir if, sonra ikincisini görür ve "tekrar ne yapıyordum" kipine girer. Bu noktada, ayrıştırıcının değişken bir durumda oldukça fazla kod var ve zaten zaten çıkış filestreamine itmeyi tercih ediyordu.

Tüm bu sorunlara ve ne olur? Ancak, akıllı olması için ayrıştırıcı algoritmasının karmaşıklığını arttırması için gereken kod veya ayrıştırıcının bu aptal olmasına izin veren dil spesifikasyonu, gibi sonlandırma ifadeleri gerektirerek, dil kaynağı kodunun ayrıntı düzeyini artırır end ifveya iç içe gösteren parantezler ififadenin else(her ikisi de diğer dil stillerinde yaygın olarak görülen) olup olmadığını engeller .

Bu, birkaç ififadenin sadece basit bir örneğidir ve derleyicinin vermesi gereken tüm kararlara ve nerede kolayca dağılabileceğine bakın. Sorunuzdaki Wikipedia'dan gelen bu zararsız ifadenin arkasındaki ayrıntı budur.


1
İlginç ama Wikipedia makalesinde amaçlanandan emin değilim. İlk bakışta içeriği açıklamanızla uyumlu olmayan Eelco Visser'in bir raporuna (tarayıcısız giriş yoluyla) atıfta bulunur.
AProgrammer

3
Yanıtınız için teşekkürler, ancak OP'yi gerçekten ele almıyor. Taramasız bir ayrıştırıcının amacının ne olduğu ve nasıl uygulandığı ile ilgili yazıdaki varsayımlara katılmıyorum. Tarayıcısız ayrıştırıcıları uygulamanın birçok yolu vardır ve bu yazı yalnızca sınırlı bir alt kümeyle ilgilenir.
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.