Смекни!
smekni.com

Розробка системних програмних модулів систем програмування (стр. 3 из 4)


Лексеми мають такі класи:

- клас лексем блоку

- клас операторів вводу виводу

- клас операторів присвоєння

- клас математичних операторів

- клас операторів порівняння

- клас логічних операторів

- клас ідентифікаторів

- клас операторів циклу

- клас лексем оголошення

- клас лексем опису і аргументів виводу

- клас констант

Атрибути лексем з використовуються при синтаксичному аналізі. Лексеми мають наступні коди:

Нерозпізнана лексема - -1

Ключові слова - 0

Ідентифікатори - 1

Числові константи - 2

Рядкові константи - 3

Коментарі - 4

= - 5

! - 6

& - 7

| - 8

<> - 9

>> - 10

; - 11

, - 12

) - 13

( - 14

Ключові слова мають такі коди:

PROGRAMM - 15

VAR - 16

START - 17

FINISH - 18

INT32_t - 19

BOOLEAN - 20

READ - 21

WRITE - 22

ADD - 23

SUB - 24

TRUE - 25

FALSE - 26

WHILE -27

DO - 28

MUL - 29

DIV -30

MOD - 31

LE - 32

GE -33

Атрибути використовуються генератором коду для формування відповідних процедур мовою асемблер.

Для зберігання таблиці ідентифікаторів використовується Hashtable identy = new Hashtable()

Полем таблиці є клас Iden_info він містить наступні поля:

id type Id_value
зберігання ідентифікаторів зберігання типу змінної зберігання значення змінної

public class Iden_info

{

private string id="";

private string type = "";

private string Id_value = "";

public string Id

{

get { return id; }

set { id = value; }

}

public string Type

{

get { return type; }

set { type = value; }

}

public string Value

{

get { return Id_value; }

set { Id_value = value; }

}

}

Для запам’ятовування виразу в постфікс ній формі використовується ArrayList.

3.3. Розробка лексичного аналізатора.

Лексичний аналіз – перша фаза трансляції, призначена для групування символів вхідного ланцюга в більш крупні конструкції, що називаються лексемами. З кожною лексемою зв’язано два поняття:

Клас лексеми, що визначає загальну назву для категорії елементів, що мають спільні властивості (наприклад, ідентифікатор, ціле число, рядок символів і т. д.).

Значення лексеми, що визначає підрядок символів вхідного ланцюга, що відповідають розпізнаному класу лексеми. В залежності від класу, значення лексеми може бути перетворено у внутрішнє представлення вже на етапі лексичного аналізу. Так, наприклад, роблять з числами, перетворюючи їх в машинне двійкове представлення, що забезпечує більш компактне зберігання і перевірку правильності діапазону на ранній стадії аналізу.

3.3.1. Розробка граф-схеми алгоритму

При розробці алгоритму роботи лексичного аналізатора використовується скінченний автомат.

Особливостями цього алгоритму є те, що розбір виконується відносно кількості символів з яких складаються лексеми. За даним алгоритмом всі лексеми поділяються на односимвольні (!, &, |, ; ) дво символьні (>>, <>, ==) та багатосимвольні. Для кожного класу багатосимвольної лексеми розроблена функція, яка виділяє лексему, або констатує що дана лексема не відноситься до жодного з заданих класів лексем.

Рис 1.Граф-схема роботи лексичного аналізатора

Блок 1 – Початок роботи лексичного аналізатора

Блок 2 – Відкриття і порядкове читання вхідного файлу з текстом програми

Блок 3 – Перевірка чи не досягнутий кінець файлу

Блок 4 – Виділення першого символу нової лексеми

Блок 5 – Перевіряє чи перший символ A-Z

Блок 6 – Виконання функції ParseKeyWords()

Блок 7 – Перевіряє чи перший символ a-z

Блок 8 – Виконання функції ParseIdent()

Блок 9 – Перевіряє чи перший символ 0-9

Блок 10 – Виконання функції ParseNum()

Блок 11 – Перевіряє чи перший символ “

Блок 12 – Виконання функції ParseString()

Блок 13 – Перевіряє чи символ є оператор

Блок 14 – Зберігання до таблиці лексем

Блок 15 – Перевіряє чи перший символ є $

Блок 16 – Виконання функції ParseComments()

Блок 17 – Перевіряє чи символ є розділювач

Блок 18 – Зберігання до таблиці лексем

Блок 19 – Якщо перший символ не є жодним з вищеперечислених

Блок 20 – Виконання функції ParseNoLex()

Блок 21 – Якщо файл прочитано, завершення роботи лексичного аналізатора

3.3.2Опис програми реалізації лексичного аналізатора

Програма по рядках читає вхідний файл. Прочитаний рядок передає як параметр функції Parse класу Parser. В лексичному аналізаторі для розпізнання використовуються наступні функції:

- Функція Parse() аналізує перший символ нової лексеми:

якщо перший символ A-Z, то запускається функція ParseKeyWords()

якщо перший символ a-z, то запускається функція ParseIdent()

якщо перший символ 0-9 або -, то запускається функція ParseNum()

якщо перший символ =,<,>,!,&,|,;, , ,(,) відбувається збереження лексеми

якщо перший символ $, то запускається функція ParseComments()

якщо перший символ “,то запускається функція ParseString()

якщо перший символ не є жодним з вищезгаданих то запускається процедура ParseNoLex()

- Функція ParseKeyWords() виділяє послідовність символі, які можуть містити ключові слова і перевіряє чи ця послідовність символів є ключовим словом і якщо це ключове слово зберігає його, як лексему

- Функція ParseIdent()виділяє послідовність символі, які можуть містити ідентифікатори і зберігає ідентифікатор

- Функція ParseNum()виділяє послідовність символі, які можуть містити числові константи і зберігає лексему

- Функція ParseComments() перевіряє чи 2 символ теж $, то всі символи до кінця рядка вважає коментарем

- Функція ParseString() шукає символ завершення рядка і всі символи між початком і кінцем рядка вважає рядковою константою

- Функція ParseNoLex() шукає розділювач і вважає що всі символи, які вона виділила є нерозпізнаною лексемою


3.4.Розробка синтаксичного аналізатора

Синтаксичний розбір (розпізнавання) є першим етапом синтаксичного аналізу. Саме при його виконанні здійснюється підтвердження того, що вхідний ланцюжок символів є програмою, а окремі підланцюжки складають синтаксично правильні програмні об'єкти. Вслід за розпізнаванням окремих підланцюжків здійснюється аналіз їх семантичної коректності на основі накопиченої інформації. Потім проводиться додавання нових об'єктів в об'єктну модель програми або в проміжне представлення.

Розбір призначений для доказу того, що аналізований вхідний ланцюжок, записаний на вхідній стрічці, належить або не належить безлічі ланцюжків породжуваних граматикою даної мови. Виконання синтаксичного розбору здійснюється розпізнавачами, тому даний процес також називається розпізнаванням вхідного ланцюжка. Мета доказу в тому, щоб відповісти на питання: чи належить аналізований ланцюжок безлічі правильних ланцюжків заданої мови. Відповідь «так» дається, якщо така приналежність встановлена. Інакше дається відповідь «ні». Отримання відповіді «ні» пов'язано з поняттям відмови. Єдина відмова на будь-якому рівні веде до загальної відмови.

Щоб одержати відповідь «так» щодо всього ланцюжка, треба його одержати для кожного правила, що забезпечує розбір окремого підланцюжка. Аналізатор вибирає перший символ з сукупності лексем аналізуючи його визначає, яку функцію треба запустити щоб виконати перевірку заданого підланцюжка. Цей метод називається методом рекурсивного спуску, аналіз проводиться від кореня до листків.

Основним завданням семантичного аналізатора є перевірка типів. Також семантичний аналізатор повинен знаходити вирази, що використовуються без присвоєння та видавати попередження.

Сама програма перевірки типів базується на інформації про синтаксичні конструкції мови, представлення типів і правилах присвоєння типів конструкціям мови.

3.4.1. Розробка дерева граматичного розбору

Дерево граматичного розбору розроблено згідно правил, даних у формі розширеної нотації Бекуса-Наура, та оформлено згідно правил ЄСКД.

3.4.2 Розробка граф-схеми алгоритму

Рис 2.Граф-схема роботи синтаксичного аналізатора

Блок 1 – Початок синтаксичного аналізатора

Блок 2 – Основна функція аналізатора

Блок 3 – Перевіряє чи наступний символ Var

Блок 4 – Виконання функції ParseVAR()

Блок 5 - Перевіряє чи наступний символ INT32_t

Блок 6 - Виконання функції ParseDeclar_i()

Блок 7 - Виконання функції ParseVAR()

Блок 8 - Перевіряє чи наступний символ BOOLEAN

Блок 9 - Виконання функції ParseDeclar_b()

Блок 10 - Виконання функції ParseVAR()

Блок 11 - Перевіряє чи наступний символ START

Блок 12 - Перевіряє чи наступний символ WRITE

Блок 13 - Виконання функції ParseWRITE()

Блок 14 - Виконання функції ParseSTART()

Блок 15 - Перевіряє чи наступний символ READ

Блок 16 - Виконання функції ParseREAD()

Блок 17 - Виконання функції ParseSTART()

Блок 18 - Перевіряє чи наступний символ <ident>

Блок 19 - Виконання функції ParseEqution()

Блок 20 - Виконання функції ParseSTART()

Блок 21 - Перевіряє чи наступний символ WHILE

Блок 22 - Виконання функції ParseWHILE()

Блок 23 - Виконання функції ParseSTART()

Блок 24 – Якщо інший символ?

Блок 25 – Функція Error();

Блок 26 - Виконання функції ParseSTART()

Блок 27 - Перевіряє чи наступний символ FINISH

Блок 28 – Якщо не фініш виконання функції Error();

Блок 29 - Завершення Синтаксичного аналізатора

3.4.3 Опис програми реалізації синтаксичного та семантичного аналізатора

На вхід синтаксичного аналізатора подається таблиця лексем, створена на етапі лексичного аналізу.

В синтаксичному аналізі використовуються функції для робору всіх конструкції вхідної мови, вони рекурсивно викликають одна одну відповідно до заданих правил. Для кожного нетерміналу розроблена функція, яка перевіряє правило, яке відповідає даному нетерміналові. Також додатково описані функції Infix_to_Postfix() і Infix_to_Postfix_b() і функція isDeclaredVariable() яка виконує семантичний аналіз, тобто перевіряє чи змінна оголошена, чи вона відповідно до контексту має правельний тип і чи має значення.