- •Учебное пособие
- •Учебное пособие
- •Оглавление
- •2. 2 Регулярные выражения
- •2. 3 Грамматика
- •2. 4 Способы получения одних цепочек символов из других
- •2. 5 Формальное определение языка
- •2. 6 Расширенные грамматики
- •2. 7 Задачи анализа
- •2. 8 Синтаксические диаграммы
- •2. 9 Введение в компиляцию
- •2. 30 Структура компилятора
- •2. 11 Проходы компилятора
- •3 Алгоритмический язык spl
- •3. 4 Символы
- •3. 4 Оператор цикла
- •4 Лексический анализ
- •4. 5 Блок-схема функции void main (int ac, char * av [ ])
- •4. 5 Блок-схема функции void number ()
- •4. 5 Блок-схема функции void word ()
- •4. 5 Блок-схема функции char*add(char*nm)
- •5 Полный синтаксис языка spl
- •5.6Алфавит нетерминальных символов
- •5. 6 Синтаксические диаграммы и функции распознавания цепочек для нетерминальных символов
- •6 Пояснения к выполнению курсовой работы
- •6. 7 Пример выполнения курсовой работы
- •6. 7 Варианты заданий для курсовой работы
- •6. 7 Требования к оформлению курсовой работы
- •7 Вопросы к экзамену
- •8 Список литературы
- •Учебное пособие
6 Пояснения к выполнению курсовой работы
Постановка задачи. Составить программу на Си для лексического анализа программы на модифицированном языке SPL. Вывести в файл "getrez.dan" и на экран таблицу идентификаторов и их адресов.
Программа на модифицированном языке SPL (вычисляет xy)
exp(a,b)
begin int z;
z=1;
while b do
if b%2 then z=z*a end;
a=a*a;b=b/2
end;
return z
end
main()
begin int x,y;
read x;
read y;
print exp(x,y)
end
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<conio.h>
#include<alloc.h>
#include<string.h>
/*Коды лексем языка SPL*/
enum{BEGINL=257,ENDL,IFL,THENL,WHILEL,DOL,RETRL,READL,PRITL,INTL,CONSTL,IDEN,NUMB};
int nst=0;
int lval,lex;
static char nch='\n';
FILE*PF,*padres;
void get(void);
void number(void);
void word(void);
char*add(char*nm);
void main(int ac,char*av[])
{
clrscr();
if(!ac)
puts("Hет исходного файла");
PF=fopen(av[1],"r");
padres=fopen("getrez.dan","w");
if(!PF)
puts("Файл не открывается");
else
get();
}
void get()
{
while(nch!=EOF)
{
while(isspace(nch))
{
if(nch=='\n')
nst++;
nch=getc(PF);
}
if(isdigit(nch))
number();
else
if(isalpha(nch))
word();
else
if(nch=='('||nch==')'||nch==','||nch==';'||nch=='='||nch=='+'||nch=='-'||nch=='*'||nch=='/'||nch=='%')
{
lex=nch;
nch=getc(PF);
}
}
if(nch==EOF)
lex=EOF;
else
puts("Hедопустимый символ");
return;
}
void number()
{
for(lval=0;isdigit(nch);nch=getc(PF))
lval=lval*10+nch-'0';
lex=NUMB;
return;
}
void word()
{
static int cdl[]={BEGINL,ENDL,IFL,THENL,WHILEL,DOL,RETRL,READL,
PRITL,INTL,CONSTL,IDEN,NUMB};
static char*serv[]={"begin","end","if","then","while","do","return","read",
"print","int","const"};
int i;
char tx[40];
char*p;
for(p=tx;isdigit(nch)||isalpha(nch);nch=getc(PF))
*(p++)=nch;
*p='\0';
for(i=0;i<11;i++)
if(strcmp(tx,serv[i])==0)
{
lex=cdl[i];
return;
}
lex=IDEN;
lval=(int)add(tx);
printf("Адрес для %s =%p\n",tx,lval);
fprintf(padres,"Адрес для %s =%p\n",tx,lval);
return;
}
char TNM[400];
char*ptn=TNM;
char*add(char*nm)
{
char*p;
for(p=TNM;p<ptn;p+=strlen(p)+1)
if(strcmp(p,nm)==0)
return p;
if((ptn+=strlen(nm)+1)>TNM+400)
{
puts("Переполнение таблицы");
exit(0);
}
return(strcpy(p,nm));
}
Образец результата работы программы
Адрес для exp =0586
Адрес для a =058B
Адрес для b =058D
Адрес для z =058F
Адрес для z =058F
Адрес для b =058D
и т. д.
6. 7 Пример выполнения курсовой работы
Вариант задания курсовой работы
Составить программу на Си для лексического анализа программы на модифицированном языке SPL,в котором все ключевые слова переведены на русский язык и вместо begin и end используются соответственно левая и правая фигурные скобки. Вывести в файл и на экран таблицу идентификаторов и их адресов.
Вариант программы на модифицированном языке SPL (вычисляет xy), где по условию задачи все ключевые слова заменены на соответствующие на русском языке, а вместо begin и end используются соответственно { и }
exp(a,b)
{
целый z;
z=1;
пока b делать
если b%2 тогда z=z*a };
a=a*a;b=b/2
};
возврат z
}
main()
{
целый x,y;
читать x;
читать y;
печатать exp(x,y) }
Замечание: жирным шрифтом выделены изменения, которые необходимо внести в предыдущую программу, согласно варианту задания.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<conio.h>
#include<alloc.h>
#include<string.h>
/*Коды лексем языка SPL*/
enum{BEGINL=257,ENDL,IFL,THENL,WHILEL,DOL,RETRL,READL,PRITL,INTL,CONSTL,IDEN,NUMB};
int nst=0;
int lval,lex;
static char nch='\n';
FILE*PF,*padres;
void get(void);
void number(void);
void word(void);
char*add(char*nm);
int isalpharus(char c);
int isspace1(char c);
int isdigit1(char c);
void main(int ac,char*av[])
{
clrscr();
if(!ac)
puts("Hет исходного файла");
PF=fopen(av[1],"r");
padres=fopen("getrez.dan","w");
if(!PF)
puts("Файл не открывается");
else
get();
}
void get()
{
while(nch!=EOF)
{
while(isspace1(nch))
{
if(nch=='\n')
nst++;
nch=getc(PF);
}
if(isdigit1(nch))
number();
else
if(isalpharus(nch))
word();
else
if(nch=='('||nch==')'||nch==','||nch==';'||nch=='='||nch=='+'||nch=='-'||nch=='*'||nch=='/'||nch=='%'||nch=='{'||nch=='}')
{
lex=nch;
nch=getc(PF);
}
}
if(nch==EOF)
lex=EOF;
else
puts("Hедопустимый символ");
return;
}
void number()
{
for(lval=0;isdigit1(nch);nch=getc(PF))
lval=lval*10+nch-'0';
lex=NUMB;
return;
}
void word()
{
static int cdl[]={BEGINL,ENDL,IFL,THENL,WHILEL,DOL,RETRL,READL,
PRITL,INTL,CONSTL,IDEN,NUMB};
static char*serv[]={"{","}","если","тогда","пока","делать","возврат","читать","печатать","целый","const"};
int i;
char tx[40];
char*p,*add();
for(p=tx;isdigit1(nch)||isalpharus(nch);nch=getc(PF))
*(p++)=nch;
*p='\0';
for(i=0;i<11;i++)
if(strcmp(tx,serv[i])==0)
{
lex=cdl[i];
return;
}
lex=IDEN;
lval=(int)add(tx);
printf("Адрес для %s =%p\n",tx,lval);
fprintf(padres,"Адрес для %s =%p\n",tx,lval);
return;
}
char TNM[400];
char*ptn=TNM;
char*add(char*nm)
{
char*p,*strcpy();
for(p=TNM;p<ptn;p+=strlen(p)+1)
if(strcmp(p,nm)==0)
return p;
if((ptn+=strlen(nm)+1)>TNM+400)
{
puts("Переполнение таблицы");
exit(0);
}
return(strcpy(p,nm));
}
/* Добавляем к исходной программе функции пользователя для распознавания букв, специальных знаков и цифр */
int isalpharus(char c)
{
int v;
if(isalpha(c)||c=='а'||c=='б'||c=='в'||c=='г'||c=='д'||c=='е'
||c=='ж'||c=='з'||c=='д'||c=='е'||c=='ж'||c=='з'||c=='и'|| c=='й'||c=='к'||c=='л'||c=='м'||c=='н'||c=='о'||c=='п'|| c=='р'||c=='с'||c=='т'||c=='у'||c=='ф'||c=='х'||c=='ц'||c=='ч'||c=='ш'||c=='щ'||c=='ы'||c=='э'||c=='ю'||c=='я'||c== 'ь')
v=8;
else
v=0;
return v;
}
int isspace1(char c)
{
int v;
if(c=='\ '||c=='\n'||c=='\t'||c=='\f')
v=1;
else
v=0;
return v;
}
int isdigit1(char c)
{
int v;
if(c=='0'||c=='1'||c=='2'||c=='3'||c=='4'||c=='5'||c=='6'||c=='7'||c=='8'||c=='9')
v=2;
else
v=0;
return v;
}