Sözdizimi hatalarını kendi başlarına düzeltmeye çalışan derleyiciler var mı? [kapalı]


15

Bir süre önce, bağlamı analiz ederek ve amaçlananı ortaya çıkararak sözdizimi hatalarını düzeltmeye çalışan bir derleyici olduğunu duydum.

Böyle bir derleyici gerçekten var mı? Açıkçası çok az pratik değeri var, ancak oynamak ve ondan öğrenmek çok ilginç olurdu.


3
IntelliSense bu kategoriye giriyor mu? Birçok derleyicide [noktalı virgül] 'e benzer hatalar vardır.
Robert Harvey

1
@Robert: Hayır, ama bu iyi bir nokta.
Nathan Osman

1
Bir arkadaşım C ön işlemcisini biraz kırdı, örneğin 'inlcude -> include' ve açık koşulların nerede kapatılacağını anlamaya çalışmak için bazı çalışmalar yapıldı. Daha kolay bir şey için çabucak terk ettiği onun yüksek lisans teziydi. Yine de oldukça ilginç bir soru!
Tim Post

3
AC # derleyici ÇOK yararlı hata iletileri ile başarısız. Bu her hata kodu için çevrimiçi olarak mevcut iyi belgeler ile birlikte oldukça iyi çalışıyor. HTML yorumlayıcıları (örn. Tarayıcılar) genellikle bunu yapsa da sözdizimini otomatik olarak düzeltmek kötü bir fikirdir.
İş

1
Bahsettiğiniz derleyici orijinal PL / I idi. Programcının yazdığı her şeyin bir şey ifade etmesi gerektiğini varsaydı ve bunun ne olabileceğini tahmin etmeye çalıştı. Deneyimlerime göre, gerçekten çok kötü tahmin!
david.pfx

Yanıtlar:


28

Bazı anlamda, derleme eylemi olduğu belli sözdizimi yapmak anlamına geliyordu ve derleyici onu anlamaya mümkün olmadığında dolayısıyla yazım hatasıdır ne çıkarım. Derleyicinin başka şeyler çıkarması ve sözdizimiyle daha esnek olması için daha fazla "tahmin" ekleyebilirsiniz, ancak bunu belirli bir kurallar dizisi ile çıkarımda bulunmalıdır. Ve bu kurallar dilin bir parçası haline gelir ve artık hata değildir.

Yani, hayır, gerçekten böyle bir derleyici yok, çünkü soru mantıklı değil. Bazı kurallara göre sözdizimi hatalarının ne anlama geldiğini tahmin etmek sözdiziminin bir parçası haline gelir.

Bu anlamda bunu yapan bir derleyici örneği var: Herhangi bir C derleyicisi. Genellikle olması gerektiği gibi olmayan bir şeyin uyarısını basarlar ve sonra X demek istediğinizi varsayar ve devam ederler. Bu aslında (çoğunlukla kendi sözdizimi olmasa da) belirsiz kodun "tahmin edilmesidir", aynı zamanda bir hatayla derlemeyi durdurabilen ve bu nedenle bir hata olarak nitelendirilebilen bir şeydir.


4
Bu doğru cevap. Derleyici bir hatadan kurtarabilirse, artık gerçekte bir hata değildir. Perl bu "Ne demek istediğimi yap" davranışı ile ünlüdür ve programcıya belirsiz kaynak verilme ihtimalinin en yüksek olduğunu seçer.
Jon Purdy

Perl kaynak kodu boyutu için ayrıntılardan ödün verir.
Nathan Osman

@George Edison: Bu bir totoloji veya çelişki.
Jon Purdy

Ya da derin bir içgörü. :)
Lennart Regebro

23

Kulağa gerçekten tehlikeli geliyor. Bir derleyici niyetinizi çıkarmaya çalışırsa, yanlış girerse, kodu düzeltirse ve sonra size söylemezse (veya bazı uyarılarla, herkes gibi görmezden geldiğinizi söyler), o zaman olabilecek kodu çalıştırmak üzeresiniz ciddi hasar ver.

Böyle bir derleyici muhtemelen çok kasıtlı olarak yaratılmamış bir şeydir.


5
Bunu biliyorum. Böyle bir derleyicinin derleme için bir faydası olmaz, ancak konsept oldukça ilginçtir ve öğrenme potansiyeline sahiptir.
Nathan Osman

2
neredeyse tüm son IDE sözdizimi için öneri sağlar ve gerçekten yararlıdır. ve bölümün geri kalanı için nganju ile anlaştı
Joshi

Böyle bir derleyici kullanmam. 'Kara büyü' başlığı altında gelir.
Michael K

Hmmm Scala'nın bu türden çıkarımını nerede değerlendirirsiniz? Bunu denedikten sonra, özlü koda büyük bir katkı olduğunu söyleyebiliriz. Öte yandan, zaman zaman beni ayağımdan vurdu (örneğin listelerle uğraştığımı düşündüm ama aslında setlerle uğraşıyordum).
timday

OMP'de otoskop gibi şeyler var, bu yüzden biraz yapılabilir. Tabii ki üzerinde çalıştığım kod otomatik kodlamayı kapattı çünkü ona güvenmiyoruz. 'XXX mu demek istediniz?' Gitmeye istekli olduğum kadarıyla. Ve bu bile muhtemelen çok tehlikelidir.
Omega Centauri

12

Bir programlama dili için IDE genellikle bugünlerde arka planda bir şekilde çalışan bir derleyiciye sahiptir, böylece sözdizimi renklendirme, IntelliSense, hatalar ve benzeri gibi analiz hizmetleri sağlayabilir. Açıkçası, böyle bir derleyicinin derinden kırılmış kodları anlayabilmesi gerekir; çoğu zaman düzenleme yaparken, kod doğru değil. Ama yine de anlamamız gerekiyor.

Ancak, genellikle hata kurtarma özelliği yalnızca düzenleme sırasında kullanılır; "ana hat" senaryolarında gerçek derlemeye izin vermek pek mantıklı değil.

İlginç bir şekilde, bu özelliği JScript.NET derleyicisine oluşturduk; temel olarak, derleyiciyi, bir hata ile karşılaşılsa bile, IDE kurtarılmış olsa bile derleyicinin ilerlemesine izin verdiğimiz bir moda sokmak mümkündür. Visual Basic kodunu yazabilir , üzerinde JScript.NET derleyicisini çalıştırabilir ve diğer ucu çıkan bir çalışma programının makul bir şansına sahip olabilirsiniz!

Bu eğlenceli bir demo, ancak birçok nedenden ötürü "ana hat" senaryoları için çok iyi bir özellik değil. Tam bir açıklama oldukça uzun olacaktır; kısa açıklama, öngörülemeyen ve yanlışlıkla çalışan programlar için yaptığı ve aynı kodu birden çok derleyici veya aynı derleyicinin birden çok sürümü aracılığıyla çalıştırmayı zorlaştırmasıdır. Özelliğin eklediği büyük masraflar, küçük faydalar ile doğrulanmaz.

Bu özelliği gün içinde PM yapan Peter Torr, 2003'ten bu blog yayınında kısaca tartışıyor .

Bu özelliği JScript .NET motorunun komut dosyası barındırma API'ları aracılığıyla göstermemize rağmen, onu kullanan herhangi bir gerçek müşteri bilmiyorum.


