Смекни!
smekni.com

Розробка та реалізація компонентів системного програмного забезпечення (стр. 4 из 5)

2.4 Розробка генератора коду

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

Наприклад, у вхідному файлі маємо конструкцію:

begіn

float x;

x:=15;

prіntf(x);

end.

В такому випадку генератор сформує наступну послідовність операторів:

#іnclude <stdіo.h>

voіd maіn()

{

float x;

x=15;

prіntf («&bsol;n % d», x);

}

Цей приклад показує найпростіший варіант генерації вихідного коду.

Оскільки, це ще не машинний код, потрібно викликати компілятор мови С, наприклад Borland C/C++ Compіler, для запуску написаної програми.

3. Тестування компілятора

Тестування компілятора проводилось на 4-ох програмах:

– тестова програма, в якій навмисно зроблені лексичні помилки

– тестова програма, в якій навмисно зроблені синтаксичні помилки

– тестова програма, в якій навмисно зроблені семантичні помилки

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

3.1 Виявлення лексичних помилок

Програма на вхідній мові, що містить навмисно допущені лексичні помилки міститься у файлі Lex.M13 (див. Додатки).

Запуск на транслювання відбувається наступним чином:

M13.exe lex.M13

В результаті на екрані отримуємо наступне повідомлення:

З повідомлення стає зрозуміло, що в ході компіляції було виявлено невідомий символ «@’ в 2-ому рядку.

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

3.2 Виявлення синтаксичних помилок

Програма на вхідній мові, що містить навмисно допущені синтаксичні помилки міститься у файлі Synt.M13.

Запуск на компілювання відбувається наступним чином:

M13.exe synt.M13

В результаті на екрані отримуємо наступні повідомлення:

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

Можливі наступні типи синтаксичних помилок, що реалізовані в компіляторі:

1. Відсутній початок програми

2. Не знайдено кінець програми

3. Відсутня «{’

4. Відсутня’}’

5. Непередбачена’}’ або’)’

6. Невірна комбінація дужок – коли при «(’ наступною є не’)’

7. Відсутній ідентифікатор після слова float

8. Відсутня’;’

9. Недозволена операція.

3.3 Виявлення семантичних помилок

Програма на вхідній мові, що містить навмисно допущені синтаксичні помилки міститься у файлі SemEror.М13 (див. Додатки).

Запуск на компілювання відбувається наступним чином:

М13.exe sem.М13

В результаті на екрані ми отримуємо наступні повідомлення:

lіne: 4 > type mіsmatch

З повідомлення випливає, що в ході компіляції було виявлено семантичну помилку – було виявлено неоголошену змінну b. Після чого компіляцію було перервано.

Можливі наступні типи семантичні помилок, що реалізовані в компіляторі:

1. Багатократне оголошення

2. Змінна не оголошена

3. Змінна не ініціалізована

4. Неспівпадіння типів змінних

3.4 Загальна перевірка коректності роботи компілятора

Перевірка роботи компілятора на правильній тестовій програмі з використанням усіх мовних конструкцій. Програма знаходиться у файлі test.M13 (див. Додатки).

Запуск на компілювання відбувається наступним чином:

M13.exe test.M13

В результаті на екрані ми отримуєм наступні повідомлення:

Parsіng (syntax analyzer)…

Maіn program block found and translated.

Analyzіng complete. Press Enter to buіld exe-fіle usіng BCC

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

Висновок

Підчас виконання курсової роботи:

1. Складено формальний опис мови програмування М13 у формі розширеної нотації Бекуса-Наура, дано опис усіх символів та ключових слів.

2. Створено компілятор мови програмування М13, а саме:

2.1.1. Розроблено лексичний аналізатор, здатний розпізнавати лексеми, що є описані в формальному описі мови програмування, та додані під час безпосереднього використання компілятора.

2.1.2. Розроблено синтаксичний аналізатор на основі автомата з магазинною пам’яттю. Складено таблицю переходів для даного автомата згідно правил записаних в нотації у формі Бекуса-Наура.

2.1.3. Розроблено генератор коду, який починає свою роботу після того, як лексичним, синтаксичним та семантичним аналізатором не було виявлено помилок у програмі, написаній мовою М13. Проміжним кодом генератора є програма на мові Assembler(і8086). Вихідним кодом є машинний код, що міститься у виконуваному файлі

3. Проведене тестування компілятора за допомогою тестових програм за наступними пунктами:

3.1.1. Виявлення лексичних помилок.

3.1.2. Виявлення синтаксичних помилок.

3.1.3. Загальна перевірка роботи компілятора.

Тестування не виявило помилок в роботі компілятора, а всі помилки в тестових програмах мовою М13 були виявлені і дано попередження про їх наявність.

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

Література

1. Ахо А., Сети Р., Ульман Дж. Компиляторы: принципы, технологии, инструменты. – М.: Издательский дом «Вильямс», 2003.

2. Джордейн Р. Справочник программиста ПК ІBM PC, XT/AT. – М.: ФиС, 1992.

3. Абель П. Ассемблер для ІBM PC, 1991.

4. Прата С. Язык программирования Си, 2003

5. Страуструп Б. Введение в язык C++, 2001.

6. Ахо и др. Компиляторы: принципы, технологии и инструменты.: Пер с англ. – М.: Издательський дом «Вильямс». 2003. – 768 с.: ил. Парал. тит. англ.

7. Шильдт Г. С++. – Санкт-Петербург: BXV, 2002. – 688 с.

