计算机网络课程设计词法分析器.docx
- 文档编号:29583786
- 上传时间:2023-07-24
- 格式:DOCX
- 页数:41
- 大小:251KB
计算机网络课程设计词法分析器.docx
《计算机网络课程设计词法分析器.docx》由会员分享,可在线阅读,更多相关《计算机网络课程设计词法分析器.docx(41页珍藏版)》请在冰豆网上搜索。
计算机网络课程设计词法分析器
计算机网络课程设计报告
班级:
计1102
姓名:
杨勇
学号:
41155047
词法分析器:
一、实验目的
调试并完成一个词法分析程序,加深对词法分析原理的理解。
二、实验要求
1、待分析的简单语言的词法
(1)关键字:
beginifthenwhiledoend
所有关键字都是小写。
(2)运算符和界符:
:
=+–*/<<=<>>>==;()#
(3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:
ID=letter(letter|digit)*
NUM=digitdigit*
(4)空格由空白、制表符和换行符组成。
空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。
2、各种单词符号对应的种别码
单词符号
种别码
单词符号
种别码
begin
1
:
17
if
2
:
=
18
then
3
>
20
while
4
<>
21
do
5
<=
22
end
6
<
23
letter(letter|digit)*
10
>=
24
digitdigit*
11
=
25
*
13
;
26
/
14
(
27
+
15
)
28
-
16
#
0
3、词法分析程序的功能
输入:
所给文法的源程序字符串。
输出:
二元组(syn,token或sum)构成的序列。
其中:
syn为单词种别码;
token为存放的单词自身字符串;
sum为整型常数。
三、C语言程序源代码:
#include
#include
charprog[80],token[8],ch;
intsyn,p,m,n,sum;
char*rwtab[6]={"begin","if","then","while","do","end"};
scaner();
main()
{p=0;
printf("\npleaseinputastring(endwith'#'):
/n");
do{
scanf("%c",&ch);
prog[p++]=ch;
}while(ch!
='#');
p=0;
do{
scaner();
switch(syn)
{case11:
printf("(%-10d%5d)\n",sum,syn);
break;
case-1:
printf("youhaveinputawrongstring\n");
getch();
exit(0);
default:
printf("(%-10s%5d)\n",token,syn);
break;
}
}while(syn!
=0);
getch();
}
scaner()
{sum=0;
for(m=0;m<8;m++)token[m++]=NULL;
ch=prog[p++];
m=0;
while((ch=='')||(ch=='\n'))ch=prog[p++];
if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))
{while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9')))
{token[m++]=ch;
ch=prog[p++];
}
p--;
syn=10;
for(n=0;n<6;n++)
if(strcmp(token,rwtab[n])==0)
{syn=n+1;
break;
}
}
elseif((ch>='0')&&(ch<='9'))
{while((ch>='0')&&(ch<='9'))
{sum=sum*10+ch-'0';
ch=prog[p++];
}
p--;
syn=11;
}
elseswitch(ch)
{case'<':
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{syn=22;
token[m++]=ch;
}
else
{syn=20;
p--;
}
break;
case'>':
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{syn=24;
token[m++]=ch;
}
else
{syn=23;
p--;
}
break;
case'+':
token[m++]=ch;
ch=prog[p++];
if(ch=='+')
{syn=17;
token[m++]=ch;
}
else
{syn=13;
p--;
}
break;
case'-':
token[m++]=ch;
ch=prog[p++];
if(ch=='-')
{syn=29;
token[m++]=ch;
}
else
{syn=14;
p--;
}
break;
case'!
':
ch=prog[p++];
if(ch=='=')
{syn=21;
token[m++]=ch;
}
else
{syn=31;
p--;
}
break;
case'=':
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{syn=25;
token[m++]=ch;
}
else
{syn=18;
p--;
}
break;
case'*':
syn=15;
token[m++]=ch;
break;
case'/':
syn=16;
token[m++]=ch;
break;
case'(':
syn=27;
token[m++]=ch;
break;
case')':
syn=28;
token[m++]=ch;
break;
case'{':
syn=5;
token[m++]=ch;
break;
case'}':
syn=6;
token[m++]=ch;
break;
case';':
syn=26;
token[m++]=ch;
break;
case'\"':
syn=30;
token[m++]=ch;
break;
case'#':
syn=0;
token[m++]=ch;
break;
case':
':
syn=17;
token[m++]=ch;
break;
default:
syn=-1;
break;
}
token[m++]='\0';
}
三、实验结果:
1、给定源程序
beginx:
=9;ifx>0thenx:
=2*x+1/3;end#
输出结果
2、源程序(包括上式未有的while、do以及判断错误语句):
begin
x<=$;
while
a<0
do
b<>9-x;
end
#
输出结果
四、总结分析:
通过此次实验,让我了解到如何设计、编制并调试词法分析程序,加深对词法分析原理的理解;熟悉了构造词法分析程序的手工方式的相关原理,根据识别语言单词的状态转换图,使用某种高级语言(例如C++语言)直接编写此法分析程序。
另外,也让我重新熟悉了C++语言的相关内容,加深了对C++语言的用途的理解。
比如:
main()函数中,用cin>>ch;语句得到ch值的话,给定源程序的结果第一行得到的是(10,beginx),因为得到的字符串中省略了空格,改用cin.get(ch);问题便解决了。
另外,我在程序中加入了row变量,以便能够准确得到错误所在。
语法分析器
一、实验目的
调试并完成一个语法分析程序,加深对语法分析原理的理解。
二、实验内容
语法分析程序用LL
(1)语法分析方法。
首先输入定义好的文法书写文件(所用的文法可以用LL
(1)分析),先求出所输入的文法的每个非终结符是否能推出空,再分别计算非终结符号的FIRST集合,每个非终结符号的FOLLOW集合,以及每个规则的SELECT集合,并判断任意一个非终结符号的任意两个规则的SELECT集的交集是不是都为空,如果是,则输入文法符合LL
(1)文法,可以进行分析。
对于文法:
G[E]:
E->E+T|T
T->T*F|F
F->i|(E)
分析句子i+i*i是否符合文法。
三、基本思想
1、语法分析器实现
语法分析是编译过程的核心部分,它的主要任务是按照程序的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行词法检查,为语义分析和代码生成作准备。
这里采用自顶向下的LL
(1)分析方法。
语法分析程序的流程图如图5-4所示。
该程序可分为如下几步:
(1)读入文法
(2)判断正误
(3)若无误,判断是否为LL
(1)文法
(4)若是,构造分析表;
(5)由句型判别算法判断输入符号串是为该文法的句型。
四、源程序代码
#include
#include
#include
/*******************************************/
intcount=0;//产生式的个数
intnumber;//所有终结符和非终结符的总数
charstart;//开始符号
chartermin[50];//终结符号
charnon_ter[50];//非终结符号
charv[50];//所有符号
charleft[50];//左部
charright[50][50];//右部
charfirst[50][50],follow[50][50];//各产生式右部的FIRST和左部的FOLLOW集合
charfirst1[50][50];//所有单个符号的FIRST集合
charselect[50][50];//各个产生式的SELECT集合
charfirstflag[50],followflag[50];//记录各符号的FIRST和FOLLOW是否已求过
charempty[20];//记录可推出&的符号
charnonempty[20];//记录不可推出&的符号
charempt[20];//求_emp()时使用
charTEMP[50];//求FOLLOW时存放某一符号串的FIRST集合
intvalidity=1;//表示输入文法是否有效
intll=1;//表示输入文法是否为LL
(1)文法
intM[20][20];//分析表
charchoose;//用户输入时使用
charfoll[20];//求FOLLOW集合时使用
/*******************************************
判断一个字符c是否在指定字符串p中
********************************************/
intin(charc,char*p)
{
inti;
if(strlen(p)==0)
return(0);
for(i=0;;i++)
{
if(p[i]==c)
return
(1);//若在,返回1
if(i==(int)strlen(p))
return(0);//若不在,返回0
}
}
/*******************************************
将单个符号或符号串并入另一符号串
********************************************/
voidmerge(char*d,char*s,inttype)
{//是目标符号串,s是源串,type=1,源串中的'&'一并并入目串;
//type=2,源串中的'&'不并入目串
inti,j;
for(i=0;i<=(int)strlen(s)-1;i++)
{
if(type==2&&s[i]=='&');
else
{
for(j=0;;j++)
{
if(j<(int)strlen(d)&&s[i]==d[j])
break;//若已存在,则退出,继续看下一个源串字符
if(j==(int)strlen(d))//若不存在,则并入
{
d[j]=s[i];
d[j+1]='\0';
break;
}
}
}
}
}
/*******************************************
读入一个文法
********************************************/
chargrammer(char*t,char*n,char*left,charright[50][50])
{
charvn[50],vt[50];
chars;
charp[50][50];
inti,j;
printf("请输入文法的非终结符号串:
");
scanf("%s",vn);
getchar();
i=strlen(vn);
memcpy(n,vn,i);
n[i]='\0';
printf("请输入文法的终结符号串:
");
scanf("%s",vt);
getchar();
i=strlen(vt);
memcpy(t,vt,i);
t[i]='\0';
printf("请输入文法的开始符号:
");
scanf("%c",&s);
getchar();
printf("请输入文法产生式的条数:
");
scanf("%d",&i);
getchar();
count=i;
for(j=1;j<=i;j++)
{
printf("请输入文法的第%d条(共%d条)产生式:
",j,i);
scanf("%s",p[j-1]);
getchar();
}
for(j=0;j<=i-1;j++)
{
if(p[j][1]!
='-'||p[j][2]!
='>')//检测输入错误
{
printf("\n输入错误!
");
validity=0;
return('\0');
}
}
return(s);
}
/*******************************************
判断读入的文法是否正确
********************************************/
intjudge()
{
inti,j;
for(i=0;i<=count-1;i++)
{
if(in(left[i],non_ter)==0)
{//若左部不在非终结符中,报错
printf("\n文法左部出错!
");
validity=0;
return(0);
}
for(j=0;j<=(int)strlen(right[i])-1;j++)
{
if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!
='&')
{//若右部某一符号不在非终结符、终结符中且不为'&',报错
printf("\n文法右部出错!
");
validity=0;
return(0);
}
}
}
return
(1);
}
/*******************************************
求所有能直接推出&的符号
********************************************/
voidemp(charc)
{
chartemp[10];
inti;
for(i=0;i<=count-1;i++)
{
if(right[i][0]==c&&strlen(right[i])==1)
{
temp[0]=left[i];
temp[1]='\0';
merge(empty,temp,1);//求所有能直接推出'&"的符号,结果保存到empty[]中
emp(left[i]);
}
}
}
/*******************************************
求某一符号能否推出'&'
********************************************/
int_emp(charc)
{//若能推出&,返回1;否则,返回0
inti,j,k,result=1,mark=0;
chartemp[20];
temp[0]=c;
temp[1]='\0';
merge(empt,temp,1);//存放到一个临时数组empt里,标识此字符已查找其是否可推出空字
if(in(c,empty)==1)//如果c在可直接推出空字的empty[]中,返回1
return
(1);
for(i=0;;i++)
{
if(i==count)
return(0);
if(left[i]==c)//找一个左部为c的产生式
{
j=strlen(right[i]);//j为c所在产生式右部的长度
if(j==1&&in(right[i][0],empty)==1)//右部长度为1且右部第一个字符在empty[]中.返回1(A->B,B可推出空)
return
(1);
elseif(j==1&&in(right[i][0],termin)==1)//右部长度为1但第一个字符为终结符,返回0(A->a,a为终结符)
continue;
else
{
for(k=0;k<=j-1;k++)
{
if(in(right[i][k],empt)==1)//查找临时数组empt[].(A->AB)
mark=1;
}
if(mark==1)//找到的字符与当前字符相同(A->AB)
continue;//结束本次循环
else//(mark等于0)
{
for(k=0;k<=j-1;k++)
{
result*=_emp(right[i][k]);//递归调用,查找右部符号是否可推出空字,把返回值赋给result
temp[0]=right[i][k];
temp[1]='\0';
merge(empt,temp,1);//把当前符号加入到临时数组empt[]里,标记已查找
}
}
}
if(result==0&&i continue; elseif(result==1&&i return (1); } } } /******************************************* 求单个符号的FIRST ********************************************/ voidfirst2(inti) {//i为符号在所有输入符号中的序号 charc,temp[20]; intj,k,m; charch='&'; c=v[i]; emp(ch);//求所有能直接推出空字的符号,结果保存到empty[]中 if(in(c,termin)==1)//若为终结符--c∈VT,则FIRST(c)={c} { first1[i][0]=c; first1[i][1]='\0'; } elseif(in(c,non_ter)==1)//若为非终结符 { for(j=0;j<=count-1;j++)//j为所有产生式中的序列 { if(left[j]==c)//找一个左部为c的产生式 { if(in(right[j][0],termin)==1||right[j][0]=='&') {//若产生式右部第一个字符为终结符或空.---产生式X→a(a∈VT)或X→&,则把a或&加进FIRST(X) temp[0]=right[j][0]; temp[1]='\0'; merge(first1[i],temp,1); } //------X→Y1Y2…Yk的产生式,若Y1∈VN,则把FIRST(Y1)中的一切非空符号加进FIRST(X) elseif(in(right[j][0],non_ter)==1)//产生式右部第一个字符为非终结符 { if(right[j][0]==c)//产生式右部的第一个符号等于当前字符,则跳到下一条产生式进行查找 continue; for(k=0;;k++) { if(v[k]==right[j][0])//求右部第一个字符在所有字符集中的位置k break; } if(firstflag[k]=='0') { first2(k);//求其FIRST集 firstflag[k]='1';//标识其为查找状态 } merge(first1[i],first1[k],2);//求得结果并入到X的FIRST集. for(k=0;k<(int)strlen(right[j]);k++) { empt[0]='\0';//存放到一个临时数组里,标识此字符已查找其是否可推出空字 if(_emp(right[j][k])==1&&k<(int)strlen(right[j])-1) {//当前产生式右部符号可推出空字,且当前字符不是右部的最后一个字符 for(m=0;;m++) { if(v[m]==right[j][k+1])//获取右部符号下一个字符在所有字符集中的位置 break; } i
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机网络 课程设计 词法 分析器