LL(1)文法分析器(来自一个十八线菜鸟写的**代码)

目录

 

开篇废话

运行环境说明

重要说明

测试文件说明 

程序设计思路

重要数据结构

实验代码

运行结果


开篇废话

假如你来到了这........因为代码管理的很乱, 可能你们看都不会看, 不看没关系, 如果你急需的话, 这份代码可以让你复制黏贴起来应付老师..........大家都懂的....^_^

 

这是我自己做的一个很水很水的一个LL(1)文法分析器,代码鲁棒性不强, 比如对文件中存放的产生式的右部的输入有要求, 详情看如下的测试文件说明。 需要的话可以自己看看。 思路书本都有, 先求first集,后求follow集合, 然后再自动生成分析表等等....

假如我的程序在你的机器跑的结果不对, 或者跑到程序中途崩溃了, 那是我的代码对输入数据格式有要求,请原谅我,  没错, 就是我太菜了, 没有加防止胡乱输入的限制。 在心里骂几句 “我***,什么**程序也发出来” ,然后消消气, 请看回  “重要说明” 和 "测试文件说明" 那里, 当然还有运行环境那里, 确认自己的数据文件格式是不是和我的一样。  ^_^

 

 

运行环境说明

win10,  编译器vs2010 

 

重要说明

LL(1)分析器的使用的前提是消除了左递归和最左公因子, 此程序不完善, 没有加入消除左递归和最左公因子的功能, 因此输入的测试文法必须自己消除了左递归和最左公因子!可以按照我下面的expression.txt那个文件的格式来测试。 

 

测试文件说明 

  • expression.txt 存放产生式。产生式左部,中部, 右部之间用空格或者TAB分隔开。
  • 注意产生式右部的各个侯选式要紧挨在一起, 比如
  • F -> (E)|i    的右部 (E)|i    就不要写成 (E)  |   i  
  • 也就是产生式右部的各个侯选式不要加空格。 。。我这样是为了方便程序处理拆开以 |  分隔的各个侯选式。   同时产生式的空串用@ 表示。 
  • 如下的expression.txt是一个实现乘法和加法的文法。 
  • 还有千万不要在文件末尾加多余的空格和空行!比如如下图只要让你的鼠标光标最后只能在我图中的那个 i  后面。 
  • 还有就是每行的结尾不要加多余的空格了!

 

  •  final.txt是用来存储产生式终结符号。 以end表示文件结束。 比如上面expression.txt 里面的产生式的终结符如下图片。 

 

  • notFinal.txt 是用来存放产生式的非终结符。 同样以end结尾。  比如上面expression.txt 里面的产生式的终结符如下图片

 

程序设计思路

first集合设计思路

  1. 对产生式X->a....。 且a属于终结符, 那么就直接把a加入FIRST[X]
  2. 对产生式X->ε, 把ε加入FIRST[X]
  3. 对产生式X->Y..... 且Y是非终结符。 那么就把FIRST(Y)去除ε的结果加入FIRST[X]中。 如果发现X->Y1Y2Y3.....Yi-1  Y1,...Yi-1都是非终结符, 并且Y1...Yi-1的first集合都有ε,那么就把Y1...Yi 的去掉 ε的first集合加入FIRST[X]. 如果Y1....Yn的first集都有ε,那么就把ε加入到FIRST[X].

follow集合设计思路

把 # 直接置于文法开始符(比如E)的FOLLOW集合中

对每个非终结符,比如Z, 找到它在产生式的位置, 看他后面有没有什么符号:

(1) 如果其后面是终结符, 那么就直接把这个终结符加入到该非终结符号Z的FOLLOW集合中。 比如E->FE)  那么把 ) 加入E的follow集合中。

(2)如果后面什么都没有, 比如F->KE ,E的后面什么都没有, 那么就把该非终结符 所在的产生式的左部的那个符号的FOLLOW集合加入到该非终结符号的FOLLOW中。 比如F->KE中的求E的FOLLOW集合就要把FOLLOW(F)加入到FOLLOW(E)

(3)如果后面有一个非终结符。 那么就把该非终结符的FIRST集合去掉ε然后再加入Z的FOLLOW集合中, 比如F->KH。求K的FOLLOW集合要把FIRST(H)\{ε}再加入FOLLOW(K)。

特别地,假如上面的产生式中H可以推出ε,也就是first(H)包含ε,那么就要把产生式左部的FOLLOW集加入,  如上的产生式,要把FOLLOW(F)加入到FOLLOW(K)中。

 

 

