DevioLabавтоматичне керування капіталом
ПРАЦЮЄ 24/7
КРИПТОВАЛЮТИ · АКЦІЇ · 10 БІРЖ

Портфель, який керується автоматично

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

10підключених біржCrypto + Stocksв одному портфелі24/7автоматичний контроль

Лабораторна робота №3 з системного програмування: Синтаксичний аналіз

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

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

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

Рік:
2010
Тип роботи:
Лабораторна робота
Предмет:
Системне програмування
Група:
ПМ-31
Коротко про документ

Про що ця робота

У роботі реалізовано синтаксичний аналізатор методом рекурсивного спуску для підмножини мови Pascal. Наведено опис граматики, програмний код на C++ та контрольний приклад виконання.

У роботі розглядаються

  • Системне програмування
  • Синтаксичний аналіз
  • Рекурсивний спуск
  • Мова програмування Pascal
  • Лексичний аналіз
  • Обробка помилок
  • Формальні граматики

Зміст і розділи

  1. Мета
  2. Граматика
  3. Код програми
  4. Контрольний приклад
  5. Висновок
Для кого:Студенти технічних спеціальностей та викладачі дисципліни Системне програмування.
Викладачі:Викладач кафедри

Ключові поняття

синтаксичний аналізрекурсивний спускграматикалексемасинтаксична помилкаPascalC++терміналнетермінал

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

Міністерство освіти та науки України Національний університет «Львівська політехніка» кафедра прикладної математики ЛАБОРАТОРНА РОБОТА №3 з системного програмування на тему: «Синтаксичний аналіз» Мета: побудувати граматику, яка породжує запропоновану підмножину мови програмування, визначити типи можливих помилок та форму відповідного повідомлення . Написати програму синтаксичного контролю методом рекурсивного спуску (низхідний аналіз), попередньо застосувавши еквівалентні перетворення граматики (якщо потрібно). При потребі внести доповнення у підпрограму лексичного аналізу. Написати програму – синтаксичний аналізатор, що отримує на вході – текст вхідної програми на запропонованій підмножині мови програмування (у вхідному файлі), а на виході – повідомлення про наявність синтаксичних помилок у вхідній програмі (можна вести контроль до першої помилки) з інформацією про тип помилки та місце її знаходження. Для виділення чергової лексеми використати підпрограму, розроблену у Лаб. Роботі №2. Варіант №9. Завдання: Розглянути підмножину мови Pascal, у якій є ідентифікатори (довжина – не більше 10 символів), цілі константи (довжина – не більше 6 символів), які використовуються у операторах опису (типи змінних – real , integer,boolean), оператори присвоєння, оператори циклу типу while (умова – логічний вираз, утворений з логічних змінних і відповідних логічних операцій). Граматика: S → Program I; [R] T R → var P P → Z: Y;{Z: Y;} Z → I {, I} Y → Real | Integer | Boolean T → begin A end. A → B {;B} B → V | W | L V → I := U W → while G do B L → begin A end U → M | M + U | M – U | M or U M → N | N * M | N / M | N and M N → I | C | (G) | not N D → = | < | > | <> | <= | >= G → U D U | (G) Де: S = <Програма> R = <Розділ описів> P = <Опис> Z = <Змінні> Y = <Тип> T = <Тіло програми> A = <Оператори> B = <Оператор> V=<Присвоєння> W = <While> L = <Блок> U = <Вираз> M = <Терм> N = <Множ> D = <Відношення> G = <Логічний вираз> Код програми: #include <fstream.h> #include <string.h> #include <stdio.h> #include <iostream.h> #include <ctype.h> #include <windows.h> //*********************Opus Global'nuh zminnuh***********************// FILE *in; char *f1 = "input.txt"; char *lex, syn, lit = ' ', ch = 0; int cl = 9, f = 0, num = 1, id_num = 0; struct st { char *id; int type; }; st M_id[100]; //************************Prototupu fynkcij**************************// int getlit(); int zarezerv(char*); void scan(); void S(); void R(); void P(); void Z(); void Y(); void T(); void A(); void B(); void V(); void W(); void L(); void U(); void M(); void N(); void G(); void D(); void Vudilutu_Lexemy(); //****************************MAIN***********************************// void main(void) { in=fopen(f1, "r"); S(); if(f) Vudilutu_Lexemy(); else cout<<"\n\nV programi nemae pomulok...\n"; for(int j = 0; j < id_num; j++) cout<<"\n"<<M_id[j].id<<"\t"<<M_id[j].type; } //*************************Opus fynkcij******************************// int getlit() { lit = fgetc(in); if(ch != 0) putchar(ch); ch = lit; if(lit >= 'A' && lit <= 'Z') lit -= 'A' - 'a'; switch (lit) { case '+': return 3; break; case '-': return 3; break; case '*': return 3; break; case '/': return 3; break; case ';': return 3; break; case '(': return 3; break; case ')': return 3; break; case ',': return 3; break; case '.': return 3; break; case '<': return 4; break; case ':': return 5; break; case '=': return 6; break; case '>': return 7; break; } if(isalpha(lit)) return 1; else if(isdigit(lit))return 2; else return 9; } int zarezerv(char* lex) { if (!stricmp(lex,"begin")) {syn ='G';return 1;} if (!stricmp(lex,"end")) {syn ='N';return 1;} if (!stricmp(lex,"integer")) {syn ='I';return 1;} if (!stricmp(lex,"real")) {syn ='R';return 1;} if (!stricmp(lex,"boolean")) {syn ='L';return 1;} if (!stricmp(lex,"do")) {syn ='T';return 1;} if (!stricmp(lex,"while")) {syn ='W';return 1;} if (!stricmp(lex,"var")) {syn ='V';return 1;} if (!stricmp(lex,"program")) {syn ='M';return 1;} if (!stricmp(lex,"or")) {syn ='O';return 1;} if (!stricmp(lex,"and")) {syn ='U';return 1;} if (!stricmp(lex,"not")) {syn ='C';return 1;} return 0; } void scan() { int i; lex=new char[30]; if(cl&&!feof(in)) { i=0; while (lit==' ' || lit=='\n' || lit=='\t') { if(lit == '\n') num++; cl=getlit(); } switch(cl) { case 1: lex[i++]=lit; cl=getlit(); while ((cl<=2)&&(cl!=0)) {lex[i++]=lit;cl=getlit();} lex[i]='\0'; if(zarezerv(lex)) { break;} else {if(i<=10) syn='A'; else {syn='E';break;}} break; case 2: lex[i++]=lit; cl=getlit(); while ((cl==2)&&(cl!=0)) {lex[i++]=lit; cl=getlit();} lex[i]='\0'; if(i<=6) syn='B';else syn='F';break; case 3: lex[0]=lit;lex[1]='\0'; syn=lit; cl=getlit();break; case 4: lex[i++]=lit; cl=getlit(); if (cl==7) {lex[i++]=lit; lex[i]='\0'; syn='D'; cl=getlit();break;} else {if (cl==6) {lex[i++]=lit; lex[i]='\0'; syn='H'; cl=getlit();break;}} lex[i]='\0';syn='J';break; case 5: lex[i++]=lit; cl=getlit(); if (cl==6) {lex[i++]=lit; lex[i]='\0'; syn='K'; cl=getlit();break;} lex[i]='\0';syn=':';break; case 6: lex[i++]=lit;lex[i]='\0'; cl=getlit(); syn='P';break; case 7: lex[i++]=lit;cl=getlit(); if (cl==6) {lex[i++]=lit; lex[i]='\0'; syn='Q'; cl=getlit();break;} lex[i]='\0';syn='R';break; case 9: lex[0]=lit;lex[1]='\0'; syn='X';cl=getlit();break; } } } void S() { scan(); if(syn != 'M'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": Programa povuna po4unatus' zi slova Program!!!\n"; return;} scan(); if(syn != 'A'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": Nekorektne imja programu!!!\n"; return;} scan(); if(syn != ';'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyet'sja ';'!!!\n"; return;} scan(); if(syn != 'V' && syn != 'G'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyet'sja BEGIN abo VAR!!!\n"; return;} if(syn == 'V') R(); if(f) return; T(); } void R() { if(f) return; scan(); P(); } void P() { if(f) return; Z(); if(f) return; if(syn != ':'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja ':'!!!\n"; return;} scan(); Y(); if(f) return; if(syn != ';'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja ';'!!!\n"; return;} scan(); while(syn != 'G') { Z(); if(f) return; if(syn != ':'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja ':'!!!\n"; return;} scan(); Y(); if(f) return; if(syn != ';'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja ';'!!!\n"; return;} scan(); } } void Z() { if(f) return; if(syn != 'A'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja identufikator!!!\n"; return;} M_id[id_num].id = lex; M_id[id_num++].type = 4; scan(); while(syn != ':') { if(syn != ','){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja ':'!!!\n"; return;} scan(); if(syn != 'A'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja identufikator!!!\n"; return;} M_id[id_num].id = lex; M_id[id_num++].type = 4; scan(); } } void Y() { if(f) return; if(syn != 'I' && syn != 'R' && syn != 'L'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": Nevidomuj typ danuh!!!\n"; return;} while(M_id[id_num].type == 4) { } scan(); } void T() { if(f) return; if(syn != 'G'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja BEGIN!!!\n"; return;} scan(); A(); if(f) return; if(syn != 'N'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja END!!!\n"; return;} scan(); if(feof(in)) {printf(" "); lex = " ";} if(syn != '.'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja '.'!!!\n"; return;} } void A() { if(f) return; if(syn != 'N') B(); if(f) return; while(syn != 'N') { if(syn != ';'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja ';'!!!\n"; return;} scan(); if(syn == 'N') break; B(); if(f) return; } } void B() { if(f) return; //while(syn == ';') scan(); if(syn == 'N') return; if(syn == 'W') W(); else if(syn == 'G') L(); else if(syn == 'A') V(); else {f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": Neo4ikyvani symvolu!!!\n"; return;} } void V() { if(f) return; if(syn != 'A'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja identufikator!!!\n"; return;} scan(); if(syn != 'K'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja ':='!!!\n"; return;} scan(); G(); } void W() { if(f) return; scan(); G(); if(f) return; if(syn != 'T'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja DO!!!\n"; return;} scan(); B(); } void L() { if(f) return; scan(); A(); if(f) return; if(syn != 'N'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja END!!!\n"; return;} scan(); } void G() { U(); if(syn != 'P' && syn != 'J' && syn != 'R' && syn != 'D' && syn != 'H' && syn != 'Q') return; D(); U(); } void U() { if(f) return; M(); if(f) return; if(syn == '+' || syn == '-' || syn == 'O'){scan(); U();} } void M() { if(f) return; N(); if(f) return; if(syn == '*' || syn == '/' || syn == 'U'){scan(); M();} } void N() { if(f) return; if(syn == '(') { scan(); U(); if(f) return; if(syn != ')'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyjet'sja ')'!!!\n"; return;} } else if(syn == 'C'){scan(); N();} else if(syn == 'E'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": Dovzhuna identufikatora <= 10!!!\n"; return;} else if(syn == 'F'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": Dovzhuna ciloji konstantu <= 6!!!\n"; return;} else if(syn != 'A' && syn != 'B'){f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": Pomulka y vurazi!!!\n"; return;} scan(); } void D() { if(f) return; if(syn != 'P' && syn != 'J' && syn != 'R' && syn != 'D' && syn != 'H' && syn != 'Q') {f = 1; cout<<"\n\n!!!ERROR!!!Line "<<num<<": O4ikyet'sja logi4na operacija!!!\n"; return;} scan(); } void Vudilutu_Lexemy() { int X, Y; CONSOLE_SCREEN_BUFFER_INFO csbi; COORD coord; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); X = coord.X = csbi.dwCursorPosition.X; Y = coord.Y = csbi.dwCursorPosition.Y; coord.X -= strlen(lex); SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 192); printf(lex); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7); while(!feof(in)) { lit = fgetc(in); if(ch != 0) putchar(ch); ch = lit; } } Функція Vudilutu_Lexemy() – виділяє лексему при аналізі якої виникла помилка. Спочатку курсор перемішується на довжину лексеми назад по рядку(функція SetConsoleCursorPosition), далі змінюється атрибут тексту(192 – чорний шрифт на червоному фоні), потім друкується лексема ще раз, на сам кінець атрибут повертається в стандартний(7 – стандартний атрибут) та додруковується залишок вхідної програми. Контрольний приклад: Приклад вхідного файлу: program a34; var abcd2, f: real; b, a, s: integer; se, c, d: BooLeAn; efw,dwewe,we:Real; Begin f:=(b*b)+a*s - f * s+b; while ((s>= (s*a/s)) do begin bEgin b:=165523; c:= not true; end; d:=not false or (not se or d); c := not c and se or false; se := TrUe or FaLsE and d or not c; end; end. Приклад виводу в консолі: program a34; var abcd2, f: real; b, a, s: integer; se, c, d: BooLeAn; efw,dwewe,we:Real; Begin f:=(b*b*)+a*s - f * s+b; while ((s>= (s*a/s)) do begin bEgin b:=165523; c:= not true; end; d:=not false or (not se or d); c := not c and se or false; se := TrUe or FaLsE and d or not c; end; end. !!!ERROR!!!Line 11: Pomulka y vurazi!!! Press any key to continue Висновок: На цій лабораторній я ознайомився з принципом синтаксичного аналізу – перевірки вхідної програми на належність написаній граматиці за допомогою методу рекурсивного спуску. Метод рекурсивного спуску полягає в аналізі «з гори – до низу» - ми рухаємось від початкового не терміналу граматики до вхідної стрічки(коду програми) використовуючи рекурсію – за допомогою якої легко описуються циклічні структури. Також я написав програму синтаксичного контролю вхідного тексту програми написаної на мові Pascal, яка при виявленні помилки виводить рядок програми що містить помилку та вказує тип помилки. Результати програми виводяться на екран.
Допоможи студентському архіву

Ми допомогли тобі — допоможи наступному студенту

Файл ще не обрано

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

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

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

Admin

26.02.2023 12:38

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