ються на символи, що належать яким-небудь лексемам, і символи, що розділяють лексеми (роздільники). У деяких випадках між лексемами може і не бути роздільників. p align="justify"> Зазвичай всі лексеми поділяються на класи. Прикладами таких класів є числа (цілі, восьмеричні, шістнадцяткові, дійсні і т.д.), ідентифікатори, рядки. Окремо виділяються ключові слова і символи пунктуації (іноді їх називають символи-обмежувачі). Як правило, ключові слова - це деякий кінцевий підмножина ідентифікаторів. p align="justify"> Лексичний аналізатор побудований з використанням GNU Flex - генератора лексичних аналізаторів. Вхідним файлом для Flex є файл cl, що містить опис лексики мови. Lex-файл складається з трьох секцій - блоку визначень, блоку правил і блоку коду на Сі. Блоки поділяються c допомогою рядків, що містять%%. p align="justify"> Блок визначень включає в себе описи іменованих регулярних виразів у форматі: ім'я вираз. Кожен вираз описується в окремому рядку. br/>
([Pp] [+ -]? {D} +)
Блок правил містить правила для визначення належності лексеми класу мови в форматі: В«регулярний виразВ» {код на сі, що обробляє лексему і повертає її клас}
Кожне правило розташовується в окремому рядку. Приклад правила для визначення десяткового константи:
[1-9] {D} * {IS}?
У процесі створення лексичного аналізатора командою lex cl з Lex-файлу генерується код на C, що міститься у файлі c.lexer.c. Цей файл містить функцію yylex (), яка і виконує лексичний аналіз програми. Після кожного виклику функція повертає тип лексеми з вхідного потоку, або 0, у разі його закінчення, а також поміщає в змінну yytext текст лексеми. Крім того, в будь-яких інших зовнішніх (extern) змінних може перебувати інформація про лексеме, отримана з користувальницького коду на С. Для коректної роботи даної функції мінлива yyin повинна вказувати на відкритий файл з вихідним текстом програми. br/>В
Малюнок 1 - приклад роботи лексичного аналізатора (без помилок)
В
Малюнок 2 - приклад роботи лексичного аналізатора (з помилками)
2. Синтаксичний аналізатор
Синтаксичний аналіз - це процес, який визначає, чи належить деяка послідовність лексем мови, породжуваному граматикою. В принципі, за будь граматиці можна побудувати синтаксичний аналізатор, але граматики, використовувані на практиці, мають спеціальну форму. Наприклад, відомо, що для будь контекстно-вільної граматики може бути побудований аналізатор, складність якого не перевищує O (n3) для вхідного рядка довжини n, але в більшості випадків по заданому мови програмування ми можемо побудувати таку граматику, яка дозволить сконструювати і більш швидкий аналізатор. Аналізатори реально використовуваних мов зазвичай мають лінійну складність; це досягається, наприклад, за рахунок перегляду вихідно...