预测分析表自动生成思路

遍历每个非终结符的first集合里的的每个元素 ,比如对非终结符A的first集合,  如果 a是属于first(A):

【1】如果 a不是空字@, 并且产生A右部只有唯一的候选式,比如A->α, 那么分析表mp[A][a]就填入α

如果A->α|β|θ......也就是A右边有多个候选式, 那么就逐个扫描右边候选式,看哪个候选式能够推出a,在分析 表mp[A][a]填入能推出a的候选式。 比如 β-->a..... , 那么就mp[A][a]=β

【2】如果first[A]有a,且a是空字@, 那么遍历follow[A]的每个元素(记为fol),在mp[A][fol]填入空字@

 

 

控制程序设计思路: 如下图

 

 

 

 

重要数据结构


#define path "expression.txt" //产生式路径
map<string, set<string>>first;///first集
map<string, set<string>>follow; ///follow集

map<string, map<string, string>>mp;//预测分析表
string final[101];//终结符集
string  notFinal[101];//非终结符集
int pf = 0; //终结符数量
int pnf = 0; //非终结符数量


stack<string>st; //分析栈
string inputString; //输入串

struct production{///产生式结构, 左中右三部分
	string left;
	string middle; 
	string right; 
	//production():left("null"),middle("null"), right("null"){};
	vector<string>rightString; /*存放产生式各个右部 比如E->T|F。 
							   rightString 就放T, F。  */
};

vector<production*>vt; //存产生式

实验代码

#include<iostream>
#include<vector>
#include<fstream>
#include<string>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<iomanip>
using namespace std;

#define path "expression.txt" //产生式路径
map<string, set<string>>first;///first集
map<string, set<string>>follow; ///follow集

map<string, map<string, string>>mp;//预测分析表
string final[101];//终结符集
string  notFinal[101];//非终结符集
int pf = 0; //终结符数量
int pnf = 0; //非终结符数量


stack<string>st; //分析栈
string inputString; //输入串

struct production{///产生式结构, 左中右三部分
	string left;
	string middle; 
	string right; 
	//production():left("null"),middle("null"), right("null"){};
	vector<string>rightString; /*存放产生式各个右部 比如E->T|F。 
							   rightString 就放T, F。  */
};

vector<production*>vt; //存产生式

void readFile(){/*从文件读入产生式*/
	ifstream infile;
	infile.open(path, ios::in);
	if(!infile){
		cout<<"error in opening expression.txt"<<endl; 
		system("pause");
		exit(-1);
	}
	
	while(!infile.eof()){/*读到产生式的左部, 中部, 右部*/
		
		production * tmp = new production(); 
		string s1, s2, s3; 
		infile>>s1>>s2>>s3; 
		tmp->left = s1;
		tmp->middle = s2;
		tmp->right = s3;
		//cout<<"middle: "<<s2<<endl; 
		vt.push_back(tmp);
	}

	cout<<"从文件读入的产生式是:"<<endl; 
	int size = vt.size();
	for(int i = 0; i < size; i++){
		cout<<vt[i]->left<<"\t"<<vt[i]->middle<<"\t"<<vt[i]->right<<endl;
		//cout<<vt[i]->left<<vt[i]->middle<<vt[i]->right<<endl; 
	}
}


vector<string> split(const string &st){/*以 | 为分隔符截取字符串*/
	vector<string>res; 
	string tmp="";
	int length = st.size();
	int i = 0; 
	string token = "|";
	while(i < length){
		while(i < length && st[i] != token[0]){
			tmp += st[i];
			i++;
		}
		res.push_back(tmp);
		//cout<<"tmp "<<tmp<<endl; 
		tmp = "";
		i++;

	}
	return res; 
}

void callSplit(){
	int size = vt.size();
	for(int i = 0; i < size; i++){//对每条产生式
		vt[i]->rightString = split(vt[i]->right);//以 | 为分隔符截取产生式右部
	}
	//cout<<"check 分隔后的串"<<endl; 
	//for(int i = 0; i < size; i++){
	//	int lg = vt[i]->rightString.size();
	//	//cout<<vt[i]->left<<"这个产生式右部分解结果和每隔串的长度 ";
	//	for(int j = 0; j < lg; j++){
	//		cout<<vt[i]->rightString[j]<<":"<<vt[i]->rightString[j].length()<<" ";
	//	}
	//	cout<<endl; 
	//}
}


