---
title: 'Statik Çözümleme'
source: 'https://academia.sh/tr/kurslar/php-uretim/statik-cozumleme'
course: "PHP'de Kalite, Başarım ve Dağıtım"
language: tr
updated: '2026-10-21T05:03:36+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - "PHP'nin geliştirme ve üretim ayar dosyalarının hangi yönergelerde ayrıştığını sıralar"
    - 'Bir davranışı dört yandan biriyle ("iki yanda da", "yalnız geliştirmede", "yalnız üretimde", "koşuma girmiyor") sınıflar'
    - '`php -l` ile tokenizer eklentisinin bulduğu kusurları ayırır: söz dizimi ile tanımsız fonksiyon'
    - 'Bir statik çözümlemenin dinamik çağrı karşısındaki sınırını ölçer'
---

# Statik Çözümleme

Kodu çalıştırmadan okuyan araçların ne bulduğunu, ne bulamadığını ve bir davranışın üretime çıkıp çıkmadığını tek bir soruyla ölçmeyi öğrenin.

Web Uygulama Çerçevesi kursu kodu ve ayarı sabit tuttu, bir parçanın istekte koşup koşmadığını ölçtü. Bu kursta kod ve istek sabittir; değişen, kodun koştuğu yerdir. Aynı betik geliştiricinin makinesinde bir davranış, üretimde başka bir davranış gösterebilir. Çoğu zaman bu fark kusur değil, tasarımdır: PHP iki ayrı ayar dosyası dağıtır ve ikisi bilerek ayrışır. Kursun her dersi tek bir soru sorar: bu davranış üretime çıkıyor mu?

İlk ders kodu çalıştırmadan okuyan araçlarla açılır. Statik çözümleme (static analysis), bir programı koşturmadan kaynağını inceleyerek kusur arar. Bu yüzden eksende ayrı bir yerde durur: koşumun içinde hiç görünmeyen kusurları, yalnız koşumun dışındaki bir araç ortaya çıkarabilir.

## İki Ayar Dosyası, Yedi Fark

PHP kaynak dağıtımı iki örnek ayar dosyası içerir: `php.ini-development` ve `php.ini-production`. İkisi de aynı yönergelerin büyük bölümünü aynı değerle taşır. Yedi yönergede bilerek ayrışırlar: hata gösterimi (`display_errors`), başlangıç hatalarının gösterimi (`display_startup_errors`), hata düzeyi (`error_reporting`), iddialar (`zend.assertions`), istisna izindeki argümanlar (`zend.exception_ignore_args`), argüman dizgesinin uzunluğu (`zend.exception_string_param_max_len`) ve bellek istatistiği (`mysqlnd.collect_memory_statistics`). Üretim profili buna bir de kod önbelleği ekler.

Bu fark bir hata değildir. Üretim, hata iletisini yanıta basmaz, iddiaları derlemez, istisna izine argüman koymaz ve hata düzeyinden kullanımdan kaldırma (deprecation) bildirimlerini çıkarır. Ders bunu kapatmaya çalışmaz; her davranışın hangi yanda durduğunu adlandırır. DevOps ve Platform Mühendisliği müfredatında geliştirme ile üretim arasındaki her sapma gizli kusur sayıldı ve kapatılmaya çalışıldı. Burada farkın çoğu kasıtlıdır ve PHP'nin kendisi tarafından dağıtılır.

## Ölçüm Çekirdeği

Kurs her davranışı aynı iki dosyayla ölçer. Birincisi `yan.php`'dir ve kursun bütün derslerinde aynen kalır.

