📄 complier.cpp
字号:
#include<iostream.h>
#include<fstream.h>
#include<string.h>
#define true 1
#define false 0
#define N 100 //确定缓冲区的最大容量
int IN=0; //I表计数器
int CN=0; //C表计数器
int Len=0;//纪录待编译程序的行号
bool GetChar(char *c,char*buf,int *m);//从buffer中读取一个字符
bool IsLetter(char c);
bool IsDigit(char c);
void Concat(char *str,char ch);
int Change(char *str);//把从类型表(P,K,I,C)中读取的整数串转化成整数形式,并返回
int CheckK(char *str);
int CheckP(char *str);
int InsertI(char *str);
int InsertC(char *str);
void W_Answer(char *str,char value,int code);
//在Answer.txt中填写编译结果,包括单词符号及其所属属性,也包括错误处理信息
int main()
{
char buffer[N]; //输入缓冲区
int mark; //搜索指示器,指示下一次要读取的字符在buffer中的位置
char ch; //存放最新读进的字符
char strToken[N]; //存放构成单词符号的字符串
int code; //记录当前单词符号在所属表中的位置
char value;//单词符号所属的种别,可取得值为:K,P,I,C,分别对应于四个表,值为E表示出错
buffer[0]=strToken[0]='\0';
ifstream inSP("SourPro.txt"); //打开源程序文件SourPro
if(!inSP)
{
cout<<"Failed to open SourPro.txt"<<endl;
return 0;
}
cout<<"***Scanning the file 'SourPro.txt'***"<<endl;
inSP.getline(buffer,N);
mark=0; //mark复位
while(!inSP.eof()||(buffer[mark]!='\0'))
{
while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
//读取字母,如果超过buffer的界限,则从文件中重新读取一行存入buffer
{
inSP.getline(buffer,N);
Len++;
mark=0;
}
if(IsLetter(ch))//关键字或是标识符
{
while(IsLetter(ch) || IsDigit(ch)||ch=='_')
{
Concat(strToken,ch);//将ch连接到strToken之后 ???
while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
{
inSP.getline(buffer,N);
Len++;
mark=0; //mark复位
}
}
value='K';
code=CheckK(strToken);//查K表,如该字符存在k表中,则返回表中的位置,否则返回0
if(code==0)
{
code=InsertI(strToken); //不属于关键字,则插入到I表中
value='I';
}
mark--;
ch='\0';//回溯一个字符
}
else
if(IsDigit(ch)) //常数串
{
while(IsDigit(ch))
{
Concat(strToken,ch);//将ch连接到strToken之后 ???
while((GetChar(&ch,buffer,&mark)==0) && (!inSP.eof()))
{
inSP.getline(buffer,N);
Len++;
mark=0; //mark复位
}
}
if(ch=='.')
{
Concat(strToken,ch);//将ch连接到strToken之后
while((GetChar(&ch,buffer,&mark)==0) && (!inSP.eof()))
{
inSP.getline(buffer,N);
Len++;
mark=0; //mark复位
}
if(!IsDigit(ch))
value='E';//错误处理
else
{
while(IsDigit(ch))
{
Concat(strToken,ch);//将ch连接到strToken之后 ???
while((GetChar(&ch,buffer,&mark)==0) && (!inSP.eof()))
{
inSP.getline(buffer,N);
Len++;
mark=0; //mark复位
}
}
value='C';
code=InsertC(strToken);
mark--;
ch='\0';
}
}
}
else//操作符或分隔符处理
{
switch(ch)
{
case'=':
Concat(strToken,ch);
while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
{
inSP.getline(buffer,N);
Len++;
mark=0; //mark复位
}
if(ch=='=')//第二个等号
Concat(strToken,ch);
else
{
mark--;
ch='\0';
}
break;
case'-':
Concat(strToken,ch);
while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
{
inSP.getline(buffer,N);
Len++;
mark=0; //mark复位
}
if(ch=='>'||ch=='-')//第二个等号
Concat(strToken,ch);
else
{
mark--;
ch='\0';
}
break;
case'>':
Concat(strToken,ch);
while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
{
inSP.getline(buffer,N);
Len++;
mark=0; //mark复位
}
if(ch=='=')//第二个等号
Concat(strToken,ch);
else
{
mark--;
ch='\0';
}
break;
case'<':
Concat(strToken,ch);
while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
{
inSP.getline(buffer,N);
Len++;
mark=0; //mark复位
}
if(ch=='=')//第二个等号
Concat(strToken,ch);
else
{
mark--;
ch='\0';
}
break;
case'!':
Concat(strToken,ch);
while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
{
inSP.getline(buffer,N);
Len++;
mark=0; //mark复位
}
if(ch=='=')//第二个等号
Concat(strToken,ch);
else
{
mark--;
ch='\0';
}
break;
case'\"':Concat(strToken,ch);
code=CheckP(strToken);
value='P';
W_Answer(strToken,value,code);//将这个单词符号及属性写入answer文件中
strToken[0]='\0';
while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
{
inSP.getline(buffer,N);
Len++;
mark=0; //mark复位
}
while(ch!='\"')
{
Concat(strToken,ch);
while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
{
inSP.getline(buffer,N);
Len++;
mark=0; //mark复位
}
}
if(inSP.eof())
{
cout<<"error"<<endl;//双引号不匹配
break;
}
code=InsertC(strToken);
value='C';
W_Answer(strToken,value,code);//将这个单词符号及属性写入answer文件中
strToken[0]='\0';
Concat(strToken,ch);//处理最后一个引号
break;
case'+':
Concat(strToken,ch);
while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
{
inSP.getline(buffer,N);
Len++;
mark=0; //mark复位
}
if(ch=='+')
Concat(strToken,ch);
else
{
mark--;
ch='\0';
}
break;
case'&':Concat(strToken,ch);
while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
{
inSP.getline(buffer,N);
Len++;
mark=0; //mark复位
}
if(ch=='&')
Concat(strToken,ch);
else
{
mark--;
ch='\0';
}
break;
case'{': case'}': case'(': case')': case'[': case']':
case'*': case'\'': case'/': case';': case',': case'.':
case'#':
Concat(strToken,ch);
break;
case' ':
case'\n':
case'\t':break;
default:if(ch=='\0')//处理文件结束时最后一个字符
{
inSP.close();
cout<<"the complier results have been writen to 'Answer.txt'!"<<endl;
cout<<"Please check the answer !"<<endl;
return 0;
}
Concat(strToken,ch);
value='E';
break;
}
if(ch==' '||ch=='\t'||ch=='\n')
continue;
else
{
code=CheckP(strToken);
value='P';
}
}
W_Answer(strToken,value,code);//将这个单词符号及属性写入answer文件中
strToken[0]='\0';
}
inSP.close();
cout<<"the complier results have been writen to 'Answer.txt'!"<<endl;
cout<<"Please check the answer !"<<endl;
return 0;
}
///////////////////////////////////////////////////////////
//bool GetChar(char *c,char*buf,int *m)
//从buffer中读取一个字符,成功则返回true,否则返回false
//false表示buffer已空,需要再从SourPro.txt中再读取一行放到buffer中
bool GetChar(char *c,char*buf,int *m)
{
*c=buf[*m];
if(*c=='\0')
return false;
else
{
(*m)++;
return true;
}
}
bool IsLetter(char c)//若c为字母则返回true,否则返回false
{
if( ((c>=65)&&(c<=90)) || ((c>=97)&&(c<=122)) )
return true;
return false;
}
bool IsDigit(char c)//若c为数字则返回true,否则返回false
{
if((c>=48)&&(c<=57))
return true;
return false;
}
void Concat(char *str,char ch) //将字符ch追加到串str后面
{
int i=0;
while(str[i]!='\0')
{
i++;
}
str[i]=ch;
str[i+1]='\0';
return;
}
int Change(char *str)//把从类型表(P,K,I,C)中读取的整数串转化成整数形式,并返回
{
int i=0;
int num=0;
while(IsDigit(str[i]))
{
num=num*10+(int)str[i]-48;
i=i+1;
}
return num;
}
int CheckK(char *str) //查K表,若str存在K表中,则返回它在表中的位置,若不存在则返回0
{
int inte;
char a[N],s[N];
ifstream inK("K.txt"); //打开K文件
if(!inK)
{
cout<<"Failed to open K.txt"<<endl;
return 0;
}
while(!inK.eof())
{
inK.getline(a,N);
inte=Change(a);
inK.getline(s,N);
if(!strcmp(s,str))
break;
}
inK.close();
if(!strcmp(s,str))
return inte;
return 0;
}
int CheckP(char *str)//查P表,若str存在P表中,则返回它在表中的位置,若不存在则返回0
{
int inte;
char a[N],s[N];
ifstream inP("P.txt"); //打开P标文件
if(!inP)
{
cout<<"Failed to open P.txt"<<endl;
return 0;
}
while(!inP.eof())
{
inP.getline(a,N);
inte=Change(a);
inP.getline(s,N);
if(!strcmp(s,str))
break;
}
inP.close();
if(!strcmp(s,str))
return inte;
return 0;
}
int InsertI(char *str)//填I表并返回该单词在表中的位置
{
int inte;
char a[N],s[N];
if(IN>0)
{
ifstream iI("I.txt"); //打开I文件,并作查询是否有str
if(!iI)
{
cout<<"Failed to open I.txt"<<endl;
return 0;
}
while(!iI.eof())
{
iI.getline(a,N);
iI.getline(s,N);
inte=Change(a);
if(!strcmp(s,str))
break;
}
iI.close();
if(!strcmp(s,str))//表中已经存在str,则直接返回它在表中的位置
return inte;
}
IN++;
ofstream oI("I.txt",ios::app); //str不存在表中,打开I文件将str填入表中
if(!oI)
{
cout<<"Failed to open I.txt"<<endl;
return 0;
}
oI<<IN<<":"<<endl<<str<<endl;
oI.close();
return IN;
}
int InsertC(char *str)//填C表并返回该单词在表中的位置
{
int inte;
char a[N],s[N];
if(CN>0)
{
ifstream iC("C.txt"); //打开C表文件,并作查询是否有str
if(!iC)
{
cout<<"Failed to open C.txt"<<endl;
return 0;
}
while(!iC.eof())
{
iC.getline(a,N);
iC.getline(s,N);
inte=Change(a);
if(!strcmp(s,str))
break;
}
iC.close();
if(!strcmp(s,str))//表中已经存在str,则直接返回它在表中的位置
return inte;
}
ofstream oC("C.txt",ios::app); ////str不存在表中,打开C文件将str填入表中
if(!oC)
{
cout<<"Failed to open C.txt"<<endl;
return 0;
}
CN++;
oC<<CN<<":"<<endl<<str<<endl;
oC.close();
return CN;
}
/////////////////////////////////////////////////////////////////////
//以下子程序填写编译结果,将所得的单词符号及其所属属性写入Answer文件中
//也包括错误处理信息
void W_Answer(char *str,char value,int code)
{
ofstream outAN("Answer.txt",ios::app); //打开I标文件
if(!outAN)
{
cout<<"Failed to open Answer.txt"<<endl;
return ;
}
if(value=='E')////////错误处理
{
outAN<<str<<"---at line "<<Len<<"--illegal ! :("<<endl;
return;
}
outAN<<str<<" ----- [ "<<value<<" - "<<code<<" ]"<<endl;//输出单词信息
outAN.close();
return ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -