Not: Başlıkta "karmaşık" kelimesini kullandığımda, ifadenin çok sayıda işleci ve işleci olduğu anlamına gelir. İfadenin kendisinin karmaşık olması değil.
Son zamanlarda x86-64 montaj için basit bir derleyici üzerinde çalışıyorum. Derleyicinin ana ön ucunu (lexer ve parser) bitirdim ve şimdi programımın Soyut Sözdizimi Ağacı temsilini oluşturabiliyorum. Dilim statik olarak yazılacağı için, şimdi bir sonraki aşamayı yapıyorum: kaynak kodunu denetleyerek yazın. Ancak bir sorunla karşılaştım ve bunu kendim için makul bir şekilde çözemedim.
Aşağıdaki örneği düşünün:
Derleyicimin ayrıştırıcısı şu kod satırını okudu:
int a = 1 + 2 - 3 * 4 - 5
Ve aşağıdaki AST'ye dönüştürdü:
=
/ \
a(int) \
-
/ \
- 5
/ \
+ *
/ \ / \
1 2 3 4
Şimdi AST'yi kontrol etmeli. ilk tip =
operatörü kontrol ederek başlar . İlk önce operatörün sol tarafını kontrol eder. Değişkenin a
bir tamsayı olarak bildirildiğini görür . Bu yüzden şimdi sağ taraftaki ifadenin bir tamsayı olarak değerlendirildiğini doğrulamalıdır.
İfade 1
ya da gibi tek bir değerse, bunun nasıl yapılabileceğini anlıyorum 'a'
. Fakat bu , yukarıdaki gibi bir çok değer ve işlenen - karmaşık bir ifade - ifadesi için nasıl yapılır ? İfadenin değerini doğru bir şekilde belirlemek için, tür denetleyicisinin gerçek ifadenin kendisini yürütmesi ve sonucu kaydetmesi gerekir gibi görünüyor . Ancak bu açıkça derleme ve yürütme aşamalarını ayırma amacını ortadan kaldırıyor gibi görünmektedir.
Bunu yapabileceğimi düşünmenin tek yolu AST'deki her bir alt ifadenin yaprağını tekrar tekrar kontrol etmek ve tüm yaprak türlerinin beklenen operatör tipine uyduğunu doğrulamaktır. =
Operatörden başlayarak , tip denetleyicisi sol taraftaki AST'nin tamamını tarar ve yaprakların tüm sayıların tam olduğunu doğrular. Daha sonra alt ifadedeki her operatör için bunu tekrar eder.
"The Dragon Book" adlı kopyamdaki konuyu araştırmayı denedim , ama pek de ayrıntılı bir şekilde görünmüyor ve zaten bildiklerimi yineliyor.
Bir derleyici birçok işleç ve işleçle ifade denetleme türü olduğunda, genel yöntem nedir? Yukarıda bahsettiğim yöntemlerden herhangi biri kullanılmış mı? Eğer değilse, yöntemler nelerdir ve tam olarak nasıl çalışırlar?
double a = 7/2
, sağ tarafı çift olarak yorumlamaya çalışır, bu nedenle pay ve paydayı çift olarak yorumlamaya ve gerekirse bunları dönüştürmeye çalışır; sonuç olarak a = 3.5
. Aşağıdan yukarıya, tamsayı bölme işlemini gerçekleştirir ve yalnızca son adımda (atama) dönüştürür a = 3.0
.
int a = 1 + 2 - 3 * 4 - 5
bunlarlaint a = 5 - ((4*3) - (1+2))