k++;
S[k]=A;
}
elseerror(S[j].po,A.po);
}while(A==W[#]);
程序功能说明:
程序从文本文件读入表达式,判断语法是否正确,正确则输出结果,其中有标识符的话,结果还是含有标识符的原表达式,语法错误的话,则输出错误信息。
源程序:
程序中文本文件在桌面文件名为expression.txt
#include
#include
#include
usingnamespacestd;
#defineNULL0
#defineMAXSIZE30//单行表达式的符号总数最大值
typedefstructgrammar_symbol//文法符号
{
charch;
intpo;
stringval;
inttype;
}W;
charpre[6][6]={//优先关系表
{'>','<','<','>','<','>'},
{'>','>','<','>','<','>'},
{'<','<','<','=','<','1'},
{'>','>','2','>','2','>'},
{'>','>','2','>','2','>'},
{'<','<','<','3','<','='}
};
charGetChar(FILE*fp){//读取文件中的一个字符
charch;
ch=fgetc(fp);returnch;
charGetBC(FILE*fp){
charch;
do{
ch=GetChar(fp);
}while(ch==''||ch=='\t'||ch=='\n');returnch;
}
voidConcat(charch,charstrToken[]){charstr[2];
intlen=strlen(strToken);strToken[len]=ch;
strToken[len+1]='\0';
}
intIsLetter(charch){
为字母,是返回1,否则返回0
intflag=0;
if(ch>='a'&&ch<='z')
flag=1;
returnflag;
}
intIsDigit(charch){是返回1,否则返回0
intflag=0;
if(ch>='0'&&ch<='9')
flag=1;
returnflag;
}
〃读取文件的字符直至ch不是空白
//将ch中的字符连接到strToken之后
//布尔函数,判断ch中的字符是否
〃布尔函数,判断ch中的字符是否为数字,
intReserve(charstrToken[|){//整型函数,对strToken中的字符串查找保留字表,若它
是一个保留字则返回它的编码,否则返回0
intcode=0,i;
charkeyWord[6][6]={"if","then","else","while","do"};for(i=0;i<5;i++){
if(strcmp(strToken,keyWord[i])==0){
code=i+1;
break;
}returncode;
intSearchOP(charch){〃整型函数,对strToken中的字符串查找运算符和界符,若它
是一个运算符或界符,则返回它的编码,否则返回0
intcode=0,i;
charOP[10]={'+','*','(',')','-','/','<','>','=',';'};
for(i=0;i<10;i++){
if(ch==OP[i]){
code=i+1;
break;
}
}
returncode;
}
charRetract(FILE*fp,charch){
将ch置为空白字符
ch='';fseek(fp,-1L,1);
returnch;
}
voidProError(){
printf("输入错误!
\n");
return;
}
intscan(FILE*fp,W*E,intnum){
Ww;
charch;
charstrToken[10];
strToken[0]='\0';
ch=GetBC(fp);
if(feof(fp))return0;
if(ch==';'){
printf(";");
return0;//判断表达式尾,
}
if(IsLetter(ch)){
while(IsLetter(ch)||IsDigit(ch)){Concat(ch,strToken);ch=GetChar(fp);
//子函数,将搜索指示器回调一个字符位置,
//错误处理函数
//置strToken为空串
//先读取一个非空白的字符
是则返回调用程序
//判断标识符
ch=Retract(fp,ch);
if(Reserve(strToken)){printf("<%s,->\n",strToken);
}
else//判断标识符
{
printf("%s",strToken);
w.ch='i';
w.po=4;w.val=strToken;
w.type=0;E[num]=w;
}
}
elseif(ch>='1'&&ch<='9'){
while(IsDigit(ch)){
Concat(ch,strToken);ch=GetChar(fp);
}
ch=Retract(fp,ch);
printf("%s",strToken);
w.ch='i';
w.po=4;
w.val=strToken;
w.type=1;
E[num]=w;
}
elseif(ch=='0'){
ch=GetChar(fp);
if(ch>='1'&&ch<='7'){
while(ch>='0'&&ch<='7'){Concat(ch,strToken);ch=GetChar(fp);
}
ch=Retract(fp,ch);printf("<2,%s>\n",strToken);
}
elseif(ch=='x'){ch=GetChar(fp);
//判断关键字
//判断十进制整数
//判断八进制整数
//判断十六进制整数
while(IsDigit(ch)||ch>='a'&&ch<='f'){Concat(ch,strToken);
ch=GetChar(fp);
ch=Retract(fp,ch);
printf("<3,%s>\n",strToken);
boolcheckVt(charch){
boolflag=false;
inti;
charVt[6]={'+','*','(',')','i','#'};
for(i=0;i<6;i++){
if(ch==Vt[i]){flag=true;
}
}
returnflag;
}
WStatute(W*S,ints,inte){//规约子函数,将S中j+1到k的符号规约为N
WN;
if(S[s].ch=='i'&&s==e){
N.ch='F';
N.val=S[s].val;
N.type=S[s].type;
}
elseif(S[s].ch=='('&&!
(checkVt(S[s+1].ch))&&S[e].ch==')'){
if(S[s+1].type==1){
N.ch='F';
N.val=S[s+1].val;
N.type=S[s+1].type;
}
else{
N.ch='F';
N.val='('+S[s+1].val+')';
N.type=S[s+1].type;
}
}
elseif(!
(checkVt(S[s].ch))&&S[s+1].ch=='+'&&!
(checkVt(S[e].ch))){
N.ch='E';
if(S[s].type==1&&S[e].type==1){N.type=1;
intv=atoi(S[s].val.data())+atoi(S[e].val.data());
charl[30];
sprintf_s(l,30,"%d",v);
N.val=l;
}
else{
N.type=0;
N.val=S[s].val+S[s+1].ch+S[e].val;
}
}
elseif((s!
=e)&&!
(checkVt(S[s].ch))&&S[s+1].ch=='*'&&!
(checkVt(S[e].ch))){N.ch='T';
if(S[s].type==1&&S[e].type==1){N.type=1;
intv=atoi(S[s].val.data())*atoi(S[e].val.data());
charl[30];
sprintf_s(l,30,"%d",v);
N.val=l;
}
else{
N.type=0;
N.val=S[s].val+S[s+1].ch+S[e].val;
}
}
elseif(S[s].ch=='T'&&s==e){
N.ch='E';
N.val=S[s].val;
N.type=S[s].type;
}else{
N.ch='#';
}
N.po=4;returnN;
}
voiderror(charerrnum){//错误处理子函数
if(errnum=='1'){
printf("错误,非法左括号\n\n");
}
elseif(errnum=='2'){
printf("错误,缺少运算符\n\n");
}
elseif(errnum=='3'){
printf("错误,非法右括号\n\n");
}
elseif(errnum=='4'){
printf("错误,缺少表达式\n\n");
}
}
intsyntax(W*E,intnum){//算法对应的主要实现程序
WS[MAXSIZE];
intk=1,i=0,j;
Wborder,A,Q;border.ch='#';border.po=5;E[num]=border;S[k]=border;do{
A=E[i++];
if(checkVt(S[k].ch))//判断S[k]是终结符
j=k;
else
j=k-1;
while(pre[S[j].po][A.po]=='>'){do{
Q=S[j];
if(checkVt(S[j-1].ch))
j=j-1;
elsej=j-2;
}while(pre[S[j].po][Q.po]!
='<');
WN=Statute(S,j+1,k);if(N.ch=='#'){error('4');return0;
}
k=j+1;S[k]=N;
}
if(pre[S[j].po][A.po]=='<'||pre[S[j].po][A.po]=='='){
k++;
S[k]=A;
}else{error(pre[S[j].po][A.po]);return0;
}
}while(A.ch!
='#');if(A.ch=='#'){
printf("正确,结果为:
%s\n\n",S[k-1].val.data());return0;
}
}
intmain(){
FILE*fp;
errno_terr;
if((err=fopen_s(&fp,"C:
\\Users\\Administrator\\Desktop\\expression.txt","r"))!
=NULL){//以只读方式打开文件,失败则退出程序
printf("filecannotopen!
");exit(0);
}
intn=0;
printf("语法分析结果如下:
\n\n");while(!
feof(fp)){//若不是文件尾则执行循环
intnum=0;
WE[MAXSIZE];//存储一行表达式
GetBC(fp);
if(!
feof(fp)){
n++;fseek(fp,-1L,1);
printf("(%d)",n);
}
else{
break;
}
while
(1){//只读一行,行末标志为
intflag=scan(fp,E,num);
if(flag==0)break;
num++;
}
printf("\n输出:
");syntax(E,num);
}
fclose(fp);//关闭文件
fp=NULL;//避免指向非法内存
}
3、程序运行流程;
4、程序的测试结果和问题;实验报告源数据:
C:
\Windows\system32\cmdnexe
语法分析结果如下:
<1>10;
输岀;正确,结果为;10
<251+2;
输岀|正确,结果为;3
<3><1+2^*3+<5+6*7>;
输出*正确,结果为:
56
<4>输岀:
错误,非法左括号
<5>l*2*-3+C«4«5>;
输岀:
错误,缺少表达式
<6>*;
输出:
正确,结果为,
<7;**5>+l:
输岀:
错误,缺少表达式
请按任意键继续…■
其它数据:
expression,txt-记事本
文件(F)窗E〕榕式Q)奩8+;
(0;
(5*5))+3;
3*x+2y+5*zJ
6+5*((6+5)*2);
1+i+h;
valuel+value2+value3;
C:
fIndows\systeiii32\cmd.exe
语法分析结果如下’
<1>8+;
输岀:
错误,缺少表达式
(2X0;
输出:
错误,缺少表达式
<3><5«5>>+3;
输岀;错误,非法右括号
<"1>3*x+2y+5**z;
输岀|错误,缺少运算符
(5>6+5*<<6+5>*2);
输出1正碣,结異為.
<6>l+x+L:
输岀:
正确,结杲为:
l*x+h
(7>ualuel+ualue2-»valiJie3;
输出;正确’结果为;valuel*ualue2*ua