```php
<?php
// yan.php — bu davranış üretime çıkıyor mu?
declare(strict_types=1);

// PHP'nin dağıttığı iki ayar dosyası (php.ini-development, php.ini-production) yedi
// yönergede ayrışır; yedisi buraya birebir alındı. Üretimdeki son iki satır dağıtım
// dosyasında yorum satırıdır: kod önbelleği komut satırında da açık, dosya denetimi kapalı.
const PROFILLER = [
    'geliştirme' => [
        'display_errors' => '1',
        'display_startup_errors' => '1',
        'error_reporting' => '32767',
        'mysqlnd.collect_memory_statistics' => '1',
        'zend.assertions' => '1',
        'zend.exception_ignore_args' => '0',
        'zend.exception_string_param_max_len' => '15',
    ],
    'üretim' => [
        'display_errors' => '0',
        'display_startup_errors' => '0',
        'error_reporting' => '24575',
        'mysqlnd.collect_memory_statistics' => '0',
        'zend.assertions' => '-1',
        'zend.exception_ignore_args' => '1',
        'zend.exception_string_param_max_len' => '0',
        'opcache.enable_cli' => '1',
        'opcache.validate_timestamps' => '0',
    ],
];

/** Betiği ayar dosyası olmadan, yalnız profilin yönergeleriyle ayrı bir süreçte koşturur. */
function calistir(string $betik, array $yonergeler): bool {
    $komut = ['php', '-n'];
    foreach ($yonergeler as $ad => $deger) {
        array_push($komut, '-d', "$ad=$deger");
    }
    $komut[] = $betik;
    $surec = proc_open($komut, [1 => ['pipe', 'w'], 2 => ['file', '/dev/null', 'w']], $borular);
    $cikti = stream_get_contents($borular[1]);
    fclose($borular[1]);
    proc_close($surec);
    $satirlar = array_values(array_filter(array_map('trim', explode("\n", $cikti))));
    return end($satirlar) === 'evet';
}

/** Davranışın iki koşumda görülüp görülmediğinden yanını çıkarır. */
function yan(bool $gelistirmede, bool $uretimde): string {
    return match (true) {
        $gelistirmede && $uretimde => 'iki yanda da',
        $gelistirmede => 'yalnız geliştirmede',
        $uretimde => 'yalnız üretimde',
        default => 'koşuma girmiyor',
    };
}

function yanRaporu(string $ad, string $betik): string {
    $gelistirmede = calistir($betik, PROFILLER['geliştirme']);
    $uretimde = calistir($betik, PROFILLER['üretim']);
    $sonYan = yan($gelistirmede, $uretimde);
    echo "$ad → $sonYan\n    geliştirme ", $gelistirmede ? 'evet' : 'hayır',
        ' · üretim ', $uretimde ? 'evet' : 'hayır', "\n";
    return $sonYan;
}
```

Dosyanın dört parçası vardır. `PROFILLER` sabiti iki ayar dosyasının yedi farkını birebir taşır. Üretimdeki son iki satır dağıtım dosyasında yorum satırıdır; kurs onları açıkça kurar, çünkü kod önbelleği komut satırında varsayılan olarak kapalıdır. `calistir()` bir yoklama betiğini ayrı bir süreçte koşturur ve son satırın `evet` olup olmadığına bakar. `yan()` iki boolean değerden dört yandan birini çıkarır. `yanRaporu()` bunu bir satır ve bir ayrıntı satırı olarak basar.

İki kural bu dosyada doğar. Birincisi `-n` bayrağıdır: alt süreç makinenin ayar dosyasını hiç yüklemez, yalnız profilin yönergeleriyle koşar. Böylece ölçüm, o makinede hangi ayar dosyasının bulunduğuna bağlı kalmaz. İkincisi alt sürecin `'php'` adıyla, PATH üzerinden başlatılmasıdır. `PHP_BINARY` kullanılmaz, çünkü makinenin ikilisinin yoluna güvenilmez: o yol, ikilinin dayandığı kitaplıklar yanında durmayan bir yere işaret edebilir ve süreç hiç başlamayabilir.

Dört yan kurs boyunca değişmez: davranış iki profilde de görülürse **iki yanda da**, yalnız geliştirmede görülürse **yalnız geliştirmede**, yalnız üretimde görülürse **yalnız üretimde**, hiçbirinde görülmezse **koşuma girmiyor**. Yan, etiket olarak değil kural olarak verilir. Her yoklama davranışı gördüğünde `evet`, görmediğinde `hayır` basar. `calistir()` iki profilde de koşar, `yan()` iki sonuçtan adı üretir.

## On İki Davranış, Dört Yan

İkinci dosya `davranislar.php` on iki küçük yoklamayı bu çekirdekten geçirir. Yoklama metinleri tek tırnaklı nowdoc içindedir; böylece değişken ve kaçış karakterleri sürücüye karışmaz.