Keşke işverenimin böyle deneyecek kaynaklara sahip olmasını dilerdim; gece bile birim testleri yapmıyoruz çünkü eklenecek ve düzeltilecek çok fazla özellik var :(
İş

1
Bu, umduğum gibi bir cevap ... daha önce de belirttiğim gibi - açıkçası böyle bir özellik çok az pratik kullanıma sahiptir, ancak diğer şeylere uygulanabilecek bazı teknikleri öğrenmek için harika bir yol sağlayacaktır. (Dil ayrıştırma vb.)
Nathan Osman

1
@ İş: Genel bilgelik, birim testlerini düzenli olarak yapmazsanız, düzeltmeniz gereken çok daha fazla hataya sahip olmanızdır .
Eric Lippert

Burada sızlanmak yerine işim hakkında ne yapmam gerektiğini zaten biliyorum. Bazı yazılım şirketlerinde en üstteki insanlar bir prototip ve bitmiş bir ürün arasındaki farkı gerçekten anlamıyorlar. Sonuçta, piksel olarak çoğu zaman bir fark yoktur. Bir prototip ile başlamamak akıllıca değildir, böylece zaman boşa gitmez. Ama korkunç tepki "iyi görünüyor, bunu üretime taşımak için kaç gün var?". Mühendisler, altyapı veya yeniden düzenleme için zaman harcamak zorunda olduklarını söylerse şüpheli olanlar aynı kişilerdir. Spolsky'nin bile bundan hoşlanmadığını duydum.
İş

10

Aklıma ilk gelen Javascript'in otomatik noktalı virgül yerleştirilmesidir . Dile asla girmemeli, korkunç ve korkunç bir özellik.

Bu daha iyi bir iş yapamayacağı anlamına gelmiyor. Aşağıdaki çizgiyi ileriye bakarsa, programcının niyeti hakkında daha iyi bir tahmin yapabilir, ancak günün sonunda sözdiziminin gidebileceği birden fazla geçerli yol varsa , o zaman gerçekten bir alternatifi yoktur programcı açık olduğu için.


1
JavaScript noktalı virgül ekleme özelliğine yürekten katılıyorum - tamamen işe yaramaz.
Nathan Osman

7

Bana bir derleyici yanlış sözdizimini düzeltebiliyorsa, sözdiziminin dilde belgelenmesi gerektiği anlaşılıyor.

Sözdizimi hatalarının nedeni, ayrıştırıcının soyut sözdizimi ağacını programdan oluşturamamasıdır. Bu, bir belirteç yerinde olmadığında olur. Bu belirtecin nerede olması gerektiğini tahmin etmek için, kaldırılması gerekiyorsa veya hatayı düzeltmek için başka bir belirteç eklenmesi gerekiyorsa, bir programcının amacını tahmin edebilecek bir çeşit bilgisayara ihtiyacınız olacaktır. Bir makine bunu nasıl tahmin edebilir:

int x = 5 6;

Olması gerekiyordu:

int x = 5 + 6;

Bu gibi kolay aşağıdakilerden herhangi biri olabilir: 56, 5 - 6, 5 & 6. Bir derleyicinin bilmesi mümkün değildir.

Bu teknoloji henüz mevcut değil.


1
Böyle bir teknoloji var olamaz. Zihin okumaya izin verilmez; tüm talimatlar açık bir şekilde koddan gelmelidir.
İş

Doğru, ama gerçekten demek istediğim "Bağlama dayalı tahminler yaparak geçersiz sözdizimini düzeltmeye çalışan herhangi bir derleyici var mı?" Derleyicinin geçersiz sözdizimini düzeltmesi sözdizimini geçerli kılmaz. Ayrıca, böyle bir aracın kod geliştirme için işe yaramayacağını anlıyorum.
Nathan Osman

6

Aynı şey olmasa da, HTML'nin neden felakete dönüştüğü budur. Tarayıcılar kötü biçimlendirmeyi tolere etti ve bildiğiniz bir sonraki şey, tarayıcı A, Tarayıcı B'nin yaptığı gibi işleyemedi (evet, başka nedenler de var, ancak bu, gevşeklik kurallarının bazıları konvansiyon haline gelmeden önce yaklaşık 10 yıl önce, ilk birkaçından biriydi. ).

Eric Lippert'in ihlal ettiği gibi, bunların çoğu en iyi derleyici tarafından değil IDE tarafından ele alınmaktadır. Bu, otomatik bitlerin sizin için neyi sıkıştırmaya çalıştığını görelim.

Şimdi baskın olduğunu düşündüğüm strateji derleyiciyi gevşetmek yerine sürekli dil iyileştirme: Eğer derleyicinin otomatik olarak anlayabileceği bir şeyse, çevresine iyi tanımlanmış bir dil yapısı getirin.

Akla gelen anlık örnek, C #'daki otomatik özelliklerdir (benzer bir şeye sahip tek dil değil): Herhangi bir uygulamadaki alıcıların / ayarlayıcıların çoğunun gerçekten bir alanın etrafındaki sarmalayıcılar olduğu göz önüne alındığında, geliştiricinin ve derleyicinin geri kalanını enjekte etmesine izin verin.

Bu da beni düşünmeye itiyor: Çoğu C stili dil bunu zaten bir ölçüde yapıyor. Otomatik olarak çözülebilecek şeyler için sözdizimini geliştirin:

 if (true == x)
 {
    dothis();
 }
 else
 {
    dothat();
 }

Aşağıdakilere indirgenebilir:

if (true == x)
    dothis();
else
    dothat();

Sonunda, bence bu aşağıya geliyor: Eğilim derleyiciyi "daha akıllı" veya "daha gevşek" yapmamanızdır. Daha akıllı ya da gevşemiş bir dildir .

Ayrıca, klasik "if" hatası gibi çok fazla "yardım" tehlikeli olabilir:

if (true == x)
    if (true == y)
       dothis();
else
    dothat();

XHTML'nin HTML'nin kötü özelliklerinin oluşturduğu karışıklık için bir çözüm sağladığı unutulmamalıdır.
Nathan Osman

2
if (x && y) dothis(); else dothat();biraz daha iyi görünür.
İş

1
Bir kedi, trueveya ile her karşılaştığında ölür false.
JensG

2

DEC ve IBM minibilgisayar ve anabilgisayar sistemlerinde 80'lerin sonunda ve 90'ların başında FORTRAN ve PL / I kodlarken, derleyicilerin düzenli olarak "blah blah hatası; blah blah varsayarak ve devam eden gibi" . ". O zamanlar, bu, kodunuzu çalıştırmak için göndermek ve sonuçları geri almak arasında büyük bir bekleyiş olduğunda toplu işlem ve delikli kartların (daha önce, zamanımdan önce) bir mirasıydı. Bu yüzden derleyiciler, programcıyı ikinci olarak tahmin etmeye ve karşılaşılan ilk hatayı iptal etmek yerine devam ettirmeye gayet mantıklı geldi. Dikkat edin, "düzeltmelerin" özellikle sofistike olduğunu hatırlamıyorum. Sonunda etkileşimli Unix iş istasyonlarına (Sun, SGI vb.) Geçtiğimde,


2
Bu derleyiciler devam eder, ancak SADECE daha fazla hata bulmaya çalışmak için devam ederler, böylece yeniden göndermeden önce (potansiyel olarak) birkaç şeyi düzeltebilirsiniz. Modern PC'ler, bir "etkileşimli" derleyicinin ilk sözdizimi hatasıyla durması ve sizi bir düzenleyiciye bırakması için yeterince hızlıdır. (Ve aslında, orijinal Turbo Pascal, 1980'lerin başında tam olarak bu şekilde çalıştı.
Güzeldi

1
Evet, IBM PL / I optimizasyon derleyicisinin bazen eksik BEGIN ve END ifadeleri sağlayacağını hatırlıyorum, ISTR aynı zamanda eksik noktalı virgül de sağlayacaktır.
TMN

1

Bir derleyicinin amacı, istendiği gibi çalışan yürütülebilir dosyalar üretmektir. Bir programcı geçersiz bir şey yazarsa, derleyici% 90 olasılıkla tahmin edileni tahmin edebilse bile, genellikle programcının, derleyicinin devam etmesini ve yürütülebilir bir dosya üretmekten ziyade, amacı açık hale getirmek için programı düzeltmesini istemek daha iyidir. ve bu da bir hatayı gizlemek için önemli bir şansı olurdu.

Tabii ki, diller genellikle niyeti açıkça ifade eden kodun yasal olacağı şekilde tasarlanmalıdır ve niyeti açıkça ifade etmeyen kodlar yasaklanmalıdır, ancak bu oldukları anlamına gelmez. Aşağıdaki kodu düşünün [Java veya C #]

const double oneTenth = 0.1;
const float  oneTenthF = 0.1f;
...
float f1 = oneTenth;
double d1 = oneTenthF;

Bir derleyiciye f1, programcının f1içermek isteyebileceği tek bir mantıksal şey olduğundan ( float1/10'a en yakın değer) ödeve örtük bir örnekleme eklemek yardımcı olacaktır . Bununla birlikte, derleyicileri uygunsuz programları kabul etmeye teşvik etmek yerine, spesifikasyonun bazı bağlamlarda örtük çift-kayan dönüşümlere izin vermesi daha iyi olacaktır . Kapak tarafında, d1programlayıcının gerçekten istediği şey olabilir veya olmayabilir, ancak bunu yasaklayan bir dil kuralı yoktur.

En kötü dil kuralları, derleyicilerin bir şeyin başka şekilde meşru bir şekilde derlenemediği, ancak bir programın çıkarımın amaçlandığı bir durumda "yanlışlıkla" geçerli olabileceği durumlarda çıkarımlarda bulunacağı kurallardır. Örtülü deyim sonu içeren birçok durum bu kategoriye girer. İki ayrı ifade yazmak isteyen bir programcı bir deyim sonlandırıcısını atlarsa, bir derleyici genellikle deyim sınırını çıkarmayı başarabilir, ancak bazen bir deyim olarak iki olarak işlenmesi gereken bir şey olarak kabul edebilir.


0

Sözdizimi hatalarının düzeltilmesi özellikle zordur. Eksik hak durumunda ): Kodu ekleyerek onarabileceğimizi biliyorduk, ancak genellikle bir tane ekleyip sözdizimsel olarak doğru bir program alabileceğimiz birçok yer var.

Çok daha kolay bir nokta yanlış yazılmış tanımlayıcılardır (ancak bunun sözdizimi hataları olmadığını unutmayın). Çözülemeyen tanımlayıcı ve kapsamdaki tüm tanımlayıcılar arasındaki düzenleme mesafesini hesaplayabilir ve çözülemeyen kelimeyi kullanıcının en çok kastettiği kelime ile değiştirerek, birçok durumda doğru bir program ortaya çıkar. Bununla birlikte, hatayı işaretlemek ve IDE'nin geçerli değişiklikler önermesine izin vermek daha iyi olduğu ortaya çıkıyor.


-1

Böyle bir derleyici, derlediği dilin rahat ve standart dışı bir uygulaması olacaktır.


-2

Birden çok kez denendi, ancak genellikle istenen etkiyi elde etmedi: HAL 9000 veya GlaDOS'u düşünün.


-3

C'de dizileri değere göre geçiremezsiniz, ancak derleyici şunları yazmanıza izin verir:

void foo(int array[10]);

daha sonra sessizce şu şekilde yeniden yazılır:

void foo(int* array);

Bu ne kadar aptalca? Burada sessiz yeniden yazma yerine zor bir hatayı tercih ederim, çünkü bu özel kural birçok programcının dizilerin ve işaretçilerin temelde aynı şey olduğuna inanmasına neden oldu. Onlar değil.

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.