小言_互联网的博客

【编译原理与技术】词法分析器(C++实现)

397人阅读  评论(0)

注:

为了简化程序的编写,做了如下的限制:
(1) 空白符仅仅是空格、回车符、制表符。
(2) 代码是自由格式。
(3) 注释不允许嵌套。

单词:

根据要求,可以自行添加其他保留字或者特殊符号

实现功能:

  1. 识别单词并给出其类型
  2. 删除注释行
  3. 删除空白符 (空格、回车符、制表符)
  4. 在单词的前面加上行号
  5. 发现并定位错误。

C++代码:

#include <string.h>  
#include <string>  
#include<iostream>	
using namespace std;
 char prog[1000],ch,ch1,token[1000];
 int p=0,sym=0,n,line=1;
 char filename[30];
 FILE *fpin;
 const char *keyword[21]={"if","else","while","do","main","int","float",
 						"double","return","const","void","continue","break","char",
						 "signed","enum","long","switch","case","auto","unsigned"};
 void GetToken();
 int main() 
 {
 	p=0;
 	cout<<"请输入源文件名:";
 	for(;;)
 	{
 		cin>>filename;
 		if((fpin=fopen(filename,"r"))!=NULL)//只读 
		{
			break;
		}
		else
		{
			cout<<"文件输入错误!请输入源文件名:";
		}	
	}
	//将fpin中的所有字符通过ch传入字符数组prog[]中 
	do
	{
		ch=fgetc(fpin);
	 	prog[p++]=ch;
	}while(ch!=EOF); 
	p=0;
	do
	{
		GetToken();//启动字符识别函数 
		switch(sym)//打印字符状态 
		{
			case 1:cout<<"("<<line<<" "<<token<<" "<<"标识符"<<")"<<endl;break;
			case 2:cout<<"("<<line<<" "<<token<<" "<<"保留字"<<")"<<endl;break;
			case 3:cout<<"("<<line<<" "<<token<<" "<<"整型"<<")"<<endl;break;
			case 31:cout<<"("<<line<<" "<<token<<" "<<"浮点型"<<")"<<endl;break;
			case 32:cout<<"("<<line<<" "<<token<<"S"<<" "<<"短类型"<<")"<<endl;break;
			case 33:cout<<"("<<line<<" "<<token<<"L"<<" "<<"长类型"<<")"<<endl;break;
			case 34:cout<<"("<<line<<" "<<token<<"O"<<" "<<"八进制数"<<")"<<endl;break;
			case 35:cout<<"("<<line<<" "<<token<<"H"<<" "<<"十六进制数"<<")"<<endl;break;
			case 4:cout<<"("<<line<<" "<<token<<" "<<"特殊符号"<<")"<<endl;break;
			case -1:cout<<"("<<line<<" "<<"错误!"<<")"<<endl;break;
			default:break;
		}
	 } while(ch!=EOF);
	 return 0;
 }
 
 void GetToken() 
 {
 	sym=0;
	 //先把token[]数组清空 
 	for (n=0;n<1000;n++)
 	{
 		token[n]='\0';
	}
	n=0;
	ch=prog[p++];
	ch1=prog[p];
	//跳过空格,tab的识别 
	while(ch==' '||ch=='\t')
	{
		ch=prog[p++];
	}
	if(ch=='\n'){
		line++;
		return;
	}
	if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch=='_')) 
	{
		//标识符 状态1
		sym=1;
		do{
			token[n++]=ch;
			ch=prog[p++];
		}while ((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9'));
		//比较标识符与keyword的关键字是否相同,若相同转为状态2
		for(n=0;n<21;n++)
		{
			if(strcmp(token,keyword[n])==0){
				sym=2;
				break;	
			}
		}
		p--;
		return;
	}
	
	else if (ch>='0'&&ch<='9') 
	{	
		//识别到数字,置状态为3
		sym=3;
		do
		{	
			token[n++]=ch;
			ch=prog[p++];
			if(ch=='.'){
				sym=31;
				token[n++]=ch;
				ch=prog[p++];
			}
			if(ch=='S'){
				sym=32;
				ch=prog[p++];
			} 
			if(ch=='L'){
				sym=33;
				ch=prog[p++];
			}
			if(ch=='O'){
				sym=34;
				ch=prog[p++];
			}	
			if(ch=='H'){
				sym=35;
				ch=prog[p++];
			}		
		}while(ch>='0'&&ch<='9'); 
		p--;
		return;
	}
	//跳过注释的内容 
	else if(ch=='/' && ch1=='*')
	{	
		p++;
		do{
			ch=prog[p++];
			ch1=prog[p];
			if(ch=='\n'){
				line++;
			}
		}while(ch!='*'||ch1!='/');
		return;
	}
	else if(ch=='/'&& ch1=='/')
	{
		p++;
		do{
			ch=prog[p++];
		}while(ch!='\n');
		line++;
		return;
	}
	else if(ch=='='&& ch1=='='){
		p++;
		sym=4;
		token[0]='=';
		token[1]='=';
		return;
	}
	else if(ch=='<'&& ch1=='='){
		p++;
		sym=4;
		token[0]='<';
		token[1]='=';
		return;
	}
	else if(ch=='>'&& ch1=='='){
		p++;
		sym=4;
		token[0]='>';
		token[1]='=';
		return;
	}
	else if(ch=='!'&& ch1=='='){
		p++;
		sym=4;
		token[0]='!';
		token[1]='=';
		return;
	}		
	else if(ch=='&'&& ch1=='&'){
		p++;
		sym=4;
		token[0]='&';
		token[1]='&';
		return;
	}	
	else if(ch=='|'&& ch1=='|'){
		p++;
		sym=4;
		token[0]='|';
		token[1]='|';
		return;
	}
	else 
	{
		switch(ch)//识别关键符号 
		{	
			case '=':
			case '<':
			case '>':
			case '/':
			case '+':
			case '-':
			case '*':
			case '{':
			case '}':
			case ';':
			case '(':
			case ')':
			case ',':
			case '\'':
			case '\"':sym=4;token[0]=ch;break;
			default:sym=-1;break;
		}
	}
	return;
 }

运行结果:


转载:https://blog.csdn.net/qq_43207916/article/details/102486491
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场