![]() |
|
|
Курсовая работа: Розробка компілятора з вхідної мови програмуванняРисунок 4 Місце синтаксичного аналізатора в моделі компілятора 3.2.1 Обробка синтаксичних помилок Якщо компілятор матиме справу виключно з коректними програмами, його розробка і реалізація істотно спрощуються. Проте дуже часто програмісти пишуть програми з помилками, і добрий компілятор повинен допомогти програмісту знайти їх і локалізувати. Примітно, що хоча помилки — явище надзвичайно поширене, лише в декількох мовах питання обробки помилок розглядалося ще на фазі створення мови. Наша цивілізація істотно відрізнялася б від свого нинішнього стану, якби в природних мовах були такі ж вимоги до синтаксичної точності, як і в мовах програмування. Більшість специфікацій мов програмування, проте, не визначає реакції компілятора на помилки — це питання віддається на відкуп розробникам компілятора. Проте планування системи обробки помилок з самого початку роботи над компілятором може як спростити його структуру, так і поліпшити його реакцію на помилки. Будь-яка програма потенційно містить безліч помилок самого різного рівня. Наприклад, помилки можуть бути • лексичними, такими як невірно записані ідентифікатори, ключові слова або оператори; • синтаксичними, наприклад, арифметичні вирази з незбалансованими дужками; • семантичними, такими як оператори, використані до несумісних операндів; • логічними, наприклад нескінченна рекурсія. Часто основні дії по виявленню помилок і відновленню після них концентруються у фазі синтаксичного аналізу. Одна з причин цього полягає в тому, що багато помилок за своєю природою є синтаксичними або виявляються, коли потік токенів, що йде від лексичного аналізатора, порушує визначаючі мова програмування граматичні правила. Друга причина полягає в точності сучасних методів розбору; вони дуже ефективно виявляють синтаксичні помилки в програмі. Визначення присутності в програмі семантичних або логічних помилок — задача набагато складніша. Обробник помилок синтаксичного аналізатора має просту формульовану мету: • він повинен ясно і точно повідомляти про наявність помилок; • він повинен забезпечувати швидке відновлення після помилки, щоб продовжити пошук подальших помилок; • він не повинен істотно уповільнювати обробку коректної програми. Ефективна реалізація цієї мети є вельми складною задачею. На щастя, звичайні помилки достатньо прості, і для їх обробки часто достатньо простих механізмів обробки помилок. В деяких випадках, проте, помилка може відбутися задовго до моменту її виявлення (і за багато рядків коду до місця її виявлення), і визначити її природу вельми непросто. В складних ситуаціях обробник помилок, по суті, повинен просто здогадатися, що саме мав на увазі програміст, коли писав програму. Деякі методи розбору, такі як LL і LR, виявляють помилки, як тільки це стає можливим. Точніше кажучи, вони володіють властивістю перевірки коректності префіксів, тобто виявляють помилку, як тільки з'ясовується що префікс вхідної інформації не є префіксом жодного коректного рядка мови. 3.3 Розробка семантичного аналізатора В процесі роботи компілятор зберігає інформацію про об'єкти програми. Як правило, інформація про кожний об'єкт складається із двох основних елементів: імені об'єкта і його властивостей. Інформація про об'єкти програми повинна бути організована так, щоб пошук її був по можливості швидше, а необхідної пам'яті по можливості менше. Крім того, з боку мови програмування можуть бути додаткові вимоги. Імена можуть мати певну область видимості. Наприклад поле запису повинне бути унікально в межах структури (або рівня структури), але може співпадати з ім'ям об'єктів зовні запису (або іншого рівня запису). В той же час ім'я поля може відкриватися оператором приєднання, і тоді може виникнути конфлікт імен (або неоднозначність в трактуванні імені). Якщо мова має блокову структуру, то необхідно забезпечити такий спосіб зберігання інформації, щоб, по-перше підтримувати блоковий механізм видимості, а по-друге – ефективно звільняти пам'ять по виході з блоку. В деяких мовах (наприклад, Аді) одночасно (в одному блоці) можуть бути видимі декілька об'єктів з одним ім'ям, в інших така ситуація неприпустима. Є декілька основних способів організації інформації в компіляторах: · таблиці ідентифікаторів; · таблиці символів; · способи реалізації блокової структури; Перевірка типів Компілятор повинен переконатися, що початкова програма слідує як синтаксичним, так і семантичним угодам початкової мови. Така перевірка, іменована статичній (static checking), — на відміну від динамічної, виконуваної в процесі роботи цільової програми, — гарантує, що будуть виявлені певні типи програмних помилок. Нижче представлені приклади статичних перевірок. 1. Перевірки типів. Компілятор повинен повідомляти про помилку, якщо оператор застосовується до несумісному з ним операнда, наприклад при складанні змінних, що є масивом і функцією. 2. Перевірки управління. Передача управління за межі мовних конструкцій повинна проводитися в певне місце. Наприклад, в мові програмування С оператор break передає управління за межі самої вкладеної інструкції while, for або switch; якщо ж такі відсутні, то виводиться повідомлення про помилку. 3. Перевірки єдиності. Існують ситуації, коли об'єкт може бути визначений тільки один раз. Наприклад, в мові програмування Pascal ідентифікатор повинен оголошуватися тільки один раз, всі мітки в конструкції case повинні бути різний, а елементи в скалярному типі не повинні повторюватися. 4. Перевірки, пов'язані з іменами. Іноді одне і те ж ім'я повинне використовуватися двічі (або більше число раз). Наприклад, в мові програмування Ada цикл або блок може мати ім'я, яке повинне знаходитися як на початку, так і в кінці конструкції. Компілятор повинен перевірити, що в обох місцях використовується одне і те ж ім'я. В цьому розділі нас, в першу чергу, цікавить перевірка типів. Як видно з наведених приклади, більшість інших статичних перевірок є рутинною і може бути реалізований з використанням технологій, описаних в попередньому розділі. Деякі з них можуть використовуватися і для виконання інших дій. Наприклад, при внесенні інформації про ім'я в таблицю символів ми можемо переконатися в єдиності оголошення даного імені. Багато компіляторів Pascal об'єднують статичні перевірки і генерацію проміжного коду з синтаксичним аналізом. За наявності складніших конструкцій, на зразок тих, що використовуються в мові програмування Ada, може виявитися більш зручним виконати окремий прохід для проведення перевірок типів між синтаксичним аналізом і генерацією проміжного коду, як показано на рисунку 5. Рисунок 5 Місце семантичного аналізатора в моделі компілятора. Програма перевірки типів перевіряє, щоб тип конструкції відповідав очікуваному в даному контексті. Наприклад, вбудований арифметичний оператор mod в Pascal вимагає цілих операндів, тому програма перевірки типів повинна перевірити, щоб операнди mod в початковій програмі — цілого типу. Так само програма перевірки типів повинна переконатися, що операція розіменування застосовується до покажчика, індексація виконується з масивом, що визначена користувачем функція. 3.4 Розробка оптимізатора кодукомпілятор програмування оболонка операційна Оптимізація програмного коду - це модифікація програм, виконувана оптимізуючим компілятором або інтерпретатором з метою поліпшення їхніх характеристик, таких як продуктивності або компактності, - без зміни функціональності.Оптимізація - не обов'язковий, але важливий етап компіляції. У принципі, вона може відбуватися під час трансляції програми, але, як правило, оптимізацію програми виділяють як окремий етап функціонування компіляторів. Компонувальники також можуть виконувати частина оптимізацій, таких як видалення невикористовуваних підпрограм або перевпорядкування підпрограм.Розрізняють низько- і високорівневу оптимізацію. Низкорівнева оптимізація перетворює програму на рівні елементарних команд, наприклад, інструкцій процесорів архітектури x86. Високорівнева оптимізація здійснюється на рівні структурних елементів програми, таких як розгалуження й цикли.3.5 Розробка генератора кодуОстанньою стадією розробки компілятора є генератор коду, який дістає на вхід проміжне представлення вихідної програми і виводить еквівалентну цільову програму. Традиційно, до генератора коду висуваються жорсткі вимоги. Вихідний код повинен бути коректним і високоякісним, що означає ефективне використання ресурсів цільової машини. Крім того, ефективно повинен бути розроблений і сам генератор коду. Математично, проблема генерації оптимального коду є нерозв’язною. На практиці ми вимушені користуватись евристичними технологіями, які дають хороший, але не обов’язково оптимальний код. Вибір евристики дуже важливий, оскільки детально розроблений алгоритм розробки генератора коду може давати код, що працю в декілька раз швидше, ніж код отриманий недостатньо продуманим алгоритмом. Хоча дрібні деталі генератора колу залежать від цільової машини і операційної системи, такі питання, як керування пам’яттю, вибір інструкцій, розподіл регістрів і порядок обчислень, властиві усім задачам, зв’язаним з генерацією коду. Вхідний потік генератора коду являє собою проміжне представлення вихідної програми, отримане на початковій стадії компіляції, разом із таблицею символів, яка використовується для обчислення адрес часу виконання об’єктів даних, зазначених в проміжному представленні іменами. Результатом генератора коду являється цільова програма. Подібно до проміжного коду, результат генератора коду може приймати різні види: абсолютний машинний код, переміщуваний машинний код, або асемблерна мова. Перевагою генерації абсолютної програми в машинному коді є те, що такий код поміщається у фіксоване місце пам’яті і негайно виконується. Невеликі програми при цьому швидко компілюються і виконуються. Генерація переміщуваної програми у машинному коді (об’єктного модуля) забезпечує можливість роздільної компіляції підпрограм. Багато переміщуваних модулів можуть бути після цього зв’язані в одне ціле і завантажені на виконання спеціальною програмою – завантажувачем. Додаткові затрати на зв’язування і завантаження компенсуються можливістю роздільної компіляції підпрограм і викликом інших, раніше скомпільованих підпрограм із об’єктних модулів. Якщо цільова машина не обробляє переміщення автоматично, компілятор має надати завантажувачеві явну інформацю про переміщення для зв’язування сегментів роздільно скомпільованиз підпрограм. Отримання на виході генератора коду програми на мові асемблера трохи полегшує процес генерації коду; в результаті ми можемо створювати символьні інструкції і використовувати можливості макросів асемблера. Плата за цю простоту – додатковий крок в обробці мови програмування асемблер після генерації коду. 4 Відладка та тестування компілятора 4.6.1 Виявлення лексичних помилокПовідомлення про лексичну помилку виводиться, коли лексичний аналізатор знаходить лексему, що не відповідає лексиці мови програмування та ні одному з імен описаних користувачем змінних. Для перевірки розробленого компілятора на виявлення лексичних помилок внесемо в текст програми помилку – лексему BegAn. 'Error 13: Невідомий символ: BegAn ' З повідомлення стає зрозуміло, що в ході компіляції було виявлено невідомий символ ’ BegAn’ в 2-ому рядку. Під час роботи сканера може виникнути помилка вище наведеного типу (тобто виявлено невідому лексему), а також неправильне оголошення ім’я змінної (коли першою є цифра). Результат тестування в додатку Б. 4.6.2 Виявлення синтаксичних помилокПовідомлення про синтаксичну помилку виводиться, коли синтаксичний аналізатор знаходить ланцюжок лексем, що не відповідає граматиці заданої мови. Для перевірки компілятора на виявлення синтаксичних помилок пропустимо в тексті програми роздільник «;». В результаті на екрані отримуємо наступні повідомлення: Error15: Пропущено ; пiсля операцii writeln' З повідомлення випливає, що в ході компіляції було виявлено синтаксичну помилку – пропущено роздільник ’;’. Після цього компіляцію було перервано. Результат тестування в додатку Б. 4.6.3 Виявлення семантичних помилокПовідомлення про семантичну помилку виводиться семантичним аналізатором, коли у виразі не співпадають типи використовуваних змінних. Для перевірки компілятора на виявлення семантичних помилок внесемо в текст програми вираз з використанням змінних різних типів. Результат тестування в додатку Б. 'Error 18: Пропущено змінну: b' З повідомлення випливає, що в ході компіляції було виявлено семантичну помилку – було виявлено неоголошену змінну b. Після чого компіляцію було перервано. Можливі наступні типи семантичні помилок, що реалізовані в компіляторі: 1. Багатократне оголошення; 2. Змінна не оголошена; 3. Змінна не ініціалізована; 4. Не співпадіння типів змінних. 4.6.4 Загальна перевірка коректності роботи транслятораЗагальна перевірка полягає у здатності розробленого компілятора виконувати свої функції. Компілятор повинен транслювати програму у проміжне представлення на мові асемблер та створювати об’єктний і виконуваний файли за допомогою файлів tasm.exe та tlink.exe. Результат тестування в додатку Б. ВисновокПід час виконання курсової роботи: 1. Складено формальний опис мови програмування М13 у формі розширеної нотації Бекуса-Наура, дано опис усіх символів та ключових слів. 2. Створено компілятор мови програмування М13, а саме: 2.1.1. Розроблено лексичний аналізатор, здатний розпізнавати лексеми, що є описані в формальному описі мови програмування, та додані під час безпосереднього використання компілятора. 2.1.2. Розроблено синтаксичний аналізатор на основі автомата з магазинною пам’яттю. Складено таблицю переходів для даного автомата згідно правил записаних в нотації у формі Бекуса-Наура. 2.1.3. Розроблено генератор коду, який починає свою роботу після того, як лексичним, синтаксичним та семантичним аналізатором не було виявлено помилок у програмі, написаній мовою М13. Проміжним кодом генератора є програма на мові Assembler(i8086). Вихідним кодом є машинний код, що міститься у виконуваному файлі 3. Проведене тестування компілятора за допомогою тестових програм за наступними пунктами: 3.1.1. Виявлення лексичних помилок. 3.1.2. Виявлення синтаксичних помилок. 3.1.3. Загальна перевірка роботи компілятора. Тестування не виявило помилок в роботі компілятора, а всі помилки в тестових програмах мовою М13 були виявлені і дано попередження про їх наявність. В результаті виконання даної курсової роботи було успішно засвоєно методи розробки та реалізації компонент системного програмного забезпечення. Список використаної літератури 1. Бек Л.С. Введение в системное програмирование. – М.:Мир, 1988. 2. Касаткин М.В. Касаткина Т.Я. Професиональное програмирование на языке С.В 3т. – М. Мир, 1989.//т.3. Системное програмирование. 3. Кузьмин А.Я. Лексический анализ. – М.:ВШ.,1985. 4. Фролов А.В. Проэктирование компиляторов. –М.: Мир,1989. 5. Страуструп Б. Введение в язык C++, 2001. 6. Ахо А., Сети Р., Ульман Дж.Компиляторы: принципы, технологии, инструменты. – М.: Издательский дом «Вильямс», 2003. 7. Джордейн Р. Справочник программиста ПК IBM PC, XT/AT. – М.: ФиС, 1992. 8. Абель П. Ассемблер для IBM PC, 1991. 9. Прата С. Язык программирования Си, 2003 Додатки Додаток A
program TFirst; uses App,dialogs,drivers,menus,objects,stddlg,views,validate; type TMyApp=object(TApplication) procedure InitStatusLine; virtual; procedure InitMenuBar; virtual; procedure NewWindow; virtual; procedure HandleEvent(var Event:TEvent);virtual; procedure NewDialog;virtual; {procedure Init;virtual;} end; DialogData=record {CheckBoxData:Word; RadioButtonData:word;} InputLineData:string[128]; end; MyStruct=record b:integer; b1:integer; c:string[32]; end; PM13Window=^TM13Window; TM13Window=object(TWindow) constructor Init(Bounds:TRect; WinTitle:string;WindowNo:Word); procedure MakeInterior(Bounds:TRect); end; var M13DialogData:DialogData; s1:string; const MaxLines=2000; var LineCount:integer; Lines:array [0..MaxLines-1]of PString; type PInterior=^TInterior; TInterior=object(Tscroller) constructor Init(var Bounds:TRect;AHScrollBar, AVScrollBar:PScrollBar); procedure Draw;virtual; end; const cmNewWin=199;cmFileOpen=200;WinCount:Integer=0;cmCompile=201; procedure TMyApp.InitStatusLine; var r:TRect; begin {GetExtent(r);} r.a.y:=r.b.y+1; StatusLine:=New(PStatusLine,Init(r, NewStatusDef(0,$ffff, NewStatusKey('~Alt-X~ Exit', kbAltX, cmQuit, NewStatusKey('~Alt-F4~ New', kbF4, cmNewWin, NewStatusKey('~Alt-F3~ Close', kbAltF3, cmClose, NewStatusKey( '',kbF10, cmMenu, nil)))), nil))); end; procedure TMyApp.InitMenuBar; var r:TRect; begin GetExtent(r); r.b.y:=r.a.y+1; MenuBar:=New(PMenuBar, Init(r, NewMenu( NewSubMenu('~F~ile', hcNoContext, NewMenu( NewItem('~O~pen', 'F3',kbF3,cmFileOpen, hcNoContext, NewItem('~N~ew', 'F4',kbF4,cmNewWin, hcNoContext, NewLine( NewItem('E~x~it', 'Alt-x', kbAltX, cmQuit, hcNoContext, nil))))), NewSubMenu('~W~indow', hcNoContext, NewMenu( NewItem('~N~ext', 'F6',kbF6,cmNext, hcNoContext, NewItem('~Z~oom', 'F5',kbF5,cmZoom, hcNoContext, nil))), NewSubMenu('~C~ompile', hcNoContext, NewMenu( NewItem('~C~ompile','Alt-F9',kbAltF9,cmCompile,hcNoContext, nil)), nil ))))));end; procedure TMyApp.NewWindow; var Window:PM13Window; r:TRect; i:integer; begin i:=0; inc(WinCount); r.assign(0,0,80,23-wincount+1); r.move(0,i+wincount-1); window:=new(pM13window, init(r, 'Compile window', wincount)); desktop^.insert(window); end; procedure TMyApp.NewDialog; var Dialog:PDialog; R:TRect; control:Word; B:PView; Window:PM13Window; i:integer; f:text; s:string; begin R.Assign(20,6,60,19); Dialog:=New(PDialog,Init(R,'M13 Dialog')); with Dialog^ do begin R.Assign(15,10,25,12); Insert(New(PButton,Init(R,'~O~K',cmOK,bfDefault))); R.Assign(28,10,38,12); Insert(New(PButton,Init(R,'Cancel',cmCancel,bfNormal))); R.Assign(3,8,37,9); B:=New(PInputLine,Init(r,128)); insert(b); R.Assign(2,7,24,8); insert(New(PLabel,Init(R,'Delivery instructions',B))); end; Dialog^.SetData(M13DialogData); Control:=DeskTop^.ExecView(Dialog); if Control<>cmCancel then Dialog^.GetData(M13DialogData); i:=0; while M13DialogData.InputLineData[i]<>'.' do begin s[i]:=M13DialogData.InputLineData[i]; i:=i+1; end; s[i]:=M13DialogData.InputLineData[i]; s[i+1]:=M13DialogData.InputLineData[i+1]; s[i+2]:=M13DialogData.InputLineData[i+2]; s[i+3]:=M13DialogData.InputLineData[i+3]; s1:=s; LineCount:=0; Assign(F,s); reset(F); while not Eof(F) and (LineCount<MaxLines)do begin readln(f,s); lines[linecount]:=newstr(s); inc(linecount); {writeln(lines[linecount]^);} end; close(F); i:=0; inc(WinCount); r.assign(0,0,80,23-wincount+1); r.move(0,i+wincount-1); window:=new(pM13window, init(r, s1, wincount)); desktop^.insert(window); end; function vuraz(var s:char):integer; var w:integer; begin if ((integer(s)>=97)and(integer(s)<=122))or((integer(s)>=65)and(integer(s)<=90)) then vuraz:=30 else vuraz:=29; end; procedure Compiles; label aa; var a1:array [1..100] of MyStruct; i,j,j1,k,kk,i1,i2,var_kil,begin_kil,end_kil,var_index,begin_index,end_index:integer; q,q1:string; ss:array [1..50] of string[50]; f1,f2,f3,f4:text; ch,ch1:char; mn:string; m,nerivne,m1,pa:integer; begin assign(f1,s1); reset(f1); i:=0;j:=0; while s1[i]<>'.' do begin q[j]:=s1[i];q1[i]:=s1[i]; i:=i+1;j:=j+1; end; q[j]:=s1[i];j:=j+1;q[j]:='t';j:=j+1;q[j]:='x';j:=j+1;q[j]:='t'; q1[i]:=s1[i];q1[i+1]:='a';q1[i+2]:='s';q1[i+3]:='m'; for i:=1 to 100 do a1[i].b:=0; i1:=1; assign(f2,q); Rewrite(f2); assign(f3,q1); rewrite(f3); j1:=1;k:=0;i:=1; j:=1; while not EOF(f1) do begin readln(f1,ss[j]); a1[i].c[1]:=ss[j][1];j1:=2;ch1:=ss[j][1]; i2:=2; while ss[j][i2]<>#0 do begin if (ss[j][i2]=' ')or(ss[j][i2]=';')or(ss[j][i2]='+')or(ss[j][i2]='-')or(ss[j][i2]='*') or (ss[j][i2]='.')or(ss[j][i2]='/')or(ss[j][i2]=')')or(ss[j][i2]='(')or(ss[j][i2]=',')or(ss[j][i2]=':') or(ss[j][i2]='=')or(ss[j][i2]='>')or(ss[j][i2]='<')or((ss[j][i2]='<')and(ss[j][i2]='>')) or ((ss[j][i2]='=')and(ss[j][i2]='='))or(ss[j][i2]='^') then begin if (ch1=' ')or(ch1=';')or(ch1='+')or(ch1='-')or(ch1='*') or (ch1='.')or(ch1='/')or(ch1=')')or(ch1='(')or(ch1=',')or(ch1=':')or(ch1='=') or(ch1='>')or(ch1='<')or((ch1='<')and(ch1='>')) or ((ch1='=')and(ch1='='))or(ch1='^') then begin i:=i+1;end else begin a1[i].c[j1]:=#0;i:=i+1;end; ch1:=ss[j][i2]; a1[i].c[1]:=ss[j][i2];a1[i].c[2]:=#0;i:=i+1;j1:=1; end else begin a1[i].c[j1]:=ss[j][i2];j1:=j1+1;ch1:=ss[j][i2];end; i2:=i2+1; end; j:=j+1; end; k:=i-1; for i:=1 to k do begin if ((a1[i].c[1]='p')and( a1[i].c[2]='r')and( a1[i].c[3]='o')and( a1[i].c[4]='g') and( a1[i].c[5]='r')and( a1[i].c[6]='a')and( a1[i].c[7]='m'))then a1[i].b:=1; if (( a1[i].c[1]='v')and( a1[i].c[2]='a')and( a1[i].c[3]='r'))then a1[i].b:=2; if (( a1[i].c[1]='b')and( a1[i].c[2]='y')and( a1[i].c[3]='t')and( a1[i].c[4]='e'))then a1[i].b:=3; if (( a1[i].c[1]='c')and( a1[i].c[2]='h')and( a1[i].c[3]='a')and( a1[i].c[4]='r'))then a1[i].b:=4; if (( a1[i].c[1]='b')and( a1[i].c[2]='o')and( a1[i].c[3]='o')and( a1[i].c[4]='l') and( a1[i].c[5]='e')and( a1[i].c[6]='a')and( a1[i].c[7]='n'))then a1[i].b:=5; if (( a1[i].c[1]='b')and( a1[i].c[2]='e')and( a1[i].c[3]='g')and( a1[i].c[4]='i') and( a1[i].c[5]='n'))then a1[i].b:=7; if (( a1[i].c[1]='w')and( a1[i].c[2]='r')and( a1[i].c[3]='i')and( a1[i].c[4]='t') and( a1[i].c[5]='e')and( a1[i].c[6]='l')and( a1[i].c[7]='n'))then a1[i].b:=8; if (( a1[i].c[1]='r')and( a1[i].c[2]='e')and( a1[i].c[3]='a')and( a1[i].c[4]='d') and( a1[i].c[5]='l')and( a1[i].c[6]='n'))then a1[i].b:=9; if (( a1[i].c[1]='e')and( a1[i].c[2]='n')and( a1[i].c[3]='d'))then a1[i].b:=15; if (a1[i].c[1]=';')then a1[i].b:=16; if (a1[i].c[1]=',')then a1[i].b:=17; if (a1[i].c[1]='(')then a1[i].b:=18; if (a1[i].c[1]=')')then a1[i].b:=19; if (a1[i].c[1]='*')then a1[i].b:=20; if (a1[i].c[1]='+')then a1[i].b:=21; if (a1[i].c[1]='-')then a1[i].b:=22; if (a1[i].c[1]='/')then a1[i].b:=23; if (a1[i].c[1]=' ')then a1[i].b:=24; if (a1[i].c[1]='\n')then a1[i].b:=25; if (a1[i].c[1]=':')then a1[i].b:=26; if (a1[i].c[1]='=')then a1[i].b:=27; if (a1[i].c[1]='.')then a1[i].b:=28; if (a1[i].c[1]='>')then a1[i].b:=29; if (a1[i].c[1]='<')then a1[i].b:=30; if ((a1[i].c[1]='!')and(a1[i].c[1]='=')) then a1[i].b:=31; if ((a1[i].c[1]='=')and(a1[i].c[1]='=')) then a1[i].b:=32; if (a1[i].c[1]='^')then a1[i].b:=33; if (( a1[i].c[1]='N')and( a1[i].c[2]='O') and( a1[i].c[3]='T'))then a1[i].b:=34; end; for i:=0 to k do if a1[i].b=0 then a1[i].b:=vuraz(a1[i].c[1]); var_kil:=0;begin_kil:=0;end_kil:=0; for i:=1 to k do begin if a1[i].b=2 then var_kil:=var_kil+1; if a1[i].b=7 then begin_kil:=begin_kil+1; if a1[i].b=15 then end_kil:=end_kil+1; end; for i:=1 to k do begin writeln(f2,a1[i].b); end; if var_kil>1 then writeln(f2,'Error 1: Декiлька разiв вiдбуваеться опис даних'); if begin_kil>1 then writeln(f2,'Error 2: Декiлька разiв введено слово begin'); if end_kil>1 then writeln(f2,'Error 3: Декiлька разiв введено слово end'); if var_kil=0 then writeln(f2,'Error 4: Немає опису даних'); if begin_kil=0 then writeln(f2,'Error 5: Немає початку тiла програми'); if end_kil=0 then writeln(f2,'Error 6: Немає кiнця тiла програми'); if nevid=0 then writeln(f2,'Error 18: Невідома змінна:',k); var_index:=0;begin_index:=0;end_index:=0; for i:=1 to k do begin if a1[i].b=2 then var_index:=i; if a1[i].b=7 then begin_index:=i; if a1[i].b=15 then end_index:=i; end; for i:=var_index to begin_index do begin if a1[i].b=3 then begin if a1[i-1].b<>26 then writeln(f2,'Error 7: Пропущено- : при описi змiнних типу Byte'); j:=i-2; while a1[j].b<>16 do begin if a1[j].b=30 then a1[j].b:=35; j:=j-1; end; end; if a1[i].b=4 then begin if a1[i-1].b<>26then writeln(f2,'Error 7: Пропущено- : при описi змiнних типу Char'); j:=i-2; while a1[j].b<>26 do begin if a1[j].b=30 then a1[j].b:=36; j:=j-1; end; end; if a1[i].b=5 then begin if a1[i-1].b<>16then writeln(f2,'Error 7: Пропущено- : при описi змiнних типу Boolean'); j:=i-2; while a1[j].b<>16 do begin if a1[j].b=30 then a1[j].b:=37; j:=j-1; end; end; end; assign(f4,'1.M13'); reset(f4); readln(f4,mn); writeln(f3,'ideal'); writeln(f3,'model small'); writeln(f3,'stack 256'); writeln(f3,'dataseg'); writeln(f3,'perkur db ',mn,'$',mn); writeln(f3,'TrueStr db ',mn,'TRUE$',mn); writeln(f3,'FalseStr db ',mn,'False$',mn); writeln(f3,'InString db 255 DUP(?)'); writeln(f3,'OutString db 255 DUP(?)'); writeln(f3,'CharStr db 2,5 DUP(?)'); writeln(f3,'len dw ?'); for i:=var_index+1 to begin_index do begin if a1[i].b=31 then begin j:=1; while a1[i].c[j]<>#0 do begin write(f3,a1[i].c[j]); j:=j+1; end; writeln(f3,' dw ?'); end; if a1[i].b=32 then begin j:=1; while a1[i].c[j]<>#0 do begin write(f3,a1[i].c[j]); j:=j+1; end; writeln(f3,' db ?'); end; if a1[i].b=33 then begin j:=1; while a1[i].c[j]<>#0 do begin write(f3,a1[i].c[j]); j:=j+1; end; writeln(f3,' db ?'); end; end; writeln(f3,'codeseg'); writeln(f3,'start:'); writeln(f3,'mov ax,@data'); writeln(f3,'mov ds,ax'); i:=begin_index+1; while i<>end_index do begin kk:=i; if a1[i].b=8 then begin if (a1[i+1].b<>18)then writeln(f2,'Error: Пропущено ( при написаннi функцii writeln'); kk:=i+2; while a1[kk].b<>19 do begin if (a1[kk].b<>17) or (a1[kk].b<>19) then begin for j:=var_index+1 to begin_index do begin if (copy(a1[kk].c,1,a1[kk].b1))=(copy(a1[j].c,1,a1[j].b1)) then a1[kk].b:=a1[j].b; end; writeln(a1[kk].b); if a1[kk].b=31 then begin writeln(f3,'mov ax,[',copy(a1[kk].c,1,a1[kk].b1),']'); writeln(f3,'call WriteByte'); end; if a1[kk].b=32 then begin writeln(f3,'mov al,[',copy(a1[kk].c,1,a1[kk].b1),']'); writeln(f3,'call WriteChar'); end; if a1[kk].b=33 then begin writeln(f3,'mov al,[',copy(a1[kk].c,1,a1[kk].b1),']'); writeln(f3,'call WriteBool'); end; end; kk:=kk+1; end; if a1[kk+1].b<>16 then if a1[kk+2].b<>16 then writeln(f2,'Error: Пропущено ; пiсля операцii writeln'); end; if a1[i].b=9 then begin if (a1[i+1].b<>18)then writeln(f2,'Error: Пропущено ( при написаннi функцii writeln'); kk:=i+2;while a1[kk].b<>19 do begin if a1[kk].b<>17 then begin m:=0;while a1[kk].c[m]<>#0 do m:=m+1; m:=m+1; for j:=var_index+1 to begin_index do begin nerivne:=0;m1:=0; while m1<>m do begin if a1[kk].c[m1]=a1[j].c[m1] then nerivne:=nerivne+1; m1:=m1+1 end; if nerivne=m then a1[kk].b:=a1[j].b; end; if a1[kk].b=31 then begin writeln(f3,'call ReadInt'); writeln(f3,'mov [',a1[kk].c,'],ax'); end; if a1[kk].b=32 then begin writeln(f3,'call ReadChar'); writeln(f3,'mov [',a1[kk].c,'],al'); end; if a1[kk].b=33 then begin writeln(f3,'call ReadBool'); writeln(f3,'mov [',a1[kk].c,'],al'); end; end; kk:=kk+1; end; if a1[kk+1].b<>16 then if a1[kk+2].b<>16 then writeln(f2,'Error 15: Пропущено ; пiсля операцii writeln'); end; {if a1[i].b=30 then pa:=assign(a1,i);} i:=kk+1; end; close(f3); close(f2); close(f1); writeln('Кiнець'); end; procedure TMyApp.HandleEvent(var Event:TEvent); begin TApplication.HandleEvent(Event); if Event.What=evCommand then begin case Event.Command of cmNewWin:NewWindow; cmFileOpen:NewDialog; cmCompile:Compiles; else Exit; end; ClearEvent(Event); end; end; constructor TInterior.Init(var Bounds:TRect;AHScrollBar, AVScrollBar:PScrollBar); begin TScroller.Init(Bounds,AHScrollBar,AVScrollBar); GrowMode:=gfGrowHiX+gfGrowHiY; SetLimit(128,LineCount); end; procedure TInterior.Draw; var i,y:integer; Color:Byte; B:TDrawBuffer; begin Color:=GetColor(1); for y:=0 to size.y-1 do begin MoveChar(B,' ',Color,Size.x); i:=Delta.Y+y; if (i<LineCount) and (Lines[i]<>nil) then MoveStr(B,Copy(Lines[i]^,Delta.x+1,Size.x),Color); writeLine(0,y,Size.x,1,b); end; end; procedure ReadFile; var F:Text; S:String; begin LineCount:=0; Assign(F,'Test.M13'); reset(F); while not Eof(F) and (LineCount<MaxLines)do begin readln(f,s); lines[linecount]:=newstr(s); inc(linecount); {writeln(lines[linecount]^);} end; close(F); end; procedure TM13Window.MakeInterior(Bounds:Trect); var HScrollBar,VScrollBar:PScrollBar; interior:PInterior; R:TRect; begin VScrollBar:=StandardScrollBar(sbVertical+sbHandleKeyboard); HScrollBar:=StandardScrollBar(sbHorizontal+sbHandleKeyboard); Interior:=New(PInterior,Init(Bounds,HScrollBar,VScrollBar)); Insert(Interior); end; constructor TM13Window.Init(Bounds:TRect; WinTitle:string;WindowNo:Word); var s:string[3]; begin str(WindowNo, s); TWindow.Init(Bounds, WinTitle+' '+s, wnNoNumber); GetExtent(Bounds); Bounds.Grow(-1,-1); MakeInterior(Bounds); end; procedure DoneFile; var i:integer; begin for i:=0 to linecount-1 do if lines[i]<>nil then disposestr(lines[i]); end; var MyApp:TMyApp; begin MyApp.Init; MyApp.Run; MyApp.Done; end. Додаток БТестова програма на мові M13 з лексичною помилкою: 'Error 13: Невідомий символ: BegAn ' program ja; var a:byte; begАn a:=13; writeln ('Varian :', a); end. Тестова програма на мові M13 з синтаксичною помилкою: Error15: Пропущено ; пiсля операцii writeln' program ja; var a:byte; begin a:=13; writeln ('Varian :', a) end. Тестова програма на мові M13 з семантичною помилкою: 'Error 18: Пропущено змінну: b' program ja; var a,c:byte; begАn a:=53; b:=13; c:=a+b; writeln ('Varian :', b) end. Тестова програма на мові M13 без помилок: program ja; var a:byte; begin b:=13; writeln ('Varian :', b); end.
Рисунок 6 Вигляд працездатного компілятора. |
Страницы: 1, 2
![]() |
||
НОВОСТИ | ![]() |
![]() |
||
ВХОД | ![]() |
|
Рефераты бесплатно, реферат бесплатно, курсовые работы, реферат, доклады, рефераты, рефераты скачать, рефераты на тему, сочинения, курсовые, дипломы, научные работы и многое другое. |
||
При использовании материалов - ссылка на сайт обязательна. |