МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА”
ІКТА
/
Пояснювальна записка
до курсової роботи
з дисципліни:
"Системне програмування" (III курс, 5-й семестр)
На тему : «Розробка системних програмних модулів та компонент систем програмування.»
Анотація
Курсова робота з дисципліни "Системне програмування" вміщає в собі весь матеріал, який ми вивчали протягом даного курсу. Вона узагальнює матеріал і закріпляє навички які ми набули при вивченні матеріалу.
В ній ми маємо продемонструвати розробку транслятора з вхідної мови програмування, яка нам була задана, на мову асемблер, компілювати код і створити виконавчий файл. Транслятор повинен виконувати: лексичний аналіз, синтаксичний аналіз, семантичний аналіз, виводити список помилок при наявності та попереджень. В цій курсовій роботі буде використовуватися лексичний аналізатор на базі скінченного автомата та на основі магазинного автомата.
Анотація……………………………………………………………………………………2
Зміст………………………………………………………………………………………3
Завдання на курсову роботу……………………………………………………………..4
Вступ………………………………………………………………………………………5
Огляд методів та способів проектування трансляторів………………………….7
Формальний опис вхідної мови програмування………………………………….8
Деталізований опис вхідної мови в термінах розширеної нотації
Бекуса-Наура………………………………………………………………………………………8
Опис термінальних символів та ключових слів……………………………………..10
Розробка транслятора вхідної мови програмування……………………………12
Вибір технології програмування………………………………………………………..12
Проектування таблиць транслятора та вибір структур даних………………13
Розробка лексичного аналізатора……………………………………………………..16
Розробка граф-схеми алгоритму…………………………………………17
Опис програми реалізації лексичного аналізатора…………………..17
Розробка синтаксичного та семантичного аналізатора……………………….19
Розробка дерев граматичного розбору…………………………………20
Розробка граф-схеми алгоритму…………………………………………21
Опис програми реалізації синтаксичного та
семантичного аналізатора…………………………………………………………………….22
Розробка генератора коду………………………………………………………………23
Розробка граф-схеми алгоритму…………………………………………23
Опис програми реалізації генератора коду…………………………….24
Опис інтерфейсу та інструкції користувача……………………………………..25
Відлагодження та тестування програми…………………………………………27
Виявлення лексичних помилок……………………………………………………………27
Виявлення синтаксичних помилок………………………………………………………28
Виявлення семантичних помилок……………………………………………………….29
Загальна перевірка коректності роботи транслятора…………………………30
Висновки…………………………………………………………………………………31
Список літератури……………………………………………………………………..32
Додатки………………………………………………………………………………….33
А. Лістинг програм………………………………………………………………………………33
Завдання на курсову роботу
Тема: Розробка транслятора з вхідної мови програмування.
- типи даних: longint, boolean, const string;
- оператор вводу: read;
- оператор виводу: write;
- блок тіла програми: startblok variable, endblok
- оператор: if goto goto (Бейсік);
- регістр ключових слів: low;
- регістр ідентифікаторів: Low8 ;
- операції арифметичні: add, sub, *, /,%;
- операції порівняння: ==, <>, <<, >>
- операції логічні: !, &, |;
- коментар: ##..
- ідентифікатори змінних, числові константи, рядкові константи;
- оператор присвоєння: :=;
Для отримання виконавчого файлу з вихідного асемблерного коду потрібно використовувати ml.ex (MASM32) вбудований в MS Visual Studio 2010.
Вступ
Компілятор (англ. Compiler від англ. to compile збирати в ціле) - комп'ютерна програма , що перетворює (компілює) програмний код, написаний певною мовою програмування, на семантично еквівалентний код в іншій мові програмування, який, як правило, необхідний для виконання програми машиною.
Перші компілятори з'явилися на початку 50-х років.
Транслятор – це той самий компілятор, з тею різницею, що генерує він не об’єктний код, а код на іншій мові програмування.
Проблема трансляції полягає в пошуку відповідності тексту вхідної програми конструкціям, що визначені граматикою. Граматика визначає форму або синтаксис допустимих виразів мови. Тому текст вхідної мови зручно подавати у вигляді послідовності лексем, що є неподільними одиницями мови. За допомогою транслятора програміст повинен мати можливість редагувати текст вхідної мови. Для цього він має виявляти всі невідповідності тексту програми конструкціям мови і у випадку відсутності помилок генерувати код.
Основні задачі, які виконуються різними компіляторами та трансляторами, по суті, одні і ті ж. Розуміючи ці задачі, існує можливість створювати транслятори для різних початкових мов і цільових машин з використанням одних і тих же базових технологій.
1. Огляд методів та способів проектування трансляторів
В даній курсовій роботі згідно із завданням для парних варіантів необхідно реалізувати нисхідний метод граматичного розбору. Низхідний розбір — один з методів визначення приналежності вхідного рядка деякій формальній мові, описаній LL(k)-граматикою.
Для кожного нетермінального символу K будується функція, яка для будь-якого вхідного слова x робить дві речі:
Знаходить найбільший початок z слова x, здатний бути початком виводжуваного з K слова
Визначає, чи є початок z виводжуваним з K
Така функція має задовольняти наступні критерії:
зчитувати із ще необробленого вхідного потоку максимальний початок A, який є початком деякого слова, виводжуваного з K
визначати чи є A вивідним з K або просто невивідним початком виводжуваного з K слова
У випадку, якщо такий початок зчитати не вдається (і коректність функції для нетермінала K доведена), тоді вхідні дані не відповідають мові, і потрібно зупинити розбір.
Розбір містить у собі виклики описаних вище функцій. Якщо для зчитаного нетермінала є складене правило, тоді при його розборі будуть викликані інші функції для розбору терміналів, що входять в нього. Дерево викликів, починаючи із самої«верхньої» функції еквівалентно дереву розбору.
2. Формальний опис вхідної мови програмування
2.1. Деталізований опис вхідної мови в термінах розширеної нотації Бекуса-Наура.
<program> ::= startprogram startblok variable <VAR_blok><code_blok> endblok.
<VAR_blok> ::=<declarations> [{;<declarations>} ];.
<declarations>::=<type_i><declaration_i> [{,<declaration_i>}] | <type_b> <declaration_b> [{,<declaration_b>}] .
<type_i> ::=longint.
<type_b> ::=boolean.
<declaration_i> ::= <ident> [ := <const_i>] .
<declaration_b> ::= <ident> [ := <const_b>] .
<ident> ::= <letter>[<l _or_n>] .
<l_or_n> ::= <letter>|<number> .
<letter>::=a|b|c|d|e|f|g|h|i|j|k|l|n|m|o|p|q|r|s|t|u|v|w|x|y|z .
<number> ::= 0|1|2|3|4|5|6|7|8|9 .
<const_i> ::= [-|+]<number>[{number}] .
<const_b> ::=true|false
<code_blok> ::= <statement> [{<statement>}] .
<statement> ::= <equation>|<cycle>|<read>|<write> .
<equation> ::= <ident> := <expression_i>|<expression_b>; .
<expression_i>::= <term> [{add <term> | sub <term>}].
<term>::=<ident>|<const_i>|<factor>.
<factor>::= [{* <term> | / <term>| % <term> | <brackets>}].
<brackets>::=(<expression_i>).
<expression_b>::= <term_b> [{== <term_b> | != <term_b> | << <term_b>| >> <term_b>}].
<term_b>::=<ident>|<const_b>|<factor_b>.
<factor_b>::=<term_b> [{ |<term_b> | <and> |<not>|<brackets_b>}].
<and>::= [{ &<term_b>}]
<not>::=!<factor_b>
<brackets_b>::=(<expression_b>).
<cycle> ::= if (<expression_b>|<ident>) then [goto <label1>] <code_blok>
[goto <label2>][<label1><code_blok><label2>]
<read> ::= read(<ident>); .
<write> ::= write(<expression_і>|<string>); .
<string> ::= “[{<l_or_n>}]” .
2.2. Термінальні символи та ключові слова.
startprogram – початок тексту програми, наступним описується ім’я програми;
startblok variable - блок опису змінних і початок блоку
endblok – кінець тіла програми (циклу);
write– оператор виводу (змінних і рядкових констант)
read – оператор вводу змінних;
:= - оператор присвоєння;
if – початок умовного оператора
goto – безумовний перехід
add – операція додавання
sub – операція віднімання
* – операція множення
/ – операція ділення
% – операція знаходження залишку від ділення;
== – операція перевірки на рівність;
!= – перевірка на нерівність;
<< – перевірка чи менше;
>> – перевірка чи більше/рівно;
! – операція логічного заперечення;
& – кон’юнкція;
| – диз’юнкція;
longint – 32ох розрядні знакові цілі;
boolean – однобайтні логічні змінні;
## – початок коментаря
“ – початок/завершення рядкової константи при операції виводу;
,– розділювач між деклараціями змінних;
; – ознака кінця оператора;
(– відкриваюча дужка;
) – закриваюча дужка;
Як термінальні символи використовуються також усі арабські цифри (0–9), латинські букви (a-z, A-Z), символи табуляції, символ переходу на нову стрічку, пробіл.
3. Розробка транслятора вхідної мови програмування
3.1. Вибір технології програмування.
Для ефективної роботи створюваної програми важливу роль відіграє попереднє складення алгоритму роботи програми, алгоритму написання програми і вибір технології програмування.
Тому при складанні транслятора треба брати до уваги швидкість компіляції, якість об’єктної програми. Проект повинен давати можливість просто вносити зміни.
Для реалізації лексичного аналізу в курсовій роботі використано метод перебору, тобто до чергової лексеми додається наступна буква, а тоді здійснюється пошук лексеми в таблицях ключових слів, та ідентифікаторів, якщо лексема не знайдена, тоді видається повідомлення про помилку. Синтаксичний аналіз базується на перевірці послідовності класів лексем, наприклад, якщо після оператора присвоєння слідує синтаксична лексема, чи після математичного оператора слідує лексема з класу порівнянь, то буде сформовано повідомлення по помилку. Для розробки синтаксичного аналізатора використано метод рекурсивного спуску. На фазі семантичного аналізу здійснюється перевірка на відповідність типів. На цьому етапі перевіряється, чи не використовуються в одному виразі змінні одного типу, та чи не застосовано до них недопустимих операцій. Генератор коду починає свою роботу, якщо на попередніх фазах не було виявлено помилок. В залежності від коду лексеми в асемблерний файл вставляється конкретний набір процедур. Для реалізації обчислень арифметичних виразів використовується переведення їх у постфіксну форму, після чого такий вираз обчислюється з використанням математичного співпроцесора. Для переведення виразу у постфіксну форму використовується структура даних стек
3.2. Проектування таблиць транслятора.
Для реалізації лексичного аналізу створюємо таблицю, в яку поміщаємо всі лексеми (ArrayList lexs = new ArrayList()), і таблицю (Hashtable idt = new Hashtable()) для ідентифікаторів, які будуть введені користувачем. Ім’я програми в цю таблицю не заноситься. Для реалізації таблиці лексем описаний тнаступний клас Lex:
Поле id призначене для зберігання номера лексеми;
Поле lex призначене для зберігання самої лексеми;
Поле com призначене для зберігання класу до якого належить лексема;
Поле typeKey призначене для зберігання класу Ключових слів до якого належить лексема;
Поле typeLex призначене для зберігання коду лексеми.
Сама таблиця лексем є масивом таких структур.
Відомості про класи з таблиці лексем використовуються при синтаксичному аналізі.
Лексеми мають наступні коди:
Нерозпізнана лексема - -1
Ключові слова - 0
Ідентифікатори - 1
Числові константи - 2
Рядкові константи - 3
Коментарі - 4
== - 5
! - 6
& - 7
| - 8
!= - 9
<< - 10
; - 11
, - 12
) - 13
( - 14
* - 15
/ - 16
% - 17
<< -18
>> - 19
Ключові слова мають такі коди:
startprogram - 0
startblok variable - 1
startblok - 2
endblok - 3
longint - 4
boolean - 5
read - 6
write - 7
add - 8
sub - 9
true - 10
false - 11
if -12
goto - 13
Коди використовуються генератором коду для формування відповідних процедур мовою асемблер.
Для зберігання таблиці ідентифікаторів використовується Hashtable idt = new Hashtable()
Полем таблиці є клас Iden він містить наступні поля:
Поле iden призначене для зберігання ідентифікаторів;
Поле type призначене для зберігання типу змінної.
Поле Value призначене для зберігання значення змінної.
3.3. Розробка лексичного аналізатора.
Лексичний аналіз – перша фаза трансляції, призначена для групування символів вхідного ланцюга в більш крупні конструкції, що називаються лексемами. З кожною лексемою зв’язано два поняття:
Клас лексеми, що визначає загальну назву для категорії елементів, що мають спільні властивості (наприклад, ідентифікатор, ціле число, рядок символів і т. д.).
Значення лексеми, що визначає підрядок символів вхідного ланцюга, що відповідають розпізнаному класу лексеми. В залежності від класу, значення лексеми може бути перетворено у внутрішнє представлення вже на етапі лексичного аналізу. Так, наприклад, роблять з числами, перетворюючи їх в машинне двійкове представлення, що забезпечує більш компактне зберігання і перевірку правильності діапазону на ранній стадії аналізу.
3.3.1. Розробка граф-схеми алгоритму
Рис 1.Граф-схема роботи лексичного аналізатора
3.3.2Опис програми реалізації лексичного аналізатора
Програма по рядках читає вхідний файл. Прочитаний рядок передає як параметр функції Parse класу Parser. В лексичному аналізаторі для розпізнання використовуються наступні функції:
Функція Rozbir() аналізує перший символ нової лексеми:
якщо перший символ a-z, то запускається функція KeyWords()
якщо перший символ 0-9 або -, то запускається функція Num()
якщо перший символ ==,!=,<<,>>,:=,!,&,|,;, , ,(,),*,/,% відбувається збереження лексеми
якщо перший символ ##, то запускається функція Comments()
якщо перший символ “,то запускається функція String()
якщо перший символ не є жодним з вищезгаданих то запускається процедура NoLex()
Функція KeyWords() виділяє ключові слово
Функція Ident()виділяє ідентифікатор
Функція Num()виділяє числові константи і зберігає лексему
Функція Comments() виділяє коментарі
Функція String() шукає символ завершення рядка і всі символи між початком і кінцем рядка вважає рядковою константою
Функція NoLex() шукає розділювач і вважає що всі символи, які вона виділила є нерозпізнаною лексемою
3.4.Розробка синтаксичного аналізатора
3.4.1. Розробка дерева граматичного розбору
Коренем дерева є не термінальний символ <Program>. Безпосередньо його листками є термінали startprogram startblok variable ,endblok та не термінали <Var_Blok>, <Code_block>. Листками не терміналу <Var_Blok> є не термінал <declarations>. Листками не терміналу <declarations> є не термінали <declaration_i>і <declaration_b>.і термінали longint і boolean. Листками не терміналу <declaration_i> є не термінали <ident> і <const_i> і термінал :=. Листками не терміналу <declaration_b> є не термінали <ident> і <const_b> і термінал :=. Листками не терміналу <ident> є не термінали <letter> і <l _or_n>. Листками не терміналу <l_or_n> є не термінали <letter> і <number>. Листками не терміналу <letter> є термінали a, b, c, d, e, f, g, h, i, j, k, l, n, m, o, p, q, r, s, t, u, v, w, x, y, z. Листками не терміналу <number> є термінали 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Листками не терміналу <const_i> є не термінал <number> і термінал -. Листками <const_b> є термінали true|false. Листком не терміналу <code_blok> є не термінал <statement>. Листками <statement> є нетермінали <equation>, <cycle>, <READ>, <WRITE>. Листками <equation> є не термінали <ident>, <expression_i> і <expression_b> і термінал :=.Листками не терміналу <expression_i> є не термінал <term> і термінали add і sub. Листками не теміналу <term> є не термінали <ident>, <const_i>, <factor>. Лисками <factor> є не термінали <term> і <brackets> і термінали *, /, %. Листками <brackets> є не термінал <expression_i>і термінали (, ). Листками <expression_b> є не термінал <term_b> і термінали ==, !=, <<, >>. Листками <term_b> є не термінали <ident>, <const_b> і <factor_b>. Листками <factor_b> є не термінали <term_b>, <brackets_b>, <and>, <not>. Листками <and> є не термінал <term_b> і термінал &. Листками <not> є не термінал <factor_b> і термінал !. Листками <brackets_b> є не термінали <expression_b> і термінали ( і ). Листками не терміналу <cycle> є не термінали <expression_b>, <ident>, <code_blok> і не термінали (, ), if, startblock, endblock, goto, else. Листками <READ> є не термінал <ident> і термінал read, ( і ). Листками <WRITE> є не термінали <expression_i>, <string>, <expression_b>, write, (, ). Листками <string> є не термінал <l_or_n> і термінал “.
Дерево граматичного розбору розроблено згідно правил, даних у формі розширеної нотації Бекуса-Наура, та оформлено згідно правил ЄСКД.
3.4.2 Розробка граф-схеми алгоритму
Рис 2.Граф-схема роботи синтаксичного аналізатора
3.4.3 Опис програми реалізації синтаксичного та семантичного аналізатора
На вхід синтаксичного аналізатора подається таблиця лексем, створена на етапі лексичного аналізу. Потім по черзі перебираємо лексеми та аналізуємо класи лексем, що слідують за ними. Якщо після чергової лексеми слідує лексема, що має некоректний клас (наприклад після лексеми класу вводу/ виводу слідує лексема класу математичних операторів), то формується повідомлення про помилку. Також здійснюється перевірка чи не йдуть підряд дві лексеми однакового класу (за винятком синтаксичних та операції множення на від’ємне число), якщо це справджується то виводиться повідомлення про помилку. При знаходженні оператора присвоєння, математичних та логічних операторів чи операторів порівняння здійснюється перевірка атрибутів усіх ідентифікаторів, що входять у даний вираз. Якщо у виразі використовуються дані різних типів, то формується повідомлення про помилку.
При кожному знаходженні помилки в таблицю помилок додається одне поле.
3.5.Розробка генератора коду
3.5.1 Розробка граф-схеми алгоритму
Так як генерація коду тісно пов’язана з синтаксичним аналізом, тобто код конструкції генерується відразу після розпізнавання.
Рис 3.Граф-схема роботи генератора коду
3.5.2 Опис програми реалізації генератора коду
Програма починає по черзі перебирати лексеми із таблиці лексем. У відповідності до коду знайденої лексеми у проміжне представлення програми буде вставлено відповідний еквівалентний асемблерний текст. Наприклад, при зустрічі ключового слова Program, в асемблерний файл вставляється текст з описом моделі та сегментів, а при зустрічі ключового слова Var, вставляється опис сегменту даних.
Реакція на лексеми розроблена так, що пустий код не буде включений в асемблерний файл. Для того щоб уникнути помилок, імена ідентифікаторів, дані у вхідній програмі користувачем, вносяться у асемблерний файл із змінами. Наприклад, невідомо, як буде працювати згенерований код, якщо у ньому будуть зустрічатись створені користувачем змінні end, loop.
В даному трансляторі генератор коду послідовно викликає окремі функції, які записують у вихідний файл частини коду. Для кожного ланцюжка вхідної мови існує окрема функція, яка враховуючи послідовність лексем створює відповідний вихідний код.
4. Опис інтерфейсу та інструкції користувачеві
Програма G4 можна запустити з виконавчого файлу K16.exe. K16 є програмою, яка працює на платформі .NET і є візуальною програмою, тому для її запуску повинна бути встановлена платформа net framework не нижче 2 версії. R16 містить редактор тексту і транслятор. Редактор тексту дозволяє відкривати файли з розширенням *.v16.
/
Рис 4.Вікно редактора тексту
В редакторі присутні наступні функції:
Ведення і редагування тексту
Відкриття нового файл
Збереження файлу
Закриття файлу
Копіювання тексту
Запустити транслятор вхідної мови можна за допомогою пункту меню Build/Run (F5). Вікно транслятора складається з 5 вкладок:
Таблиця лексем
Таблиця Ідентифікаторів
Таблиця рядкових констант
Таблиця помилок
Файл Асемблерного коду
/
Рис 6.Вікно транслятора
Щоб отримати виконавчий файл потрібно згенерований код скомпілювати за допомогою ml.exe який вбудований в MS Visual Studio 2010.
5. Відлагодження та тестування програми
5.1. Виявлення лексичних помилок.
До помилок виявлених на етапі лексичного аналізу відносить тільки одна помилка – виявлення нерозпізнаної лексеми. Якщо було виявлено нерозпізнану лексему – в таблицю лексем заноситься поле з коментарем «нерозпізнана лексема», і їй присвоюється код -1, і на етапі синтаксичного аналізу буде згенерована помилка:
5.2. Виявлення синтаксичних помилок.
На етапі синтаксичного аналізу виявляється основна кількість помилок. Ці помилки пов’язані з невірними записами конструкцій вхідної мови. Всі помилки виявленні на етапі синтаксичного аналізу заносяться в таблицю помилок, Таблиця помилок містить лексему яка спричинила помилку, коментар і рядок в якому виникла помилка. Приклад таблиці помилок наведений на рис. 8:
5.3. Виявлення семантичних помилок.
Суттю виявлення семантичних помилок є перевірка числових констант на відповідність типу INT32_t , тобто знаковому цілому числу з відповідним діапазоном значень і перевірку на коректність використання змінних INT32_t і BOOLEAN у цілочисельних і логічних виразах.
5.4. Загальна перевірка коректності роботи транслятора.
Загальна перевірка полягає в транслюванні завідомо коректної вхідної програми з використанням всіх можливостей мови в асемблерний код та перевірці на правильність виконання програми попередньо скомпільованої та злінкованої за допомогою ml.exe
Текст програми:
startprogram
variable longint a:=543,b:=3,d:=56,c;
boolean b:=true;
longint fdk:=589;
startblok ##початок програми
write("Hello");
read (a);
if (b) goto
c:=a add b;
else
c:=a*d;
write(c);
endblok
Результати роботи програми:
/
Висновки
Підчас виконання курсової роботи:
1. Складено формальний опис мови програмування K16 у формі розширеної нотації Бекуса-Наура, дано опис усіх символів та ключових слів.
2. Створено транслятор мови програмування K16, а саме:
2.1.1. Розроблено лексичний аналізатор, здатний розпізнавати лексеми, що є описані в формальному описі мови програмування, та додані під час безпосереднього використання транслятора.
2.1.2. Розроблено синтаксичний аналізатор на основі рекурсивного спуску. Дерево виклику функцій згідно правил записаних в нотації у формі Бекуса-Наура.
2.1.3. Розроблено генератор коду, який починає свою роботу під час коректного виявлення кожної конструкції і генерує код який відповідає кожній конструкції вхідної мови. Проміжним кодом генератора є програма на мові Assembler(i586). Вихідним кодом є машинний код, що міститься у виконуваному файлі
3. Проведене тестування транслятора за допомогою тестових програм за наступними пунктами: Виявлення лексичних помилок. Виявлення синтаксичних помилок. Загальна перевірка роботи компілятора. Тестування не виявило помилок в роботі компілятора, а всі помилки в тестових програмах мовою prog були виявлені і дано попередження про їх наявність. В результаті виконання даної курсової роботи було успішно засвоєно методи розробки та реалізації компонент системного програмного забезпечення. Список використаної літератури
Ахо и др. Компиляторы: принципы, технологии и инструменты.: Пер с англ. – М.: Издательський дом «Вильямс». 2003. – 768 с.: ил. Парал. тит. англ.
Шильдт Г. С#. – Санкт-Петербург: BXV, 2002. – 688 с.
Компаниец Р.И., Маньков Е.В., Филатов Н.Е. Системное программирование. Основы построения трансляторов. – СПб.: КОРОНА принт, 2004. – 256 с.
Б. Керниган, Д. Ритчи «Язык программирования Си». – Москва «Финансы и статистика», 1992. – 271 с.
Л. Дао. Программирование микропроцессора 8088. Пер.с англ.М. «Мир», 1988.
Ваймгартен Ф. Трансляция языков программирования. – М.: Мир, 1977.
Додатки:
Додаток А
Лістинг програми:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Collections;
namespace Notepad
{
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; }
}
}
public class Lexem
{
private int id=0;
private string lex = "";
private string comments = "";
public int Id
{
get { return id; }
set { id = value; }
}
public string Lex
{
get { return lex; }
set { lex = value; }
}
public string Comments
{
get { return comments; }
set { comments = value; }
}
}
static class Parser
{
public static int num = 0;
public static string Comments;
public static Hashtable identy = new Hashtable();
public static ArrayList lexems = new ArrayList();
static Iden_info id_info;
static Lexem lexem;
public static void Parse(string line)
{
line = line + '\n';
for (int i = 0; i < line.Length;i++)
{
if (line.Length == 1)
continue;
if (Form1.isCom)
i = ParseComments(line, i) - 1;
if (line[i] >= 'a' && line[i] <= 'z')
{
i = ParseKeyWords(line, i) - 1;
continue;
}
if ((line[i] >= '0' && line[i] <= '9') || line[i] == '-')
{
i = ParseNum(line, i)-1;
continue;
}
switch (line[i])
{
case ':':
if (line[i + 1] == '=')
{
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = ":=";
lexem.Comments = "Оператор присвоєння";
lexems.Add(lexem);
i++;
}
else
{
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = ":";
lexem.Comments = "Нерозпізнана лексема";
lexems.Add(lexem);
}
break;
case '&':
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = "&";
lexem.Comments = "Оператор логічного I";
lexems.Add(lexem);
break;
case '!':
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = "!";
lexem.Comments = "Оператор логічного НЕ";
lexems.Add(lexem);
break;
case '|':
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = "|";
lexem.Comments = "Оператор логічного АБО";
lexems.Add(lexem);
break;
case '>':
if (line[i + 1] == '>')
{
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = ">>";
lexem.Comments = "Оператор більше";
lexems.Add(lexem);
i++;
}
else
{
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = ">";
lexem.Comments = "Нерозпізнана лексема";
lexems.Add(lexem);
}
break;
case '<':
if (line[i + 1] == '<')
{
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = "<<";
lexem.Comments = "Оператор менше";
lexems.Add(lexem);
i++;
}
else
{
if (line[i + 1] == '>')
{
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = "<>";
lexem.Comments = "Оператор нерівно";
lexems.Add(lexem);
i++;
}
else
{
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = "<";
lexem.Comments = "Нерозпізнана лексема";
lexems.Add(lexem);
}
}
break;
case '=':
if (line[i + 1] == '=')
{
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = "==";
lexem.Comments = "Оператор порівняння";
lexems.Add(lexem);
i++;
}
else
{
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = "=";
lexem.Comments = "Нерозпізнана лексема";
lexems.Add(lexem);
}
break;
case '*':
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = "*";
lexem.Comments = "Арифметичний оператор";
lexems.Add(lexem);
break;
case '/':
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = "/";
lexem.Comments = "Арифметичний оператор";
lexems.Add(lexem);
break;
case '%':
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = "%";
lexem.Comments = "Арифметичний оператор";
lexems.Add(lexem);
break;
case '\"':
i = ParseString(line, i)-1;
break;
case '#':
i = ParseComments(line, i) - 1;
break;
case ';':
lexem = new Lexem();
lexem.Id = num;
num++;
lexem.Lex = ";";
lexem.Comments = "Розділювач";
lexems.Add(lexem);
break;
case ',':
lexem = new