МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ „ЛЬВІВСЬКА ПОЛІТЕХНІКА”
Лабораторна робота №5
„Польський запис”
Завдання:
Розглянути підмножину мови C, у якій є ідентифікатори (довжина – не більше 10 символів), цілі константи (довжина – не більше 6 символів), дійсні константи з фіксованою крапкою (довжина цілої частини – до 3 символів, дробової – до 5 символів), які використовуються у операторах опису (типи змінних – float , int), оператори присвоєння, оператори циклу типу do … while (умова – одна операція порівняння). Провести синтаксичний та семантичний аналіз вхідної мови. Побудувати польський запис для цього фрагменту.
Варіант 18
Код програми:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <fstream.h>
FILE *fr;
char str[30], lit, syn,op;
int n_el, k_el=1,k_ch=1,n_ch, cl, i, q,num, f, um_cod,ppz,npz=0, polsk[100]; //f - oznaka pomylky
////////////////////////////////////////////////////////////////////////////////
typedef struct
{
char name [30];
char typ;
int ozn;
}
el_tabl;
el_tabl tabl_ident [100];
////////////////////////////////////////////////////////////////////////////////
typedef struct
{
char name [30];
char typ;
int ozn;
}
ch_tabl;
ch_tabl tabl_chysel [100];
////////////////////////////////////////////////////////////////////////////////
void scan();
void getlit();
void S ();
void O ();
void T ();
void P ();
void E ();
void I ();
void R ();
void V ();
void C ();
void W ();
void Y ();
void Z ();
void D ();
void M ();
void H ();
void poshuk ();
void zapys ();
////////////////////////////////////////////////////////////////////////////////
void main ()
{
fr = fopen("file_good.txt", "rt");
lit=' ';
num=1;
scan();
f=1;
S();
if ((f))
{cout<<"Compilation completed successfully"<<'\n'<<'\n';
cout<<"Polskyj Zapys:"<<'\n'<<'\n';
for(q=0;q<npz;q++)
cout<<polsk[q]<<'\t';
cout<<'\n'<<'\n';
cout<<"Tablycja identyficatoriv 101"<<'\n';
for(i=1;i<k_el;i++)
cout<<tabl_ident[i].name<<'\n';
cout<<'\n'<<'\n';
cout<<"Tablycja constant 102"<<'\n';
for(i=1;i<k_ch;i++)
cout<<tabl_chysel[i].name<<'\n';
cout<<'\n'<<'\n';
cout<<"Tablycja operacij"<<'\n';
cout<<"+"<<'\n'<<"-"<<'\n'<<"*"<<'\n'<<"/"<<'\n'<<"unarnyj minus"<<'\n'<<"="<<'\n'<<'\n'<<'\n';
}
fcloseall();
}
////////////////////////////////////////////////////////////////////////////////
void getlit()
{
fscanf(fr, "%c", &lit);
if(!(feof(fr)))
{cl=6;
if (isalpha(lit)) cl=1;
if (isdigit(lit)) cl=2;
if ((lit=='{')||(lit=='}') || (lit=='(') || (lit==')') || (lit=='+') || (lit=='-') ||
(lit=='*') || (lit=='/') || (lit==';') || (lit==',')) cl=3;
if (lit=='=') cl=4;
if ((lit=='>') || (lit=='<') || (lit=='!')) cl=5;
}
}
////////////////////////////////////////////////////////////////////////////////
void scan()
{
i=0;
char *kw[2]={"int", "float"} ;
if (!(feof(fr)))
{
if (lit=='\n') num++;
while ((lit==' ') || (lit=='\t') || (lit=='\n')) getlit();
switch(cl) {
case 1: str[i++]=lit; getlit(); while (cl<=2) {str[i++]=lit;getlit();}
str[i++]='\0';
int j; j=0;
while ((strcmp(str, kw[j])!=0) && (j!=2))j++;
if (j<2) {syn='s'; return;}
if (strcmp(str, "do")==0) {syn='o'; return;}
if (strcmp(str,"while")==0) {syn='w'; return;}
else syn='i'; break;
case 2: str[i++]=lit; getlit();while (cl==2) {str[i++]=lit;getlit(); }
if(lit=='.')
{
str[i++]=lit;getlit();if (cl==2)
while (cl==2) {str[i++]=lit;getlit();}
str[i++]='\0'; syn='d';break;
}
str[i++]='\0'; syn='c';break;
case 3: str[i]=lit; str[1]='\0'; syn=lit; getlit(); break;
case 4: str[i++]=lit; syn=lit; getlit(); if (lit=='=') {str[i++]=lit; getlit(); syn='r'; }
str[i++]='\0'; break;
case 5: str[i++]=lit; syn=lit;
if(lit=='<')
{getlit(); if (lit=='=') {str[i++]=lit; syn='m';getlit();}}
if(lit=='>')
{getlit(); if (lit=='=') {str[i++]=lit; syn='b';getlit();}}
if(lit=='!')
{getlit(); if (lit=='=') {str[i++]=lit; syn='n';getlit();}}
/*getlit();*/ str[i++]='\0';break;
default:str[0]=lit;syn='e'; str[1]='\0'; getlit(); f=0;
cout<<"ERROR:Leksychna pomylka\nLine "<<num<<'\n'; break;
}
}
}
////////////////////////////////////////////////////////////////////////////////
void S()
{
if (syn!='{')
{f=0; cout<<"ERROR:Nemaje vidkryvajuchoji figurnoji duzhky\nLine "<<num<<'\n';}
if (f)
{
scan ();
O();
T();
if(f)
if (syn!='}')
{f=0; cout<<"ERROR:Nemaje zakryvajuchoji figurnoji duzhky\nLine "<<num<<'\n'; }
}
}
////////////////////////////////////////////////////////////////////////////////
void O()
{
if (f)
{
P();
if(f)
{ while(syn=='s')
P();
}
}
}
////////////////////////////////////////////////////////////////////////////////
void P()
{
E();
if (f)
{
I();
if(f)
{ while(syn==',')
{
scan(); I();
}
if (syn!=';')
{f=0; cout<<"ERROR:Nemaje ';' pislja opysu\nLine "<<num<<'\n';}
}
}
scan();
}
////////////////////////////////////////////////////////////////////////////////
void E()
{
if (syn!='s')
{f=0; cout<<"ERROR:Nepravylnyj typ zminnych\nLine "<<num<<'\n';}
scan();
}
////////////////////////////////////////////////////////////////////////////////
void I()
{
if(f)
{
if(syn!='i')
{f=0; cout<<"ERROR:Nepravylnyj identyficator\nLine "<<num<<'\n';}
//semantychnyj analizator
else
{poshuk ();
if (n_el!=-1)
{printf ("Identyficator %s opysano dvichi\nLine%i\n", str,num);
f=0;}
else zapys ();
}
}
scan();
}
////////////////////////////////////////////////////////////////////////////////
void T()
{
if(f)
{
R();
if(f)
{ while((syn=='i')||(syn=='o'))
if (f)
{
R();
}
else return;
}
}
}
////////////////////////////////////////////////////////////////////////////////
void R()
{
if(f)
{ switch (syn)
{
case 'i': {V(); break; }
case 'o': {C(); break; }
default:f=0; cout<<"ERROR:Nepravylnyj operator\nLine "<<num<<'\n';break;
}
}
}
////////////////////////////////////////////////////////////////////////////////
void V()
{
if (f)
{
if(syn!='i')
{f=0; cout<<"ERROR:Nepravylne prysvojennja\nLine "<<num<<'\n';}
//semantychnyj analizator
else
{poshuk ();
if (n_el==-1)
{printf ("Identyficator %s ne opysanyj\nLine%i\n", str,num);f=0;}
else
{
polsk[npz++]=101; polsk[npz++]=n_el;}
}
scan();
if (f)
{
if(syn!='=')
{f=0; cout<<"ERROR:Nepravylne prysvojennja\nLine "<<num<<'\n';}
scan();
if (f)
{
W() ;
polsk[npz++]=6;
if(f)
{
if(syn!=';')
{f=0; cout<<"ERROR:Nepravylne prysvojennja\nLine "<<num<<'\n';}
scan();
}
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
void C()
{
if(f)
{
if (syn!='o')
{f=0; cout<<"ERROR:Nepravylnyj cykl\nLine "<<num<<'\n';}
scan();
if(f)
{
if(syn!='{')
{f=0; cout<<"ERROR:Nepravylnyj cykl\nLine "<<num<<'\n';}
scan();
if(f)
{ppz=npz;
T();
if (f)
{
if(syn!='}')
{f=0; cout<<"ERROR:Nepravylnyj cykl\nLine "<<num<<'\n';}
scan();
if(f)
{
if(syn!='w')
{f=0; cout<<"ERROR:Nepravylnyj cykl\nLine "<<num<<'\n';}
scan();
if(f)
{
if(syn!='(')
{f=0; cout<<"ERROR:Nepravylnyj cykl\nLine "<<num<<'\n';}
scan();
if(f)
{
Y();
if(f)
{
if(syn!=')')
{f=0; cout<<"ERROR:Nepravylnyj cykl\nLine "<<num<<'\n';}
polsk[npz++]=103;polsk[npz++]=ppz;polsk[npz++]=um_cod;
scan();
if(f)
{
if(syn!=';')
{f=0; cout<<"ERROR:Nepravylnyj cykl\nLine "<<num<<'\n';}
scan();
}
}
}
}
}
}
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
void Y()
{
if(f)
{
W();
if(f)
{
Z();
if(f)
{
W();
polsk[npz++]=2;
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
void W()
{
if (f)
{
if(syn=='-')
{ scan();
D();polsk[npz++]=5;}
else D();
if(f)
{
while((syn=='+')||(syn=='-'))
{op=syn;
scan(); D();if(op=='+')polsk[npz++]=1;
else polsk [npz++]=2;
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
void D()
{
if (f)
{
M();
if(f)
{
while((syn=='*')||(syn=='/'))
{op=syn;
scan(); M();if(op=='*')polsk[npz++]=3;
else polsk [npz++]=4;
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
void M()
{
if(f)
{
switch(syn)
{
case 'i':poshuk ();if (n_el==-1)
{printf ("Identyficator %s ne opysanyj\nLine%i\n", str,num);f=0;} else polsk[npz++]=101; polsk[npz++]=n_el;break;
case 'c':
case 'd':polsk[npz++]=102;
int j; n_ch=-1;
for (j=1;j<k_ch+1; j++)
{if (strcmp (str, tabl_chysel[j].name)==0) {n_ch=j;polsk[npz++]=n_ch;}}
if(n_ch==-1)
{strcpy(tabl_chysel[k_ch].name,str);
tabl_chysel[k_ch].typ=syn;
tabl_chysel[k_ch].ozn=cl;
polsk[npz++]=k_ch;k_ch++;}break;
case '(':{scan();W(); if (f){if(syn!=')'){f=0;cout<<"ERROR:Nepravylnyj vyraz\nLine "<<num<<'\n';}}break;}
default:{f=0;cout<<"ERROR:Nepravylnyj vyraz\nLine "<<num<<'\n';break;}
}
scan();}
}
////////////////////////////////////////////////////////////////////////////////
void Z()
{
if(f)
{
if((syn!='n') && (syn!='r') && (syn!='m') && (syn!='b')&&(syn!='<')&&(syn!='>'))
{f=0;cout<<"ERROR:Nepravylnyj znak\nLine "<<num<<'\n';}
else{um_cod=15;
if(strcmp(str,"<")==0)um_cod=14;
if(strcmp(str,">")==0)um_cod=13;
if(strcmp(str,"m")==0)um_cod=12;
if(strcmp(str,"b")==0)um_cod=11;
if(strcmp(str,"r")==0)um_cod=16;
}}
scan();
}
////////////////////////////////////////////////////////////////////////////////
void poshuk ()
{
int j; n_el=-1;
for (j=1;j<k_el+1; j++)
if (strcmp (str, tabl_ident[j].name)==0)
{
n_el=j; break;
}
}
////////////////////////////////////////////////////////////////////////////////
void zapys ()
{
strcpy (tabl_ident[k_el].name, str);
tabl_ident[k_el].typ=syn;
tabl_ident[k_el].ozn=cl;
k_el++;
}
Вхідна мова:
{
int a,b;
float c, d;
b=1;
d=2;
a=5+b;
c=-b*d/(4+b);
do {
a=c*c+(d+2);
b=b+2;
}
while (a>b-1);
b=8;
}
Контрольний приклад польського запису:
101 2 102 1 6 101 4 102 2 6 101 1 102 3 101
2 1 6 101 3 101 2 101 4 3 102 4 101 2 1
4 5 6 101 1 101 3 101 3 3 101 4 102 4 1
1 6 101 2 101 2 102 2 1 6 101 1 101 2 102
1 2 2 103 33 13 101 2 102 5 6
Таблиця констант
Код
1
1
2
2
5
3
4
4
8
5
Таблиця ідентифікаторів
Код
a
1
b
2
c
3
d
4
Таблиця операцій
Код
+
1
-
2
*
3
/
4
унарний мінус
5
=
6
Таблиця операторів переходу
Код
BR
10
BPZ
11
BMZ
12
BP
13
BM
14
BNZ
15
BZ
16