Розробка та реалізація компонент системного програмного забезпечення

Інформація про навчальний заклад

ВУЗ:
Національний університет Львівська політехніка
Інститут:
Не вказано
Факультет:
Не вказано
Кафедра:
Не вказано

Інформація про роботу

Рік:
2012
Тип роботи:
Курсовий проект
Предмет:
Комп’ютерна схемотехніка

Частина тексту файла (без зображень, графіків і формул):

Міністерство освіти і науки, молоді та спорту Національний університет “Львівська політехніка” Кафеда СКС Курсоий проект з курсу “Системне програмне забезпечення” Анотація В даному курсовому проекті розроблено компілятор з СІ-подібної вхідної мови програмування . Компілятор розроблений в середовищі програмування Microsoft Visual C++ на мові ANSI С, та поданий у пояснювальній записці, а також в електронному варіанті. В пояснювальній записці подано огляд існуючих методів розробки компіляторів, детальний опис мови, а також описано процес розробки програми компілятора на рівні блок-схем і тексту програми. До проекту додано результати тестування програми. Зміст Анотація 2 Зміст 3 Завдання 4 Формальний опис вхідної мови програмування 6 Деталізований опис вхідної мови 6 Перелік термінальних символів та ключових слів 6 Формальний опис вхідної мови в термінах BNF 6 Правила написання правил у розширеній нотації Бекуса-Наура: 6 Формальний опис заданої вхідної мови в термінах BNF 8 Повне дерево граматичного розбору 9 Розробка компілятора вхідної мови програмування 11 Лексичний аналiз 13 Синтаксичний аналiз 14 Генерація коду 15 Відладка та тестування компілятора 16 Робоча програма test1.txt 16 Текст програми 16 Результат лексичного аналізу 16 Результат синтаксичного аналізу 17 Результат генерації коду 17 Програма з помилкою test2.txt 18 Текст програми 18 Результат лексичного аналізу 18 Результат синтаксичного аналізу 19 Висновки 20 Література 21 Додатки 22 Текст програми 22 Завдання Розробити компілятор заданої вхідної мови програмування, до якої висуваються наступні вимоги: Кожна програма починається зі слова begin і закінчується словом end. Все що до begin і після end не аналізується. Наприклад як у мові Паскаль begin end. Програма має надавати можливість працювати зі змінними таких типів: Integer – цілі числа; Char – символи; Real – дійсні числа; String – рядки символів. Змінні перед використанням мають бути попередньо оголошені за наступним форматом: “тип даних” “змінна”; Наприклад integer x; Присвоєння до змінних виконується оператором присвоєння >> Наприклад x >> y + 5; Над змінними виконуються наступні операції. Арифметичні: +,-,*,/ додавання, віднімання, множення, ділення; ^ піднесення до степеня; % обчислення залишку; Логічні: ==,!= рівність, нерівність; >,<,>=,<= більше, менше, більше-рівне, менше-рівне; !,&,| логічні операції NOT, AND, OR. Ввід даних зі стандартного вводу відбувається оператором read, а вивід оператором write. Наприклад read x; write y. Для виконання умовних дій використовується оператор if-then. Наприклад if ( a > b ) then a >> b; Програмування циклів забезпечується оператором for-to-do. Наприклад for ( i >> 1 to 5) < оператори > do. Цільова мова компілятора ANSI C. Мова розробки компілятора: ANSI C. Потрібно також розробити інтегроване середовище, яке б включало текстовий редактор з можливістю набору, редагування програми; зчитування та запису її з/на диск, запуску трансляції. На вхід розробленого компілятора має подаватися текстовий файл, написаний на заданій мові програмування. На виході розробленого компілятора мають з’являтися три файли: файл з результатом лексичного аналізу, файл з результатом синтаксичного аналізу, файл з результуючим файлом на мові С. Для захисту курсового проекту потрібно мати: пояснювальну записку, файл з вихідним текстом компілятора на мові ANSI C або C++, виконавчий файл компілятора, набір тестових програм та вхідній мові програмування. Формальний опис вхідної мови програмування Одною з перших задач, що виникають при побудові компілятора, є визначення вхідної мови програмування. Для цього використовують різні способи формального опису, серед яких я використаю розширену нотацію Бекуса-Наура (Backus/Naur Form - BNF). Деталізований опис вхідної мови Типи даних integer, char, real, string; Арифметичні операції над числами +, -, *, /, ^, %; Логічні операції ==,!=,>,<,>=,<=,!,&,|; Оператор присвоєння значень змінним >> ; Круглі дужки ( ); Оператори вводу-виводу read, write; Позначення початку і кінця програми begin та end; Оператор циклу for to do; Умовний оператор if then; Перелік термінальних символів та ключових слів Визначаємо окремі термінальні символи та нерозривні набори термінальних символів (ключові слова): begin end ; + - * / ^ % == != > < >= <= ! & | for to do ( ) До термінальних символів треба віднести також усі цифри (0..9), символ пробілу і табуляції. Всього: 23 + 10 + 1 + 1 = 35 термінальних виразів. Це “цеглинки”, з яких має будуватися текст будь-якої вхідної програми. Формальний опис вхідної мови в термінах BNF Правила написання правил у розширеній нотації Бекуса-Наура: Нетермінальні вирази записуються у кутових дужках: “<”, “>” ; Термінальні вирази записуються жирним шрифтом або у подвійних лапках; Усі нетермінальні вирази мають бути “розкриті” за допомогою термінальних; Сивол “::=” відділяє праву частину правила від лівої; символ “|” розділяє альтернативи; сиволи “[”, “]” означають необов’язковість (вираз в дужках може бути відсутнім); символи “{”, “}” означають повторення. Формальний опис заданої вхідної мови в термінах BNF <program> ::= begin < statement > [{<statement >}] end  <statement> ::= <declaration> | <operator>  <declaration> ::= <type> <var>;  <operator> ::= <assign> | <command>  <assign> ::= <var> >> <expression>;  <var> ::= <letter> | [{<letter>}].  <letter> ::= a…z  <type> ::= integer | char | real | string  <command> ::= <condition> | <loop> | <input> | <output>;  <condition> ::= if ( <bool_expr> ) then <operator>  <loop> ::= for ( <var> >> <int_const> to <int_const> ) <operator> | [{<operator>}] do  <int_const> ::= <цифра> | [{<цифра >}]  <real_const> ::= <digit> | [{<digit>}].<digit> | [{<digit>}]  <char_const> ::= ‘<letter>’  <str_const> ::= “<letter> | [{<letter>}]”  <digit> ::= 0…9  <expression> ::= <num_expr> | <bool_expr>  <num_expr> ::= <num_operand> [{<num_operation><num_operand>}]  <bool_expr> ::= (<num_operand><bool_operation><num_operand>) | <var>  <num_operand> ::= (<num_expr>) | <var> | <int_const> | <real_const> | <char_const> | <str_const>  <num_operation> ::= + | - | * | / | ^ | %  <bool_operation> ::= == | != | > | < | >= | <= |! | &|  <input> ::= input <var>  <output> ::= print <var>  Формальний опис складено за допомогою 24 нетермінальних виразів. Повне дерево граматичного розбору  Розробка компілятора вхідної мови програмування Процедурно-орієнтовані мови програмування, такі як FORTRAN, Pascal, C, C++ та ін. засновані на принципі послідовного виконання операторів, команд або директив. Їх базові оператори, операції, команди та директиви можна класифікувати по трьох основних групах: Безумовні оператори (statements) обрахунків та перетворень; Оператори обробки розгалужень та передачі управління; Оператори організації циклічної обробки. В загальному випадку віртуальна машина складається з інформаційного, операційного, управляючого та комунікаційного компонентів. Будь-яка віртуальна машина повинна мати: Пам’ять різних видів та типів для збереження кодів програм і даних (інформаційний компонент) і механізми доступу до неї; Вказівник поточної операції (основа управляючої компоненти), що змінюється при підрахунку номера оператора; Блок виконання операцій (operators), який реалізує функції операційних та управляючих компонентів. Разом з інтерфейсним обладнанням він реалізує комунікаційний компонент, який забезпечує зв’язок віртуальної машини із зовнішнім світом. Можна виділити сім різних логічних задач: Інтерпретація – визначення точного змістового навантаження, створення матриці та таблиць з допомогою програм інтерпретації; Машинно-незалежна оптимізація – створення оптимальнішої матриці; Лексичний аналіз – розпізнавання базових елементів та створення стандартних символів; Синтаксичний аналіз – розпізнавання базових синтаксичних конструкцій з використанням редукцій; Розподіл пам’яті – модифікація таблиць ідентифікаторів та літералів. В матриці розміщується інформація, з допомогою якої генерується код, який розподіляє динамічну пам’ять; Генерація коду – використання макропроцесора для отримання більш оптимального вихідного коду; Компонування кінцевого вихідного коду – розв’язання проблеми символічних адрес та генерування програми на машинній мові. Фази з першої по четверту машинно-незалежні і визначаються тільки мовою. Фази з п’ятої по сьому – машинно-залежні і не залежать від мови. З метою забезпечення вищої ефективності ці фази можуть не розділятись так чітко. Ми повинні оцінювати компілятор не тільки по об’єктному коду, що генерується, але також і по об’єму оперативної пам’яті, що він займає і по часу, що потрібен для трансляції. На жаль, ці критерії оптимальності часто досить суперечливі. Крім того, оптимальність коду обернено пропорційна складності, розміру та часу роботи самого компілятора. Насправді необхідні компроміси. Компілятором використовуються бази даних, що забезпечують зв’язки між фазами: вхідний код, таблиця стандартних символів, таблиця термінальних символів, таблиця ідентифікаторів, таблиця літералів, редукції, матриця, кодові продукції, код компоновки, кінцевий об’єктний код. Лексичний аналiз Основна задача лексичного аналізу – розбити вихідний текст, що складається з послідовності одиночних символів, на послідовність слів, або лексем, тобто виділити ці слова з безперервної послідовності символів. Всі символи вхідної послідовності з цієї точки зору розділяються на символи, що належать яким-небудь лексемам, і символи, що розділяють лексеми. В цьому випадку використовуються звичайнi засоби обробки рядків. Вхiдна програма проглядається послiдовно з початку до кінця. Базовi елементи, або лексичнi одиницi, роздiляються пробiлами, знаками операцiй i спецiальними символами (новий рядок, знак табуляції), i таким чином видiляються та розпізнаються iдентифiкатори, лiтерали i термiнальнi символи (операцiї, ключові слова). При виділенні лексеми вона розпізнається та записується у таблицю лексем за допомогою відповідного номера лексеми, що є унікальним для кожної лексеми із усього можливого їх набору. Це дає можливість наступним фазам компiляції звертатись лексеми не як до послідовності символів, а як до унікального номера лексеми, що значно спрощує роботу синтаксичного аналізатора: легко перевіряти належність лексеми до відповідної синтаксичної конструкції та є можливість легкого перегляду програми, як вгору, так і вниз, від текучої позиції аналізу. Також в таблиці лексем ведуться записи, щодо рядка відповідної лексеми – для місця помилки – та додаткова інформація. При лексичному аналiзі виявляються i вiдзначаються лексичнi помилки (наприклад, недопустимi символи i неправильнi iдентифiкатори). Лексична фаза вiдкидає також i коментарi, оскiльки вони не мають нiякого впливу на виконання програми, отже ж й на синтаксичний розбір та генерацію коду. Лексичний аналізатор (сканер) не обов’язково обробляє всю програму до початку всіх інших фаз. Якщо лексичний аналіз не виділяється як окрема фаза компіляції, а є частиною синтаксичного аналізу, то лексична обробка тексту програми виконується по мірі необхідності по запиту синтаксичного аналізатора. Синтаксичний аналiз Синтаксичний аналіз – це процес, в якому досліджується послідовність лексем, яку повернув лексичний аналізатор, і визначається, чи відповідає вона структурним умовам, що сформульовані у визначені синтаксису мови. Синтаксичний аналізатор – це частина компілятора, яка відповідає за виявлення основних синтаксичних конструкцій вхідної мови. В задачу синтаксичного аналізатора входить: знайти та виділити основні синтаксичні конструкції мови в послідовності лексем програми, встановити тип та правильність побудови кожної синтаксичної конструкції і представити синтаксичні конструкції у вигляді, зручному для подальшої генерації тексту результуючої програми. Як правило, синтаксичні конструкції мови програмування можуть бути описані за допомогою контекстно-вільних граматик. Розпізнавач дає відповідь на питання, належить чи ні, ланцюжок вхідних лексем заданій мові. Але, задача синтаксичного аналізу, не обмежується тільки такою перевіркою. Синтаксичний аналізатор повинен мати, деяку результуючу мову, за допомогою якої він передає наступним фазам компіляції, інформацію про знайдені і розібрані синтаксичні конструкції, якщо відокремлюється фаза генерації об’єктного коду. Генерація коду На даному етапі генерується код майбутньої програми. Код може бути у вигляді асемблерної програми, у вигляді машинних інструкцій тощо. Головна мета етапу: створити оптимізований код для виконання (запуску) програми завантажувачем. Для оптимізації швидкодії критичні участки програми пишуться на нижчих мовах програмування. Це було можливим до тієї пори, поки Інтел не розробили нові сучасні процесори. Так як в сучасних процесорах програміст не в стані ефективно передбачити в якому порядку виконуватимуться інструкції, а тому він не в стані писати оптимізований код. За нього це має робити і робить оптимізуючий компілятор. Відладка та тестування компілятора Для превірки працездатності програмного продукту нижче наведені тестові приклади, які демонструють роботу компілятора. Робоча програма test1.txt Текст програми begin integer i; char c; string s; real r; read i; r >> i / 6.15; for ( i >> 1 to 5 ) read s; do; if ( r == i ) then s >> "equal"; write r; end Результат лексичного аналізу begin integer i ; char c ; string s ; real r ; read i ; r >> i / 6.15 ; for ( i >> 1 to 5 ) read s ; do ; if ( r == i ) then s >> "equal" ; write r ; end Результат синтаксичного аналізу Syntax analysis begin [Start-Begin] integer [Block-Decl]i ; [Declaration-Semicolon] char [Block-Decl]c ; [Declaration-Semicolon] string [Block-Decl]s ; [Declaration-Semicolon] real [Block-Decl]r ; [Declaration-Semicolon] read [Block-Read]i [Read-Iden]; [Block-Semicolon] r [Block-Iden]>> [Block-Iden]i [Block-Iden]/ [Block-Iden]6.15 [Block-Literal]; [Block-Semicolon] for [Block-For]( [For-OpenBr]i [For params-Iden]>> [For params-Iden]1 [For params-Literal]to [For params-Iden]5 [For params-Literal]) [For params-CloseBr] read [Block-Read]s [Read-Iden]; [Block-Semicolon] do [Block-Do]; [Block-Semicolon] if [Block-If]( [If-OpenBr]r [If condition-Iden]== [If condition-Iden]i [If condition-Iden]) [If condition-CloseBr] then [Block-Then]s [Block-Iden]>> [Block-Iden]"equal" [Block-Literal]; [Block-Semicolon] write [Block-Write]r [Write-Iden]; [Block-Semicolon] end [Block-End] Результат генерації коду #include <stdio.h> void main(){ int i; char c; char *s; float r; scanf("%d",i); r=i/6.15; for(i=1;i<=5;i++)scanf("%s",s); if(r==i)s="equal"; printf("%f",r); } Програма з помилкою test2.txt Текст програми begin integer i; char c; real r; string s; read i; r >> i / 6.15; for ( i >> 1 to 5 ) read s; do; if ( r == i ) then s >> "equal"; write r; end Результат лексичного аналізу begin char c ; string s ; real r ; read i ; r >> i / 6.15 ; for ( i >> 1 to 5 ) read s ; if ( r == i ) then s >> "equal" ; write r ; end Результат синтаксичного аналізу Syntax analysis begin [Start-Begin] char [Block-Decl]c ; [Declaration-Semicolon] string [Block-Decl]s ; [Declaration-Semicolon] real [Block-Decl]r ; [Declaration-Semicolon] read [Block-Read]i [Read-Iden] Undeclared identifier Error in syntax analiz Висновки При виконанні курсового проекту, я ознайомився з принципами роботи компіляторів, їх структурою а також різними методами їх реалізації. Також був розроблений компілятор для мови програмування, що задовольняє вимоги індивідуального завдання на курсовий проект, із генерацію коду у вигляді програми на мові СІ. Література ANSI C/ C++ 1. Громов Ю.Ю., Татаренко С.И. Прогаммирование на языке СИ, Учебное пособие, 1995. 2. Маслов А.Н. Введение в язык программирования С, 1991. 3. Страуструп Б. Введение в язык C++, 1985. Розробка компіляторів 1. Ахо А., Ульман Дж. Теория синтаксического анализа, перевода и компиляции, Т.1. Синтаксический анализ. - М.: Мир, 1978. 2. Хантер Р. Проектирование и конструирование компиляторов. – М.: ФиС, 1984. 3. Грис Д. Конструирование компиляторов для цифровых вычислительных машин. – М.: Мир, 1975. 4. Ваймгартен Ф. Трансляция языков программирования. – М.: Мир, 1977. 5. Касьянов В.Н. Оптимизирующие преобразования программ. – М.: Наука, 1988. 6. Серебряков В.А. Лекции по конструированию компиляторов, Москва 1993. 7. Варсанофьев Д.В., Дымченко А.Г. Основы компиляции, 1991. 8. Черкашин М. Компилятор пишется так..., Журнал "Монитор", № 4, 1992. 9. Легалов А.И. Основы проектирования компиляторов, Курс лекций, 2000. Додатки Текст програми #include <iostream> #include <iomanip> #include <cmath> #include <cstdlib> #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> #define SEPARATORS " \t\n\r" #define TRUE 1 #define FALSE 0 #define MAX_SRC_SIZE 4096 #define WHITE 0 #define YELLOW 1 #define BLUE 2 #define RED 3 #define GREEN 4 #define BLACK 5 FILE *fSAin; FILE *fsyn; FILE *fcode; char sFname[255]=""; // Вихiдний файл редактора char *sCurStr; int nFor=0; // Кiлькiсть For int nDo=0; // Кiлькiсть Do char *KeyWords[]={"begin","end","read","write","if","then","for", "integer","string","char","real","+","-","*","/","%","^","==","!=", "<",">","<=",">=","!","&","|",";",">>","do", "(",")","to",NULL}; struct TNameTable { char name[16]; char type[16]; char replace[16]; }; // Таблиця iдентифiкаторiв TNameTable NameTable[256]={ {"begin","",""},{"end","",""},{"read","",""},{"write","",""},{"if","",""},{"then","",""}, {"for","",""},{"integer","",""},{"+","",""},{"-","",""},{"*","",""},{"==","",""}, {"!=","",""},{"<","",""},{">","",""},{"<=","",""},{">=","",""},{"!","","!!"}, {"&","","&&"},{"|","","||"},{"/","","/"},{"%","","%"},{"^","","^"},{">>","","="}, {"to","",""},{"(","",""},{")","",""},{"do","",""} }; int NTCount=29;// К-ть записiв таблицi iмен //************************************************************** #include "console.h" using namespace std; POINT screensize; //************************************************************** // Очистка екрану //************************************************************** void clrscr() { COORD coordScreen = { 0, 0 }; DWORD cCharsWritten; CONSOLE_SCREEN_BUFFER_INFO csbi; DWORD dwConSize; HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(hConsole, &csbi); dwConSize = csbi.dwSize.X * csbi.dwSize.Y; screensize.x = csbi.dwSize.X; screensize.y = csbi.dwSize.Y; FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten); GetConsoleScreenBufferInfo(hConsole, &csbi); FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten); SetConsoleCursorPosition(hConsole, coordScreen); } //************************************************************** // Порiвняння двох стрiчок //************************************************************** int cmp(char *a, char *b) { if (!strcmp(a,b)) return 1; else return 0; } //************************************************************** // Встановити координати курсора x, y у консольному вiкнi //************************************************************** void gotoxy(int x, int y) { COORD point; // if((x < 0 || x > screensize.x) || (y < 0 || y > screensize.y)) return; point.X = x; point.Y = y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), point); } //************************************************************** // Встановити колiр тексту //************************************************************** void textcolor(int color) { switch (color) { case WHITE:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);break; case RED:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_RED);break; case GREEN:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_GREEN);break; case YELLOW:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);break; case BLUE:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_BLUE);break; } } //************************************************************** // Виводить повiдомлення про помилку //************************************************************** void error(char *s) {textcolor(RED);cprintf("\n\r%s\n\r",s);textcolor(YELLOW);} //************************************************************** // Очистити вiкно i вивести назву //************************************************************** void setwin(char *s){textcolor(YELLOW);clrscr();puts(s); gotoxy(0,24); cputs("Space - next window");gotoxy(0,1);} //************************************************************** // Вивести у результуючий файл потрiбну iнструкцiю //************************************************************** void code(char s[255]) {fprintf(fcode,s);fflush(fcode);} //************************************************************** // Заголовки обробникiв подiй //************************************************************** int hNull(int event, char *data); int hBlock(int event, char *data); int hDo(int event, char *data); int hNothing(int event, char *data); int hProgExp(int event, char *data); int hEndExp(int event, char *data); int hBegin(int event, char *data); int hDecl(int event, char *data); int hIden(int event, char *data); int hFor(int event, char *data); int hForParams(int event, char *data); int hIf(int event, char *data); int hIfCond(int event, char *data); int hWrite(int event, char *data); int hRead(int event, char *data); int hEndProg(int event, char *data); int hUndeclIden(int event, char *data); int hLiteral(int event, char *data); int hSemicolon(int event, char *data); //************************************************************** // Машина станiв //************************************************************** int SMCurState; // Стани машини станiв enum {stStart,stBegin,stBlock,stDeclaration,stAssignment,stIf,stIfCond,stIfBlock, stFor,stForParams,stForBlock,stRead,stWrite,stEnd,stEndOfProg}; #define SM_STATE_COUNT (stEndOfProg+1) static char *strSMState[]= {"Start","Begin","Block","Declaration","Assignment", "If","If condition","IfBlock","For","For params","ForBlock","Read", "Write","End","EndOfProg"}; // Подiї машини станiв enum {evBegin,evDecl,evIden,evIf,evThen,evFor,evRead,evWrite,evEnd,evEOF, evEndOfProg,evForParams,evForBlock,evOpenBr,evCloseBr,evDo,evLiteral,evSemicolon}; #define SM_EVENT_COUNT (evSemicolon+1) static char *strSMEvent[]= {"Begin","Decl","Iden","If","Then","For","Read","Write", "End","EOF","EndOfProg","ForParams","ForBlock","OpenBr","CloseBr","Do","Literal","Semicolon"}; struct SMState {int state, event;int (*func)(int,char*);}; // Таблиця обробникiв подiй static struct SMState SMFuncList[]= { {stStart,evBegin,hBlock},// Початковий стан {stStart,evDecl,hProgExp}, // Error: begin expected {stStart,evIden,hProgExp}, // Error: begin expected {stStart,evIf,hProgExp}, // Error: begin expected {stStart,evFor,hProgExp}, // Error: begin expected {stStart,evWrite,hProgExp}, // Error: begin expected {stStart,evRead,hProgExp}, // Error: begin expected {stStart,evEnd,hProgExp}, // Error: begin expected {stStart,evEOF,hProgExp}, // Error: begin expected {stStart,evOpenBr,hProgExp}, // Error: begin expected {stStart,evCloseBr,hProgExp}, // Error: begin expected {stStart,evSemicolon,hProgExp}, // Error: begin expected {stBlock,evIden,hIden}, {stBlock,evDecl,hDecl}, {stBlock,evSemicolon,hSemicolon}, {stBlock,evOpenBr,hBlock}, {stBlock,evCloseBr,hBlock}, {stBlock,evRead,hRead}, {stBlock,evWrite,hWrite}, {stBlock,evLiteral,hLiteral}, {stBlock,evFor,hFor}, {stBlock,evDo,hDo}, {stBlock,evIf,hIf}, {stBlock,evThen,hBlock}, {stBlock,evEnd,hEndProg}, {stFor,evOpenBr,hForParams}, {stForParams,evIden,hForParams}, {stForParams,evLiteral,hForParams}, {stForParams,evCloseBr,hBlock}, {stIf,evOpenBr,hIfCond}, {stIfCond,evCloseBr,hBlock}, {stIfCond,evIden,hIfCond}, {stIfCond,evLiteral,hIfCond}, {stDeclaration,evSemicolon,hBlock}, {stRead,evIden,hIden}, {stWrite,evIden,hIden}, }; //************************************************************** // Обробники подiй //************************************************************** int hNull(int event, char *data) {error("Unknown error");return 1;}// Null event handler int hBlock(int event, char *data) {SMCurState=stBlock;return 0;} int hSemicolon(int event, char *data) {SMCurState=stBlock;return 0;} int hEndProg(int event, char *data) {SMCurState=stEndOfProg;return 0;} int hNothing(int event, char *data) {return 0;} int hProgExp(int event, char *data) {error("'begin' expected");return 1;}// Error event handler int hEndExp(int event, char *data) {error("'end' expected");return 1;} int hBegin(int event, char *data) {SMCurState=stBlock;return 0;} int hFor(int event, char *data) {SMCurState=stFor;nFor++;return 0;} int hForParams(int event, char *data) {SMCurState=stForParams;return 0;} int hIf(int event, char *data) {SMCurState=stIf;return 0;} int hIfCond(int event, char *data) {SMCurState=stIfCond;return 0;} int hRead(int event, char *data) {SMCurState=stRead;return 0;} int hWrite(int event, char *data) {SMCurState=stWrite;return 0;} int hUndeclIden(int event, char *data) {error("Undeclared identifier");return 1;} int hDecl(int event, char *data) { char type[255]; char name[255]; SMCurState=stDeclaration; strcpy(NameTable[NTCount].type,data); strcpy(type,data); if(cmp(data,"integer")) strcpy(type,"int "); else if(cmp(data,"string")) strcpy(type,"char* "); else if(cmp(data,"char")) strcpy(type,"char "); else if(cmp(data,"real")) strcpy(type,"float "); // Читаємо iм'я змiнної if (!feof(fSAin)) fgets(sCurStr,255,fSAin); strpbrk(sCurStr,SEPARATORS)[0]='\0'; cprintf("%s ",sCurStr); fprintf(fsyn,"%s ",sCurStr); strcpy(NameTable[NTCount].name,sCurStr); NTCount++; strcat(type,sCurStr);strcat(type,";"); return 0; } int hIden(int event, char *data) { int bExists=0; for (int i=0;i<NTCount;i++) {if (cmp(data,NameTable[i].name)) {bExists=1;break;}} if (!bExists) {error("Undeclared identifier");return 1;} if (SMCurState!=stBlock) strcat(data,");"); if (!cmp(NameTable[i].replace,"")) strcpy(data,NameTable[i].replace); SMCurState=stBlock; return 0; } int hLiteral(int event, char *data) { strcpy(NameTable[NTCount].type,"Literal"); strcpy(NameTable[NTCount].name,data); NTCount++; return 0; } int hDo(int event, char *data) { nDo++; if (nFor<nDo) {error("Do without For");return 1;} if (nFor==nDo) {nFor=nDo=0;} return 0; } #define SM_FN_COUNT (sizeof(SMFuncList)/sizeof(struct SMState)) long smjmp[SM_EVENT_COUNT]; // Таблиця переходiв для машини станiв int sminit() { int i;
Антиботан аватар за замовчуванням

22.11.2013 01:11-

Коментарі

Ви не можете залишити коментар. Для цього, будь ласка, увійдіть або зареєструйтесь.

Ділись своїми роботами та отримуй миттєві бонуси!

Маєш корисні навчальні матеріали, які припадають пилом на твоєму комп'ютері? Розрахункові, лабораторні, практичні чи контрольні роботи — завантажуй їх прямо зараз і одразу отримуй бали на свій рахунок! Заархівуй всі файли в один .zip (до 100 МБ) або завантажуй кожен файл окремо. Внесок у спільноту – це легкий спосіб допомогти іншим та отримати додаткові можливості на сайті. Твої старі роботи можуть приносити тобі нові нагороди!
Нічого не вибрано
0%

Оголошення від адміністратора

Антиботан аватар за замовчуванням

Подякувати Студентському архіву довільною сумою

Admin

26.02.2023 12:38

Дякуємо, що користуєтесь нашим архівом!