📄 scanner.cpp
字号:
/************词法分析程序*****************/
#define Null 0
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
/*****************************************/
struct signtable{ //定义符号表文件的结构
int serialno; //序号
int type; //类型号
char name[30] ; //名字
};
struct wordsn{ //单词序列文件结构
int label; //单词序号
int code; //单词的类型码
int addr; //单词地址
char name[30]; //名字
};
struct Keyword{ //关键字
char name[30]; //名字
int code; //类型码
};
struct sign{ //符号表
signtable s;
sign *next;
};
/*****************************************/
int error_count; //错误数
int label_count; //单词序号
int code_count; //类型码
int addr_count; //单词地址
int var_count; //符号数
int Line_count; //行号
Keyword *keylist; //关键字表
int tatal=0; //关键字总数
sign *head=Null; //符号表头指针
sign *tail=Null; //符号表尾指针
signtable symble; //单词表
wordsn words; //单词序列
ifstream ifile; //输入文件
ofstream wordsnfile; //单词序列表文件
ofstream symtablefile; //单词表文件
ifstream keywordfile; //关键字文件
char ch;
/*******************************************/
int searchword(); //查找符号表
void Insertword(); //插入符号表
void Isstring(); //识别保留字,标识符
void Isnumber(); //识别整型,与浮点型
void Ischar(); //识别字符
void Ischars(); //识别字符串
void Isexplain(); //识别注释
void Isother(); //识别其它符号
void Iserror(); //错误处理
void initialize(); //读取关键字表
void dis(); //输出结果
/*********输出单词序列及符号表文件***********/
void dis()
{ifstream WORD; //单词序列表文件
ifstream SYM; //单词表文件
WORD.open("wordsnfile.txt",ios::binary); //单词序列文件
SYM.open("symtablefile.txt",ios::binary);//符号表文件
cout<<"单词序列:\n" //输出单词序列
<<"名称\t\t\t 序号 类型 地址 \n";
while(!WORD.eof())
{WORD.read((char *)&words,sizeof(words));
if(!WORD.eof())
cout<<setiosflags(ios::left)<<setw(30)<<words.name<<setw(5)<<words.label
<<setw(5)<<words.addr<<setw(5)<<words.code<<endl;
}
cout<<"符号表:\n" //输出符号表
<<"符号名\t\t\t 序号 号类型\n";
while(!SYM.eof())
{SYM.read((char*)&symble,sizeof(symble));
if(!SYM.eof())
cout<<setiosflags(ios::left)<<setw(30)<<symble.name
<<setw(4)<<symble.serialno<<setw(4)<<symble.type
<<endl;
}
WORD.close();
SYM.close();
}
/**************填充数组*********************/
void fill(char *name,int n)
{for(int i=0;i<n;i++)
name[i]='\0';
}
/*************初始化读取保留字列表**************/
void initialize()
{keywordfile.open("keyword.txt");
if(keywordfile.fail())
{cout<<"关键字文件打开失败\n";
exit(1);
}
int n;
keywordfile.read((char *)&n,sizeof(n));
tatal=n;
keylist=new Keyword[n];
for(int i=0;i<n;i++)
{keywordfile.read((char *)&keylist[i],sizeof(keylist[i]));
}
}
/*****************错误处理*******************/
void Iserror(int code)
{error_count++;
switch(code)
{case 1:cout<<"非法字符,行号:"<<Line_count<<endl;
cout<<words.name <<endl;
break;
case 2:cout<<"实常数错误,行号:"<<Line_count<<endl;
cout<<words.name <<endl;
break;
case 3:cout<<"没有匹配的注释符:行号:"<<Line_count<<endl;
cout<<words.name <<endl;
break;
case 4:cout<<"字符串错误,或没有匹配的\""<<Line_count<<endl;
cout<<words.name<<endl;
break;
case 5:cout<<"字符错误,或没有匹配的\'"<<Line_count<<endl;
cout<<words.name<<endl;
break;
default:break;
}
return;
}
/*******************查找符号表*********************/
int searchword()
{sign *temp=head;
while(!temp==Null)
//如果符号存在符号表中,则返回1,否则返回0;
{if(strcmp(words.name,temp->s.name)==0)
{words.addr=temp->s.serialno;
return 1;}
else
temp=temp->next;
}
return 0;//如果符号不在符号表中,则返回0
}
/************写入符号表与文件****************/
void insertword()
{sign *temp=new sign;
temp->next=Null;
strcpy(temp->s.name,words.name);
temp->s.serialno=words.addr;
temp->s.type=words.code;
fill(symble.name,30);
strcpy(symble.name,words.name);
symble.serialno=words.addr;
symble.type=words.code;
//写入符号表文件中
symtablefile.write((char *)&symble,sizeof(symble));
if(head==Null)//插入符号表中
{head=temp;tail=temp;}
else
{tail->next=temp;
tail=tail->next;
}
}
/***************识别保留字与标识符******************/
void Isstring()
{
int i;int h=0;
i=0;
while(ch>=48&&ch<=57||ch>=65&&ch<=90||ch>=97&&ch<=122)
{words.name[i]=ch;
i++;
ifile.get(ch);
}//while 拼出单词
Keyword *temp=keylist;
for(i=0;i<tatal;i++) //判断是否为保留字;
{h=strcmp(words.name,temp->name);
if(h==0)//为保留字,h置0;
break;
else
temp++;
}
if(h==0) //为保留字
{words.code=temp->code;
words.label=label_count++;
words.addr=-1;
}//if
else//为标识符
{words.code=16;
words.label=label_count++;
h=searchword();//查找符号表
if(h==0) //如果不存在,则插入
{words.addr=addr_count++;
insertword();}
//else words.addr=addr_count++
}
//输出单词到单词序列文件中
wordsnfile.write((char*)&words,sizeof(words));
var_count++;
}
/********************识别数字***************/
void Isnumber()
{int i=0;int flag=0;
char cht;
words.name[i++]=ch;
for(;;)
{ifile.get(ch);
if(ch>=48&&ch<=57)
words.name[i++]=ch;
else
break;
}//for
if(ch=='.')
{cht=ch;
ifile.get(ch);
if(ch>=48&&ch<=57)
{words.name[i++]=cht;
words.name[i++]=ch;
flag=1;
for(;;)
{ifile.get(ch);
if(ch>=48&&ch<=57)
words.name[i++]=ch;
else
break;
}//for
}//if
else
{Iserror(2);
for(;;)
{ifile.get(ch);
if(ch!='.'&&(ch<=47||ch>=58&&ch<=64||ch>=123))
break;
}//for
}//else
}//if
if(ch>=65&&ch<=90||ch>=97&&ch<=122)
{Iserror(2);
for(;;)
{ifile.get(ch);
if(ch!='.'&&(ch<=47||ch>=58&&ch<=64||ch>=123))
break;
}//for
}//if
else
{if(flag==0)
words.code=17;
else
words.code=18;
}
words.label=label_count++;
words.addr=addr_count++;
insertword();
wordsnfile.write((char*)&words,sizeof(words));
var_count++;
}
/*************识别字符************************/
void Ischar()
{char cht;
ifile.get(ch);
cht=ch;
ifile.get(ch);
if(ch=='\'')
{words.name[0]=cht;
words.addr=addr_count++;
words.code=19;
words.label=label_count++;
insertword();
wordsnfile.write((char*)&words,sizeof(words));
ifile.get(ch);
var_count++;
}//if
else
{Iserror(5);
ifile.get(ch);
}
}//end
/******************识别字符串****************/
void Ischars()
{int i=0;
ifile.get(ch);
while(ch!='\"'&&!ifile.eof())
{words.name[i++]=ch;
ifile.get(ch);
}
if(ch=='\"')
{words.addr =addr_count++;
words.code =20;
words.label =label_count++;
insertword();
wordsnfile.write((char*)&words,sizeof(words));
var_count++;
ifile.get(ch);
}
else
Iserror(4);
}
/***************识别注释与除号*********************/
void Isexplain()
{ifile.get(ch);
if(ch=='*')//说明是注释
{ifile.get(ch);
for(;;)
{if(ifile.eof())//没有匹配的注释符
{Iserror(3);break;}
if(ch=='*')
{ifile.get(ch);
if(ch=='/')//注释的结尾
{ifile.get(ch);break;}
}//if
else
ifile.get(ch);
}//for
}//if
else if(ch=='/') //is explaination
{while(ch!='\n'&&!ifile.eof())
ifile.get(ch);
}
else //说明是除号
{words.name[0]='/';
words.code=34;
words.addr=-1;
words.label=label_count++;
wordsnfile.write((char*)&words,sizeof(words));
var_count++;
}
}
/****************识别其它符号********************/
void addword(char n,int addr,int code)
{words.name[0]=n;
words.addr=addr;
words.code=code;
words.label=label_count++;
wordsnfile.write((char*)&words,sizeof(words));
var_count++;
ifile.get(ch);
}
void Isother()
{char cht;
switch(ch)
{case ';':addword(';',-1,21);
break;
case '{':addword('{',-1,24);
break;
case '}':addword('}',-1,25);
break;
case '(':addword('(',-1,26);
break;
case ')':addword(')',-1,27);
break;
case ',':addword(',',-1,28);
break;
case '[':addword('[',-1,29);
break;
case ']':addword(']',-1,30);
break;
case '+':addword('+',-1,31);
break;
case '-':addword('-',-1,32);
break;
case '*':addword('*',-1,33);
break;
case '&':addword('&',-1,35);
break;
case '|':addword('|',-1,36);
break;
case '%':addword('%',-1,37);
break;
case ':':addword(':',-1,46);
break;
case '.':addword('.',-1,47);
break;
case ' ':ifile.get(ch);
break;
case '!':cht=ch;
words.name[0]=cht;
ifile.get(ch);
if(ch=='=')
{words.name[1]=ch;
words.addr=-1;
words.label=label_count++;
words.code=44;
wordsnfile.write((char*)&words,sizeof(words));
var_count++;
ifile.get(ch);
}
else
{words.addr=-1;
words.label=label_count++;
words.code=38;
wordsnfile.write((char*)&words,sizeof(words));
var_count++;
}
break;
case '>':cht=ch;
words.name[0]=cht;
ifile.get(ch);
if(ch=='=')
{words.name[1]=ch;
words.addr=-1;
words.label=label_count++;
words.code=42;
wordsnfile.write((char*)&words,sizeof(words));
var_count++;
ifile.get(ch);
}
else
{words.addr=-1;
words.label=label_count++;
words.code=39;
wordsnfile.write((char*)&words,sizeof(words));
var_count++;
}
break;
case '<':cht=ch;
words.name[0]=cht;
ifile.get(ch);
if(ch=='=')
{words.name[1]=ch;
words.addr=-1;
words.label=label_count++;
words.code=43;
wordsnfile.write((char*)&words,sizeof(words));
var_count++;
ifile.get(ch);
}
else
{words.addr=-1;
words.label=label_count++;
words.code=40;
wordsnfile.write((char*)&words,sizeof(words));
var_count++;
}
break;
case '=':cht=ch;
words.name[0]=cht;
ifile.get(ch);
if(ch=='=')
{words.name[1]=ch;
words.addr=-1;
words.label=label_count++;
words.code=45;
wordsnfile.write((char*)&words,sizeof(words));
ifile.get(ch);
var_count++;
}
else
{words.addr=-1;
words.label=label_count++;
words.code=41;
wordsnfile.write((char*)&words,sizeof(words));
var_count++;
}
break;
case '\n':Line_count++;
ifile.get(ch);
break;
default:Iserror(1);
ifile.get(ch);
break;
}//switch
}
/************************主程序**************/
void main()
{error_count=0;
label_count=0;
code_count=0;
addr_count=0;
var_count=0;
keylist=Null;
cout<<"词法分析程序\n";
cout<<"输入文件名:";
char filename[30];
cin>>filename;
initialize();
ifile.open(filename); //读取源文件
if(ifile.fail())
{cout<<"源文件不存在,请确认文件名正确\n";
exit(1);}
wordsnfile.open("wordsnfile.txt",ios::binary); //创建单词序列文件
symtablefile.open("symtablefile.txt",ios::binary);//创建单词表文件
ifile.get(ch); //读取一个字符
while(!ifile.eof())
{fill(words.name,30);
//cout<<var++;
if((ch>=65&&ch<=90)||(ch>=97&&ch<=122))//是字母
Isstring();
else if(ch>=48&&ch<=57) //数字
Isnumber();
else if(ch=='/') //注释
Isexplain();
else if(ch=='\'')
Ischar();
else if(ch=='\"')
Ischars();
else
Isother();
}//while
cout<<error_count<<" error"<<endl;
wordsnfile.close();
symtablefile.close();
ifile.close();
cout<<"分析完毕\n";
dis();
cout<<"\nsymbel tatal: "<<var_count;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -