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

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

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

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

Лабораторна робота №3. Синтаксичний аналіз

Оригінальна назва роботи

Синтаксичний аналіз

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

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

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

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

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

У роботі реалізовано алгоритм синтаксичного аналізу вхідного файлу на основі результатів лексичного аналізу. Наведено код програми на мові C та приклади обробки помилок.

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

  • Синтаксичний аналіз
  • Лексичний аналіз
  • Граматика мови
  • Обробка помилок
  • Мова програмування C
  • Компілятори

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

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

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

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

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

Міністерство освіти і науки України Національний університет «Львівська політехніка» ЛАБОРАТОРНА РОБОТА №3. Синтаксичний аналіз Львів – 2007 Мета: виконати синтаксичний аналіз вхідного файлу використовуючи результат лексичного аналізу. Вхідні дані – текст вхідної програми підмножині мови програмування С. В-19 Розглянути підмножину мови C, у якій є ідентифікатори (довжина – не більше 10 символів), цілі константи (довжина – не більше 6 символів), дійсні константи з фіксованою крапкою, які використовуються у операторах опису (типи змінних – float , int), оператори присвоєння, оператори циклу типу for. 1. Вхідний файл: (один з можливих варіантів, без помилок) void main( ) {int i,j , k = -10; //int ident10k ; int id40 ; i = 2567; j =-3239 ; float fiden = - 22.38; float abcd123ef ; avcd1dd2 = 1259.38 ; for (id40 = 0; id40< i ; i++) {j = j;dfd=43;}; for (ident10k = 200; ident10k >= 100; ident10k--) {abcd123ef= abcd123ef; }; for(uhuh=2;j==-1;j++){j=fdj;int df=34;}; } 2. Потік лексем: z void z main o ( o ) o { t int i i o , i j o , i k = = - - c 10 o ; t int i id40 o ; i i = = c 2567 o ; i j = = - - c 3239 o ; a float i fiden = = - - d 22.38 o ; a float i abcd123ef o ; i avcd1dd2 = = d 1259.38 o ; f for o ( i id40 = = c 0 o ; i id40 s < i i o ; i i p ++ o ) o { i j = = i j o ; i dfd = = c 43 o ; o } o ; f for o ( i ident10k = = c 200 o ; i ident10k n >= c 100 o ; i ident10k m -- o ) o { i abcd123ef = = i abcd123ef o ; o } o ; f for o ( i uhuh = = c 2 o ; i j t == - - c 1 o ; i j p ++ o ) o { i j = = i fdj o ; t int i df = = c 34 o ; o } o ; o } Всі символи були розбиті на класи: букви – для ідентифікаторів цифри – для цифр та ідентифікаторів лексеми одиничної довжини ( , ; { } * ) ( ) – для знаків одиничної довжини знак + - для виділення знаку + та інкременту ++ знак – - для виділення знаку – та декременту -- знак / - для виділення знаку / та коментарів знак < > - для виділення знаків <, > та <=, >= знак . – для визначення дійсного числа решта знаків які не ввійшли до класів 1-8, 10 знак = - для виділення знаку = та порівняння = = Дескриптори лексем: z – визначає службове (зарезервоване) слово: main, void f - визначає for a - визначає float t - визначає int i – ідентифікатор c – ціле число d – дійсне число o – одно символьна лексема: , ; { } * ) ( + - операцію + p - інкремент - - операція - m - декремент / - операцію / s – строга нерівність <, > n – нестрога нерівність <=, >= = - операція присвоєння = t – операція порівняння = = 3. Граматика: Примітка1. Крапка після «відкриваючого» символу і крапка до «закриваючого» символу вказує на те що ці символи не належать до термінальних символів Не термінальні символи: M T F P O I D N M – заголовок основної програми – main T – тіло програми або циклу F – оператор for P – операція присвоєння O – опис змінних I – ініціалізація оператора for D – інкремент або декремент ідентифікатора. Використовується в 3тій складовій ініціалізації for ( I ) N – порівняння в другій складовій ініціалізації for ( I ) Термінальні символи: z f a t i c d , ; { } ) ( p m s n t = Аксіома: M Правила виводу: M => [. z .] z ( [. z .] ) { T } T => F | P | O F => f ( I ) { T } ; P => i = (. i | d | c .) ; O => t i [. = (. i | c .) .] {. , i [. = (. i | c .) .] .} ; | a i [. = (. i | d .) .] {. , i [. = (. i | d .) .] .} ; I => (. O | P .) N D D => i (. p | m .) N => i (. s | n | t .) (. i | d | c .) ; 4. Реалізація виводу про помилки: Всі помилки розбиті на такі класи: 0 – Помилки в main (при наявності такої помилки подальший аналіз може не відбутись – для тіла T) 1 – Помилки в операторі for ( в тому числі і і його ініціалізації I ) 2 – Помилки в операторі присвоєння 3 – Помилки в описі змінних 4 – Помилки лексичного аналізу, що стосуються перевищення довжини ідентифікаторів, цілих і дійсних чисел. Примітка2. При виконанні лексичного аналізу дескриптору лексеми надається значення «е»(при наявності помилки 4). В подальшому, при синтаксичному аналізі це ствоює незручності. Тому при роботі синтаксичного аналізатора, при зчитуванні рядка в якому дескриптор лексеми має значення «е», читається наступний рядок. Тобто дана лексема не розглядається. Це приводить до виникнення ряду помилок після цієї лексеми. Тому при виправленні помилок необхідно враховувати цю особливість. 5 – Помилки в тілі циклу або main Інформація про виведені помилки включає в себе тип помилки та кількість помилок певного типу. 5. Контрольний приклад: Варіант вхідного файлу: void main( ) {int i,j , k = -10; //int ident10k ; int d id40 ; i = 4 2567; j =-3239 ; float fiden = - 22.38; float abcd123ef ; avcd1dd2 = 1259.38 ; for (id40 = 0; id40<> i ; i+++) {j = j;dfd=43;}; for (ident10k = 200; ident10k >= 100; ident10k--) {abcd123ef= abcd123ef; }; for(uhuh=2;j==-1;j++){j=fdj;int ddffgfsdqqw=34;}; } Результат виконання:  Висновок: Реалізована програма яка на основі результатів лексичного аналізу, виконує синтаксичний аналіз вхідного файлу. Спочатку відбувається лексичний прохід а потім синтаксичний. Після цього виконується вивід помилок. 6. Код програми: #include <stdio.h> #include <conio.h> #include <iostream.h> #include <string.h> #define path1 "c:/workpol/3kurs/sysprog/lab303/vhid.txt" #define path2 "c:/workpol/3kurs/sysprog/lab303/leksemy.txt" //#define path1 "p:/lab303/vhid.txt" //#define path2 "p:/lab303/leksemy.txt" //--------------------------FUNCTION PROTOTIPES-------------------------- void analize(FILE*fw,char *str); int setclas(char sym); void getlit(char *str,int* i,int* clasnum); void write(FILE*fw,char lekstype,int p,int q,char*str); void leksyka(void); //--------------------- void errors(void); void syntax(void); char getsym(void); //-------------------- void M(void); void T(void); void F(void); void P(void); void O(void); void I(void); void N(void); void D(void); //-----------------------GLOBAL VARIABLES----------------------------- char str[200]; //strichka. z vhidnogo faila zchytuem po strichci char sym; FILE *fr; //vhidny fail int maserror[6]; //masyv pomylok //------------------------------MAIN------------------------------------- void main(void) { clrscr(); leksyka(); syntax(); errors(); getch(); } //---------------------FUNCTION BODIES------------------------------------- void syntax(void) { fr=fopen(path2,"r"); sym=getsym(); M(); //provirka main fclose(fr); cout<<"\nSytaxsychny analiz vhidnogo potoku leksem ("<<path2<<")uspishno vykonanyy.\n"; } //------------------------------------------------------------------------- void errors(void) { if(maserror[0]>=1)cout<<"\nDopushceni pomylky v Main. Kilkist - "<<maserror[0]; if(maserror[1]>=1)cout<<"\nDopushceni pomylky v For. Kilkist - "<<maserror[1]; if(maserror[2]>=1)cout<<"\nDopushceni pomylky v Operacii prysvoennya. Kilkist - "<<maserror[2]; if(maserror[3]>=1)cout<<"\nDopushceni pomylky v Opysi zminnyh. Kilkist - "<<maserror[3]; if(maserror[4]>=1)cout<<"\nNa etapi syntaxsychnogo analizu vyyavleno pervyschenyya rozmiru identyfikatoriv abo cilyh chysel. Kilkist - "<<maserror[4]; if(maserror[5]>=1)cout<<"\nDopushceni pomylky v Tili main abo for. Kilkist - "<<maserror[5]; } //---------------------------------------------------------------------- void M(void) { int e; e=0; //pomylok nemae if((sym=='z')&&(str[2]=='v')) { sym=getsym(); if((sym=='z')&&(str[2]=='m')) { sym=getsym(); if((sym=='o')&&(str[2]=='(')) { sym=getsym(); if((sym=='z')&&(str[2]=='v')) { sym=getsym(); if((sym=='o')&&(str[2]==')')) { sym=getsym(); if((sym=='o')&&(str[2]=='{')) { sym=getsym(); T(); if((sym=='o')&&(str[2]=='}')) { //sym=getsym(); }else e=1; }else e=1; }else e=1; } else { if((sym=='o')&&(str[2]==')')) { sym=getsym(); if((sym=='o')&&(str[2]=='{')) { sym=getsym(); T(); if((sym=='o')&&(str[2]=='}')) { //sym=getsym(); }else e=1; }else e=1; }else e=1; }; }else e=1; }else e=1; }else { if((sym=='z')&&(str[2]=='m')) { sym=getsym(); if((sym=='o')&&(str[2]=='(')) { sym=getsym(); if((sym=='z')&&(str[2]=='v')) { sym=getsym(); if((sym=='o')&&(str[2]==')')) { sym=getsym(); if((sym=='o')&&(str[2]=='{')) { sym=getsym(); T(); if((sym=='o')&&(str[2]=='}')) { //sym=getsym(); }else e=1; }else e=1; }else e=1; } else { if((sym=='o')&&(str[2]==')')) { sym=getsym(); if((sym=='o')&&(str[2]=='{')) { sym=getsym(); T(); if((sym=='o')&&(str[2]=='}')) { //sym=getsym(); }else e=1; }else e=1; }else e=1; }; }else e=1; }else e=1; }; sym=getsym(); maserror[0]+=e; } //---------------------------------------------------------------------- void T()//tilo obovyazkovo v {} { while( (!feof(fr)) && (str[2]!='}') ) { if(maserror[5]>10000){cout<<"\nPomylka programy abo nadto velyka kilkist pomylok...";break;}; if((sym!='f')&&(sym!='i')&&(sym!='t')&&(sym!='a')){maserror[5]+=1;sym=getsym();}; if(sym=='f') { F(); }; if(sym=='i') { P(); }; if((sym=='t')||(sym=='a')) { O(); }; } } //------------------------------------------------------------------------ void F(void) { int e; e=0; if(sym=='f') { sym=getsym(); if((sym=='o')&&(str[2]=='(')) { sym=getsym(); I(); if((sym=='o')&&(str[2]==')')) { sym=getsym(); if((sym=='o')&&(str[2]=='{')) { sym=getsym(); T(); if((sym=='o')&&(str[2]=='}')) { sym=getsym(); if((sym=='o')&&(str[2]==';')) {} else e=1; } else e=1; } else { e=1; } } else e=1; } else e=1; } else e=1; if(e==0){sym=getsym();}; maserror[1]+=e; } //----------------------------------------------------------------------- void P(void) { int e=0; if(sym=='i') { sym=getsym(); if(sym=='=') { sym=getsym(); if(sym=='-'){sym=getsym();}; //neobhidno shob obiyty - sho stoit pered cilym chyslom if((sym=='i')||(sym=='d')||(sym=='c')) { sym=getsym(); if((sym=='o')&&(str[2]==';')){} else e=1; } else e=1; } else e=1; } else e=1; maserror[2]+=e; while(str[2]!=';'){sym=getsym();};//vse sho do ; ye pomylkove sym=getsym(); } //------------------------------------------------------------------------ void O(void) { int e=0; if((sym!='t')&&(sym!='a'))e=1; else { if(sym=='t') { sym=getsym(); if(sym=='i') { sym=getsym(); if(sym=='=') { sym=getsym(); if(sym=='-'){sym=getsym();}; //neobhidno shob obiyty - sho stoit pered cilym chyslom if((sym=='i')||(sym=='c')) { sym=getsym(); } else e=1; } else { while((sym=='o')&&(str[2]==',')) { e=1; sym=getsym(); if(sym=='i') { sym=getsym(); if(sym=='=') { sym=getsym(); if(sym=='-'){sym=getsym();}; //neobhidno shob obiyty - sho stoit pered cilym chyslom if((sym=='i')||(sym=='c')) { sym=getsym(); if((sym=='o')&&(str[2]==';')) { e=0; break; }; } else e=1; } else { if((sym=='o')&&(str[2]==';')) { e=0; break; }; }; } else e=1; }//while }; if(str[2]!=';')e=1; } else e=1;//yaksho ne identyf }; if(sym=='a') { sym=getsym(); if(sym=='i') { sym=getsym(); if(sym=='=') { sym=getsym(); if(sym=='-'){sym=getsym();}; //neobhidno shob obiyty - sho stoit pered cilym chyslom if((sym=='i')||(sym=='d')) { sym=getsym(); } else e=1; } else { while((sym=='o')&&(str[2]==',')) { e=1; sym=getsym(); if(sym=='i') { sym=getsym(); if(sym=='=') { sym=getsym(); if(sym=='-'){sym=getsym();}; //neobhidno shob obiyty - sho stoit pered cilym chyslom if((sym=='i')||(sym=='d')) { sym=getsym(); if((sym=='o')&&(str[2]==';')) { e=0; break; }; } else e=1; } else { if((sym=='o')&&(str[2]==';')) { e=0; break; }; }; } else e=1; }//while }; if(str[2]!=';')e=1; } else e=1; }; };//else maserror[3]+=e; while(str[2]!=';'){sym=getsym();};//vse sho do ; ye pomylkove sym=getsym(); } //------------------------------------------------------------------------ void I(void) { int e=1; if((sym=='t')||(sym=='a')) { e=0; O(); N(); D(); if((sym=='p')||(sym=='m'))sym=getsym(); }; if(sym=='i') {e=0; P(); N(); D(); if((sym=='p')||(sym=='m'))sym=getsym(); }; if(str[2]==')'){e=0;} else {e=1;while(str[2]!=')'){sym=getsym();};}; //shob mogna bulo dali prodovguvaty maserror[1]+=e; } //------------------------------------------------------------------------ void N(void) { int e=0; if(sym=='i') { sym=getsym(); if((sym=='s')||(sym=='n')||(sym=='t')) { sym=getsym(); if(sym=='-'){sym=getsym();}; if((sym=='i')||(sym=='d')||(sym=='c')) { sym=getsym(); if((sym=='o')&&(str[2]==';')){} else e=1; } else e=1; } else e=1; } else e=1; maserror[1]+=e; sym=getsym(); } //------------------------------------------------------------------------- void D(void) { int e=0; if(sym=='i') { sym=getsym(); if((sym=='p')||(sym=='m')){} else e=1; } else e=1; maserror[1]+=e; } //----------------------------------------------------------------------- char getsym(void) { char sym; fgets(str,200,fr); //chytaem strichku sym=str[0]; //chytaem leksemu if(sym=='e'){fgets(str,200,fr);sym=str[0];}; return sym; } //-------------------------------------------------------------------------- void leksyka (void) { FILE *fr; //vhidny fail FILE *fw; //vyhidny fail char str[200]; //strichka. z vhidnogo faila zchytuem po strichci fr=fopen(path1,"r"); fw=fopen(path2,"w"); while(!feof(fr)) //poky ne kinec vhidnogo faila { fgets(str,200,fr); //chytaem strichku analize(fw,str); //analizuem ii. fw peredaem dlya zapysu v vyhidny fail } fclose(fr); fclose(fw); cout<<"Leksychny analiz vhidnogo faylu ("<<path1<<")uspishno vykonanyy.\nResultat u faili("<<path2<<")\n"; } //---------------------------------------------------------------------- void analize(FILE*fw,char *str) //analiz strichky str. zapys u fail fw leksem { char lekstype; //typ leksemy char leksvalue[20]; int p,q; //pozyciya pochatku i kincya leksemy int clasnum; char sym; //symvol yaky zchytaly p=0; //nomer pozycii - pochatku leksemy int i=0; //lichylnyk - probig po strichci while(str[i]!='\0') //poky ne kinec ryadka { if((str[i]==' ')||(str[i]=='\t')){i++;}; //probil i tab propuskaem getlit(str,&i,&clasnum); //berem i-tyy symvol.daem yomu nomer klasu. i++ switch (clasnum) //cey symvol vyznachae: { case 1: {lekstype='i';p=i;q=i; //identyficator do //poky bukva,cyfra to ce identyf. { getlit(str,&i,&clasnum); q++; //naroschuvannya dovgyny } while((clasnum==1)||(clasnum==2)); i--; write(fw,lekstype,p,q,str);break; //zapys v fw leksemy typu lekstype, }; //dovgynou q-p pochynayuchy z p-yi case 2: {lekstype='c';p=i;q=i+1; //cile chyslo //pozycii strichky str, shco analizuetsya getlit(str,&i,&clasnum); if(clasnum==8){lekstype='d';getlit(str,&i,&clasnum);}; //yakshco . to diysne while(clasnum==2) { getlit(str,&i,&clasnum); if(clasnum==8){lekstype='d';q++;getlit(str,&i,&clasnum);}; //yakshco . to diysne q++; }; i--; write(fw,lekstype,p,q,str);break; //zapys v fw leksemy typu lekstype, }; case 3: {lekstype='o';p=i;q=i+1;write(fw,lekstype,p,q,str);break;}; //odnosymvolni leksemy case 4: { //znak + odnosym leksem abo p-dvosymvolna increment int pr=0; lekstype='+';p=i;q=i+1; getlit(str,&i,&clasnum); if(clasnum==4){lekstype='p';pr=1;q++;write(fw,lekstype,p,q,str);}; if(pr==0){write(fw,lekstype,p,q,str);i--;}; break; }; case 5: { //znak - odnosym leksem abo m-dvosymvolna decrement int pr=0; lekstype='-';p=i;q=i+1; getlit(str,&i,&clasnum); if(clasnum==5){lekstype='m';pr=1;q++;write(fw,lekstype,p,q,str);}; if(pr==0){write(fw,lekstype,p,q,str);i--;}; break; }; case 6: { //znak / odnosym leksem abo propuskaem komentar int pr=0; lekstype='/';p=i;q=i+1; getlit(str,&i,&clasnum); if(clasnum==6) { while(str[i]!='\n'){i++;}; pr=1; }; if(pr==0){write(fw,lekstype,p,q,str);i--;}; break; }; case 7: { //znak <,> strogoi(s) abo <=,>= nestrogoi(n) nerivnosti int pr=0; lekstype='s';p=i;q=i+1; getlit(str,&i,&clasnum); if(clasnum==10){lekstype='n';pr=1;q++;write(fw,lekstype,p,q,str);}; if(pr==0){write(fw,lekstype,p,q,str);i--;}; break; }; case 8: { //krapka ne vvagaem shcho e chysla vydu .4598 i=strlen(str);puts("zustrilas krapka yaka ne ye oznakoyu diysnogo chysla. ignoruem ii");getch(); }; case 9: {break; }; case 10:{//lekstype='=';p=i;q=i+1;write(fw,lekstype,p,q,str);break;}; int pr=0; lekstype='=';p=i;q=i+1; getlit(str,&i,&clasnum); if(clasnum==10){lekstype='t';pr=1;q++;write(fw,lekstype,p,q,str);}; if(pr==0){write(fw,lekstype,p,q,str);i--;}; break; }; } } } //------------------------------------------------------------------------ void getlit(char *str,int* i,int* clasnum) //daem i-tu pozyciyu //i-tomu symvolu strichky str nadaem nomer yog klasu clasnum { char sym=str[*i]; *clasnum=setclas(sym); //vstanovluem klas symvolu sym=str[i] *i=*i+1; //nastupny budem chytaty } int setclas(char sym) //vstanovlennya do yakogo klasu nalegyt sym {int r=9; //inshi symvoly if((sym>='a')&&(sym<='z')||(sym>='A')&&(sym<='Z'))r=1; //bukvy if((sym>='0')&&(sym<='9'))r=2; //cyfry if((sym=='(')||(sym==')')||(sym==';')||(sym==',')||(sym=='{')||(sym=='}')||(sym=='*'))r=3; if(sym=='+')r=4; //odynychni leksemy if(sym=='-')r=5; if(sym=='/')r=6; if((sym=='<')||(sym=='>'))r=7; //znaky porivnyannya if(sym=='.')r=8; //des krapka. dlya float if(sym=='=')r=10; return r; } //-------------------------------------------------------------------- void write(FILE*fw,char lekstype,int p,int q,char*str) //zapys u file fw { //typ leksemy lekstype i ii znachennya yake pochynaetsya v p i mae //dovgynu q-p v strichci str char value[30]=""; //znachennya leksemy int k=q-p-1; //dovgyna leksemy for (int i=0;i<=k;i++,p++){value[i]=str[p-1];}; //formuem znachennya leksemy if(lekstype=='i'){ if(strcmp(value,"for")==0)lekstype='f'; if(strcmp(value,"main")==0)lekstype='z'; if(strcmp(value,"float")==0)lekstype='a'; if(strcmp(value,"int")==0)lekstype='t'; if(strcmp(value,"void")==0)lekstype='z'; } if(lekstype=='i'){ if(k>=9){lekstype='e';maserror[4]+=1;}; }; if(lekstype=='c'){ if(k>=5){lekstype='e';maserror[4]+=1;}; }; fprintf(fw,"%c\t%s\n",lekstype,value); //zapys u fail }
Допоможи студентському архіву

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

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

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

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

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

Admin

26.02.2023 12:38

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