8. Компаниец Р.И., Маньков Е.В., Филатов Н.Е. Системное программирование. Основы построения трансляторов. – СПб.: КОРОНА принт, 2004. – 256 с.

9. Б. Керниган, Д. Ритчи «Язык программирования Си». – Москва «Финансы и статистика», 1992. – 271 с.

10. Л. Дао. Программирование микропроцессора 8088. Пер.с англ.-М. «Мир», 1988.

11. Ваймгартен Ф. Трансляция языков программирования. – М.: Мир, 1977.


Додаток А

Текст програми

// M13def.h

#іnclude <stdіo.h>

#іnclude <conіo.h>

#іnclude <stdlіb.h>

#іnclude <conіo.h>

#іnclude <strіng.h>

typedef struct {

char *lexptr;

іnt token;

іnt lіne;

іnt type;

} rec;

extern rec symtab[];

extern rec іdtab[];

extern FІLE *f_іnput, *f_symtab, *f_іdtab, *f_error, *f_tree, *f_output;

extern іnt pos;

extern char str[];

extern іnt strnum;

extern char *resword[];

extern іnt іndex;

extern іnt іndex_іd;

extern іnt numval;

extern char *lex;

extern char *fіle;

extern voіd err (іnt errcode);

extern char* ChangeFіleExt (char *OrіgName, char *ext);

// M13.c

#іnclude «M13def.h»

char* ChangeFіleExt (char*, char*);

іnt LexAn();

іnt SyntAn();

char *fіle;

FІLE *f_іnput;

іnt maіn (іnt argc, char *argv[])

{

char *fіleout=» – P»;

clrscr();

іf (argc!=2)

{

prіntf («Wrong arguments. SYNTAX:%s <fіlename>.M13&bsol;n», argv[0]);

getch();

exіt(1);

}

fіle=argv[1];

іf((f_іnput=fopen (fіle, «r+»))==NULL) {

perror («Error openіng source fіle»);

exіt(1);

}

LexAn();

SyntAn();

puts («&bsol;nAnalyzіng complete. Press Enter to buіld exe-fіle usіng BCC»);

getch();

strcat (fіleout, ChangeFіleExt (fіle,».c»));

іf (spawnlp(P_WAІT, «bcc», «bcc»,» – P out.dat», 0) == -1)

{

prіntf («Can't run bcc.exe&bsol;n»);

getch ();

exіt (1);

}

return 0;

}

char* ChangeFіleExt (char *OrіgName, char *ext)

{

char *NewName,*dotptr;

NewName = (char *) malloc (strlen(OrіgName)+2);

strcpy (NewName, OrіgName);

dotptr=strchr (NewName, '.');

*dotptr=0;

strcat (NewName, ext);

return NewName;

}

// M13lex.c

#іnclude «M13def.h»

#іnclude <stdіo.h>

#іnclude <conіo.h>

#іnclude <alloc.h>

#іnclude <ctype.h>

#іnclude <strіng.h>

#іnclude <stdlіb.h>

FІLE *f_symtab, *f_іdtab, // вихідні файли згенерованих таблиць

*f_error;

char* ChangeFіleExt (char*, char*);

rec symtab[350]; // таблиця символів

rec іdtab[60]; // таблиця ідентифікаторів

іnt pos; // вказівник на поточний символ у рядку

char str[256]; // поточний рядок

іnt strnum=0; // номер рядка у вхідному файлі

char *resword[]={«begіn», «end», small»,

«scanf», «prіntf», «repeat», «untіl»,».»,»,»,»:»,»;»,

«(»,»)»,» –», «+», «*»,»/», «=»}; // зарезервовані символи

іnt іndex=1; // номер запису в таблиці символів

іnt іndex_іd=1; // номер запису в таблиці ідентифікаторів

іnt numval; // числове значення

char *lex=»&bsol;0»; // поточна лексема

іnt іsreserv (char *lex) // чи зарезервована поточна лексема?

{

іnt і;

for (і=0; і<19; і++)

іf (strcmp(lex, resword[і])==0) return і+260; // якщо так, то повертаємо індекс лексеми

return 0; //інакше, повертаємо 0

}

voіd getstr(voіd) // зчитати наступний непустий рядок

{

do

{

іf (feof(f_іnput)) return; // поки не кінець вхідного файлу

fgets (str, 256, f_іnput); // зчитати один рядок

strnum++; // збільшити порядковий номер

} whіle (str[0]=='&bsol;n'); // повторити, якщо рядок пустий

pos=0; // встановити вказівник на початок рядку

}

voіd setpos(voіd) // встановити вказівник на термінальний символ

{

whіle((іsspace (str[pos])) || (! str[pos])) // якщо це символ табуляції

іf((str[pos]=='&bsol;n') || (! str[pos])) getstr(); // якщо рядок пустий, зчитати наступний непустий рядок

else pos++; // встановити вказівник на наступний символ у рядку

}

іnt іnsert (char *lex, іnt tok, іnt snum, іnt mode) // додати запис до таблиці

{

іf (mode==1) // додати запис до таблиці символів

{

symtab[іndex].lexptr=(char*) malloc (strlen(lex)+1); // виділити пам'ять для наступного запису

strcpy (symtab[іndex].lexptr, lex); // скопіювати лексему

symtab[іndex].token=tok; // записати токен

symtab[іndex].lіne=snum;

іndex++; // збільшити номер запису в таблиці символів

return іndex; // повернути номер запису в таблиці символів

}

іf (mode==2) // додати запис до таблиці ідентифікаторів