📄 b05513 36 张晓 词法分析器最终版.cpp
字号:
#include<iostream>
#include<stdio.h>
#include<string>
#include<fstream>
using namespace std;
ifstream infile("123.txt",ios::out);
string getWorld(string&,int&);//取连续的字符和数字。
static int line = 1; //表示光标所在的行数
struct ID{ string name; int count;int worldLine[30];}id[300];//用于存放ID号码--ID符号表
static int ID = 0; //用于记录ID存放的数量
int Number[250]; //用于存放数字 ,常数表
static int N = 0; //用于记录存放数字的个数
void Error(string &); //记录非法字符错误
void loginID(string&); //注册ID号
void loginNumber(string&); //记录数字
bool same(string&); //判断单词是否已经存在
void yunsuan(string &,string &,int &);//对于运算符的分析
bool isKey(string&);//判断是不是关键字
void expline(string&,int&,string&,int&);// 对于注释错误的判断,注释没有结束标志
struct errorWorld{string name;int line;}ed[250];//记录非法符号的名称及所在行
int worldNumber=0;//记录非法字符个数
////////////////////////////////////////////////////
void ifBlank(string &str,int &i)//跳过空格
{
while(str[i]==' ')
i++;
}
////////////////////////////////////////////////////////
string getWorld(string &str,int &i)
{
string s;
if(('0'<=str[i] && str[i]<= '9')||('a'<=str[i]&&str[i] <= 'z')||('A'<=str[i]&&str[i]<='Z'))
while(('0'<=str[i] && str[i]<= '9')||('a'<=str[i]&&str[i] <= 'z')||('A'<=str[i]&&str[i]<='Z'))
{
s+=str[i];
i++;
}
else
while(str[i]!=EOF&&str[i]!=' '&&str[i]!='\n'&&!('0'<=str[i] && str[i]<= '9')&&!('a'<=str[i]&&str[i] <= 'z')&&!('A'<=str[i]&&str[i]<='Z'))
{
s+=str[i];
i++;
}
ifBlank(str,i);
return s;
}
//////////////////////////////////////////////////
void Error(string &ch)//记录非法字符错误的行
{
ed[worldNumber].name=ch;
ed[worldNumber].line=line;
worldNumber++;
}
//////////////////////////////////////////////////
bool isKey(string &str)//判断是不是关键字
{
string p[14]={"char","int","float","void","const","for","if","else","then","while","switch","break","begin","end"};
for(int i=0;i<14;i++)
{
if(!str.compare(p[i]))
{
cout<<"\t\t"<<"_"<<"\t\t"<<str<<endl;
return true;
}
}
return false;
}
/////////////////////////////////////////////////////
bool same(string &str)//判断该单词是否出现过
{
for(int i=0;i<ID;i++)
{
if(!str.compare(id[i].name))
{
id[i].count++;
id[i].worldLine[id[i].count]=line;
cout<<"\t\t"<<i<<"\t\t"<<str<<endl;
return true;
}
}
return false;
}
/////////////////////////////////////////////////////
void loginID(string &str)//注册ID号
{
if(!same(str))
{
id[ID].name=str;
id[ID].count=1;
id[ID].worldLine[id[ID].count]=line;
cout<<"\t\t"<<ID<<"\t\t"<<str<<endl;
ID++;
}
}
///////////////////////////////////////////////////
void loginNumber(string &str)//记录数字
{
int i=0;
while(i<str.length())
{
if('0'<=str[i] && str[i]<= '9')
i++;
else break;
}
if(i==str.length())
{
for(int j=0;j<str.length();j++)
Number[N]=Number[N]* 10 + (str[j]-'0');
N++;
cout<<"\t\t"<<N-1<<"\t\t"<<Number[N-1]<<endl;
}
else
{
Error(str);
}
}
//////////////////////////////////////////////////
void yunsuan(string &str,string &str1,int &j)//对于运算符及其他符号的判断
{
string s;
for(int i=0;i<str.length();i++)
{
if(str[i]=='('||str[i]==')'||str[i]=='['||str[i]==']'||str[i]==';')
cout<<"\t\t"<<"_"<<"\t\t"<<str[i]<<endl;
else
if(str[i]=='<'||str[i]=='>'||str[i]=='!'||str[i]=='=')
{
if(i+1<str.length()&&str[i+1]=='=')
cout<<"\t\t"<<"rlop"<<"\t\t"<<str[i++]<<str[i+1]<<endl;
else
{
if(str[i]=='<'||str[i]=='>')
cout<<"\t\t"<<"rlop"<<"\t\t"<<str[i]<<endl;
if(str[i]=='!')
cout<<"\t\t"<<"not"<<"\t\t"<<str[i]<<endl;
if(str[i]=='=')
cout<<"\t\t"<<"_"<<"\t\t"<<str[i]<<endl;
}
}
else
if(str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='%')
{
if(i+1<str.length()&&str[i+1]=='=')
cout<<"\t\t"<<"rlop"<<"\t\t"<<str[i++]<<str[i+1]<<endl;
else
cout<<"\t\t"<<"_"<<"\t\t"<<str[i]<<endl;
}
else
if(str[i]=='|')
{
if(i+1<str.length()&&str[i+1]=='|')
cout<<"\t\t"<<"or"<<"\t\t"<<str[i++]<<str[i+1]<<endl;
else
{
s=str[i];
Error(s);
}
}
else
if(str[i]=='&')
{
if(i+1<str.length()&&str[i+1]=='&')
cout<<"\t\t"<<"or"<<"\t\t"<<str[i++]<<str[i+1]<<endl;
else
{
s=str[i];
Error(s);
}
}
else
if(str[i]=='/')
{
if(i+1<str.length()&&str[i+1]=='=')
cout<<"\t\t"<<"rlop"<<"\t\t"<<str[i++]<<str[i+1]<<endl;
if(i+1<str.length()&&str[i+1]=='*')
{
i++;
expline(str,i,str1,j);
}
else
cout<<"\t\t"<<"_"<<"\t\t"<<str[i]<<endl;
}
else
{
s=str[i];
Error(s);
}
}
}
///////////////////////////////////////////////////
void expline(string &str1,int &j,string &str2,int&i)//str1代表当前的一个单词,j代表当前的分析道本单词的下标,str2代表当前缓冲区中的一行,i代表str2分析到的位置
{
int flag=0;
for(;j<str1.length();j++)//在当前单词中寻找注释结束符
{
if(str1[j]=='*'&&str1[j+1]=='/'&&j+1<str1.length())
{
j++;flag=1;break;
}
}
int l;
char ch;
while(!infile.eof()&&flag!=1)
{
l=line;
if(i==0)
{
string s;
do//取文件中的一行字符串进行分析
{
ch=infile.get();
s+=ch;
str2=s;
}
while(ch!='\n'&&ch!=EOF);
}
do
{
str1=getWorld(str2,i);
for(j=0;j+1<str1.length();j++)//在以后文本中寻找注释结束符
{
if(str1[j]==EOF)break;
if(str1[j]=='*'&&str1[j+1]=='/'&&j+1<str1.length())
{
j++;flag=1;
break;
}
}
if(str2[i]=='\n'&&flag==0){line++;i=0;}//分析完一行后换行
}
while(l==line&&flag==0);
if(ch==EOF&&flag==0)
{
ed[worldNumber].line=l;
ed[worldNumber].name="'/*'注释开始,未发现匹配注释结束符";
worldNumber++;break;
}
}
}
///////////////////////////////////////////////////////
void main()
{
string oneworld;
int i=0;
int j;
char ch;
cout<<"\t\t"<<"分析结果如下:"<<endl;
while(!infile.eof())
{
string worldline;
do//取文件中的一行字符串进行分析
{
if(ch==EOF)break;
ch=infile.get();
worldline+=ch;
}
while(ch!='\n'&&ch!=EOF);
j=line;
while(line==j&&worldline[i]!=EOF)
{
oneworld=getWorld(worldline,i);//取单个的变量进行分析
if(!isKey(oneworld))
{
if(('a'<=oneworld[0]&&oneworld[0] <= 'z')||('A'<=oneworld[0]&&oneworld[0]<='Z'))
loginID(oneworld);
else
if('0'<=oneworld[0] && oneworld[0]<= '9')
loginNumber(oneworld);
else
{
yunsuan(oneworld,worldline,i);
if(line!=j&&worldline[i]!=EOF)j=line;
}
}
if(worldline[i]==EOF)break;
if(worldline[i]=='\n'){line++;i=0;}//分析完一行后换行
}
}
cout<<endl;
cout<<"分析完毕,共有 "<<worldNumber<<" 处错误。"<<endl;
if(worldNumber>0)
{
for(int i=0;i<worldNumber;i++)
cout<<" 第 "<<ed[i].line<<" 行:"<<ed[i].name<<"\t\t非法!"<<endl;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -