---
title: 'Derleme Aşamaları'
source: 'https://academia.sh/tr/kurslar/bilgisayarlar-nasil-calisir/derleme-asamalari'
course: 'Bilgisayarlar Nasıl Çalışır'
language: tr
updated: '2026-08-17T18:08:06+00:00'
license: 'CC BY-SA 4.0'
---

# Derleme Aşamaları

Sözcüksel çözümleme, ayrıştırma, anlam denetimi, ara gösterim ve kod üretimi adımları.

Önceki ders, çevirinin ne zaman yapıldığına göre üç model tanımladı. Bu ders, çevirinin
kendisini açar: kaynak metin hangi adımlardan geçerek komutlara dönüşür?

Adımlar hemen her gerçekleştirimde aynıdır. Bir yorumlayıcı ile bir derleyici, ilk
aşamalarda aynı işi yapar; yollar sondaki üretim adımında ayrılır.

## Sözcüksel Çözümleme

İlk aşama, karakter dizisini anlamlı en küçük birimlere ayırır. Bu birimlere **sözcük
birimi (token)** denir.

`toplam = 3 + 4 * 2` satırı şu birimlere ayrılır:

| Birim | Tür |
|---|---|
| `toplam` | ad |
| `=` | atama işleci |
| `3` | sayı sabiti |
| `+` | toplama işleci |
| `4` | sayı sabiti |
| `*` | çarpma işleci |
| `2` | sayı sabiti |

Bu aşamada boşluklar ve yorum satırları atılır; sayı sabitleri, karakter dizisinden
sayısal değere çevrilir. Sözcüksel çözümleyici yapıyla ilgilenmez: `3 + * 4` dizisi de
sorunsuz biçimde birimlere ayrılır, çünkü her birim tek başına geçerlidir.

Bu aşamada üretilen hatalar, dilin alfabesine ait olmayan karakterler veya
kapatılmamış dizgi sabitleri gibi durumlardır.

## Ayrıştırma

İkinci aşama, sözcük birimlerinin dilin dilbilgisine uyup uymadığını denetler ve
uyuyorsa yapıyı ağaç biçiminde kurar. Bu ağaca **soyut sözdizim ağacı (abstract syntax
tree)** denir.

`3 + 4 * 2` ifadesinin ağacı, işleç önceliğini yapısına gömer:

```
      +
     / \
    3   *
       / \
      4   2
```

Çarpmanın toplamadan önce yapılması, ağaçta çarpma düğümünün daha derinde olmasıyla
kodlanmıştır: bir düğümün değeri hesaplanmadan üstündeki düğüm hesaplanamaz. Öncelik
kuralları, dilbilgisinin yazılış biçimiyle sağlanır; ayrı bir "öncelik denetimi" adımı
yoktur.

Ayrıştırma aşamasının hataları, birimlerin sırasına ilişkindir: kapatılmamış parantez,
eksik işlenen, beklenmeyen anahtar sözcük.

## Anlam Denetimi

Sözdizimi doğru olan her program anlamlı değildir. `toplam = tanimsiz_ad + 1` satırı
dilbilgisine uyar, ancak adın neye karşılık geldiği bilinmiyorsa yürütülemez.

Bu aşamada derleyici bir **simge tablosu** kurar: her adın nerede tanımlandığını, türünü
ve kapsamını tutar. Ağaç bu tabloya karşı denetlenir:

- Kullanılan adlar tanımlı mı?
- İşleçlerin işlenen türleri uyumlu mu?
- Atamalarda tür dönüşümü geçerli mi?
- Fonksiyon çağrılarında argüman sayısı ve türleri doğru mu?

Statik tipli dillerde bu denetimlerin çoğu derleme sırasında yapılır. Dinamik tipli
dillerde tür bilgisi çalışma anında değerlerin üzerinde taşınır; aynı hatalar, ilgili
satır yürütüldüğünde ortaya çıkar. İki yaklaşım arasındaki fark, hatanın **ne zaman**
görüldüğüdür.

## Ara Gösterim ve Eniyileme

Ağaç doğrudan makine koduna çevrilebilir, ancak çoğu derleyici araya bir katman koyar:
belirli bir işlemciye bağlı olmayan **ara gösterim (intermediate representation)**.

Ara gösterimin iki yararı vardır. Eniyilemeler burada, hedef makineden bağımsız olarak
yazılır; ve $m$ dil ile $n$ hedef mimari için $m \times n$ değil, $m + n$ bileşen yazmak
yeterli olur.

Bu düzeydeki tipik eniyilemeler:

- **Sabit katlama:** `3 + 4 * 2` ifadesi çalışma anında değil, derleme sırasında
  hesaplanır ve yerine `11` konur.
- **Ölü kod eleme:** Sonucu hiçbir yerde kullanılmayan hesaplar çıkarılır.
- **Ortak alt ifade eleme:** Aynı hesabın tekrarı bir kez yapılıp saklanır.
- **Döngü değişmezini dışarı alma:** Döngü boyunca değişmeyen hesap, döngü öncesine
  taşınır.

Eniyilemenin sınırı, programın **gözlenebilir davranışını** değiştirmemektir. Bu
kısıt, kayan noktalı aritmetiğin neden serbestçe yeniden sıralanamayacağını açıklar:
toplama birleşme özelliği taşımadığından, sıra değişimi sonucu değiştirebilir.

## Kod Üretimi

Son aşama, ara gösterimi hedef komut kümesine çevirir. Burada mimariye özgü kararlar
verilir:

- **Komut seçimi:** Aynı işlem birden çok komut dizisiyle yapılabilir; en ucuzu seçilir.
- **Yazmaç ayırma:** Değerlerin hangisi yazmaçta tutulacak, hangisi belleğe taşınacak.
  Yazmaç sayısı sınırlı olduğundan bu, derleyicinin en zorlu görevlerinden biridir.
- **Komut sıralama:** Boru hattının boşta kalmaması için komutlar yeniden sıralanabilir.

Bu aşamada uyulması gereken bir dış kural daha vardır: **çağrı sözleşmesi (calling
convention)**. Sözleşme, argümanların hangi yazmaçlara veya yığıt konumlarına
yerleştirileceğini, dönüş değerinin nerede taşınacağını ve hangi yazmaçları çağrılan
tarafın koruyacağını belirler. Ayrı ayrı derlenmiş dosyaların birbirini çağırabilmesi,
hepsinin aynı sözleşmeye uymasına bağlıdır; sözleşme derleyicinin değil, hedef
platformun tanımıdır.

Yorumlayıcılar bu aşamayı atlar: ağacı veya bayt kodu doğrudan yürütür. Sanal makine
modelinde ise hedef, gerçek bir işlemci değil sanal makinenin komut kümesidir.

## Hata Bildirimi ve Kurtarma

Bir derleyici, ilk hatada durup çıkabilir. Bu davranış geliştirici için verimsizdir:
her hata ayrı bir derleme turu gerektirir. Bu nedenle ayrıştırıcılar **hata kurtarma**
uygular — hatayı bildirir, tutarlı bir noktaya kadar birimleri atar ve çözümlemeyi
sürdürür.

Kurtarmanın bedeli, ardışık hatalardır. Kapatılmamış tek bir parantez, sonraki
yapıların yanlış konumda görünmesine ve onlarca ek hata iletisine yol açabilir. Pratik
kural şudur: iletilerin ilki, en güvenilir olanıdır; sonrakiler ilkinin türevi olabilir.

Hata iletisinin niteliği de bir tasarım işidir. İyi bir ileti üç şeyi söyler: sorunun
ne olduğunu, nerede oluştuğunu ve ne beklendiğini. Bunun için ayrıştırıcı, ürettiği her
düğümde kaynak konumunu (satır ve sütun) taşır; bu bilgi ağaç boyunca korunur ve anlam
denetimi aşamasında da kullanılır.

## Aşamaları Programla Görmek

Aşağıdaki program, ilk iki aşamayı küçük bir ifade dili üzerinde gerçekler ve üçüncü
aşamayı standart kütüphaneyle gösterir:

```python
import re, ast

DESEN = re.compile(r"\s*(?:(\d+)|([A-Za-z_]\w*)|(.))")

def sozcuklere_ayir(metin: str) -> list[tuple[str, str]]:
    """Kaynak metni (tür, değer) çiftlerine ayırır."""
    birimler = []
    for sayi, ad, simge in DESEN.findall(metin):
        if sayi:
            birimler.append(("sayi", sayi))
        elif ad:
            birimler.append(("ad", ad))
        elif simge.strip():
            birimler.append(("simge", simge))
    return birimler


print(sozcuklere_ayir("toplam = 3 + 4 * 2"))
# [('ad', 'toplam'), ('simge', '='), ('sayi', '3'), ('simge', '+'),
#  ('sayi', '4'), ('simge', '*'), ('sayi', '2')]

agac = ast.parse("3 + 4 * 2", mode="eval")
print(ast.dump(agac.body, annotate_fields=False))
# BinOp(Constant(3), Add(), BinOp(Constant(4), Mult(), Constant(2)))
```

`ast.dump` çıktısı, ayrıştırma bölümündeki ağacın metin biçimidir: dıştaki düğüm
toplama, sağ işleneni ise çarpma düğümüdür. Öncelik, ağacın biçimine yerleşmiştir.

Aynı programda sözcüksel çözümleyicinin `3 + * 4` girdisini sorunsuz ayırdığı, ancak
`ast.parse` çağrısının aynı girdide sözdizim hatası verdiği denenebilir; bu, iki
aşamanın farklı sorular sorduğunun doğrudan gösterimidir.

## Özet

- Sözcüksel çözümleme, karakter dizisini sözcük birimlerine ayırır ve boşlukları atar.
- Ayrıştırma, birimlerin dilbilgisine uygunluğunu denetler ve soyut sözdizim ağacını
  kurar; işleç önceliği ağacın biçiminde kodlanır.
- Anlam denetimi, simge tablosuna karşı ad ve tür uyumunu sınar; statik ve dinamik tipli
  diller bu denetimi farklı zamanlarda yapar.
- Ara gösterim, eniyilemeleri hedef mimariden bağımsız kılar ve dil–mimari
  bileşimlerinin sayısını azaltır.
- Kod üretimi komut seçimi, yazmaç ayırma ve komut sıralama kararlarını verir.
- Bir derleme hatası, üretildiği aşama bilinerek daha çabuk okunur.

## Sonraki Adım

Kod üretimi, her kaynak dosya için ayrı bir çıktı verir. Ancak bir program tek dosyadan
oluşmaz ve kullandığı kütüphaneler başka yerlerde derlenmiştir. Sonraki ders, bu
parçaların tek bir çalıştırılabilir bütüne nasıl bağlandığını ve çalışma anında belleğe
nasıl yüklendiğini ele alacak.