```php
<?php
// davranislar.php — on iki davranış, dört yan
declare(strict_types=1);
require 'yan.php';

// Her yoklama, davranış görüldüyse son satıra "evet", görülmediyse "hayır" basar.
$davranislar = [
    'bellek sınırını aşan istek durur' => <<<'PHP'
        <?php
        ini_set('memory_limit', '32M');
        register_shutdown_function(function () {
            $son = error_get_last();
            echo ($son['type'] ?? 0) === E_ERROR ? "evet\n" : "hayır\n";
        });
        $buyuk = str_repeat('x', 64 * 1024 * 1024);
        PHP,
    'istek bitince yıkıcı koşar' => <<<'PHP'
        <?php
        $baglanti = new class {
            public function __destruct() { echo "evet\n"; }
        };
        PHP,
    'uyarı günlüğe düşer' => <<<'PHP'
        <?php
        $gunluk = __DIR__ . '/gunluk.txt';
        @unlink($gunluk);
        ini_set('log_errors', '1');
        ini_set('error_log', $gunluk);
        ob_start();
        echo $tanimsiz;
        ob_end_clean();
        echo str_contains((string) @file_get_contents($gunluk), 'Warning') ? "evet\n" : "hayır\n";
        PHP,
    'yanlış tipteki argüman durdurur' => <<<'PHP'
        <?php
        declare(strict_types=1);
        function adet(int $n): int { return $n; }
        try { adet('3'); echo "hayır\n"; } catch (TypeError) { echo "evet\n"; }
        PHP,
    'tutmayan iddia isteği durdurur' => <<<'PHP'
        <?php
        try { assert(1 === 2); echo "hayır\n"; } catch (AssertionError) { echo "evet\n"; }
        PHP,
    'uyarı yanıta basılır' => <<<'PHP'
        <?php
        ob_start();
        echo $tanimsiz;
        $yanit = ob_get_clean();
        echo str_contains($yanit, 'Warning') ? "evet\n" : "hayır\n";
        PHP,
    'kullanımdan kaldırılmış çağrı günlüğe düşer' => <<<'PHP'
        <?php
        $gunluk = __DIR__ . '/gunluk.txt';
        @unlink($gunluk);
        ini_set('log_errors', '1');
        ini_set('error_log', $gunluk);
        ob_start();
        strlen(null);
        ob_end_clean();
        echo str_contains((string) @file_get_contents($gunluk), 'Deprecated') ? "evet\n" : "hayır\n";
        PHP,
    'istisna izi argüman değerini taşır' => <<<'PHP'
        <?php
        function ode(string $kart) { throw new RuntimeException('red'); }
        try { ode('kart-0042'); } catch (RuntimeException $e) {
            echo count($e->getTrace()[0]['args'] ?? []) > 0 ? "evet\n" : "hayır\n";
        }
        PHP,
    'yerinde değişen dosyanın eski sürümü koşar' => <<<'PHP'
        <?php
        $surum = __DIR__ . '/surum.php';
        file_put_contents($surum, "<?php return 1;\n");
        touch($surum, time() - 60);
        $once = include $surum;
        file_put_contents($surum, "<?php return 2;\n");
        touch($surum, time() - 30);
        $sonra = include $surum;
        echo $sonra === $once ? "evet\n" : "hayır\n";
        PHP,
    'sembolik bağ geçişinden sonra eski sürüm koşar' => <<<'PHP'
        <?php
        foreach ([1, 2] as $n) {
            @mkdir("surum-$n");
            file_put_contents("surum-$n/selam.php", "<?php return $n;\n");
            touch("surum-$n/selam.php", time() - 60);
        }
        @unlink('guncel');
        symlink('surum-1', 'guncel');
        $once = include 'guncel/selam.php';
        @unlink('guncel-yeni');
        symlink('surum-2', 'guncel-yeni');
        rename('guncel-yeni', 'guncel');
        $sonra = include 'guncel/selam.php';
        echo $sonra === $once ? "evet\n" : "hayır\n";
        PHP,
    'çağrılmayan koldaki tanımsız fonksiyon bildirilir' => <<<'PHP'
        <?php
        function rapor(bool $ozet): string { return $ozet ? ozetle() : 'tam'; }
        rapor(false);
        echo error_get_last() !== null ? "evet\n" : "hayır\n";
        PHP,
    'biçimsiz kod bildirilir' => <<<'PHP'
        <?php
        file_put_contents(__DIR__ . '/bicimsiz.php', "<?php\nfunction  topla(\$a,\$b){return \$a+\$b;}   \n");
        include __DIR__ . '/bicimsiz.php';
        topla(1, 2);
        echo error_get_last() !== null ? "evet\n" : "hayır\n";
        PHP,
];

$sayim = array_fill_keys(['iki yanda da', 'yalnız geliştirmede', 'yalnız üretimde', 'koşuma girmiyor'], 0);
foreach ($davranislar as $ad => $kod) {
    file_put_contents('yoklama.php', $kod);
    $sayim[yanRaporu($ad, 'yoklama.php')]++;
}
echo "\n";
foreach ($sayim as $sonYan => $adet) {
    echo "$sonYan: $adet\n";
}
```

