Направо към съдържанието

Компилатор

от Уикипедия, свободната енциклопедия
(пренасочване от Компилиране)

Компилаторът (англ. compiler, от compile – съчетавам, съставям) е компютърна програма, която превежда (компилира) даден компютърен изходен код в семантично отговарящ код на език от (обикновено) по-ниско ниво. Целевият език може да бъде машинен език или асемблерен език за конкретен процесор или процесорна фамилия, както и междинен език за конкретна виртуална машина (например байткод за виртуална машина на Java) или друг език от високо ниво. Когато се компилира до машинен език, крайният продукт е изпълнима програма или обектен код.

Стъпки на превеждане

[редактиране | редактиране на кода]

Има две основни фази при създаването на кода:

  • Аналитична, при която се изследва изходният код, като резултатът е синтактична дървовидна структура съдържаща (спомагателни) атрибути.
  • Синтезираща (съчетаваща), където се създава крайният код въз основа на данните получени от предишната фаза.

Нарича се също така предно стъпало (frontend).

Изходният код се разгражда на отделни лексикални единици – токени (tokens), напр. ключови думи, идентификатори, числа и оператори. С това се занимава програма, наречена лексически анализатор или скенер.

Лексическият анализатор понякога използва решетъчник (screener), който „пресява“ програмния код от белите знаци (whitespace) и от коментарите.

Синтактичен анализ

[редактиране | редактиране на кода]

При тази стъпка се проверява дали използваните градивни единици са формално допустими, т.е. дали отговарят на зададената граматика за програмния език. За целта програмният код се превръща в синтактична дървовидна структура.

Следващата стъпка е да се провери дали зададените програмни единици са логически свързани помежду си. Например:

  • дали една променлива е обявена за използване (т.е. дали е заделена оперативна памет за нея), преди да бъде използвана в програмата,
  • при прехвърляне на стойността на една променлива в друга, дали типовете на данните им са съвместими.

Тези проверки се осъществяват посредством атрибутивна граматика (attribute grammar).

Нарича се също така задно стъпало (backend), където създадената синтактична дървовидна структура се превежда в крайния код.

Създаване на междинен код

[редактиране | редактиране на кода]

При тази стъпка се създава междинен код, който по правило е близък до структурата на целевия език. Чрез него се осъществява и подобрение на бързината на изпълнение. Това стъпало се използва и за изходна точка при създаване на код за различни платформи.

Това е най-сложната част от превеждането на програмите. Оптимизацията може да бъде в различни насоки, в зависимост от желаната цел:

  • увеличаване на бързината на изпълнение
  • намаляване на използваната оперативна памет
  • намаляване на разхода на електроенергия
  • намаляване на размера на кода

Окончателно създаване на код

[редактиране | редактиране на кода]

При таза стъпка окончателно се превежда синтактичната дървовидна структура на програмата в целевия език. Ако последният е машинен език, създаденият код може директно да бъде изпълнен или се създава така нареченият обектен файл, който чрез свързване (linking) с други обектни файлове и библиотеки води до създаване на изпълним код.

Свързването се нарича статично ако необходимите програмни функции от библиотеки или програми се „копират“ в машинния код директно. Свързването се нарича динамично, ако програмата се компилира с използване на споделени библиотеки, които се зареждат в оперативната памет, само когато са нужни. Самият код съдържа извикване на функциите от тези библиотеки. Тези библиотеки използват относителни адреси в паметта и целта на програмата зареждач на операционната система е да нагоди адресите според адресното пространство на стартираната програма. Такива библиотеки се казва, че са компилирани с позиционно независим код. Същестува и възможността за компилиране с позиционно зависим код, който се използва в определени случаи тъй като пропускането на процеса на релокация спестява изчислителни ресурси и води до подобрение на скоростта на изпълнение. Позиционно зависим код се използва и при вградените ОС като Windows CE, където програмите се зареждат винаги на строго определен адрес.

Видове компилатори

[редактиране | редактиране на кода]
  • Местен (native) компилатор
Резултатът от превеждането е код, изпълним на платформата, върху която върви самият компилатор.
  • Смесен (cross) компилатор
Резултатът е изпълним код, предназначен за платформа различна от тази на която е извършена компилацията. Използва се например при създаване на код за вградени системи (embedded systems), където няма възможност, или е по-трудно, да се създават програми.
  • Еднопреходен компилатор (single-pass compiler), също ограничен компилатор (narrow compiler)
Този компилатор превежда програмата последователно и на един път (single-pass) за всеки компилиран блок. Казано по друг начин, компилаторът не се връща обратно на вече преведени части. Много програмни езици са замислени така, че да бъдат превеждани еднопреходно (напр. Паскал).
  • Многопреходен компилатор (multi-pass compiler), също разширен компилатор (wide compiler)
Този компилатор превежда програмата на няколко стъпки и намира приложение най-вече за:
  • прекъсване на предходни заявявания на променливите (forward declaration, forward reference)
  • провеждане на оптимизациите (свързани с изразходване на много ресурси) върху пълната синтактична дървовидна структура

Особени видове компилатори

[редактиране | редактиране на кода]
  • Транскомпилатор (също транспилатор) е особен компилатор, който превежда програмен код от един програмен език на друг програмен език, например от Паскал на C.
  • Компилатор-Компилатор (compilergenerator) или помощни програми, създаващи автоматично компилаторни части или цели компилатори. Такива програми са напр. JavaCC, Yacc, Bison
  • На-момента-компилатори (англ. Just-In-Time compiler/JIT compiler) превеждащи кода преди самото му изпълняване.