词法分析器 c语言

本文介绍了一种使用C++实现的源代码解析方法,通过识别变量、关键字、常量等元素,将源代码分解成一系列有意义的符号。该方法能够处理包括变量声明、字符串、字符型常量及各种界符等在内的多种语法结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设计思路:对于所有的以字母,或者下划线的字符串提取出来,然后在从这些字符串中识别出一进在关键字中的字符串。对于所有的数字组成的字符串我们都提取出来,便是整型变量,对于所有的以“开头的,我们要一直读取,知道读取到”结尾。这便是字符串,对于所有的字符型,我们有‘\n’,或者‘a’这两种情况,我们需要分类读取变可以了。剩下的便是界符,运算符,我们分别讨论就可以了。
先贴出一些部分代码:头文件 main.cpp
 #include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iomanip>
#define p_error 0
using namespace std;
struct node
{
	string str;
	int id;
	node(string s,int pid)
	{
		str = s;
		id = pid;
	};
	node()
	{
	};
};
int input()
{
	freopen("pre.txt","r",stdin);
	string str;
	int i;
	for( i = 0 ; i < 30 ; i++)
	{
		cin>>str;
		node mynode(str,i);
		arr.push_back( mynode);
		cout<<arr[i].str<<" "<<arr[i].id<<endl;
	}
	defiid = i;
	fclose(stdin);
	return 0;
}
//提取各个编码
int process()
{
	FILE * fp;
	if((fp = fopen("in.txt","rb"))== NULL)
	{
		return p_error;
	}
	char c ;//= fgetc(fp); //读取一个字符
	string str ="";
	while(myread(fp,c))
	{
		while( (c == '\n' || c == '\r' || c == '\t'|| c == 32) && myread(fp,c)) ;
		//判断是否为变量或者为关键字
		str = "";
		//识别出所有以字母或者下划线组成的变量,在从这些变量中识别出是否为关键字
		if( c!= EOF && ( c == '_' || isalpha(c)))
		{
			str = c;
			while( myread(fp,c) && (isalpha(c) || c == '_')) 
			{
				str += c;
			}
			fseek(fp,(sizeof(char) * -1),SEEK_CUR);
		//	if(str != "")
			//			cout<<str<<endl;
			insrtIntoAns(str);//判断插入哪一个表中标示符表还是关键字表
			str = "";
			continue;
		}

		
		//提取数字,所有的以数字组成的字符串
		if(  c!= EOF && isdigit(c))
		{
			str = c;
			while(c = fgetc(fp),c != EOF && isdigit(c))
			{
				str += c;
			}
			fseek(fp,(sizeof(char) * -1),SEEK_CUR);
				if(str != "")
						cout<<str<<endl;
			insertIntoVector(str,symbol,symid);
			str = "";
			continue;
		}

	    //提取字符串,以“开头的,以”结尾的 如果找不到以“结尾的,便是出错
		if( c!= EOF && (int)c == 34)
		{
			//cout<<(int)c<<endl;
			str += c;
			while(c = fgetc(fp) ,(int)c != 34 )
			{
				if(c == EOF) break;
				//cout<<str<<endl;
				str += c;
			}
			str+="\"";
			if(c == EOF)
			{
				cout<<"字符串错误\n";
				return p_error;
			}
			if(str != "")
						cout<<str<<endl;
			insertIntoVector(str,symbol,symid);
			str = "";
			continue;
		}
	
		//提取字符,两种情况‘a’,'\n',分类提取出这两种情况
		if( c!= EOF && c == '\'')
		{
			cout<<"hello"<<endl;
			str += c;
			//两种情况‘a’,'\n'
			if( myread(fp,c))
			{
				str += c;
				if( c== '/' && myread(fp,c))
					str+=c;
			}
		
			if(!myread(fp,c) || c !='\'' ) {cout<<"字符读入错误"<<endl;	return p_error;}
			str+= c;
			if(str != "")
						cout<<str<<endl;
			insertIntoVector(str,symbol,symid);
			str = "";
			continue;
		}
		
		//提取界符
		cout<<"界符"<<c<<endl;
		str ="";
		switch(c)
		{
			case '(' :
			case ')' :
			case '{' :
			case '}' :
			case ',' :
			case ';' :
			case '+' : 
			case '-' :
			case '*' :
			case '/' : str = c;insertIntoVector(str,defi,defiid);break;
			case '<' :
			case '=' :
			case '>' :
				str += c;
				if( myread(fp,c ) && c == '=') 
				{ 
					str += c;
					insertIntoVector(str,defi,defiid);break;
				}
				else
				{
					fseek(fp,(sizeof(char) * -1),SEEK_CUR);
					insertIntoVector(str,defi,defiid);break;
				}
				break;
			default:
				cout<<"不能识别的字符"<<(int)c<<endl;

		}
		str = "";
	
	}
	fclose(fp);
	return 1;
}


