判断程序中标识符的使用是否合法

判断程序中标识符的使用是否合法

从键盘输入一个程序,以‘#’结束,判断程序中的标识符使用是否合法(即判断标识符是否有重复定义或未声明就使用的情形)
判断程序中标识符的使用是否合法_第1张图片
附:C++字符串分词

思路

  采用vector动态数组来存储符号表是比较合适的,动态数组中可以根据需要增加数组长度,不论是哪种类型的标识符都可有存储下其需要的所有相应属性。
  先对输入的程序进行预处理,将程序中的标识符都以一个空格相隔,去除分界符、运算符等,将预处理完成的字符串进行分词处理,把字符串中每一个单词分开存储到一个动态数组中,在后续的符号表建立中能够更方便使用。通过map存储系统预定义的类型int,double等, 以便判断所声明的变量类型,然后逐步对标识符进行分类判断 ,在加入符号表前,要先去查找符号表,看当前定义的变量是否在符号表中出现(之前就定义过),如果能找到,说明变量重复定义,如果找不到,则说明是第一次定义,可加入符号表。遇到使用性变量的时候,检查符号表中是否有该变量的出现 ,如果没有,则说明变量未被定义就使用,进行报错处理。

测试数据

Input

#define maxn 1000
int a;
int b;
typedef int datatype;
typedef struct {
	char a[maxn];
	int k;
	datatype m;
} node;
int a;
c=a+b;
分词结果:
#define maxn 1000 int a int b typedef int datatype typedef struct { char a[maxn] int k datatype m } node int a c a b 

Output

a 重复定义!
c 未定义就使用!

代码

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int maxn=1e4+5;
int mfc;
int cv;
vector<string> v[maxn];
vector<string> dv;
map<string,int> mf;
int now;
void init()
{
	mf.clear();
	mf["int"]=1;
	mf["double"]=2;
	mf["float"]=3;
	mf["char"]=4;
}
string process(string s)//删除多余空格,空格连续处只留一个 
{
	string st;
	int cnt=0;
	for(int i=0;i<s.length();i++)
	{
		if(s[i]=='\n'||s[i]==';'||s[i]=='\t'||
		s[i]=='+'||s[i]=='='||s[i]=='*'||s[i]=='-'||s[i]=='/')
			s[i]=' ';
	}
	for(int i=0;i<s.length();i++)//处理多余空格
	{
		if(s[i]!=' ')
		cnt=0;
		if(s[i]==' ')
		cnt++;
		if(s[i]==' '&&cnt>1)
		continue;
		st+=s[i];
	}
	//cout<
	return st;
}
int vfind(string s)
{
	for(int i=0;i<cv;i++)
	{
		if(v[i][0]==s)
		return i;
	}
	return -1;
}
int main()
{
	init();
	freopen("out1.txt","w",stdout);
	fstream fs("in.txt");//创建一个文件流对象,并打开文件 
	string s="",st="";
	stringstream ss;//创建字符串流对象 
	ss<<fs.rdbuf();//把文件流中的字符串读到字符串流中 
	s=ss.str();
	st=process(s);
	cout<<st<<endl;

	stringstream sm;
	sm<<st;
	string tok;
	while(getline(sm,tok,' '))//进行分词
   	{
      dv.push_back(tok);
   	}

	//cout<
	//for(int i=0;i
	//cout<
	//cout<

	for(int i=0;i<dv.size();)
	{
		string str;
		if(dv[i]=="#define")
		{
			if(vfind(dv[i+1])!=-1)
			{
				printf("%s 重复定义!\n",dv[i+1].c_str());
				i+=3;
				continue;
			}
			v[cv].push_back(dv[i+1]);
			v[cv].push_back("#");
			v[cv].push_back("conskind");
			v[cv].push_back(dv[i+2]);
			cv++;
			i+=3;
		}else if(dv[i]=="typedef")
		{
			int k;
			if(dv[i+1]=="struct")
			{
				k=i+2;
				while(dv[k]!="}")
				{
					k++;
				}
				k=k+1;
				if(vfind(dv[k])!=-1)
				{
					printf("%s 重复定义!\n",dv[k].c_str());
					i+=k+1;
					continue;
				}
				v[cv].push_back(dv[k]);
				v[cv].push_back("#");//typeptr需要建立类型表后回填
				v[cv].push_back("typekind");
				cv++;
				i=k+1;
			}else
			{
				if(vfind(dv[i+2])!=-1)
				{
					printf("%s 重复定义!\n",dv[i+2].c_str());
					i+=3;
					continue;
				}
				v[cv].push_back(dv[i+2]);
				v[cv].push_back(dv[i+1]+"ptr");
				v[cv].push_back("varkind");//后续内容待添加
				i+=3;
				cv++;	
			}
		}else if(mf[dv[i]])
		{
			if(vfind(dv[i+1])!=-1)
			{
				printf("%s 重复定义!\n",dv[i+1].c_str());
				i+=2;
				continue;
			}
			v[cv].push_back(dv[i+1]);
			v[cv].push_back(dv[i]+"ptr");
			v[cv].push_back("varkind");//后续内容待添加
			i+=2;
			cv++;
		}else//使用性出现
		{
			if(vfind(dv[i])==-1)
				printf("%s 未定义就使用!\n",dv[i].c_str());	
			i++;
		}
		
	}
	return 0;
}

你可能感兴趣的:(编译原理)