Міністерство освіти та науки України
Національний університет «Львівська політехніка»
кафедра прикладної математики
ЛАБОРАТОРНА РОБОТА №2
з системного програмування на тему:
«Лексичний аналіз»
Мета: розбити всі елементарні конструкції мови на класи, визначити формат лексеми-дескриптора, розбити всі літери вхідної мови на класи(для ідентифікації класу чергової лексеми), побудувати скінченний автомат. Написати програму лексичного аналізу коду програми, що отримує на вході – текст програми на запропонованій підмножині мови програмування (у вхідному файлі), на виході – потік лексем-дескрипторів (у вихідному файлі). Лексичний аналізатор організувати як підпрограму, що викликається у циклі головною програмою для формування чергової лексеми-дескриптора.
Варіант №9.
Завдання:
Розглянути підмножину мови Pascal, у якій є ідентифікатори (довжина – не більше 10 символів), цілі константи (довжина – не більше 6 символів), які використовуються у операторах опису (типи змінних – real , integer,boolean), оператори присвоєння, оператори циклу типу while (умова – логічний вираз, утворений з логічних змінних і відповідних логічних операцій).
Дескриптори лексем:
zminna – A
4uslo – B
not – C
<> – D
zm<10 – E
4uslo<6 – F
begin – G
<= – H
integer – I
< – J
:= – K
boolean – L
program – M
end – N
or – O
= – P
>= – Q
real – R
> – S
do – T
and – U
while – W
var – V
inwuj – X
true – Y
false – Z
Код програми:
#include<fstream.h>
#include<string.h>
#include<stdio.h>
#include<iostream.h>
FILE * in;
char *f1="input.txt",* f2="output.txt";
char *lex, syn, lit;
int cl=9;
ofstream out;
int getlit(); //z4utyvannja literu
int zarezerv(char*); //perevirka nalezhnosti ident. do zarezervovanuh sliv
void scan(); //jadro algorutmy
void main(void)
{
in=fopen(f1,"r");
out.open(f2);
lit=' ';
scan();
cout<<"DONE!!!";
}
int getlit()
{
lit=fgetc(in);
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)
{
int pr=0;
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;}
if (!stricmp(lex,"program")) {syn ='M';return 1;}
return pr;
}
void scan()
{
int i;
lex=new char[30];
while((cl)&&(!(feof(in))))
{
i=0;
while ((lit==' ')||(lit=='\n')||(lit=='\t'))
{
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='E';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=lit;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='E';cl=getlit();break;
}
out<<syn<<"\t"<<lex<<"\n";
}
}
Контрольний приклад:
Приклад вхідного файлу:
program fd;
var
abcd12345678:real;
{b}:integer;
begin
a:=(b/b)+b;
if (a<=4)then
while (b<>5) do
begin
b:=123;
end;{
1234567
1234.34
123.3456778
end .
Приклад вихідного файду:
M program
A fd
; ;
V var
E abcd12345678
r :
R real
; ;
E {
A b
E }
i :
I integer
; ;
G begin
A a
K :=
( (
A b
/ /
A b
) )
+ +
A b
; ;
A if
( (
A a
H <=
B 4
) )
A then
W while
( (
A b
D <>
B 5
) )
A do
G begin
A b
K :=
B 123
; ;
N end
; ;
E {
E 1234567
B 1234
. .
B 34
B 123
. .
E 3456778
N end
. .
Висновок:
На цій лабораторній я ознайомився з принципами лексичного аналізу в системному програмуванні, написав програму що аналізує лексичну структуру програми, ділить її на лексеми, класифікує їх та записує в файл ці лексеми та відповідні їм односимвольні лексичні класи.