А съставител е програма което в превод означава четене от човека програмен код в машинно изпълним машинен код. За да направите това успешно, четеният от човека код трябва да съответства на синтаксис правила на кой език за програмиране е написан. Компилаторът е само програма и не може да коригира вашия код за вас. Ако направите грешка, трябва да коригирате синтаксиса или той няма да се компилира.
Какво се случва, когато компилирате кода?
Сложността на компилатора зависи от синтаксиса на езика и колко абстракция този език за програмиране осигурява. C компилаторът е много по-прост от компилатора за C ++ или C #.
Лексикален анализ
Когато компилира, компилаторът първо чете поток от знаци от файл с изходен код и генерира поток от лексикални маркери. Например кодът C ++:
int C = (A * B) +10;
може да се анализира като тези маркери:
- тип "int"
- променлива "C"
- се равнява
- leftbracket
- променлива "A"
- пъти
- променлива "B"
- rightbracket
- плюс
- буквално "10"
Синтактичен анализ
Лексикалният изход отива в частта на синтактичния анализатор на компилатора, която използва правилата на граматиката, за да реши дали входът е валиден или не. освен ако
променливи А и Б бяха декларирани по-рано и бяха в обхвата, компилаторът може да каже:- 'A': недеклариран идентификатор.
Ако са декларирани, но не са инициализирани. компилаторът издава предупреждение:
- локална променлива 'A', използвана без инициализация.
Никога не трябва да пренебрегвате предупрежденията на компилатора. Те могат да разбият кода ви по странни и неочаквани начини. Винаги фиксирайте предупрежденията на компилатора.
Един пропуск или два?
Някои езици за програмиране са написани, така че компилаторът може да прочете изходния код само веднъж и да генерира машинен код. паскал е един такъв език. много компилатори изискват най-малко два прохода. Понякога това се дължи на предварително декларации на функции или класове.
В C ++ клас може да бъде деклариран, но не дефиниран до по-късно. Компилаторът не може да определи колко памет се нуждае от клас, докато компилира тялото на класа. Той трябва да препрочете изходния код, преди да генерира правилния машинен код.
Генериране на машинен код
Ако приемем, че компилаторът успешно завършва лексикалния и синтактичния анализ, последният етап е генериране на машинен код. Това е сложен процес, особено при съвременните процесори.
Скоростта на съставения изпълним кодът трябва да бъде възможно най-бърз и може да варира значително според качеството на генерирания код и колко оптимизация е поискана.
Повечето компилатори ви позволяват да определите размера на оптимизацията - обикновено известен с бързо отстраняване на грешки при компилиране и пълна оптимизация за освободения код.
Генерирането на кодове е предизвикателство
Авторът на компилатора е изправен пред предизвикателства, когато пише генератор на кодове. Много процесори ускоряват обработката чрез използване
- Инструкция за тръбопровод
- вътрешен кешове.
Ако всички инструкции в рамките на код контур може да се проведе в процесор кеш, тогава този цикъл работи много по-бързо, отколкото когато процесорът трябва да получи инструкции от основната оперативна памет. CPU кешът е блок памет, вградена в чипа на процесора, до който се осъществява достъп много по-бързо от данните в основната оперативна памет.
Кешове и опашки
Повечето процесори имат опашка за предварително извличане, където процесорът чете инструкции в кеша, преди да ги изпълни. Ако се случи условен клон, процесорът трябва да презареди опашката. Кодът трябва да се генерира, за да се сведе до минимум това.
Много процесори имат отделни части за:
- Аритметика на цели числа (цели числа)
- Аритметика с плаваща запетая (дробни числа)
Тези операции често могат да се извършват успоредно, за да се увеличи скоростта.
Компилаторите обикновено генерират машинен код в обектни файлове, които са след това свързан заедно от програма за свързване.