辅导教师 张静 成绩
实验日期
实验时间
1实验名称:词法分析器的设计与实现
2、实验目的(1) 掌握C语言单词符号的划分、正规式、状态转换图及词法分析器的实现。
(2) 掌握词法分析程序的作用。
3、实验要求
(1) 对任给的一个C语言源程序,能够滤掉空格、回车换行符、tab键及注释。
(2) 识别各类单词符号,如关键字、标识符、运算符、常数、界符,结果以二 元式形式输出,并构造符号表。
(3) 输出有词法错误的单词及所在行号。(在此阶段只能识别有限的词法错误)
4、实验原理
根据扫描到的单词符号的第一个字符的种类,分别转到相应的程序进行处 理。这些程序的功能就是识别以相应字符开头的各类单词符号。
5、实验步骤
(1) 根据C语言各类单词的正规式,构造能识别各类单词的状态转换图。
(2) 根据状态转换图,构造识别各类单词的词法分析器 。
6、状态转换图及词法分析程序
状态转换图:
词法分析程序:
#i nclude<stdio.h>
#i nclude<stdlib.h>
#in clude<stri ng>
#in clude<iostream>
using n amespace std;
stri ng
keywords[20]={"i nclude","void","ma in"," in t","char","float","double","if","else","then ","break","co ntin ue","for","do","while","pri ntf","sca nf","begi n","e nd","return"};
char rz[99999]="";
string id[10000];
int pp=0;
string nu[10000];
int qq=0;
int choice1(char a) //判断是否是字母
{
if((a>='a'&&a<='z')||(a>='A'&&a<='Z'))
return 1;
else return 0;
}
int choice2(char a) 〃判断是否是数字
{
if(a>='0'&&a<=9)
return 1;
else return 0;
int alpha(i nt st) 〃识别保留字和标识符
{
char wordbuf[20]="";
int n=0;
for(;;)
{
wordbuf[ n]=rz[st];
st++;
n++;
if((choice2(rz[st])==1)||(choice1(rz[st])==1)||(rz[st]=='_')) wordbuf[ n]=rz[st];
else break;
}
int flag=0;
for(int k=0;k<20;k++)
{
if(strcmp(keywords[k].c_str(),wordbuf)==0) flag=1;
} if(flag==0)
{
int flagg=-1;
for(i nt t=0;t<pp;t++)
{
if(strcmp(id[t].c_str(),wordbuf)==0)
{ _
flagg=t;
}
}
if(flagg!=-1) pri ntf(" (id,%d) ",flagg);
else
{
id[pp]=wordbuf;
printf(" (id,%d) ",pp); pp++;
}
}
else
{
printf(" (");
for(i nt i=0;i <n ;i++)
{
prin tf("%c",wordbuf[i]);
}
prin tf(",-)");
}
return st;
}
int number(i nt st) // 识别整数
{
char numbuf[20]="";
int n=0;
int k=0;
int flag=0;
for(;;)
{
nu mbuf[ n]=rz[st];
st++;
n++;
if(choice2(rz[st])==1)
{
nu mbuf[ n]=rz[st];
}
else if((k==0)&&(rz[st]=='.'))
{
nu mbuf[ n]=rz[st]; k++;
}
else if(choice1(rz[st])==1)
{
nu mbuf[ n]=rz[st];
flag=1; con ti nue;
}
else break;
}
if(flag==0)
{
int flagg=-1;
for(i nt t=0;t<qq;t++)
if(strcmp( nu[t].c_str(), nu mbuf)==0) flagg=t;
if(flagg!=-1) printf(" (nu,%d) ",flagg); else
{
nu[qq]=nu mbuf; printf(" (n u,%d) ",qq);
qq++;
}
}
else
{
printf(" (");
for(int i=0;i<n;i++) printf("%c",numbuf[i]); prin tf(",error digital!)");
}
return st;
}
int anotation(int st) 〃处理除号/和注释
{
char tabuf[9999]="";
int n=0;
st++;
if(rz[st]=='/')
{
prin tf(" (//,-)");
st++;
while(rz[st]!=10)
{
tabuf[ n]=rz[st]; st++;
n++;
} printf(" \n 注释"); for(i nt i=0;i <n ;i++) prin tf("%c",tabuf[i]);
}
else if(rz[st]=='*')
{
prin tf(" (/*,-)");
st++;
int stt=st+1;
while(1)
{ if(rz[st]=='*'&&rz[st+1]=='/') break; tabuf[ n]=rz[st];
st++; n++;
if(rz[st+1]=='\0')
{
prin tf("(/* error!!\n)");
return st+1;
}
} printf(" \n 注释");
for(i nt i=0;i <n ;i++) prin tf("%c",tabuf[i]);
prin tf(" (*/,-)");
st=st+2;
}
else if(rz[st]=='=')
{
st++;
prin tf(" (/*,-)");
}
else printf(" (/,-) ");
return st;
}
in t other(i nt st) //函数识别其他特殊字符
{
switch(rz[st])
{
case '=': st++; if(rz[st]=='=')
{ st++; prin tf(" (rlop,==)");
} else prin tf(" (rlop,=)");
break;
case '+': st++;
if(rz[st]=='=') { st++;
printf(" (+=,-)");
} else if(rz[st]=='+')
{ st++; printf(" (++,-)");
} else printf(" (+,-)"); break;
case '-': st++;
if(rz[st]=='=')
J
st++;
prin tf(" (-=,-)");
}
else if(rz[st]=='-')
{
st++;
prin tf(" (--,-)");
}
else printf(" (-,-)"); break;
case '*': st++;
if(rz[st]=='=')
{
st++; prin tf(" (*=,-)");
}
else printf(" (*,-)"); break;
case '>': st++;
if(rz[st]=='=')
{
st++;
prin tf(" (rlop,>=)");
}
else printf(" (rlop,>)"); break;
case '<': st++;
if(rz[st]=='=')
{
st++;
prin tf(" (rlop,<=)");
}
else printf(" (rlop,<)"); break;
case %: st++;
if(rz[st]=='=')
{
st++;
prin tf(" (\%=,-)");
}
else printf(" (\%,-)"); break;
case '!': st++;
if(rz[st]=='=')
{ st++;
prin tf(" (!=,-)");
}
else printf(" (!,wrong thing!) "); break;
case &: st++;
if(rz[st]=='&')
{ st++;
printf(" (&&,-)");
}
else prin tf(" (&, worng word!) "); break;
case T: st++;
if(rz[st]==T)
{ st++;
printf(" (||,-)");
}
else prin tf(" (|,wor ng word!) "); break;
case '{': st++;
printf(" ({,-)");
break; case '}': st++;
printf(" (},-)");
break;
case '(': st++;
printf(" ((,-)");
break;
case ')': st++;
printf(" (),-)");
break;
case '[': st++; printf(" ([,-)");
break;
case ']': st++; printf(" (],-)");
break;
case ':': st++;
printf(" (:,-)");
break;
case #: st++;
printf("倂,-)");
break;
case ';': st++;
printf(" (;,-)");
break;
case '.': st++;
printf(" (.,-)");
break;
case ',': st++; printf(" (,,-)");
break;
case ' ': st++;
break;
case ' ': st++;
break;
case 10: st++;
prin tf("\n");
break;
case 34: st++;
prin tf(" (\",-)");
break;
case 39: st++;
printf(" (',-)");
break;
default: printf(” (%c,wor ng thing) ",rz[st]);
st++;
}
return st;
}
int choice(i nt st) //根据读入的单词的第一个字符确定调用不同的单词识别
函数
{
if(choice1(rz[st])==1)
st=alpha(st);
else if(choice2(rz[st])==1)
st=nu mber(st);
else if(rz[st]=='/')
st=a no tati on( st);
else st=other(st);
return st;
}
int mai n()
L
int i=0;
FILE *fp;
char n ame[10];
printf("请输入文件名:\n"); scan f("%s",&n ame);
if((fp=fope n(n ame,"r"))==NULL) {
prin tf("Ope n error!"); exit(0);
}
char ch=fgetc(fp); while(ch!=EOF)
{
rz[i]=ch; i++;
ch=fgetc(fp);
}
fclose(fp);
int j=0;
while(rz[j]!='\0')
j=choice(j);
cout?e ndlvv" 程序中标示符如下 "<<e ndl;
for(int i=0;i<pp;i++)
couW "<<id[i]<<e ndl;
cout?"程序中数字如下"<<endl;
for(i nt j=0;j<qq;j++) coutvvjvv" "<<nu [j]<<e ndl;
system("pause");
}
7、测试及结果
测试代码:
int choice(i nt st) //根据读入的单词的第一个字符确定调用不同的单词识别
函数
{
if(choice1(rz[st])==1) st=alpha(st);
else if(choice2(rz[st])==1)
st=nu mber(st); else if(rz[st]=='/') st=a no tati on( st); else st=other(st); return st;
}
测试结果:
8心得
通过本次的实验,使我真正的了解词法分析器的实现过程,让我更加深刻 领悟词法分析器的实现原理。虽然在本次实验中遇到了各种各样的困难和错误, 但在同学们的帮助下我都一一克服了,使得词法分析器能够正确的识别相应的词 法和表达式。
在做实验的过程中,总是会忽略各种细节,从而导致经常修改一些很小的低 级错误才能使程序正常运行,不仅浪费时间,还影响对其他地方的修改,并且在 很多步骤处理上,方法不正确。使结果不能符合要求,深刻体会到了自己在编程 方面与别人的差距,在今后的学习中,我会注意改正自己在这方面的缺点, 促使 自己的编程水平不断进步。编译原理是一门专业学科,对于现阶段的我来说,只 能掌握它的一些基本原理和概念,对于一些更深层的知识还是有很多难以理解的 地方。但在这次实验过程中,锻炼了自己的思考能力,也锻炼了自己的动手编程 能力,对于将知识的转化有了很大的帮助。
辅导教师 张静 成绩
实验日期 实验时间
1实验名称计算器的设计与实现
2、 实验目的掌握自上而下语法分析方法、自下而上语法分析方法
3、 实验要求
实验内容
设计及实现计算表达式的计算器。
表达式中可包含+、-、*、/、(、)等运算符。
实验要求:
对已给的一个二元式形式表达式,能够检查有无语法错误。并指定出错位 置。
将表达式的语法树输出(或将语法分析过程输出) 。
4、 实验原理
根据算符优先分析思想实现语法分析程序。
5、 实验步骤
根据文法构造语法分析表。
编写总控程序实现语法分析。
6、算符优先分析表及语法分析程序
算符优先分析表:
—
*
/
T
(
)
■
1
■F
>
>
>
一
>
>
<
<
>
*
>
>
1/
>
>
rr
>
A
>
A
-ff
A
<
£
<
*
二
)
>
A
>
>
>
>
i
>
>
>
#
<
<
■
语法分析程序:
#i nclude<stdio.h>
#i nclude<stdlib.h>
#defi ne MaxSize 99
void tran slate(char str[],char exp[]) /*将算术表达式转换成后缀表达式 */
{
struct
{
char data[MaxSize]; int top;
}op;
构体*/
char ch;
int i = 0,t = 0;
op.top = -1;
ch = str[i];
i++;
while(ch != '\0')
应的转换情况*/
{
switch(ch)
{
/*top为栈顶*//*
/*top为栈顶*/
/*定义一个含data和top的结
/*将str的每一个数转换成ch*/
/*ch对应不同的符号的时候对
/*当是.的时候 将此括号存入
栈 op*/
op.top++;op.data[op.top]=ch;
break;
case ')':
先级最咼强故先提
先级最咼强故先提
取表达式*/
{
exp[t]=op.data[op.top];
op.top--;
t++;
}
op.top--;
break;
case '+':
case '-':
while(op.top != -1&&op.data[op.top] !='(')
exp[t] = op.data[op.top];
op.top--;
t++;
}
op.top++; /*恢复可插入位置*/
op.data[op.top] = ch;
break;
case case '/':
/*优先级
/*优先级*/
{
exp[t] = op.data[op.top];
op.top--;
t++;
}
op.top++;
op.data[op.top] = ch;
casebreak;
case
/*忽略空格珂i排除误操
作*/
break;
default:
while(ch >= '0'&&ch <= 9)
{
exp[t] = ch;t++;
ch = str[i];i++;
exp[t] = '#';
观也为了以后好
分隔操作数*/
t++;
}
ch = str[i];
i++;
}
while(op.top != -1)
{
exp[t] = op.data[op.top];
t++;
op.top--;
}
exp[t] = '\0';
/*分隔操作数为了美
/*得到剩下的部分*/
/*表达式结束*/
}
float cal_value(char exp[]) {
struct
{
float data[MaxSize];
int top;
}st; /*操作数栈*/
float d;
char ch;
int t = 0;
st.top = -1;
ch = exp[t];
t++;
while(ch != '\0')
{
switch(ch) /* 运算主体 */
{
case '+':
st.data[st.top-1] = st.data[st.top-1]+st.data[st.top];
st.top--;
break;
case '-':
st.data[st.top-1] = st.data[st.top-1]-st.data[st.top];
st.top--;
break;
case
st.data[st.top-1] = st.data[st.top-1]*st.data[st.top];
st.top--;
break;
case '/':
if(st.data[st.top] != 0)
st.data[st.top-1]=st.data[st.top-1]/st.data[st.top];
else
{
printf("\n\t 除 0 是错误的");
}
st.top--;
break;
default:
d=0;
while(ch >= 'O'&&ch <= 9) /* 从后缀表达
式中获取操作数珥f
#作用在此体现*/
{
d = 10*d+ch-'0';
ch=exp[t];
t++;
}
st.top++;
st.data[st.top] = d;
ch = exp[t];
t++;
}
return st.data[st.top];
}
int mai n()
{
char str[MaxSize],exp[MaxSize];
后缀表达式*/
printf("请输入一个求值表达式\n");
gets(str);
printf("原表达式是:%s\n",str);
tran slate(str,exp);
表达式*/
printf("后缀表达式 %s\n",exp);
/*可以提到前面去*//*str为算术表达式,exps为/*输入一个算术表达式*//*将算术表达式转换成后缀
/*可以提到前面去*/
/*str为算术表达式,exps为
/*输入一个算术表达式*/
/*将算术表达式转换成后缀
return 0;
}
7、测试及结果
L' CAU se r&\Adm' n i strator\C eskto p\c ak.exe
r^-
r^-宵
8心得
此次实验,经过对计算器的设计与实现,让我对编译原理的基本知识有了深 入的了解,加强了对语法分析的认识,掌握了自上而下语法分析方法、自下而上 语法分析方法。熟悉了算符优先分析思想实现语法分析程序。在代码调试过程中 结果出现许多无法解释的错误,但仍旧坚持下来了,最终调试出了结果。通过这 次实验,我的动手实践能力得到很大的提高。