编译原理词法分析器代码.docx
- 文档编号:8162012
- 上传时间:2023-01-29
- 格式:DOCX
- 页数:18
- 大小:19.27KB
编译原理词法分析器代码.docx
《编译原理词法分析器代码.docx》由会员分享,可在线阅读,更多相关《编译原理词法分析器代码.docx(18页珍藏版)》请在冰豆网上搜索。
编译原理词法分析器代码
#include
#include
#include
#include
#include
#defineKEYWORD_LEN32//保留字个数
#defineSTR_MAX_LEN300//标识符最大长度
#definePRO_MAX_LEN20480//源程序最大长度
#defineSTB_MAX_LEN1000//符号表最大容量
#defineCTB_MAX_LEN1000//常数表最大容量
#defineERROR0//错误
#defineID(KEYWORD_LEN+1)//标识符
#defineCONST(KEYWORD_LEN+2)//常量
#defineOPERAT(KEYWORD_LEN+3)//运算符
#defineDIVIDE(KEYWORD_LEN+4)//界符
interrorLine=0;charproBuffer[PRO_MAX_LEN]="";//存储程序代码的全局缓冲区
charch;//读出来的当前字符
charwordget[STR_MAX_LEN];//标识符或常量
intpoint=0;//源程序当前位置指针
charsignTab[STB_MAX_LEN][STR_MAX_LEN];//符号表
intpointSTB=0;//符号表指针
charconstTab[CTB_MAX_LEN][STR_MAX_LEN];//常量表
intpointCTB=0;//常数表指针
charkwTab[KEYWORD_LEN][10]={//保留字表C语言一共有32个保留字[关键字]
"auto","break","case","char",
"const","continue","default",
"do","double","else","enum",
"extern","float","for","goto",
"if","int","long","register",
"return","short","signed","sizeof",
"static","struct","switch","typedef",
"union","unsigned","void","volatile","while"};
charerrorTab[][50]={//错误代码表
/*0*/"未知错误",/*1*/"非法的字符",/*2*/"不正确的字符常量表达",
/*3*/"不正确的字符串表达",/*4*/"不正确的数字表达",/*5*/"注释丢失'*/'"};
typedefstructsignDuality
{
intkind;
intvalue;
}*pDualistic,Dualistic;
voidpretreatment();//预处理
voidProcError(intid);//错误
boolGetChar();//获得一个字符不包括结束标记
boolGetBC();//获得一个非空白字符
voidConcat(char*str);//将ch连接到str后
intReserve(char*str);//对str字符串查找保留字表若是一个保留字-返回其编码否则返回0
voidRetract();//将搜索指示器回调一个字符位置
intInsertId(char*str);//将str串以标识符插入符号表,并返回符号表指针
intInsertConst(char*str);//将str串以常数插入符号表,并返回常数表指针
boolwordAnalyse(pDualisticpDu);//词法分析true正常
//预处理将缓冲区内的源代码去掉注释和无效空格
voidpretreatment()
{
intlines=0;
chartmp[PRO_MAX_LEN];//先将处理结果保存到临时空间
inttmpp=0;//这个临时空间的末尾指针
boolflg;
chartmpc;//去掉注释先//注释有两种一种是//另一种是/**/
point=0;
do
{
flg=GetChar();
if(ch=='/')
{
flg=GetChar();
switch(ch)
{
case'/':
do
{
flg=GetChar();
}while(!
(ch=='\n'||flg==false));//注释一直到行尾或文件结束
if(ch=='\n')
Retract();//归还换行
break;
case'*':
do
{
flg=GetChar();
tmpc=ch;
//为了保证出错处理程序能正确定位出错位置保留注释中的换行
if(tmpc=='\n')
tmp[tmpp++]=tmpc;
flg=GetChar();
Retract();//归还一个字符
}while(flg&&!
(flg&&tmpc=='*'&&ch=='/'));
flg=GetChar();
if(!
flg)
{
ProcError(5);
}
break;
default:
//不是任何一种注释
Retract();
Retract();
GetChar();
tmp[tmpp++]=ch;
flg=GetChar();
tmp[tmpp++]=ch;
}
}
else
{
tmp[tmpp++]=ch;
}
}while(flg);
tmp[tmpp]='\0';
strcpy(proBuffer,tmp);
}
//错误
voidProcError(intid)
{
printf("\nError:
第%d行,%s\n",errorLine,errorTab[id]);
}
//获得一个字符
boolGetChar()
{
if(point ='\0') { //如果当前下标合法且当前字符为结束标记则取字符增游标 ch=proBuffer[point++]; if(ch=='\n') errorLine++; returntrue; } ch='\0'; returnfalse; } //获得一个非空白字符 boolGetBC() { do { if(! GetChar())//获取字符失败 { ch='\0'; returnfalse; } }while(isspace(ch));//直到获得一个非空白字符 returntrue; } //将ch连接到str后 voidConcat(char*str) { inti; for(i=0;str[i];++i) ; str[i]=ch; str[i+1]='\0'; } //对str字符串查找保留字表若是一个保留字-返回其编码否则返回0 intReserve(char*str) { inti; for(i=0;i { if(0==strcmp(kwTab[i],str)) returni+1;//注意,这里加一原因是0值被错误标记占用 } return0; } //将搜索指示器回调一个字符位置 voidRetract()///char*ch { if(proBuffer[point]=='\n'&&errorLine>0) errorLine--; point--; } //将str串以标识符插入符号表,并返回符号表指针 intInsertId(char*str) { inti; for(i=0;i if(0==strcmp(signTab[i],str)) returni; strcpy(signTab[pointSTB++],str); return(pointSTB-1); } //将str串以常数插入常量表,并返回常数表指针 intInsertConst(char*str) { inti; for(i=0;i if(0==strcmp(constTab[i],str)) returni; strcpy(constTab[pointCTB++],str); return(pointCTB-1); } //词法分析false--分析结束 boolwordAnalyse(pDualisticpDu) { intcode,value; charjudge;//这里有个技巧借用此变量巧妙的运用SWITCH结构 inti=0;//辅助 GetBC(); judge=ch; if(isalpha(ch)||ch=='_') judge='L'; if(isdigit(ch)) judge='D'; switch(judge) { case'L': while(isalnum(ch)||ch=='_') {//标识符 wordget[i++]=ch; GetChar(); } wordget[i]='\0'; Retract();//回退一个字符 code=Reserve(wordget); if(code==0) { value=InsertId(wordget); pDu->kind=ID; pDu->value=value; } else { pDu->kind=code; pDu->value=-1; } returntrue; case'D': while(isdigit(ch)) { wordget[i++]=ch; GetChar(); } wordget[i]='\0'; Retract(); value=InsertConst(wordget); pDu->kind=CONST; pDu->value=value; returntrue; //()[].,! ! =~sizeof<<<<=>>>>====&&&&=||||=? : ++++= //-->---=**=//=%%=>>=<<=^^= case'"': //字符串常量 do { wordget[i++]=ch; GetChar(); }while(ch! ='"'&&ch! ='\0'); wordget[i++]=ch; wordget[i]='\0'; if(ch=='\0') { printf("%s",wordget); ProcError(3); pDu->kind=ERROR; pDu->value=0; } else { value=InsertConst(wordget); pDu->kind=CONST; pDu->value=value; } returntrue;//字符常量 case'\'': wordget[i++]=ch;//' GetChar(); wordget[i++]=ch; if(ch=='\\')//'\n' { //如果是转义字符则要多接收一个字符 GetChar();//ch=' wordget[i++]=ch; } GetChar(); wordget[i++]=ch; wordget[i]='\0'; if(ch! ='\'') {//'\b' printf("%s",wordget); ProcError (2); pDu->kind=ERROR; pDu->value=0; } else { value=InsertConst(wordget); pDu->kind=CONST; pDu->value=value; } returntrue; case'(': case')': case'[': case']': case'.': case',': case'~': case'? ': case': ': case';': case'{': case'}': case'#': wordget[i++]=ch; wordget[i]='\0'; pDu->kind=DIVIDE;//界符 pDu->value=-1; returntrue; case'! ': //! = wordget[i++]=ch; GetChar(); if(ch=='=') wordget[i++]=ch; else Retract(); wordget[i]='\0'; break; case'<': //<<<= wordget[i++]=ch; GetChar(); if(ch=='<'||ch=='=') wordget[i++]=ch; else Retract(); wordget[i]='\0'; break; case'>': //>>>= wordget[i++]=ch; GetChar(); if(ch=='>'||ch=='=') wordget[i++]=ch; else Retract(); wordget[i]='\0'; break; case'=': //== wordget[i++]=ch; GetChar(); if(ch=='=') wordget[i++]=ch; else Retract(); wordget[i]='\0'; break; case'&': //&&&= wordget[i++]=ch; GetChar(); if(ch=='&'||ch=='=') wordget[i++]=ch; else Retract(); wordget[i]='\0'; break;case'|': //|||= wordget[i++]=ch; GetChar(); if(ch=='|'||ch=='=') wordget[i++]=ch; else Retract(); wordget[i]='\0'; break; case'+': //+++= wordget[i++]=ch; GetChar(); if(ch=='+'||ch=='=') wordget[i++]=ch; elseRetract(); wordget[i]='\0'; break; case'-': //---=-> wordget[i++]=ch; GetChar(); if(ch=='-'||ch=='='||ch=='>') wordget[i++]=ch; else Retract(); wordget[i]='\0'; break; case'*': //***= wordget[i++]=ch; GetChar(); if(ch=='*'||ch=='=') wordget[i++]=ch; else Retract(); wordget[i]='\0'; break; case'/': ///= wordget[i++]=ch; GetChar(); if(ch=='=') wordget[i++]=ch; else Retract(); wordget[i]='\0'; break; case'%': //%= wordget[i++]=ch; GetChar(); if(ch=='=') wordget[i++]=ch; else Retract(); wordget[i]='\0'; break; case'^': //^= wordget[i++]=ch; GetChar(); if(ch=='=') wordget[i++]=ch; else Retract(); wordget[i]='\0'; break; case'\0': returnfalse; default: ProcError (1); returnfalse; } pDu->kind=OPERAT; returntrue; } //主函数 intmain() { Dualistictmp; pDualisticptmp=&tmp; FILE*fin,*fout; inti; charc; charfilename[20]; printf("源代码读入\n"); //scanf("%s",filename); //将源程序读入缓冲区 if((fin=fopen("Test.txt","r"))==NULL) { printf("Cannotopeninfile\n"); return0; } i=0; //c=fgetc(fin); while((c=fgetc(fin))! =EOF) { if(i>=PRO_MAX_LEN-1) { printf("\n程序代码太长,无法处理\a"); return0; } proBuffer[i++]=c; } fclose(fin);//关闭文件 proBuffer[i++]='\0'; printf("\n***************************\n源代码读入成功,源代码如下: \n%s",proBuffer); printf("\n按任意键继续\n"); getch();//预处理 printf("\n预处理\n"); pretreatment(); printf("\n***************************\n预处理成功,去掉注释后的源代码为: \n%s*",proBuffer); printf("\n按任意键继续\n"); getch(); printf("\n词法分析\n"); point=0; //词法分析 if((fout=fopen("Result.txt","wb"))==NULL) {
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 词法 分析器 代码