编译原理词法分析课程设计Word文档格式.docx
《编译原理词法分析课程设计Word文档格式.docx》由会员分享,可在线阅读,更多相关《编译原理词法分析课程设计Word文档格式.docx(28页珍藏版)》请在冰点文库上搜索。
![编译原理词法分析课程设计Word文档格式.docx](https://file1.bingdoc.com/fileroot1/2023-5/7/f6d45225-6c73-4b8a-9d0a-dfbcb807f54e/f6d45225-6c73-4b8a-9d0a-dfbcb807f54e1.gif)
,|;
|(|)|{|}|……
其中l表示a~z中的任何一个英文字母,d表示0~9中的任一个数字。
关键字也是一种单词,一般关键字都是由字母构成,关键字集合时标识符集合的子集。
2.2词法分析方法
从待分析文件中取出当前符号ch=fgetc(fp)
If(Isalpha(ch))
{
读出字符串,放进TOKEN代码中
If(Iskey(token))
对不同关键字进行种别码设置
}
else标识符种别码设置
elseif(Isdigit(ch))
统一设置为一种种别码
数字放入TOKEN代码中
elseif(Isoperation(ch))
对不同操作符设置不同种别码
将读出的操作符放入TOKEN代码
elseif(Isboundrary(ch))
设置每种界符的种别码
将读出的界符放入TOKEN代码中
2.3符号表设计和TOKEN代码设计
typedefstruct_token_list//记录词法分析结果
{
Tokentoken;
struct_token_list*next;
}TokenNode,*PTokenList;
typedefstruct_symtab{//符号表
charname[10];
//名称
chartype[10];
//类型
intlength;
//长度
intoffset;
//相对数
struct_symtab*next;
}sym,*PSYMLIST;
typedefstruct_token//TOKEN代码设计
intsym;
//种别码
charstr[10];
//存放单词
}*PToken,Token;
3.简要分析与概要设计:
设置一个TOKEN结构体,用来存放单词信息,其中包含sym和str[10]两个成员,sym用来存放单词种别码,str[10]数组用来存放单词符号。
设置一个Symtab结构体,用来存放符号表中个变量的信息,其中name[10]用来存放单词名称,type[10]用来存放单词类型,length用来存放单词存储位置信息。
在程序运行之前,先把要分析的程序放在一个.txt记事本中,分析过程中通过ch=fgetc(ch)从文件中读取字符,并进行分析,分析过程见2.2词法分析方法。
对分析之后的单词用二元式进行输出。
接下来进行符号表内容的输出,将已经分析过的关键字,存放在table[]数组中,当遇到分析出的符号为‘;
’时,将table[]数组清空。
对分析出的标识符进行判断,如果是第一次分析出,则用symtab.type存放其类型,用symtab.name存放其名称,symtab.length存放其长度,symtab.offset存放其相对数,然后输出符号表信息,如果不是第一次分析出,则输出错误提示。
4.程序主要流程图
5.源代码
#define_CRT_SECURE_NO_WARNINGS//字符串和内存操作时关闭函数的安全警告
#include<
stdio.h>
stdlib.h>
string.h>
intj,n;
charch;
typedefstruct_token
typedefstruct_token_list{//记录词法分析结果
char_type[5][10]={"
int"
"
float"
char"
double"
long"
};
//符号表类型
int_size[5]={32,32,8,64,32};
//及对应的长度
PSYMLISTsymtab=NULL;
//符号表的头指针
PSYMLISTsymtail=symtab;
//符号表的尾指针
Tokentoken;
chartype[10]={0};
//保存类型名称
PTokenListptl=NULL;
//TokenList的头指针
PTokenListptltail=ptl;
//TokenList的尾指针
intLineNumber=1;
//记录代码行数
intoffset=0;
//计算变量偏移地址
voidScan(FILE*);
//词法分析
boolIsoperation(charch);
//判断i当前所指的字符是否为一个运算符
boolIsboundary(charch);
//判断i当前所指的字符是否为一个分界符
boolIskey(charch[]);
//判断i当前所指的字符是否为关键字
boolIsalpha(charch);
//判断i当前所指的字符是否为字母
boolIsdigit(charch);
//判断i当前所指的字符是否为数字
boolIsType(charch[]);
//判断是否为类型
intGetSizeOfType(chartype[]);
//获得类型大小
intSearchSymTab(charname[]);
//查找符号表
voidAddToSymTab(Tokentoken);
voidPrintSymTab();
//显示符号表
voidAddToTokenList(Tokentoken);
//保存到词法分析表
voidPrintTokenList();
//显示词法分析表
//主函数
voidmain()
charinput[20];
FILE*fp;
printf("
*****************************************\n"
"
10~~22----------------表示关键字\n"
2---------------------表示标识符\n"
3---------------------表示数字\n"
40~~57----------------表示操作符\n"
60~~65----------------表示界符\n"
*******************************************\n"
);
pleaseinputthesourcefilename:
"
while(true)
{
gets(input);
if((fp=fopen(input,"
r"
))!
=NULL)break;
//读取文件内容,并返回文件指针,该指针指向文件的第一个字符
else
printf("
fileopenfiled!
Pleaseinputagain:
}
\n********theresultisasfollows********\n"
while(!
feof(fp))Scan(fp);
//扫描源程序
//符号表
PrintSymTab();
//词法分析
PrintTokenList();
getchar();
//暂停
//判断i当前所指的字符是否为一个运算符,是的话返回真,反之假
boolIsoperation(charch)
intt;
chararr[8]={'
+'
'
*'
/'
='
'
>
!
for(t=0;
t<
8;
t++)
if(ch==arr[t])
returntrue;
returnfalse;
}
//判断i当前所指的字符是否为一个分界符,是的话返回真,反之假
boolIsboundary(charch)
chararr[6]={'
;
{'
}'
('
)'
for(t=0;
6;
if(ch==arr[t])
returntrue;
returnfalse;
//判断i当前所指的字符是否为一个关键字,是的话返回真,反之假
boolIskey(charch[])
char*keywords[13]={"
const"
"
auto"
if"
else"
break"
for"
do"
printf"
case"
13;
t++)
if(strcmp(token.str,keywords[t])==0)
boolIsType(charch[])
char*keywords[5]={"
for(t=0;
t<
5;
t++)
//判断i当前所指的字符是否为字母,是的话返回真,反之假
boolIsalpha(charch)
if(((ch<
z'
)&
&
(ch>
a'
))||((ch<
Z'
A'
)))
returntrue;
returnfalse;
//判断i当前所指的字符是否为数字,是的话返回真,反之假
boolIsdigit(charch)
if(ch>
0'
ch<
9'
)
intGetSizeOfType(chartype[])
for(inti=0;
i<
i++)
if(strcmp(type,_type[i])==0)
{
return_size[i];
}
return0;
voidAddToSymTab(Tokentoken)
PSYMLISTs=(PSYMLIST)malloc(sizeof(sym));
if(s==NULL)return;
memset(s,0,sizeof(sym));
memcpy(s->
name,token.str,10);
type,type,10);
s->
length=GetSizeOfType(s->
type);
offset=offset;
offset+=s->
length;
next=NULL;
if(symtab==NULL)//如果链表为空则初始化链表
symtab=s;
symtail=symtab;
else//链表不为空则将节点增加到链表尾部
symtail->
next=s;
symtail=s;
intSearchSymTab(charname[])
intexist=0;
//如果没有找到
intindex=-1;
for(PSYMLISTs=symtab;
s!
=NULL;
s=s->
next)
{
index+=1;
if(strcmp(name,s->
name)==0)
exist=1;
returnexist?
index:
-1;
voidPrintSymTab()
符号表:
\n"
名称类型长度相对数\n"
for(PSYMLISTs=symtab;
printf("
%-10s%-10s%-10d%-10d\n"
s->
name,s->
type,s->
length,s->
offset);
voidAddToTokenList(Tokentoken)
TokenNode*tn=(TokenNode*)malloc(sizeof(TokenNode));
if(tn==NULL)return;
memcpy(&
(tn->
token),&
token,sizeof(Token));
tn->
if(ptl==NULL)
ptl=tn;
ptltail=tn;
else
ptltail->
next=tn;
voidPrintTokenList()
词法分析表:
名称类型\n"
for(PTokenLists=ptl;
%-10s%-10d\n"
s->
token.str,s->
token.sym);
voidScan(FILE*fp)
token.str[10]=NULL;
j=0;
ch=fgetc(fp);
//获取字符,指针fp并自动指向下一个字符
if(ch=='
\n'
)
LineNumber++;
//记录分析的代码的行号
strcpy(type,"
//分析字符串
if(Isalpha(ch))//判断该字符是否是字母
while((ch>
='
)&
(ch<
)||((ch>
)))
token.str[j++]=ch;
ch=fgetc(fp);
token.str[j++]='
\0'
//'
代表字符结束(空格)
fseek(fp,-1,1);
//回退一个字符
if(Iskey(token.str))
switch(n)//关键字种别码设置
{
case0:
token.sym=10;
break;
case1:
token.sym=11;
case2:
token.sym=12;
case3:
token.sym=13;
case4:
token.sym=14;
case5:
token.sym=15;
case6:
token.sym=16;
case7:
token.sym=17;
case8:
token.sym=18;
case9:
token.sym=19;
case10:
token.sym=20;
case11:
token.sym=21;
case12:
token.sym=22;
}
else
token.sym=2;
//2表示标识符种别码
//printf("
(%d,%s)\n"
token.sym,token.str);
AddToTokenList(token);
elseif(Isdigit(ch))
token.sym=3;
//3表示数字种别码
while((ch>
(ch<
))
elseif(Isoperation(ch))//运算符
switch(ch)
case'
:
token.str[j]='
if(ch=='
token.sym=40;
token.str[j++]=ch;
token.str[j]='
else
token.sym=41;
token.str[j++]='
fseek(fp,-1,1);
break;
token.sym=42;
token.sym=43;
token.str[j++]='
fseek(fp,-1,1);
if(ch=='
token.sym=44;
token.sym=45;
token.sym=46;
token.sym=47;
token.sym=48;
elseif(ch=='
token.sym=49;
token.sym=50;