Page 33 - 4761
P. 33
Послідовна робота лексичного аналізатора і синтаксичного являє собою самий
простий варіант їхньої взаємодії. Вона простіша в реалізації і забезпечує більш високу
швидкість роботи комп’ютера, ніж їхня паралельна взаємодія.
Для більшості мов програмування границі лексем розпізнаються за заданим
термінальним символом ( пробіл , знаки операцій, символ коментарів, розділювачі і т.д.).
Набір цих символів залежить від синтаксису вхідної мови.
Проте для багатьох мов програмування на етапі лексичного аналізу може не
вистачати інформації для однозначного визначення типу і границь чергової лексеми. Але
й тоді стараються уникнути паралельної роботи лексичного і синтаксичного аналізаторів.
В ряді випадків допомагає принцип вибору з усіх можливих лексем лексеми найбільшої
довжини: тобто черговий символ з вхідного потоку даних додається в лексему завжди,
коли він може бути туди доданий. Як тільки символ не можна додати в лексему, то
вважається, що він є границею лексеми і початком наступної лексеми (якщо він не є
пустим розділювачем , знаком табуляції, знаком переводу рядка, знаком коментарю тощо.
Такий принцип не завжди дозволяє правильно визначити границі лексеми в такому
випадку, коли вони не розділені пустими символами.
Наприклад, рядок в мові С
К = і+++++j
можна буде розбито на лексеми так
К=i++ ++ + j // і це – невірно.
Лексичний аналізатор розбираючи рядок з 5 знаків, 2 рази вибрав лексему
найбільшої довжини – знак операції інкремента ++, хоча це невірно. Компілятор має дати
повідомлення про помилку, хоча існує вірний варіант розпізнавання цього рядка.
Розробники компіляторів деколи відсікають деякі вірні, але не цілком читабельні
варіанти вхідних програм. Спроби ускладнити лексичний розпізнавач приведуть до
необхідності його взаємозв’язку з синтаксичним розбором. Це приведе до їхньої
паралельної роботи, що знизить ефективність всього компілятора.
Отже, останній варіант організації взаємодії лексичного і синтаксичного
аналізаторів є більш ефективним, так як не потребує організації складних механізмів
обміну даними і не потребує повторного читання вже розібраних лексем.
Виконання дій, пов’язаних з лексемами
Ця проблема є меншою, ніж визначення границь лексеми. Фактично кінцевий
автомат, який лежить в основі лексичного аналізатора, повинен мати не тільки вхідну
мову, але й вихідну. Він повинен не тільки вміти розпізнавати правильну лексему на
вході, але й породити зв’язану з нею послідовність символів на виході.
Лексичний аналізатор повинен вміти: знаходити лексеми, породжувати ланцюг
символів на вихідній мові, записувати лексему в таблицю лексем, шукати її в ТІ,
записувати нову лексему в ТІ. Як правило ці дії виконуються зразу ж при виявленні кінця
лексеми, що розпізнаються.
В кінцевому автоматі, який лежить в основі лексичного аналізатора, ці дії
відображаються просто – досить мати можливість з кожним переходом на графі автомата
(або в функції переходів автомата) зв’язати виконання деякої довільної функції f (q,a), де q
– поточний стан автомата, а – поточний стан вхідних символів. Функція f (q,a) може
виконувати любі дії, доступні лексичному аналізатору:
- поміщати нову лексему в ТЛ;
- перевіряти наявність знайденої лексеми в ТІ;
- додавати нову лексему в ТІ;
- видавати користувачу повідомлення про знайдені помилки і попереджувати про
знайдені неточності в програмі;
- переривати процес компіляції.
31