
- •6.040303 Системний аналіз
- •Завдання на лабораторну роботу
- •Лабораторна робота № 2 Лексичний аналізатор
- •Теоретичний вступ
- •Завдання на лабораторну роботу
- •Лабораторна робота № 3 Граматичний аналізатор
- •Теоретичний вступ
- •Результат
- •Лабораторна робота № 4 Семантичний аналізатор
- •Теоретичний вступ
- •Результат
Результат
Лабораторна робота № 4 Семантичний аналізатор
Завдання до лабораторної роботи:
Розглянути підмножину мови Pascal, у якій є ідентифікатори (довжина – не більше 10 символів), цілі константи (довжина – не більше 6 символів), дійсні константи з фіксованю крапкою ( довжина цілої частини – до 3 символів, дробової – до 5 символів),які використовуються у операторах опису (типи змінних – real , integer,boolean), оператори присвоєння, оператори циклу типу for…to. Забезпечити компілювання програми.
Теоретичний вступ
Синтаксичний аналіз (парсинг) (англ. parsing) — в інформатиці це процес аналізу вхідної послідовності символів, з метою розбору граматичної структури згідно із заданою формальною граматикою. Синтаксичний аналізатор (англ. parser) — це програма або частина програми, яка виконує синтаксичний аналіз.
Під час синтаксичного аналізу текст оформлюється у структуру даних, зазвичай — в дерево, яке відповідає синтаксичній структурі вхідної послідовності, і добре підходить для подальшої обробки. Зазвичай синтаксичні аналізатори працюють в два етапи: на першому ідентифікуються осмислені токени (виконується лексичний аналіз), на другому створюється дерево розбору.
Метод рекурсивного спуску або низхідний розбір — один з методів визначення приналежності вхідного рядка деякій формальній мові, описаній LL(k)-граматикою. Це клас алгоритмів лексичного аналізу, де правила формальної граматики розкриваються, починаючи зі стартового символу до отримання потрібної послідовності токенів.
Ідея методу
Для кожного нетермінального символу K будується функція, яка для будь-якого вхідного слова x робить дві речі:
Знаходить найбільший початок z слова x, здатний бути початком виводжуваного з K слова
Визначає, чи є початок z виводжуваним з K
Така функція має задовольняти такі критерії:
зчитувати із ще необробленого вхідного потоку максимальний початок A, який є початком деякого слова, виводжуваного з K
визначати чи є A вивідним з K або просто невивідним початком виводжуваного з K слова
У випадку, якщо такий початок зчитати не вдається (і коректність функції для нетермінала K доведена), тоді вхідні дані не відповідають мові, і потрібно зупинити розбір.
Розбір містить у собі виклики описаних вище функцій. Якщо для зчитаного нетермінала є складене правило, тоді при його розборі будуть викликані інші функції для розбору терміналів, що входять в нього. Дерево викликів, починаючи із самої«верхньої» функції еквівалентно дереву розбору.
Найбільш простий і «людяний» варіант створення аналізатора, що використовує метод рекурсивного спуску, - безпосереднє програмування за кожним правилом вводу для нетерміналів граматики.
#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream.h>
#include<fstream.h>
//******************************************************************************
struct identifire
{char ident[20];
int opys;
int inicial;
char typ;
identifire *next;
};
//******************************************************************************
identifire *num_id;
int sl,i,k, count;
char str[20],lek,lit,n[20],m[20],typins,typouts;
FILE *VhidProg,*Tab1,*Tab2;
//******************************************************************************
char opys(char *);
void correct(char ,char);
//******************************************************************************
void pochatok();
void opys();
void vykon();
void cikl();
void Operatory();
void prysv();
void e();
void t();
void f();
void vidn();
void UNTIL();
void Umova();
void Error_01(int);
//******************************************************************************
void openfile();
void Official_word();
int isrozpod(char);
int getlit();
void scan();
//******************************************************************************
void Official_word()
{ char c[1];
fseek(Tab1,0,0);
for(;!feof(Tab1);)
{ fscanf(Tab1,"%s %s\n",c,n);
if(strcmp(n,str)==0)
{ lek=c[0];break;
}
}
}
//******************************************************************************
int isrozpod(char)
{ char c[1];
fseek(Tab2,0,0);
while(!feof(Tab2))
{ fscanf(Tab2,"%s\n",c);
if(c[0]==lit)return 1;
}
return 0;
}
//******************************************************************************
int getlit()
{ lit=getc(VhidProg);
printf("%c",lit);
if(isalpha(lit)) return 1;
if(isdigit(lit)) return 2;
if(isrozpod(lit)) return 3;
if(lit==':') return 4;
if(lit=='<') return 5;
if(lit=='>') return 6;
return 13;
}
/************** procedura povertae syntaksy4nyj kod lexemy ****************/
void scan()
{ i=0;
while((lit==' ')||(lit=='\n')||(lit=='\t'))
{if(lit=='\n'){k++; cout << "[" <<k <<"]\t";};
sl=getlit();}
switch(sl)
{
case 1:
str[i++]=lit;sl=getlit();
while(sl<=2)
{ str[i++]=lit;sl=getlit();
}
str[i]='\0';lek='i';Official_word();break;
case 2:
str[i++]=lit;sl=getlit();
while(sl==2)
{ str[i++]=lit;sl=getlit();
}
str[i]='\0';lek='c';break;
case 3:
str[0]=lit;str[1]='\0';
lek=lit;
sl=getlit();break;
case 4:
str[i++]=lit;lek=lit;sl=getlit();
if(lit=='=')
{ lek='m';str[i++]=lit;sl=getlit();
}
str[i]='\0';break;
case 5:
str[i++]=lit; lek='<';sl=getlit();
if(lit=='=')
{ lek='n';str[i++]=lit;sl=getlit();
}
else if(lit=='>')
{ lek='o';str[i++]=lit;sl=getlit();
}
str[i]='\0';break;
case 6:
str[i++]=lit; lek='>';sl=getlit();
if(lit=='=')
{ lek='b';str[i++]=lit;sl=getlit();
}
str[i]='\0';break;
case 13:
str[0]=lit;str[1]='\0';
lek='e';sl=getlit();break;
}
}
//******************************************************************************
void pochatok()
{ if(lek=='p')scan();
else Error_01(1);
if(lek=='i')scan();
else Error_01(2);
if(lek==';')scan();
else Error_01(3);
opys();
}
//******************************************************************************
void opys()
{ if(lek=='v')scan();
else Error_01(1);
count=0;
while(lek!='b')
{ if(lek=='i')
{ if(opys(str)!='0')Error_01(12);
switch(count)
{ case 0:
num_id=(identifire*)malloc(1 * sizeof(identifire));
strcpy(num_id[count].ident,str);
num_id[count].typ='1';
num_id[count].opys=1;
num_id[count].inicial=0;
count++;
scan();break;
default:
num_id[count-1].next=(identifire*)malloc(1 * sizeof(identifire));
strcpy(num_id[count].ident,str);
num_id[count].typ='1';
num_id[count].opys=1;
num_id[count].inicial=0;
count++;
scan();break;
}
}
else Error_01(2);
switch (lek)
{
case ',':
scan(); break;
case ':':
scan();
if(lek=='n'||lek=='r'||lek=='$')
{ for(k=0;k<count;k++)
if(num_id[k].typ=='1')num_id[k].typ=lek;
scan();
}
else Error_01(1);
if(lek==';')
scan();
else Error_01(3); break;
default: Error_01(4);
}
}
if(lek=='b')scan();
else Error_01(1);
vykon();
}
/**************** procedura perevirky vykonav4oj 4astyny **********************/
void vykon()
{ while(lek!='d')
{ k=0;
switch(lek)
{
case 'i':
if((typouts=opys(str))=='0')Error_01(13);
strcpy(m,str);
scan();
Operatory(); break;
case 'f':
scan();
cikl(); break;
default: Error_01(5);
}
}
scan();
if(lek!='.')Error_01(6);
}
/**************** procedura perevirky prostogo ciklu **************************/
void cikl()
{ if(lek=='i')
{
if(lek=='i'&&(typins=opys(str))!='0')
correct(typouts,typins);
else Error_01(13);scan();
}
else Error_01(2);
Operatory();
{
if(lek=='u'){
scan();
if(getlt()==2){
scan();
if(lek=='d'){
scan();
}
}
} else Error_01(1);
UNTIL();
}
if(lek==';')scan();
else Error_01(3);
}
//******************************************************************************
void Operatory()
{ for(;;)
{ prysv();
if(k==2)
{ for(k=0;k<count;k++)
if(strcmp(num_id[k].ident,m)==0)num_id[k].inicial=1;
}
if(lek==';')scan();
else Error_01(3);
strcpy(m,str);k=0;
if(lek=='i')
{ if((typouts=opys(str))=='0')Error_01(13);
scan();
}
else break;
}
}
//******************************************************************************
void prysv()
{ k=0;
if(lek=='m')scan();
else Error_01(7);
if(lek=='c')k=1;
e();
}
//******************************************************************************
void UNTIL()
{
if(lek=='(' )
{ scan(); Umova();
if(lek==')')
scan();
else Error_01(9);
} else if(lek!='(' )
{ Umova();
if(lek==')') Error_01(11);
}
}
//******************************************************************************
void Umova()
{ if((lek=='i')||(lek=='c')||(lek=='$'))
{if((lek=='i')&&(typouts=opys(str))=='0')Error_01(13);
strcpy(m,str);
scan();}
else Error_01(2);
vidn();
if((lek=='i')||(lek=='c')||(lek=='$'))
{if((lek=='i')&&(typouts=opys(str))=='0')Error_01(13);
strcpy(m,str);
scan();}
else Error_01(8);
}
//******************************************************************************
void vidn()
{ switch(lek)
{ case '>': scan();break;
case '<': scan();break;
case 'b': scan();break;
case 'n': scan();break;
case 'o': scan();break;
default : Error_01(10);
}
}
//******************************************************************************
void e()
{ if(lek=='-')scan();
t();
while((lek=='+')||(lek=='-'))
{ scan();t();
}
}
//******************************************************************************
void t()
{ f();
if(k==1&&(lek==';'))k=2;
else k=0;
while((lek=='*')||(lek=='/'))
{ scan(); f();
}
}
//******************************************************************************
void f()
{ switch(lek)
{
case '$': scan();break;
case 'c': scan();break;
case 'i':
if((lek=='i')&&(typins=opys(str))=='0')Error_01(13);
else correct(typouts,typins);
k=0;scan();break;
case '(': k=0;scan();e();
if(lek==')')scan();
else Error_01(9);break;
default : Error_01(15);
}
}
//******************************************************************************
void Error_01(int d)
{ printf("\nERROR:");
switch (d)
{ case 1:
printf("\nPered '%s' v %i-stri4ci vidsutne zarezervovane slovo!",str,k+1);break;
case 2:
printf("\nPered '%s' v %i-stri4ci vidsutnij identyfikator!",str,k+1);break;
case 3:
printf("\nPered '%s' v %i-stri4ci vidsutnij pozdiluva4 ';'!",str,k+1);break;
case 4:
printf("\nPered '%s' v %i-stri4ci vidsutnij ',' abo ':'!",str,k+1);break;
case 5:
printf("\nPered '%s' v %i-stri4ci vidsutnij identyfikator abo 'repeat'!",str,k+1);break;
case 6:
printf("\n%i-stri4ci vidsutnij kinec programy (Nemae '.')!",str,k+1);break;
case 7:
printf("\nPered '%s' v %i-stri4ci vidsutnij znak ':='!",str,k+1);break;
case 8:
printf("\nPered '%s' v %i-stri4ci vidsutnij identyfikator abo const!",str,k+1);break;
case 9:
printf("\nPered '%s' v %i-stri4ci vidsutnij znak zakryttja vyrazu ')'!",str,k+1);break;
case 10:
printf("\nPered '%s' v %i-stri4ci zadano nepravulne vidnowennja",str,k+1);break;
case 11:
printf("\nPered '%s' v %i-stri4ci vidsutnij znak vidkrutja vyrazu '('!",str,k+1);break;
case 12:
printf("\nZminna < %s > opysana dvichi!",str);break;
case 13:
printf("\nZminna < %s > ne opysana!",str);break;
case 14:
printf("\nNekorrektnict typiv zminnyh, zminnij < %c > := < %c >!",typouts,typins);
case 15:
printf("\nNekorrektnict typiv zminnyh!");
}
puts("\nThe end of the program");
puts("Press any key to exit this program");
getch();
exit(0);
}
//*****************************************************************************
void openfile()
{ if((VhidProg=fopen("VhidProg.txt","r"))==NULL)
{ puts("\nError of reading lab2.txt\n");
getch();exit(0);
}
if((Tab1=fopen("Tabl1.txt","r"))==NULL)
{ puts("\nError of reading tabl1.txt\n");
getch();exit(0);
}
if((Tab2=fopen("Tabl2.txt","r"))==NULL)
{ puts("\nError of reading tabl2.txt \n");
getch();exit(0);
}
}
//******************************************************************************
void main()
{ clrscr();
openfile();
lit=' ';
while(!feof(VhidProg))
{ scan();
pochatok();
cout << "\n\nEnd of the check, mistake is not found. \n";
cout << "The end of the program \n";
cout << "Press any key to exit this program \n";
}
for(k=0;k<count;k++)
if(num_id[k].inicial==0)
printf("Worning: %s ne inicializovana!\n",num_id[k].ident);
free(num_id);
num_id=NULL;
fcloseall();
getch();
}
//******************************************************************************
char opys(char str[20])
{ int k;
char d;
for(k=0;k<count;k++)
if(strcmp(num_id[k].ident,str)==0)
{ d=num_id[k].typ;
return d;
}
return '0';
}
//******************************************************************************
void correct(char typouts,char typins)
{ switch (typouts)
{
case 'r':
if((typins!='r'))Error_01(14);
}
}
Вхідний код
program Bwc1;
var a:real;
s,b:integer;
begin
a:=1;
a:=1-m;
for i:=1 to n do
begin
sdad
end;
end.