输入:
int main()
{
     FILE * fp;
     char ch = 'a';
     ch ='/n';
     string p = "hello wor\'ld";
     if ((fp = fopen("in.txt","rb")) == NULL)
     {
         return 0;
     }
    char c = fgetc(fp);
    cout<<"now is"<<c <<endl;
    return 0;
}

输出
---------------------------------变量表----------------------------------------
main                1
FILE                2
fp                  3
ch                  4
string              5
p                   6
fopen               7
NULL                8
return              9
c                   10
fgetc               11
cout                12
endl                13
---------------------------------关键字表----------------------------------------
int                 31
(                   32
)                   33
{                   34
*                   35
;                   36
char                37
=                   38
if                  39
,                   40
==                  41
}                   42
<                   43
---------------------------------常量表----------------------------------------
'a'                 1
'/n'                2
"hello wor\'ld"     3
"in.txt"            4
"rb"                5
0                   6
"now is"            7

#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iomanip>
#define p_error 0
using namespace std;
struct node
{
	string str;
	int id;
	node(string s,int pid)
	{
		str = s;
		id = pid;
	};
	node()
	{
	};
};
//  基本字、运算符、界符:一符一种; defi
// 标识符:统一为一种;ans
//常量:按类型编码; symbol
vector<node> arr,defi,ans,symbol;
//各个表的标号
int ansid = 0 ;
int symid = 0 ;
int defiid = 0;