Çıktının tamamı şudur:

```text
bellek sınırını aşan istek durur → iki yanda da
    geliştirme evet · üretim evet
istek bitince yıkıcı koşar → iki yanda da
    geliştirme evet · üretim evet
uyarı günlüğe düşer → iki yanda da
    geliştirme evet · üretim evet
yanlış tipteki argüman durdurur → iki yanda da
    geliştirme evet · üretim evet
tutmayan iddia isteği durdurur → yalnız geliştirmede
    geliştirme evet · üretim hayır
uyarı yanıta basılır → yalnız geliştirmede
    geliştirme evet · üretim hayır
kullanımdan kaldırılmış çağrı günlüğe düşer → yalnız geliştirmede
    geliştirme evet · üretim hayır
istisna izi argüman değerini taşır → yalnız geliştirmede
    geliştirme evet · üretim hayır
yerinde değişen dosyanın eski sürümü koşar → yalnız üretimde
    geliştirme hayır · üretim evet
sembolik bağ geçişinden sonra eski sürüm koşar → yalnız üretimde
    geliştirme hayır · üretim evet
çağrılmayan koldaki tanımsız fonksiyon bildirilir → koşuma girmiyor
    geliştirme hayır · üretim hayır
biçimsiz kod bildirilir → koşuma girmiyor
    geliştirme hayır · üretim hayır

iki yanda da: 4
yalnız geliştirmede: 4
yalnız üretimde: 2
koşuma girmiyor: 2
```

Sayılar bağlayıcıdır ve kursun on dersinin hiçbiri bunları değiştirmez: on iki davranışın dördü iki yanda da, dördü yalnız geliştirmede, ikisi yalnız üretimde, ikisi koşuma girmiyor. Dört grup şöyle okunur.

İki yanda da duran dört davranış (bellek sınırı, yıkıcının istek sonunda koşması, açık günlük, `strict_types` altındaki `TypeError`) ayar dosyasından bağımsızdır. Üretimde ekrana basma kapalı olduğu için bir hatayı görmenin başlıca yolu günlüktür ve günlük iki yanda da aynı yere düşer.

Yalnız geliştirmede duran dört davranış, üretimin bilerek sustuğu yerlerdir: tutmayan iddia, yanıta basılan uyarı, günlüğe düşen kullanımdan kaldırma bildirimi ve argüman taşıyan istisna izi. Üretimde `zend.assertions=-1` iddiayı hiç derlemez.

Yalnız üretimde duran iki davranış geliştiricinin hiç görmediği davranışlardır: kod önbelleği dosyayı bir kez derler ve bir daha diske bakmaz, bu yüzden üzerine yazılan dosya da çevrilen sembolik bağ da eski sürümü koşturur.

Koşuma girmeyen iki davranış, koşumun yakalayamadığı kusurlardır. Dersin geri kalanı bunlardan ilkini inceler.

## Koşumun Bulamadığı Kusur

On iki yoklamadan on birincisi, çağrılmayan koldaki tanımsız fonksiyondur. Kesit şudur.

```php
<?php
// rapor.php — bir kolda tanımsız fonksiyon çağıran fonksiyon
declare(strict_types=1);

function rapor(bool $ozet): string {
    return $ozet ? ozetle() : 'tam';
}
```

`ozetle()` hiçbir yerde tanımlı değildir, ama `rapor(false)` çağrıldığında o kola hiç girilmez. PHP bir fonksiyon adını çağrı anında çözer; çağrılmayan kol için ne derleme ne koşum aşamasında bildirim üretir. Bu davranış iki profilde de aynıdır ve `error_get_last()` `null` kalır. Web Uygulama Çerçevesi kursunun sorusu, parçanın bu istekte çağrılıp çağrılmadığıydı. Burada parça her zaman çağrılır; sorulan, çağrılan parçanın davranışının iki profilde aynı olup olmadığıdır. Bu kusurda cevap iki profilde de aynıdır: sessizlik.

PHP'nin kendi denetimi olan `php -l` bu kusuru da göremez. Komut yalnız söz dizimini denetler; yani dosyanın PHP olarak ayrıştırılıp ayrıştırılamayacağına bakar ve hiçbir fonksiyonu çözmez.

```bash
# kontrol.sh — php -l yalnız söz dizimine bakar
printf '<?php\nfunction rapor( {\n' > bozuk.php
php -n -l bozuk.php >/dev/null 2>&1
echo "bozuk dosya: $?"
printf '<?php\nfunction rapor() { return 1; }\n' > saglam.php
php -n -l saglam.php >/dev/null 2>&1
echo "sağlam dosya: $?"
php -n -l rapor.php >/dev/null 2>&1
echo "tanımsız fonksiyonlu dosya: $?"
```

```text
bozuk dosya: 255
sağlam dosya: 0
tanımsız fonksiyonlu dosya: 0
```

Bozuk dosya 255 verir. Sağlam dosya ile tanımsız fonksiyon çağıran dosya aynı kodu, 0 verir. Komut, hata iletisini ve dosya yolunu içerir; ders yalnız çıkış kodunu basar.

Tokenizer eklentisi bir adım ileri gider. `PhpToken::tokenize()` kaynağı belirteçlere (token) ayırır: anahtar sözcük, ad, değişken, işleç. Bu, kodu çalıştırmadan okumanın en küçük biçimidir. Aşağıdaki denetleyici, tanımlanan fonksiyon adlarını çağrılan adlarla karşılaştırır. Bir ad, kaynakta `function` sözcüğünden hemen sonra geliyorsa tanımlıdır. Bir ad, ardından `(` geliyorsa ve önünde `->`, `::` ya da `new` yoksa çağrılmıştır. Tanımsız sayılan, ne kaynakta tanımlı ne de PHP'nin kendi `function_exists()` denetimini geçen çağrıdır.

```php
<?php
// denetle.php — çağrılan adları tanımlı adlarla karşılaştıran küçük denetleyici
declare(strict_types=1);

/** Kaynağı belirteçlere ayırır; boşluk ve yorumları atar. */
function belirtecler(string $kaynak): array {
    $liste = PhpToken::tokenize($kaynak);
    return array_values(array_filter($liste, fn(PhpToken $b) => !$b->isIgnorable()));
}

/** Tanımlanan ve çağrılan fonksiyon adlarını toplar. */
function adlariTopla(string $kaynak): array {
    $b = belirtecler($kaynak);
    $tanimli = [];
    $cagrilan = [];
    foreach ($b as $i => $belirtec) {
        if (!$belirtec->is(T_STRING)) {
            continue;
        }
        $onceki = $b[$i - 1] ?? null;
        $sonraki = $b[$i + 1] ?? null;
        if ($onceki !== null && $onceki->is(T_FUNCTION)) {
            $tanimli[] = $belirtec->text;
        } elseif ($sonraki !== null && $sonraki->text === '('
            && ($onceki === null || !$onceki->is([T_OBJECT_OPERATOR, T_DOUBLE_COLON, T_NEW]))) {
            $cagrilan[] = $belirtec->text;
        }
    }
    return ['tanimli' => $tanimli, 'cagrilan' => $cagrilan];
}

/** Tanımı bulunamayan çağrıların adlarını döndürür. */
function tanimsizCagrilar(string $kaynak): array {
    $adlar = adlariTopla($kaynak);
    $eksik = [];
    foreach (array_unique($adlar['cagrilan']) as $ad) {
        if (!in_array($ad, $adlar['tanimli'], true) && !function_exists($ad)) {
            $eksik[] = $ad;
        }
    }
    return $eksik;
}
```

Sürücü önce kusurun iki profilde sessiz kaldığını yoklamayla ölçer, sonra denetleyiciyi aynı dosyaya uygular ve son olarak kolu gerçekten çalıştırır.

```php
<?php
// cozumleme.php — koşum mu, okuma mı
declare(strict_types=1);
require 'yan.php';
require 'denetle.php';

file_put_contents('yoklama.php', <<<'PHP'
    <?php
    include 'rapor.php';
    rapor(false);
    echo error_get_last() !== null ? "evet\n" : "hayır\n";
    PHP);
yanRaporu('çağrılmayan koldaki tanımsız fonksiyon bildirilir', 'yoklama.php');

echo 'denetleyicinin bulduğu: ', implode(', ', tanimsizCagrilar(file_get_contents('rapor.php'))), "\n";

include 'rapor.php';
try {
    rapor(true);
} catch (Error $e) {
    echo 'kola girilince: ', get_class($e), "\n";
}
```

```text
çağrılmayan koldaki tanımsız fonksiyon bildirilir → koşuma girmiyor
    geliştirme hayır · üretim hayır
denetleyicinin bulduğu: ozetle
kola girilince: Error
```

Koşum iki profilde de sessizdir: yan, koşuma girmiyor. Denetleyici `ozetle` adını bulur. Kola girildiğinde ise PHP bir `Error` atar; yani kusur gerçektir, yalnız koşum onu o isteğe kadar saklar.

## Sınırlayıcı Ölçüm

Statik çözümleme koşumun göremediğini görür, ama onun da bir sınırı vardır: adın kaynakta okunabilir olması gerekir. Aşağıdaki kod aynı tanımsız fonksiyonu çağırır, ama adı bir değişkenden alır.

```php
<?php
// sinir.php — adı bir değişkende taşınan çağrıyı denetleyici görür mü
declare(strict_types=1);
require 'denetle.php';

file_put_contents('dinamik.php', <<<'PHP'
    <?php
    $ad = 'ozetle';
    $ad();
    PHP);

echo 'denetleyicinin bulduğu tanımsız çağrı: ', count(tanimsizCagrilar(file_get_contents('dinamik.php'))), "\n";
try {
    include 'dinamik.php';
} catch (Error $e) {
    echo 'doğrudan koşum: ', get_class($e), "\n";
}
```

```text
denetleyicinin bulduğu tanımsız çağrı: 0
doğrudan koşum: Error
```

Denetleyici hiçbir şey bulamaz, doğrudan koşum ise `Error` atar. Çağrının adı belirteç düzeyinde `ozetle` sözcüğü bile değildir; bir dize sabitidir (`T_CONSTANT_ENCAPSED_STRING`) ve `$ad` bir değişkendir. Kaynağı okuyan her araç bu noktada ya adı çözmeye çalışan bir çıkarım katmanı gerektirir ya da sınırını kabul eder. Ölçümün öğrettiği, "denetleyici temiz çıktı verdi" cümlesinin "kusur yok" anlamına gelmediğidir: yalnız "bu araç, bu okuma biçimiyle kusur görmedi" anlamına gelir.

## Özet

- Statik çözümleme kodu koşturmadan okur; bu yüzden ölçü eksenindeki yanı **koşuma girmiyor**'dur.
- PHP'nin geliştirme ve üretim ayar dosyaları yedi yönergede bilerek ayrışır: hata gösterimi, başlangıç hatalarının gösterimi, hata düzeyi, iddialar, istisna izindeki argümanlar, argüman dizgesi uzunluğu ve bellek istatistiği.
- Ölçü sınıfı tek sorudur, bu davranış üretime çıkıyor mu; dört yanıt (iki yanda da, yalnız geliştirmede, yalnız üretimde, koşuma girmiyor) kurs boyunca değişmez ve on iki davranışın dağılımı 4, 4, 2, 2'dir.
- `php -n -l` yalnız söz dizimini denetler: bozuk dosya 255, sağlam dosya ve tanımsız fonksiyonlu dosya 0 verir.
- Belirteçleri okuyan küçük bir denetleyici çağrılan adları tanımlı adlarla karşılaştırıp `ozetle` adını bulur, ama dize olarak taşınan adı göremez.

## Sonraki Adım

Bu derste koşumun göremediği kusuru, kodu okuyan bir araç gösterdi. Aynı sınıfın ikinci davranışı da koşuma girmez: biçimsiz kod iki profilde sorunsuz koşar. Sonraki ders, kodun biçiminin koşumu değiştirip değiştirmediğini sorar ve aynı belirteç okumasını boşluk, satır sonu ve girinti için kullanır.
