⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scanner.cpp

📁 我做的一个C子集的词法分析器可以分析C语言的一个子集,包括17个关键字以及绝大部分的符号.能正确的报错
💻 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 + -