Page 48 - 4761
P. 48
для виконання розбору вхідної програми обчислювальних ресурсів від довжини вхідного
ланцюга, то компілятор, побудований на основі такого розпізнавача буде неефективним з
точки зору швидкості роботи. Тому такі компілятори практично не використовуються, а
всі реально існуючі компілятори виконують аналіз вхідної програми в 2 етапи:
1) синтаксичний аналіз на основі МП-розпізнавача;
2) семантичний аналіз.
КВ-граматики, за допомогою яких описують синтаксис мов програмування, не
дозволяють задавати контекстні умови, які має люба мова.
Найбільш часто зустрічаються такі такі контекстні умови:
1. Кожен ідентифікатор, який використовується в програмі повинен бути
описаний не більше одного разу в одній зоні опису;
2. При виклику функцій кількість фактичних параметрів і їхні типи повинні
відповідати числу і типам формальних параметрів.
3. Як правило в мовах програмування накладаються обмеження на типи
операндів любої операції, визначеної в даній мові, наприклад, на типи лівої і
правої частини оператора присвоєння і тип порівняння в циклі і т. д.
Перевіркою контекстних умов часто називають семантичним аналізом. Його можна
виконувати зразу після синтаксичного аналізу, а деякі вимоги (наприклад, обмеження на
типи операндів в виразі) під час генерації коду.
Для перевірки семантичної правильності програми необхідно мати всю інформацію
про знайдені лексичні одиниці мови.
3. 10 Розподіл пам’яті. Принципи розподілу пам’яті
Розподіл пам’яті – це процес, який ставить у відповідність лексичним одиницям
вхідної програми адресу, атрибути і розмір області пам’яті, необхідний для цієї лексичної
одиниці. Область пам’яті – це блок комірок, який виділяється для даних, якимось чином
об’єднаних логічно. Логіка таких об’єднань задається семантикою вхідної мови. Розподіл
пам’яті працює з лексичними одиницями мови. Як правило вхідними даними для процесу
розподілу пам’яті в комп’ютері служить ТІ, побудована ЛА, і декларативна частина
програми (так звана “область опису”), отримана в результаті синтаксичного аналізу.
Процес розподілу в сучасних компіляторах, як правило, працює з відносними, а не
абсолютними адресами комірок пам’яті. Розподіл пам’яті виконується перед генерацією
коду результуючої програми, тому що його результати повинні бути використані в
процесі генерації коду.
В усіх мовах програмування є поняття “базового типу даних”. Розмір області
пам’яті , необхідних для лексичної одиниці базового типу, вважається наперед відомим.
Розмір пам’яті, який виділяється під такі лексичні одиниці не залежить від версії
компілятора, що забезпечує сумісність і переносимість вхідної програми.
Частіше за все розмір пам’яті для базового типу залежить і від семантики вхідної
мови і від архітектури обчислювальної системи.
Наприклад, в С базових типах є: char, int і так далі. Розмір типу int для 16-
розрядного процесора 2 байта, а для 32-розряного - 4 байта.
Щоб не прив’язувати програму жорстко до конкретної архітектури
використовуючи механізми визначення розміру пам’яті для типу даних (в С наприклад,
функція sizeof).
Для більш складних структур даних використовують правила розподілу пам’яті, які
визначаються семантикою (змістом) цих структур.
Правила розподілу пам’яті під основні види структур даних:
- для масивів – добуток числа елементів в масиві на розмір пам’яті для одного
елемента
46