#include "main.h"
int input()
{
	freopen("pre.txt","r",stdin);
	string str;
	int i;
	for( i = 0 ; i < 30 ; i++)
	{
		cin>>str;
		node mynode(str,i);
		arr.push_back( mynode);
		cout<<arr[i].str<<" "<<arr[i].id<<endl;
	}
	defiid = i;
	fclose(stdin);
	return 0;
}
int isInVector(string str,vector<node> &p)//如果str 存在关键字表中就返回他的关键字的标识id
{
	if(p.size() > 0)
	for(vector<node>::iterator it = p.begin();it != p.end();it++)
	{
		if(it->str == str) return	it->id;
	}
	return -1;
}
//向表内插入str串,编号为id
void insertIntoVector(string str,vector<node> &p,int &id)
{
	if(str != "")
	{
		if(isInVector(str,p) == -1)
		{
			p.push_back(node(str,++id));
		}
	}
}
//判断在关键字表中时候出现过 出现过插入到关键字表中,否则插入到标示符表中
void insrtIntoAns(string str)
{
	int id;
	node mynode;
	if(str != "")
	{
		if(  isInVector(str ,arr) != -1)
		{
			insertIntoVector(str,defi,defiid);
			//cout<<"insert into ans标示符"<<endl;
		}
		else
		{
			
			insertIntoVector(str,ans,ansid);
		//cout<<"insert into 关键字表"<<endl;
		}
	}
}
//从文件中读入一个字符复制给c
bool myread(FILE *fp,char &c)
{
	c = fgetc(fp);
	if(c != EOF) return true;
	return false;
}
//提取各个编码
int process()
{
	FILE * fp;
	if((fp = fopen("in.txt","rb"))== NULL)
	{
		return p_error;
	}
	char c ;//= fgetc(fp); //读取一个字符
	string str ="";
	while(myread(fp,c))
	{
		while( (c == '\n' || c == '\r' || c == '\t'|| c == 32) && myread(fp,c)) ;
		//判断是否为变量或者为关键字
		str = "";
		//识别出所有以字母或者下划线组成的变量,在从这些变量中识别出是否为关键字
		if( c!= EOF && ( c == '_' || isalpha(c)))
		{
			str = c;
			while( myread(fp,c) && (isalpha(c) || c == '_')) 
			{
				str += c;
			}
			fseek(fp,(sizeof(char) * -1),SEEK_CUR);
		//	if(str != "")
			//			cout<<str<<endl;
			insrtIntoAns(str);//判断插入哪一个表中标示符表还是关键字表
			str = "";
			continue;
		}

		
		//提取数字,所有的以数字组成的字符串
		if(  c!= EOF && isdigit(c))
		{
			str = c;
			while(c = fgetc(fp),c != EOF && isdigit(c))
			{
				str += c;
			}
			fseek(fp,(sizeof(char) * -1),SEEK_CUR);
				if(str != "")
						cout<<str<<endl;
			insertIntoVector(str,symbol,symid);
			str = "";
			continue;
		}

	    //提取字符串,以“开头的,以”结尾的 如果找不到以“结尾的,便是出错
		if( c!= EOF && (int)c == 34)
		{
			//cout<<(int)c<<endl;
			str += c;
			while(c = fgetc(fp) ,(int)c != 34 )
			{
				if(c == EOF) break;
				//cout<<str<<endl;
				str += c;
			}
			str+="\"";
			if(c == EOF)
			{
				cout<<"字符串错误\n";
				return p_error;
			}
			if(str != "")
						cout<<str<<endl;
			insertIntoVector(str,symbol,symid);
			str = "";
			continue;
		}
	
		//提取字符,两种情况‘a’,'\n',分类提取出这两种情况
		if( c!= EOF && c == '\'')
		{
			cout<<"hello"<<endl;
			str += c;
			//两种情况‘a’,'\n'
			if( myread(fp,c))
			{
				str += c;
				if( c== '/' && myread(fp,c))
					str+=c;
			}
		
			if(!myread(fp,c) || c !='\'' ) {cout<<"字符读入错误"<<endl;	return p_error;}
			str+= c;
			if(str != "")
						cout<<str<<endl;
			insertIntoVector(str,symbol,symid);
			str = "";
			continue;
		}
		
		//提取界符
		cout<<"界符"<<c<<endl;
		str ="";
		switch(c)
		{
			case '(' :
			case ')' :
			case '{' :
			case '}' :
			case ',' :
			case ';' :
			case '+' : 
			case '-' :
			case '*' :
			case '/' : str = c;insertIntoVector(str,defi,defiid);break;
			case '<' :
			case '=' :
			case '>' :
				str += c;
				if( myread(fp,c ) && c == '=') 
				{ 
					str += c;
					insertIntoVector(str,defi,defiid);break;
				}
				else
				{
					fseek(fp,(sizeof(char) * -1),SEEK_CUR);
					insertIntoVector(str,defi,defiid);break;
				}
				break;
			default:
				cout<<"不能识别的字符"<<(int)c<<endl;

		}
		str = "";
	
	}
	fclose(fp);
	return 1;
}
void output(vector<node> &ans)
{

	//cout<<"---------------------------------------------------------------------------"<<endl;
	vector<node>::iterator it;
	for(it = ans.begin();it != ans.end();it++)
	{
		
		cout<<setw(20)<<setiosflags(ios::left)<<it->str<< it->id<<endl;
	}
}
int main()
{
	freopen("out.txt","w",stdout);
	input();
	process();
	cout<<"---------------------------------变量表----------------------------------------"<<endl;
	output(ans);
	cout<<"---------------------------------关键字表----------------------------------------"<<endl;
	output(defi);
	cout<<"---------------------------------常量表----------------------------------------"<<endl;
	output(symbol);
	fclose(stdout);
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值