bool isBelongFinal(const char  & x){//判断是否属于终结符号
	string tmp = "";
	tmp += x; 
	if(tmp == "@") //返回true把 @ 也当作终结符一遍直接加入first集合
	{
		return true; 
	}
	 
	for(int i = 0; i < pf; i++){
		if(final[i] == tmp)
			return true; 
	}
	return false; 
}


void solveFirst(string s){/*求s的first集,即是first[s]*/
	int size = vt.size();
	for(int i = 0; i < size; i++){
		if(s == vt[i]->left){//找到s所在的产生式
			int lg = vt[i]->rightString.size();//s产生式右部的侯选式个数
			for(int j = 0 ; j < lg; j++){//对每条产生式右边的的候选式子
				//cout<<"first!! "<<"i: "<<i<<" j: "<<j<<" 第一个字符 "<< vt[i]->rightString[j][0]<<endl; 
				if(isBelongFinal(vt[i]->rightString[j][0])){//终结符加入first
					string tmp = "";
					tmp += vt[i]->rightString[j][0];
					//cout<<"s: "<<s<<" tmp: "<<tmp<<endl; 
					//first[vt[i]->left].insert(vt[i]->rightString[j][0]);
					first[s].insert(tmp);
				}
				else{
						int numCh = vt[i]->rightString[j].size();//侯选式的长度
						int flag = 1; /*要把候选式多少个连续的符号的去除空字后的first集加入到
									  first[s]. 
									  比如E->TE'。 flag若为为2表示把first[T]/@,first[E']/@
									  加入first[s]
									  */
						for(int k = 0; k < numCh; k++){
							if(isBelongFinal(vt[i]->rightString[j][k])){//终结符直接加入first
								string tmp = "";
								tmp += vt[i]->rightString[j][k];
								first[vt[i]->left].insert(tmp);
								break;
							}
							//非终结符
							string tmp = "";
							tmp += vt[i]->rightString[j][k];
							solveFirst(tmp);//非终结符递归求其first集
							
							if(first[tmp].find("@") != first[tmp].end()){//first[tmp]有空字
								flag++; 
								continue; 
							}
							else
								break; 
						}
						//cout<<"flag: "<<flag<<endl; 
						for(int h = 0; h < flag && h < numCh; h++){
							/*char 转换为 string*/
							string tmp = "";
							tmp += vt[i]->rightString[j][h];
					
							set<string>::iterator it; 

							set<string>nw; 
							nw.insert(first[tmp].begin(), first[tmp].end());
							/*去除空字*/
							it = nw.find("@");
							if(it != nw.end()){
								nw.erase(it);
							}
							/*去除空字后的结果加入first[s]*/
							first[s].insert(nw.begin(), nw.end());

						}
						if(flag == numCh +1)//侯选式里的每个符号的first集都有空字
							first[s].insert("@");

				}
				

			}
		}
	}
}


void callFirst(){
	callSplit();
	for(int i = 0; i < pnf; i++)//求每个非终结符的first集
		solveFirst(notFinal[i]);

	cout<<"-----------------检查各个非终结符的first集-------------"<<endl; 
	for(int i =0; i < pnf; i++){
		//cout<<"in..."<<endl; 
		set<string>::iterator st;
		cout<<"first["<<notFinal[i]<<"]"<<"	";
		for(st = first[notFinal[i]].begin(); st != first[notFinal[i]].end(); st++){
			cout<<*st<<" ";
		}
		cout<<endl; 
	}
}

int getIndex(const string & orgin, const string & target){//返回target匹配orgin的最后一个位置
	int olength = orgin.length();
	int tlength = target.length();
	if(tlength == 1){//比如E 后面没有单引号'
		for(int i = 0; i <olength; i++){
			if(orgin[i] == target[0]){
				if(i + 1 < olength && orgin[i+1] != '\'')
					return i; 
			}
		}
	}
	else{//有单引号比如E'
		for(int i = 0; i < olength; i++){
			if(orgin[i] == target[0]){
				if(i + 1 < olength && orgin[i + 1] == '\'')
					return i + 1; 
			}
		}
	}

	return -1; 
}

set<string> clearNull(set<string>arg){///返回集合arg去掉空字
	set<string>::iterator it; 
	it = arg.find("@");
	if(it != arg.end()){
		arg.erase(it);
	}
	return arg; 
	
}

void musterInsert(set<string>&a, set<string>b){//集合b的first去掉空字后的结果加入集合a
	set<string>::iterator it; 
	it = b.find("@");
	if(it != b.end()){//集合b去掉空字
		b.erase(it);
	}
	a.insert(b.begin(), b.end());
	
}

bool hasNull(const set<string> & st){/*集合st是否有空字*/
	set<string>::iterator it; 
	it = st.find("@");
	if(it != st.end()){
		return true; //有空字
	}
	return false; 
}

set<string> solveFollow(string arg){//求argfollow集
	
	int sz = vt.size(); 
	for(int i = 0; i < sz; i++){
		//cout<<"当前要求follw["<<arg<<"]"<<endl; 
		int lg = vt[i]->rightString.size();
		for(int j = 0; j < lg; j++){//对vt[i]这个产生式右部的每个候选式
			int numCh = vt[i]->rightString[j].size();//该侯选长度
			int index = getIndex(vt[i]->rightString[j], arg);//匹配位置
	
			if(index == -1 )//该候选式没有arg
				continue; 
			if(index >= 0 && index < numCh - 1){//求arg后面的那个符号去除空字后的结果
				string tmp = ""; 
				tmp += vt[i]->rightString[j][index+1];
				if(index + 2 < numCh && vt[i]->rightString[j][index + 2] == '\'')
				{
						tmp += '\'';//比如E' 后面的‘ 不能漏掉
						//i++;
				}
				//cout<<"tmp: "<<tmp<<endl; 
				set<string>tmpSet;
				
				if(isBelongFinal(tmp[0]))//arg后面是终结符,直接加入tmpSet集合
					tmpSet.insert(tmp);
				else 
					tmpSet = clearNull(first[tmp]);//first[tmp]集合去掉空字
				musterInsert(follow[arg], tmpSet);//去掉空字后的结果加入follow[arg]集合
				if(hasNull(first[tmp])){//tmp可以推出空字@
					set<string>left;
					if(vt[i]->left != notFinal[0] && follow[vt[i]->left].size())
						left = follow[vt[i]->left];//产生式左部的follow集已求
					else{
						if(vt[i]->left != arg)//将产生式左部的follow集加入left
							left = solveFollow(vt[i]->left);
					}
					musterInsert(follow[arg], left);//把left去掉空字加入到follow[arg]
				}
				//break;

			}
			if(index == numCh - 1){//比如K->FE 来求follow(E)E后面没有东西
				//那么将产生式左部follow集合加入follow[arg]
				set<string>left;
				if(vt[i]->left != notFinal[0] && follow[vt[i]->left].size())
					left = follow[vt[i]->left];//产生式左部follow集已求
				else
					left = solveFollow(vt[i]->left);
				//set<string>left = solveFollow(vt[i]->left);
				musterInsert(follow[arg], left);//把follow[left]加入follow[arg]
			}
			/*cout<<"当前follow["<<arg<<"]"<<endl; 

			for(set<string>::iterator it = follow[arg].begin(); it != follow[arg].end(); it++){
				cout<<*it<<" ";
			}
			cout<<endl; 
			cout<<"finsih output follow["<<arg<<"]====="<<endl; */
			//break;
		}
	}

	return follow[arg];
}

void startCalFollow(){/*开始求follow集*/
	follow[notFinal[0]].insert("#");

	for(int i = 0; i < pnf; i++){
		if(i !=0 && follow[notFinal[i]].size()>0)//该符号的follow集已求
			continue; 
		solveFollow(notFinal[i]);
	}

	cout<<"-----------检查各个元素的follow集合----------------"<<endl; 

	for(int i = 0; i < pnf; i++){
		cout<<"follow["<<notFinal[i]<<"]:"<<" "; 
		set<string>::iterator it; 
		for(it = follow[notFinal[i]].begin(); it != follow[notFinal[i]].end();it++){
			cout<<*it<<" ";
		}
		cout<<endl; 
		//cout<<"finish this "<<notFinal[i]<<" 的follow"<<endl;  
	}
	return ; 
	//solveFollow();
}


void in(){/*读入终结符合非终结符*/
	
	ifstream infile;
	infile.open("final.txt", ios::in);
	if(!infile){
		cout<<"error in opening final.txt"<<endl;
		system("pause");
		exit(-1);
	}
	
	string tmp; 
	while(!infile.eof()){
		infile>>tmp;
		if(tmp == "end")
			break; 
		final[pf++] = tmp; 
	}
	infile.close();//关闭
	//------读入非终结符
	infile.open("notFinal.txt", ios::in);
	if(!infile){
		cout<<"error in opening notFinal.txt"<<endl;
		system("pause");
		exit(-1);
	}
	while(!infile.eof()){
		infile>>tmp;
		if(tmp == "end")
			break; 
		notFinal[pnf++] = tmp; 
	}
	infile.close();

	for(int i = 0; i < pnf; i++){//分析表全部初始化为error
		for(int j = 0; j < pf; j++){
			mp[notFinal[i]][final[j]] = "error";
		}
	}

	cout<<"----------检查终结符号------------"<<endl;
	for(int i = 0; i < pf; i++)
		cout<<final[i]<<"	";
	cout<<endl;

	cout<<"-----------检查非终结符号-------------"<<endl; 
	for(int i = 0; i < pnf; i++)
		cout<<notFinal[i]<<"	";
	cout<<endl; 
	
}

void outTable(){//输出分析表
	
	cout<<"输出分析表"<<endl; 
	cout<<"	";
	for(int i = 0; i < pf; i++){
		//cout<<"in.."<<endl;
		cout<<final[i]<<"	";
	}
	cout<<endl; 

	for(int i = 0; i < pnf; i++){//输出分析表内容
		cout<<notFinal[i]<<"	";
		for(int j = 0; j < pf; j++){
			cout<<mp[notFinal[i]][final[j]]<<"	";
		}
		cout<<endl; 
	}
	return ; 
}

bool isInfer(const string & tmp, const string & target){
	//tmp是候选式,判断tmp能否推出target
	int length = tmp.length();
	for(int i = 0; i < length; i++){
		string t = "";
		t += tmp[i];
		if(first[t].find(target) != first[t].end())//tmp可以推出target
			return true; 
		else{
			if(first[t].find("@") == first[t].end())//tmp[i]不能推出target又没有空串@顶替 
				return false; 
			else{//first[t]有空串。 跳过tmp[i],看后面的能不能推出target 
				continue; 
			}

		}
	}

	return false; //tmp不能推出target 
}

void initContent(){//填写预测分析表
	int sz = vt.size();
	for(int i = 0; i < sz; i++){/*对分析表的每个非终结符*/
		set<string>::iterator it; 
		for(it = first[vt[i]->left].begin(); it != first[vt[i]->left].end(); it++){
			//对每个非终结符的first集合的每个元素*it
			if(*it != "@"){//不是空字
				if(vt[i]->rightString.size() == 1){//右边只有一个侯选式
					mp[vt[i]->left][*it] = vt[i]->rightString[0];

				}
				else{//右边有多个侯选式子
					string  ch = *it;
					for(int j = 0; j < vt[i]->rightString.size(); j++){//对每个侯选式
						string tmp = vt[i]->rightString[j];//获得候选式
						string col = *it; 
						//cout<<"这个候选式: "<<tmp<<" 要推出 "<<*it<<endl; 
						
						//如果候选式首字符和*it匹配或者
						//或者侯选式tmp可以推出以*it开头 那么表格就填入侯选式tmp
						if(tmp[0] == col[0] || isInfer(tmp, *it)){
							mp[vt[i]->left][*it] = tmp;//选中这个候选式填入表
							break; 
						}

					}
				}
			}
			else if(*it == "@"){//first集合有空串
				//就把A->@ 写入到mp[A][fol](A是产生式左部,fol是follow集合的元素)
				set<string>::iterator fol;
				for(fol = follow[vt[i]->left].begin(); fol != follow[vt[i]->left].end(); fol++){
					mp[vt[i]->left][*fol] = "@";
				}
			}
		}
	}

	outTable();//输出分析表
	return ; 
}

string  outStack(stack<string>target){/*输出分析栈内容*/
	string res = "";
	while(target.size()){
		res = target.top() + res;
		target.pop();
	}
	return res; 
}

string getRestString(const string & st, const int & index){
	///从st的index处截取字符串到末尾
	int length = st.length();
	string res = "";
	for(int i = index ; i < length; i++)
		res += st[i];

	return res; 
}

bool analyze(){//文法分析
	//用户忘记输入串没有结尾加入 # 就让程序加上去。 
	if(inputString[inputString.length()-1] != '#')
		inputString += '#';

	cout<<"---------文法分析过程如下---------------"<<endl;
	cout<<setw(16)<<setiosflags(ios::left)<<"符号栈"<<" "<<setw(16)<<setiosflags(ios::left)<<"当前输入符号"<<" "
		<<setw(16)<<setiosflags(ios::left)<<"输入串"<<" "<<setiosflags(ios::left)<<"说明"<<endl;
	st.push("#");
	st.push(notFinal[0]);
	int length = inputString.length();
	string x;//栈顶
	for(int i = 0; i < length; i++){
		//cout<<"in...."<<endl; 
		if(st.size() <= 0){
			cout<<"符号栈为空!!"<<endl; 
			system("pause");
			exit(-1);
		}
		x = st.top();
		string sinput = "";
		sinput += inputString[i];
		if(sinput == " ") // 比如 i + i ,跳过i和+之间的的空格
			continue; 

		
		cout<<setw(16)<<setiosflags(ios::left)<<outStack(st)<<setw(16)<<setiosflags(ios::left)
			<<sinput<<setw(16)<<setiosflags(ios::left)<<getRestString(inputString, i + 1);
		//

		if( !isBelongFinal(sinput[0])){
			cout<<"分析表不存在mp["<<x<<","<<sinput<<"]!!文法不匹配"<<endl; 
			return false;
		}

		if(x == sinput && x == "#"){
			cout<<setiosflags(ios::left)<<"匹配, 分析成功"<<endl; 
			return true; 
		}

		if(x == sinput && x != "#"){
			st.pop();
			//cout<<setw(64)<<setiosflags(ios::left)<<"弹出栈顶符号"<<x<<",因为mp["<<
			cout<<setiosflags(ios::left)<<"匹配,弹出栈顶符号"<<x<<"并读出输入串的下一个符号"<<getRestString(inputString , i +1)[0]<<endl; 
			continue;
		}

		//!!如果 x是终结符且x != sinput返回错误
		if(isBelongFinal(x[0]) && x != sinput)
		{
			cout<<x<<" 和 "<<sinput<<"不匹配"<<endl; 
			return false; 
		}
		
		//!!是非终结符号
		if(mp[x][sinput] == "error")//没有找到产生式
		{	//cout<<"文法不匹配!!"<<endl; 
			cout<<"mp["<<x<<","<<sinput<<"]"<<"的值是error, 不匹配!!"<<endl; 
			return false; 
		}

		//找到产生式定义为空串
		//也就是是A->@  @用@表示
		if(mp[x][sinput] == "@"){
			st.pop();
			i--; //保持i仍然指向当前的输入串的位置
			cout<<"弹出"<<x<<"因mp["<<x<<","<<sinput<<"]中为"
				<<x<<"->"<<"@ ,固不压栈"<<endl; 
			continue; 
		}

		//从分析表中找到产生式不是A->@
		st.pop();
		cout<<setiosflags(ios::left)<<"弹出栈顶符号 "<<x
			<<" 将mp["<<x<<","<<sinput<<"]中"<<x<<"->"<<mp[x][sinput]<<"的"
			<<mp[x][sinput]<<"逆序压入栈"<<endl;
		int k = mp[x][sinput].length();
		string token = "";
		for(int j = k - 1; j >= 0;){//逆序压入栈
			token += mp[x][sinput][j];
			if(token == "'"){
				//token += mp[x][sinput][j - 1];
				token = mp[x][sinput][j-1]+ token; 
				j -= 2; 
				
				st.push(token);
				//cout<<"当前压 "<<token<<" 逆序入栈"<<endl; 
				token = "";
			}
			else{
				st.push(token);
				//cout<<"当前压 "<<token<<" 逆序入栈"<<endl; 
				token = "";
				j--;
			}
			


		}
		i--; //保持要识别的串指针不变
		
	}

	return false; 
}

void resetStack(stack<string> &s){//清空分析栈
    s = stack<string>();
}

int main(){
	in();//读入终结符和非终结符
	readFile();//读入产生式
	cout<<"求first集合"<<endl; 
	callFirst();
	cout<<"求follow集合"<<endl; 
	startCalFollow();

	initContent();//填写分析表

	cout<<"输入要分析的串, 串结尾要加入 # "<<endl; 
	
	while(getline(cin, inputString)){
		if(inputString == ""){
			cout<<"请不要输入空串"<<endl; 
			continue; 
		}
		if(inputString == "finish")
			break; 
		if(analyze())
		{
			cout<<"输入串 "<<inputString<<"  文法匹配"<<endl; 
		}
		else{
			cout<<"输入串 "<<inputString<<"  文法不匹配"<<endl; 
		}

		resetStack(st);//清空栈
		cout<<"继续输入要分析的串或者输入 finish 退出程序"<<endl; 
	}

	system("pause");
}

 

运行结果

 

 

 

 

 

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值