词法分析.docx
《词法分析.docx》由会员分享,可在线阅读,更多相关《词法分析.docx(26页珍藏版)》请在冰豆网上搜索。
![词法分析.docx](https://file1.bdocx.com/fileroot1/2022-11/20/b9053592-7074-4276-9500-009910065554/b9053592-7074-4276-9500-0099100655541.gif)
词法分析
#include
#include
#include
#include
#include
usingnamespacestd;
ifstreamfp("source.txt",ios:
:
in);
charcbuffer;
char*key[13]={"if","else","for","while","do","return","break","continue","int","void"
"main","const","printf"};//关键字
char*border[7]={",",";","{","}","(",")","//"};//分界符
char*arithmetic[6]={"+","-","*","/","++","--"};//运算符
char*relation[7]={"<","<=","=",">",">=","==","!
="};//关系运算符
char*lableconst[80];//标识符
intconstnum=40;
intlableconstnum=0;
intlinenum=1;//统计常数和标识符数量
intsearch(charsearchchar[],intwordtype)
{
inti=0,t=0;
switch(wordtype)
{
case1:
{for(i=0;i<=12;i++)//关键字
{
if(strcmp(key[i],searchchar)==0)
return(i+1);
}
return(0);}
case2:
{
for(i=0;i<=6;i++)//分界符
{
if(strcmp(border[i],searchchar)==0)
return(i+1);
}
return(0);
}
case3:
{
for(i=0;i<=5;i++)//运算符
{
if(strcmp(arithmetic[i],searchchar)==0)
return(i+1);
}
return(0);
}
case4:
{
for(i=0;i<=6;i++)//关系运算符
{
if(strcmp(relation[i],searchchar)==0)
return(i+1);
}
return(0);
}
case5:
{
for(t=40;t<=constnum;t++)//常数
{
if(strcmp(searchchar,lableconst[t])==0)//判断该常数是否已出现过
return(t+1);
}
lableconst[t-1]=(char*)malloc(sizeof(searchchar));//为新的元素分配内存空间
strcpy(lableconst[t-1],searchchar);//为数组赋值lableconst指针数组名
constnum++;//常数个数自加
return(t);
}
case6:
{
for(i=0;i<=lableconstnum;i++)
{
if(strcmp(searchchar,lableconst[i])==0)//判断标识符是否已出现过
return(i+1);
}
lableconst[i-1]=(char*)malloc(sizeof(searchchar));
strcpy(lableconst[i-1],searchchar);
lableconstnum++;//标识符个数自加
return(i);
}
default:
cout<<"错误!
";
}
}
charalphaprocess(charbuffer)//字符处理过程
{
intatype;
inti=-1;
charalphatp[20];
while((isalpha(buffer))||(isdigit(buffer)))
//这两个函数分别是判字符和判数字函数位于ctype.h中
{
alphatp[++i]=buffer;
fp.get(buffer);
}
alphatp[i+1]='\0';//在末尾添加字符串结束标志
if(atype=search(alphatp,1))
cout<<"linenum:
"<else
{
atype=search(alphatp,6);//标识符
cout<<"linenum:
"<}
return(buffer);
}
chardigitprocess(charbuffer)//数字处理过程
{
inti=-1;
chardigittp[20];
intdtype;
while((isdigit(buffer)))
{
digittp[++i]=buffer;
fp.get(buffer);
}
digittp[i+1]='\0';
dtype=search(digittp,5);
cout<<"linenum:
"<return(buffer);
}
charotherprocess(charbuffer)//分界符、运算符、逻辑运算符、等
{
inti=-1;
charothertp[20];
intotype,otypetp;
othertp[0]=buffer;
othertp[1]='\0';
if(otype=search(othertp,3))
{
fp.get(buffer);
othertp[1]=buffer;
othertp[2]='\0';
if(otypetp=search(othertp,3))//判断该运算符是否是
//由连续的两个字符组成的
{
cout<<"linenum:
"<fp.get(buffer);
gotoout;
}
else//单字符逻辑运算符
{
othertp[1]='\0';
cout<<"linenum:
"<gotoout;
}
}
if(otype=search(othertp,4))//关系运算符
{
fp.get(buffer);
othertp[1]=buffer;
othertp[2]='\0';
if(otypetp=search(othertp,4))//判断该关系运算符是否是
//由连续的两个字符组成的
{
cout<<"linenum:
"<fp.get(buffer);
gotoout;
}
else//单字符逻辑运算符
{
othertp[1]='\0';
cout<<"linenum:
"<gotoout;
}
}
if(buffer=='!
')//"=="的判断
{
fp.get(buffer);
if(buffer=='=')
//cout<<"!
=(2,2)\n";
fp.get(buffer);
gotoout;
}
else
{
if(otype=search(othertp,2))//分界符
{
cout<<"linenum:
"<fp.get(buffer);
gotoout;
}
}
if((buffer!
='\n')&&(buffer!
=''))
cout<<"错误!
字符非法"<<"\t\t\t"<fp.get(buffer);
out:
return(buffer);
}
voidmain()
{
inti;
for(i=0;i<=50;i++)
{
lableconst[i]="";//用于保存标识符
}
if(!
fp)
cout<<"文件打开错误!
!
"<else
{
fp.get(cbuffer);
while(!
fp.eof())
{
if(cbuffer=='\n')
{
linenum++;
fp.get(cbuffer);
}
elseif(isalpha(cbuffer))
{
cbuffer=alphaprocess(cbuffer);
}
elseif(isdigit(cbuffer))
{
cbuffer=digitprocess(cbuffer);
}
else
cbuffer=otherprocess(cbuffer);
}
}
cout<<"标识符个数是:
"<i=0;
while(i{
cout<}
cout<cout<<"完成\n";
getchar();
}
23
其他回答共1条
(一)Block子程序分析
procedureenter(k:
object1);//填写符号表
begin{enterobjectintotable}
tx:
=tx+1;//下标加1,tx的初始值为零,零下标不地址不填写标志符,用于查找失败使用
withtable[tx]do//填入内容,保存标志符名和类型
beginname:
=id;kind:
=k;
casekof//根据类型判断是否正确
constant:
beginifnum>amaxthen//如果是常量,判断是否大于最大值,若是则报30号错
beginerror(30);num:
=0end;
val:
=num//否则保存数值
end;
varible:
beginlevel:
=lev;adr:
=dx;dx:
=dx+1;//如果是变量,填写变量内部表示,LEVEl是变量的层次,adr为地址
end;
proc:
level:
=lev//如果是过程,保存过程的层次
end
end
end{enter};
//查找符号表的位置
functionposition(id:
alfa):
integer;
vari:
integer;
begin{findindentifieridintable}//从后向前查找
table[0].name:
=id;i:
=tx;//找到保存类型
whiletable[i].name<>iddoi:
=i-1;
position:
=i//返回标志符在符号表中的位置
end{position};
procedureblock(lev,tx:
integer;fsys:
symset);
vardx:
integer;{dataallocationindex}//数据分配索引
tx0:
integer;{initialtableindex}//初始符号表索引
cx0:
integer;{initialcodeindex}//初始代码索引
procedureenter(k:
object1);//填写符号表,下次分析
begin{enterobjectintotable}
tx:
=tx+1;
withtable[tx]do
beginname:
=id;kind:
=k;
casekof
constant:
beginifnum>amaxthen
beginerror(30);num:
=0end;
val:
=num
end;
varible:
beginlevel:
=lev;adr:
=dx;dx:
=dx+1;
end;
proc:
level:
=lev
end
end
end{enter};
functionposition(id:
alfa):
integer;//查找符号表,下次分析
vari:
integer;
begin{findindentifieridintable}
table[0].name:
=id;i:
=tx;
whiletable[i].name<>iddoi:
=i-1;
position:
=i
end{position};
procedureconstdeclaration;//常量声明
beginifsym=identthen//如果是标志符,读入一个TOKEN
begingetsym;
ifsymin[eql,becomes]then//读入的是等号或符值号继续判断
beginifsym=becomesthenerror
(1);//如果是“=”报1号错
getsym;//读入下一个TOKEN
ifsym=numberthen//读入的是数字,填写符号表
beginenter(constant);getsym
end
elseerror
(2)//如果不是数字,报2号错
endelseerror(3)//不是等号或符值号,报3号错
endelseerror(4)//如果不是标志符,报4号错
end{constdeclaration};
procedurevardeclaration;//变量声明
beginifsym=identthen//读入的是标志符,填写符号表
beginenter(varible);getsym
endelseerror(4)//不是标志符,报4号错
end{vardeclaration};
procedurelistcode;
vari:
integer;
begin{listcodegeneratedforthisblock}
fori:
=cx0tocx-1do
withcode[i]do
writeln(i:
5,mnemonic[f]:
5,1:
3,a:
5)
end{listcode};
procedurestatement(fsys:
symset);
vari,cx1,cx2:
integer;
procedureexpression(fsys:
symset);//表达式分析
varaddop:
symbol;
procedureterm(fsys:
symset);//项分析
varmulop:
symbol;
procedurefactor(fsys:
symset);//因子分析
vari:
integer;
begintest(facbegsys,fsys,24);//读入的是“(”,标志符或数字
whilesyminfacbegsysdo
begin
ifsym=identthen//是标志符,查表
begini:
=position(id);
ifi=0thenerror(11)else//未找到,报11号错
withtable[i]do//找到,读入标志符类型
casekindof
constant:
gen(lit,0,val);//写常量命令
varible:
gen(lod,lev-level,adr);//写变量命令
proc:
error(21)//过程名,报21号错
end;
getsym//读入下一个TOKEN
endelse
ifsym=numberthen//读入的是数字
beginifnum>amaxthen//如果数字大于最大数,报30号错误
beginerror(30);num:
=0
end;
gen(lit,0,num);getsym//调用数字命令,读入下一个TOKEN
endelse
ifsym=lparenthen//读入的是“(”
begingetsym;expression([rparen]+fsys);//调用表达式分析函数
ifsym=rparenthengetsymelseerror(22)//如果“(”后无“)”,报22号错
end;
test(fsys,[lparen],23)
end
end{factor};//因子分析结束
//项分析
begin{term}factor(fsys+[times,slash]);//调用因子分析程序
whilesymin[times,slash]do//取得是乘、除号循环
beginmulop:
=sym;getsym;factor(fsys+[times,slash]);//记录符号,调用因子分析
ifmulop=timesthengen(opr,0,4)elsegen(opr,0,5)//写乘除指令
end
end{term};
begin{expression}
ifsymin[plus,minus]then//如果是加减号
beginaddop:
=sym;getsym;term(fsys+[plus,minus]);//记录符号,调用项分析程序
ifaddop=minusthengen(opr,0,1)//写加减指令
endelseterm(fsys+[plus,minus]);
whilesymin[plus,minus]do//如果是加减号循环
beginaddop:
=sym;getsym;term(fsys+[plus,minus]);
ifaddop=plusthengen(opr,0,2)elsegen(opr,0,3)
end
end{expression};
//条件过程
procedurecondition(fsys:
symset);
varrelop:
symbol;
begin
ifsym=oddsymthen//如果是判奇符
begingetsym;expression(fsys);gen(opr,0,6)//取下一个TOKEN,调用expression,填指令
endelse
beginexpression([eql,neq,lss,gtr,leq,geq]+fsys);
ifnot(symin[eql,neq,lss,leq,gtr,geq])then//如果不是取到逻辑判断符号,出错.20
error(20)else
beginrelop:
=sym;getsym;expression(fsys);
caserelopof
eql:
gen(opr,0,8);//=,相等
neq:
gen(opr,0,9);//#,不相等
lss:
gen(opr,0,10);//<,小于
geq:
gen(opr,0,11);//],大于等于
gtr:
gen(opr,0,12);//>,大于
leq:
gen(opr,0,13);//[,小于等于
end
end
end
end{condition};
begin{statement}
ifsym=identthen//如果是标识符
begini:
=position(id);//查找符号表
ifi=0thenerror(11)else//未找到,标识符未定义,报11号错
iftable[i].kind<>variblethen//如果标识符不是变量,报12号错
begin{assignmenttonon-varible}error(12);i:
=0
end;
getsym;ifsym=becomesthengetsymelseerror(13);//如果是变量读入下一个TOKEN,不是赋值号,报13好错;是则读入一个TOKEN
expression(fsys);//调用表达是过程
ifi<>0then//写指令
withtable[i]dogen(sto,lev-level,adr)
endelse
ifsym=callsymthen//如果是过程调用保留字,读入下一个TOKEN
begingetsym;
ifsym<>identthenerror(14)else//不是标识符报14号错
begini:
=position(id);
ifi=0thenerror(11)else//是标识符,未定义,报13号错
withtable[i]do/