📄 词法分析器--最终的.cpp
字号:
#include <iostream>
#include <string>
#include <fstream>
#include <ctype.h>
#include <iomanip>
#include <string.h>
#define NMax 200//定义最大单词符号个数
using namespace std;
typedef struct token
{
int label; //单词序号
char name[30]; //单词本身
int code; //单词的机内码
int addr; //地址,单词为保留字时为-1,为标识符或常数时为大于0的数值,即在符号表中的入口地址。
} token;
typedef struct symble
{
int number; //序号
int type; //类型
char name[30]; //名字
} symble;
//定义全局变量
int temp=0;
int btemp=0;
int i=1;//当前行号
token t[NMax];
symble s[NMax];
int err=0;//出错个数
char* ReserveWords[17]={"and","begin","bool","do","else","end","false","if","integer",
"not","or","program","real","then","true","var","while"};
char* Biaohao[]={"(",")","+","-","*","/",".",",",":",";",":=","=","<=","<","<>",">",">="};
//读入ch
char getChar(ifstream& src)
{
char ch1;
src.get(ch1);
return ch1;
}
//读入空格 跳过空格
char getBC(ifstream& src)
{
char ch2;
src.get(ch2);
while(ch2==' ')
{
src.get(ch2);
}
return ch2;
}
//连接单词符号
void concat(char *str,char ch3)
{
size_t n=strlen(str);
str[n++]=ch3;
str[n]='\0';
}
//判断是否为保留字,为保留字返回编码,否返回0
int reserve(const char* str)
{
int k=-1;
for(int i=0;i<17;i++)
{
if(_stricmp(ReserveWords[i],str)==0)
{
k=i;
break;
}
}
return (k+1);
}
//回调字符
char retract(ifstream& src)
{
src.seekg(-1,ios::cur);
return '\0';
}
//分析函数
int analyzer(ifstream& src,ofstream& dst1,ofstream& dst2)
{
char ch;//当前字符
char strToken[1024]="";
ch=getBC(src);
//开头为字母
if(ch=='\n')
{
i++;
}
else if(isalpha(ch))
{
while (isalpha(ch) || isdigit(ch) || ch=='_')
{
concat(strToken,ch);
ch=getChar(src);
}
ch=retract(src);
if(reserve(strToken)>0)
{
t[temp].label=temp+1;
strcmp(t[temp].name,strToken);
t[temp].code=reserve(strToken);
t[temp].addr=-1;
dst1<<setw(3)<<++temp<<setw(10)<<strToken<<setw(3)<<reserve(strToken)<<setw(3)<<t[temp].addr<<endl;
}
else
{
t[temp].label=temp+1;
strcmp(t[temp].name,strToken);
t[temp].code=18;
t[temp].addr=btemp+1;
dst1<<setw(3)<<++temp<<setw(10)<<strToken<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
s[btemp].number=btemp+1;
s[btemp].type=18;
strcpy(s[btemp].name,strToken);
dst2<<setw(3)<<++btemp<<setw(3)<<s[btemp].type<<setw(10)<<strToken<<endl;
}
}
//判断为数字的情况
else if(isdigit(ch))
{
t[temp].code=19;
bool k=true;
while(isdigit(ch))
{
concat(strToken,ch);
ch=getChar(src);
if(k==true)
{
if(ch=='.')
{
k=false;
concat(strToken,ch);
ch=getChar(src);//跳过第一个'.'
t[temp].code=20;
}
}
}
if(isalpha(ch)||ch=='_'||ch=='.')
{
err++;
cout<<"error("<<err<<") "<<"line("<<i<<") "<<"Word Error"<<endl;
while(isalpha(ch)||ch=='_'||ch=='.'||isdigit(ch))
ch=getChar(src);
}
ch=retract(src);
t[temp].label=temp+1;
strcmp(t[temp].name,strToken);
t[temp].addr=btemp+1;
dst1<<setw(3)<<++temp<<setw(10)<<strToken<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
s[btemp].number=btemp+1;
s[btemp].type=t[temp-1].code;
strcpy(s[btemp].name,strToken);
dst2<<setw(3)<<++btemp<<setw(3)<<s[btemp].type<<setw(10)<<strToken<<endl;
}
//判断是否为运算符
else if(ch=='+')
{
t[temp].label=temp+1;
t[temp].code=23;
t[temp].addr=-1;
dst1<<setw(3)<<++temp<<setw(10)<<"+"<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
}
else if(ch=='-')
{
t[temp].label=temp+1;
t[temp].code=24;
t[temp].addr=-1;
dst1<<setw(3)<<++temp<<setw(10)<<"-"<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
}
else if(ch=='*')
{
t[temp].label=temp+1;
t[temp].code=25;
t[temp].addr=-1;
dst1<<setw(3)<<++temp<<setw(10)<<"*"<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
}
else if(ch=='/')
{
t[temp].label=temp+1;
t[temp].code=26;
t[temp].addr=-1;
dst1<<setw(3)<<++temp<<setw(10)<<"/"<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
}
//判断是否为界符(无歧异界符)
else if(ch=='('||ch==')'||ch==','||ch==';'||ch=='=')
{
t[temp].label=temp+1;
if(ch=='(') t[temp].code=21;
if(ch==')') t[temp].code=22;
if(ch==',') t[temp].code=28;
if(ch==';') t[temp].code=30;
if(ch=='=') t[temp].code=32;
t[temp].addr=-1;
dst1<<setw(3)<<++temp<<setw(10)<<ch<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
}
//":"和":="
else if(ch==':')
{
ch=getChar(src);
if(ch=='=')
{
t[temp].label=temp+1;
t[temp].code=31;
t[temp].addr=-1;
dst1<<setw(3)<<++temp<<setw(10)<<":="<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
}
else
{
t[temp].label=temp+1;
t[temp].code=29;
t[temp].addr=-1;
dst1<<setw(3)<<++temp<<setw(10)<<":"<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
retract(src);
}
}
//"<"、"<="和"<>"
else if(ch=='<')
{
ch=getChar(src);
if(ch=='=')
{
t[temp].label=temp+1;
t[temp].code=33;
t[temp].addr=-1;
dst1<<setw(3)<<++temp<<setw(10)<<"<="<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
}
if(ch=='>')
{
t[temp].label=temp+1;
t[temp].code=35;
t[temp].addr=-1;
dst1<<setw(3)<<++temp<<setw(10)<<"<>"<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
}
else
{
t[temp].label=temp+1;
t[temp].code=34;
t[temp].addr=-1;
dst1<<setw(3)<<++temp<<setw(10)<<"<"<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
retract(src);
}
}
//">" ">="
else if(ch=='>')
{
ch=getChar(src);
if(ch=='=')
{
t[temp].label=temp+1;
t[temp].code=37;
t[temp].addr=-1;
dst1<<setw(3)<<++temp<<setw(10)<<">="<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
}
else
{
t[temp].label=temp+1;
t[temp].code=36;
t[temp].addr=-1;
dst1<<setw(3)<<++temp<<setw(10)<<">"<<setw(3)<<t[temp].code<<setw(3)<<t[temp].addr<<endl;
retract(src);
}
}
else
{
if(getChar(src)!=' '||getChar(src)!='\n')
{
err++;
cout<<"error("<<err<<") "<<"line("<<i<<") "<<"Char define invalid"<<endl;
}
}
return err;
}
int main(int argc,char *argv[])
{
string strSrc;
if(argc==1)
{
cout<<"Please input Pascal sourse file name:";
getline(cin,strSrc);
}
else
{
strSrc=argv[1];
}
ifstream src(strSrc.c_str());
if(src.fail())
{
cerr<<"\aFailed openning \""<<strSrc<<"\"!"<<endl;
return 1;
}
ofstream dst1("word.txt");
ofstream dst2("sym.txt");
//开始分析
while(!src.eof())
err=analyzer(src,dst1,dst2);
src.close();
dst1.close();
dst2.close();
cout <<"The sum of errors is "<<err<<endl;
cout << "The result of Analyzing is written into word.txt and sym.txt." << endl;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -