?? cck.cpp
字號:
#include<iostream.h>
#include<fstream.h>
#include<string.h>
#include<iomanip.h>
#define $other 19
#define $mul 20
#define $div 21
#define $add 22
#define $sub 23
#define $fen 24
#define $equal 25
#define $WHILE 26
#define $DO 27
#define $big 29
#define $small 30
#define $ID 31 //字符
#define $num 32 //數字
/////////////////////////////////////////////////////////////
typedef struct Token
{
int type;
char ch;
}Token; //定義輸入串的結構
typedef enum{JUMP,JG,JL,equal,END,add,mul,sub,div}OpKind; //操作符
typedef struct
{
int label;//標號
OpKind op;//操作符
char par1,par2; //操作數
union{
char result; //結果
int address; // 地址
};
}Quad;
typedef struct{ //逆波蘭
char nbl1[10]; //操作數數組
char nbl2[20]; //操作符數組
}Nbl;
/////////////////////////////////////////////////////////////
#define MAX_TOKEN 256 //Token表大小 詞法分析
#define MAX_QUAD 256 //逆波蘭式數組大小
Token tokentable[MAX_TOKEN]; //建立詞法表
Quad quad[MAX_QUAD]; //建立逆波蘭式表
Nbl nbl[10];
int nbln=0; //第幾條逆波蘭式
int n=0; //nbl1中當前包含幾個字符
int j=0;
int m=0;
int token_index;//token表索引
int total_len;//token表有效長度
int quad_len;//逆波蘭式表有效長度
int quad_index;//逆波蘭式索引
Token cur;
Token queue[10];
int label,k,one; //標記接口
ifstream ins;
int trueadd,falseadd,end;
//申明函數
bool init(char filename[255]);
bool cifa(); //詞法分析函數
void print(); //詞法輸出函數
void backpath(int,int);
void ERROR();
void S();
char M_addsub();
char F_addsub(char);
char P_muldiv(char);
char T_muldiv();
char B_number();
void E();
bool nexttoken();
int newlabel();
char newchar();
void push();
void nextone();
void yuyi(); //語義分析函數
void printQuad(); //輸出逆波蘭式表
void AD_ADDRESS(int nlabel,OpKind nop,char npar1,char npar2,int naddress);
void AD_RESULT(int nlabel,OpKind nop,char npar1,char npar2, char nresult);
///////////////////////////////////////////////////////////////
void main()
{
cout<<"文法結構:"<<endl;
cout<<"------------------------------"<<endl;
cout<<"S->M | WHILE E DO S "<<endl;
cout<<"E->id ^ id | id v id | ! id"<<endl;
cout<<"M->TF|T"<<endl;
cout<<"F-> +TF |-TF|ε"<<endl;
cout<<"T->BP|B"<<endl;
cout<<"P->*BP|/BP|ε"<<endl;
cout<<"B->id|digit"<<endl;
cout<<"------------------------------"<<endl;
cout<<"請輸入文件名稱:";
char fname[200];
cin>>fname;
if(!init(fname)) //打開文件
return ;
if(!cifa()) //調用cifa()函數進行詞法分析
return ;
char ch;
while(1)
{
if(ins.eof())
break;
ins>>ch;
}
cout<<"詞法分析結果:"<<endl;
print(); //輸出詞法分析結果
cout<<endl;
cout<<"詞法分析結束"<<endl;
cout<<endl;
yuyi(); //調用語法語義分析函數
printQuad(); //輸出逆波蘭式
if(label==0)
cout<<"語法語義分析成功!"<<endl;
else
cout<<"語法語義分析失敗!"<<endl;
}
char newchar()
{ char p;
p=char(k);
k++;
return p;
}
//文件打開初始化
bool init(char filename[255])
{
one=0;
token_index=0;
total_len=0;
quad_len=0;
quad_index=0;
label=0;
end=0;
k=48;
ins.open(filename,ios::nocreate | ios::in);
if(ins.fail())
{
cout<<"文件打開出錯!"<<endl;
return false;
}
return true;
}
//////////////////////////////////////////////////////////
//詞法分析
bool cifa()
{
int k=0;
char buf[16];
char ch;
while(1)
{
ins>>ch;
if(ins.fail())
break;
while(ch==' ')
{ ins>>ch;}
if(ch=='W') //對輸入串進行掃描
{
ins>>buf;
if(strcmp(buf,"HILE")==0) //掃描到while
tokentable[total_len++].type=$WHILE; //就將while關鍵字存入表中
}
else if(ch=='D')
{
ins>>buf;
if(strcmp(buf,"O")==0)
tokentable[total_len++].type=$DO; //將do關鍵字存入表中
}
else if(ch=='>') //以下將其他字符或數字存入表中
{
tokentable[total_len++].type=$big;
}
else if(ch=='<')
{
tokentable[total_len++].type=$small;
}
else if(ch=='=')
{
tokentable[total_len++].type=$equal;
}
else if((ch>='A'&& ch<='Z' )|| (ch>='a' && ch<='z'))
{
tokentable[total_len].type=$ID;
tokentable[total_len++].ch=ch;
}
else if(ch>='0' && ch<='9')
{ tokentable[total_len].type=$num;
tokentable[total_len++].ch =ch;
}
else
switch (ch) //將掃描到的操作符存入表中
{case '+' :
tokentable[total_len].type=$add;
tokentable[total_len++].ch =ch;
break;
case '-' :
tokentable[total_len].type=$sub;
tokentable[total_len++].ch =ch;
break;
case '/' :
tokentable[total_len].type=$div;
tokentable[total_len++].ch =ch;
break;
case '*' :
tokentable[total_len].type=$mul;
tokentable[total_len++].ch =ch;
break;
case ';' :
tokentable[total_len].type=$fen;
tokentable[total_len++].ch =ch;
break;
default:cout<<"!"<<endl;
}
}
return true;
}
void AD_RESULT(int nlabel,OpKind nop,char npar1,char npar2, char nresult)
{quad[quad_len].label=nlabel;
quad[quad_len].op=nop;
quad[quad_len].par1=npar1;
quad[quad_len].par2=npar2;
quad[quad_len].result=nresult;
quad_len++;
}
void AD_ADDRESS(int nlabel,OpKind nop,char npar1,char npar2,int naddress)
{ quad[quad_len].label=nlabel;
quad[quad_len].op=nop;
quad[quad_len].par1=npar1;
quad[quad_len].par2=npar2;
quad[quad_len].address=naddress;
quad_len++;
}
//掃描下一個單詞函數
bool nexttoken()
{
if(token_index>=total_len)
return false;
if(tokentable[token_index].type==$fen)
token_index++;
cur.type=tokentable[token_index].type;
cur.ch=tokentable[token_index].ch;
token_index++;
return true;
}
//進隊列
void push()
{
while(tokentable[token_index].type!=$fen)
{
queue[one].type=tokentable[token_index].type;
queue[one].ch=tokentable[token_index].ch;
token_index++;
one++;
}
}
//隊列下一個字符
void next()
{
one--;
cur.type=queue[one].type;
cur.ch =queue[one].ch ;
}
//錯誤處理
void ERROR(char str[20])
{ label++;
cout<<endl;
cout<<"error! "<<str<<endl;
}
void S() //處理S->id=M | while E do S語句
{ char rtn;
char c;
if(!nexttoken())
ERROR("s(0)");
if(cur.type==$ID)
{
c=cur.ch;
if(!nexttoken())
ERROR("S(0)");
if(cur.type!=$equal)
ERROR("S(equal)");
push();
rtn=M_addsub(); //調用M_addsub()函數分析加減法
AD_RESULT(quad_len,equal,rtn,0,c); //分析同時產生逆波蘭式
nexttoken(); //加入逆波蘭式表中
while(cur.type==$ID)
{
c=cur.ch;
if(!nexttoken())
ERROR("S(0)");
if(cur.type!=$equal)
ERROR("S(equal)");
push();
rtn=M_addsub();
AD_RESULT(quad_len,equal,rtn,0,c);
nexttoken();
}
}
else if(cur.type==$WHILE) //當當前字符為while時
{
E(); //判斷表達式E真值,調用E()函數
if(!nexttoken())
ERROR("S(0)");
if(cur.type==$DO) //
{
backpath(trueadd,quad_len+1);
S(); //遞歸調用S()分析do 之后的表達式
end=quad_len;
AD_ADDRESS(quad_len,JUMP,0,0,end);
}
else
{
ERROR("S(do)");
}
}
else
ERROR("S(while)");
}
void E() // 處理E->id < id | id > id語句
{
char a,b;
int c;
if(!nexttoken())
ERROR("E(0)");
if(cur.type==$ID||cur.type==$num)
{
a=cur.ch;
if(!nexttoken())
ERROR("E(0)");
if(cur.type==$big||cur.type==$small)
{
c=cur.type ;
if(!nexttoken())
ERROR("E(0)");
if(cur.type==$ID||cur.type==$num)
b=cur.ch;
else
ERROR("E(id/num)");
if(c==$big)
{
trueadd=quad_len;
falseadd=quad_len+1;
AD_ADDRESS(quad_len,JG,a,b,trueadd); //語法分析同時產生逆波蘭式
AD_ADDRESS(quad_len,JUMP,0,0,falseadd); //并加入逆波蘭式表中
}
else
{
trueadd=quad_len;
falseadd=quad_len+1;
AD_ADDRESS(quad_len,JL,a,b,trueadd);
AD_ADDRESS(quad_len,JUMP,0,0,falseadd);
}
}
else
ERROR("E(id/num)");
}
else
ERROR("E(big/small)");
}
//處理M->TF|T 規則對應句子
char M_addsub()
{
char rtn,t;
rtn=T_muldiv(); //調用T_muldiv()函數分析乘除法
t=rtn;
rtn=F_addsub(t); //調用F_addsub(t)函數分析加減法
return rtn;
}
//處理乘除法,處理P->*BP|/BP|ε 規則對應句子
char P_muldiv(char a)
{
char t,b;
next();
if(cur.type==$mul||cur.type==$div)
{
int op=cur.type;
b=B_number();
t=newchar();
if(op==$mul)
AD_RESULT(quad_len,mul,a,b,t); //分析同時產生逆波蘭式
else //加入逆波蘭式表中
AD_RESULT(quad_len,div,a,b,t);
}
else
t=a;
return t;
}
//處理加減法,處理F-> +TF |-TF|ε 規則對應句子
char F_addsub(char a)
{ char t,b;
if(cur.type==$add||cur.type==$sub)
{int op=cur.type ;
b=T_muldiv();
t=newchar();
if(op==$add)
AD_RESULT(quad_len,add,a,b,t); //分析同時產生逆波蘭式
else
AD_RESULT(quad_len,sub,a,b,t);
}
else
t=a;
return t;
}
//處理T->BP|B 規則對應句子
char T_muldiv()
{
char t;
char rtn;
rtn=B_number();
t=rtn;
rtn=P_muldiv(t);
return rtn;
}
//處理B->id|digit 規則對應句子
char B_number()
{
char rtn;
next();
if(cur.type==$num||cur.type==$ID)
rtn=cur.ch ;
else
cout<<"error:B()"<<endl;
return rtn;
}
///////////////////////////////////////////////////////////
//語義分析
void yuyi()
{
cout<<"語法語義分析,逆波蘭式如下:"<<endl;
S(); //調用S()函數分析第一條規則
AD_RESULT(quad_len,END,0,0,'-');
}
///////////////////////////////////////////////////////////
void backpath(int nlabel,int addr)
{
quad[nlabel].address=addr;
}
//輸出詞法分析單詞表
void print()
{
for(token_index=0;token_index<total_len;token_index++)
{
if(tokentable[token_index].type==$WHILE)
cout<<setw(10)<<"WHILE";
if(tokentable[token_index].type==$DO)
cout<<setw(10)<<"DO"<<endl;
if(tokentable[token_index].type==$ID)
cout<<setw(10)<<tokentable[token_index].ch;
if(tokentable[token_index].type==$num)
cout<<setw(10)<<tokentable[token_index].ch;
if(tokentable[token_index].type==$equal)
cout<<setw(10)<<'=';
if(tokentable[token_index].type==$big)
cout<<setw(10)<<'>';
if(tokentable[token_index].type==$small)
cout<<setw(10)<<'<';
if(tokentable[token_index].type==$add)
cout<<setw(10)<<'+';
if(tokentable[token_index].type==$sub)
cout<<setw(10)<<'-';
if(tokentable[token_index].type==$mul)
cout<<setw(10)<<'*';
if(tokentable[token_index].type==$div)
cout<<setw(10)<<'/';
if(tokentable[token_index].type==$fen)
cout<<setw(10)<<';'<<endl;
}
token_index=0;
}
//輸出逆波蘭式
void printQuad()
{
for(int i=0;i<quad_len;i++)
{
if(quad[i].op==JG)
{
}
else if(quad[i].op==JL)
{
}
else if(quad[i].op==JUMP)
{
}
else if(quad[i].op==equal)
{
nbl[nbln].nbl1[n++]=quad[i].result;
strcat(nbl[nbln].nbl2,"=");
nbln++;
n=0;
}
else if(quad[i].op==END)
{
}
else if(quad[i].op==add)
{
nbl[nbln].nbl1[n++]=quad[i].par1;
nbl[nbln].nbl1[n++]=quad[i].par2;
strcat(nbl[nbln].nbl2,"+");
}
else if(quad[i].op==sub)
{
nbl[nbln].nbl1[n++]=quad[i].par1;
nbl[nbln].nbl1[n++]=quad[i].par2;
strcat(nbl[nbln].nbl2,"-");
}
else if(quad[i].op==div)
{
nbl[nbln].nbl1[n++]=quad[i].par1;
nbl[nbln].nbl1[n++]=quad[i].par2;
strcat(nbl[nbln].nbl2,"/");
}
else if(quad[i].op==mul)
{
nbl[nbln].nbl1[n++]=quad[i].par1;
nbl[nbln].nbl1[n++]=quad[i].par2;
strcat(nbl[nbln].nbl2,"*");
}
}
for(j=0;j<nbln;j++)
{
cout<<"L"<<j+1<<":";
for(m=strlen(nbl[j].nbl1);m>0;m--)
cout<<nbl[j].nbl1[m-1];
cout<<nbl[j].nbl2<<endl;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -