语法分析器

1.课程设计内容与要求

1.1实验目的

1.了解掌握算符优先分析的基本方法、内容;
2.学会科学思考并解决问题,提高程序设计能力。

1.2实验内容与要求

用算符优先分析方法设计一个分析解释程序,对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。

1.3文法表示

S→v=E|E?|clear
E→E+T|E-T|T
T→T*F|T/F|F
F→ (E)|v|c

2.分析与设计

程序分为以下五个模块

  1. 构建firstvt和lastvt集合
  2. 根据firstvt 和lastvt 集合构建优先关系表
  3. 词法分析得到单词串
  4. 语法分析
  5. 主函数

单词符号二元组:
typedef struct
{
int code;//种别码
string attr;//属性值
}WordType;
输入串:用字符串对象s来存放输入串
单词串:用队列对象 queue res存放单词串
变量表:使用map<string,int>对象来充当变量表
归约栈:使用vector对象来表示
可归约串语义解释:
变量归约:Nv,在变量表中查找该变量,若不存在则报错:变量未定义,否则修改非终结符N 的属性值为变量v的值,并设N的种别码为13
常量归约:Nc,修改非终结符的属性值为常量c的值,并设N的种别码为13
运算归约:设运算的操作数为N1,N2;将N1,N2进行相应的运算并将运算结果设N的属性值,将N的种别码设为13
括号归约: 将(N)归约为N
赋值语句:在变量表中查找被赋值的v,若不存在,则先在变量表中创建该变量,然后再将N的属性值赋值给v,最后将v=N归约为N
输出语句:先输出表达式N的属性值,然后将N?归约为N
清除语句:将变量表中的所有变量以及屏幕上的内容清空,然后clear归约为N

2.1模块一 求firstvt和lastvt集合

2.1.1 数据结构

map<char,vector> firstvt;//char为字符,vector则为集合
map<char,vector> lastvt;

2.1.2 主要函数

bool istermi(char c);//判断是否是终结符
bool isnontermi(char c);//判断是否是非终结符
void First_VT(vector s,char c) ;//求非终结符c的firstvt集合
void Last_VT(vector s,char c);//求终结符c的lastvt集合
void print_fv_lv();//打印FIRSTVT和LASTVT集合

2.1.3 算法描述

2.1.3.1 First_VT

定位非终结符P所在的产生式,遍历P的候选式
对每个候选式,执行以下程序
若P的候选式出现:
若该候选式形如P a…,将终结符a加入firstvt§中
否则:
若该候选式形如P Ba…,将终结符a加入firstvt§中
若firstvt(B)存在,则将firstvt(B)的所有元素加入firstvt§,反之,若firstvt(B)不
存在,先求firstvt(B)之后,再将firstvt(B)的所有元素加入firstvt§

2.1.3.2 Last_VT

定位非终结符P所在的产生式,遍历P的候选式
对每个候选式,执行以下程序
若A的候选式出现:
若该候选式形如P …a,将终结符a加入lastvt§中
否则:
若该候选式形如P …aB,将终结符a加入lastvt§中
若lastvt(B)存在,则将lastvt(B)的所有元素加入lastvt§,反之,若lastvt(B)不
存在,先求lastvt(B)之后,再将lastvt(B)的所有元素加入lastvt§

2.1.4 运行结果

在这里插入图片描述

2.2 模块二 构建优先关系表

2.2.1 数据结构

map<char,int> term_pos;//终结符以及其在数组中的位置
vector<vector> table;//算符优先关系表

2.2.2 主要函数

void table_init(vector s);//初始化算符优先关系表
void Get_Table(vector s);//构建算符优先关系表

2.2.3 算法描述

FOR 每条产生式PX1X2…Xn
FOR i=1 TO n-1 DO
BEGIN
IF Xi和Xi+1均为终结符 THEN 置 Xi=Xi+1
IF i<=n-2且Xi和Xi+2均为终结符,但Xi+1为非终结符 THEN 置 Xi=Xi+2
IF Xi为终结符而Xi+1为非终结符 THEN
FOR firstvt(Xi+1)中的每个a DO
置 Xi<a
IF Xi为非终结符而Xi+1为终结符 THEN
FOR lastvt(Xi)中的每个a DO
置 a> Xi+1

2.2.4 运行结果

在这里插入图片描述

注:l代表clear

2.3 模块三 词法分析

2.3.1 单词种别码设计

在这里插入图片描述

2.3.2 状态转换图

在这里插入图片描述

2.3.3 数据结构

typedef struct
{
int code;//种别码
string attr;//属性值
}WordType;//单词二元组
queue res; //存储词法分析的结果
map<string,int> v_table;//符号表,-1表示未赋值

2.3.4 主要函数

bool isdigit(char c);//判断是不是数字
bool ischar(char s);//判断是不是字符
bool isremain(string s);//判断是不是保留字,即clear
queue LEX(string s);//词法分析程序
void print_word(queue res);//打印词法分析结果

2.3.5 算法描述

对输入的字符串s,前后加上#号,长度为n
For i=0 to n-1:
IF s[i]==‘ ’,THEN CONTINUE。
ELSE:
IF s[i]为字母,THEN 进行标识符和保留字的识别;
ELSE IF s[i]为数字,THEN 进行数字的判断。
ELSE 依次对这个字符可能的情况进行判断。
每次成功识别了一个单词后,创建新的WordType t,将单词种别码和单词属性值存入其中,然后将t加入队列res中。
END

2.3.6 运行结果

在这里插入图片描述

2.4 模块四 语法分析

2.4.1 数据结构

vector Stack;//归约栈

2.4.2 主要函数

void print_stack();//打印归约栈中的元素
bool handle(int j,int k);//归约子程序,对s[j]到s[k]进行归约
void MainHandle();//归约主程序

2.4.3 算法描述

t=res.pop();//从单词串中取出一个单词
top=1;//栈顶指针
Stack.push_back(t);//压栈
DO
把下一个输入符号读入a中;
IF Stack[k]∈VT THEN j=top ELSE j=top-1;
IF Stack[j]>a DO
BEGIN
REPEAT
Q=Stack[j];
IF Stack[j-1] ∈VT THEN j=j-1 ELSE j=j-2
UNTIL Stack[j]<Q
把Stack[j+1]…Stack[top]归约为N;
top=j+1;
END
ELSE IF Stack[j]<a OR Stack[j]=a THEN
BEGIN res.pop();将a入栈; END
ELSE ERROR
WHILE a!=’#’

2.5 模块五 主函数

程序流程:
在这里插入图片描述

3.程序运行测试

【输入示例】
a=5
b=a+10
b?
b+a*a?
a=a+b

【运行结果】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.源代码

#include <iostream>
#include<stdio.h>
#include <string>
#include <map>
#include <set>
#include<vector>
#include<queue>
#include <fstream>
#include <iomanip>
#include <stack>
using namespace std;


/*******   求firstvt和lastvt集合   *******/
/*
  
      求firstvt和lastvt集合
  
                 */
map<char,vector<char>> firstvt;
map<char,vector<char>> lastvt;
bool istermi(char c)//判断是否是终结符
{
	if(c>='a'&&c<='z'||c=='+'||c=='*'||c=='('||c==')'||c=='-'||c=='/'||c=='='||c=='?'||c=='v'||c=='c')
		return 1;
	return 0;
}
bool isnontermi(char c)//判断是否是非终结符
{
	if(c>='A'&&c<='Z')
		return 1;
	return 0;
}
void First_VT(vector<string> s,char c)//求非终结符c的firstvt集合
{
	vector<char> temp;
	firstvt[c]=temp;
	//定位c在第几条产生式
	int pos;
	int s_len=s.size();
	for(int i=0;i<s_len;i++)
	{
		if(s[i][0]==c)
		{
			pos=i;
			break;
		}
	}
	//对产生式进行分析
	int len2=s[pos].size();
	string tmp="";
	int j=4;
	while(j<=len2)
	{
		if((j==len2||s[pos][j]=='|')&&tmp!="")
		{
			if(istermi(tmp[0]))//P-->a.....
				firstvt[c].push_back(tmp[0]);
			else
			{
				if(tmp.size()>1&&istermi(tmp[1]))//P-->Ba...
					 firstvt[c].push_back(tmp[1]);
				if(tmp[0]!=c)
				{
				     First_VT(s,tmp[0]);//求该非终结符的firstvt集合,P-->B....
				     firstvt[c].insert(firstvt[c].end(),firstvt[tmp[0]].begin(),firstvt[tmp[0]].end());
				}

			}
			tmp="";
		}
		else
		{
			tmp+=s[pos][j];
		}
		j++;
	}
	//去重
	set<char> set1(firstvt[c].begin(),firstvt[c].end());
	firstvt[c].assign(set1.begin(),set1.end());
	return;
}

void Last_VT(vector<string> s,char c)//求终结符c的lastvt集合
{
	vector<char> temp;
	lastvt[c]=temp;
	//定位c在第几条产生式
	int pos;
	int s_len=s.size();
	for(int i=0;i<s_len;i++)
	{
		if(s[i][0]==c)
		{
			pos=i;
			break;
		}
	}
	//对产生式进行分析
	int len2=s[pos].size();
	string tmp="";
	int j=4;
	while(j<=len2)
	{
		if((j==len2||s[pos][j]=='|')&&tmp!="")
		{
			int tlen=tmp.size();
			if(istermi(tmp[tlen-1]))//P-->.....a
				lastvt[c].push_back(tmp[tlen-1]);
			else
			{
				if(tmp.size()>1&&istermi(tmp[tlen-2]))//P-->....aB
					 lastvt[c].push_back(tmp[tlen-2]);
				if(tmp[tlen-1]!=c)
				{
					if(lastvt.count(tmp[tlen-1])==0)
				         Last_VT(s,tmp[tlen-1]);//求该非终结符的lastvt集合,P-->....B
				    lastvt[c].insert(lastvt[c].end(),lastvt[tmp[tlen-1]].begin(),lastvt[tmp[tlen-1]].end());
				}

			}
			tmp="";
		}
		else
		{
			tmp+=s[pos][j];
		}
		j++;
	}
	//去重
	set<char> set1(lastvt[c].begin(),lastvt[c].end());
	lastvt[c].assign(set1.begin(),set1.end());
	return;
}

//打印FIRSTVT和LASTVT集合
void print_fv_lv()
{
	cout<<"FIRSTVT_SET"<<endl;
	map<char, vector<char>>::iterator   iter;     
	for(iter=firstvt.begin(); iter != firstvt.end(); iter++)
	{          
		cout<<"FIRSTVT("<<iter->first<<")={" ;
		int len2=iter->second.size();
		for(int j=0;j<len2;j++)
		{
			cout<<iter->second[j];
			if(j==len2-1)
				cout<<" }";
			else
				cout<<" ,";
		}
		cout<<endl;
	}     
	cout<<"LASTVT_SET"<<endl;
	for(iter=lastvt.begin(); iter != lastvt.end(); iter++)
	{          
		cout<<"LASTVT("<<iter->first<<")={" ;
		int len2=iter->second.size();
		for(int j=0;j<len2;j++)
		{
			cout<<iter->second[j];
			if(j==len2-1)
				cout<<" }";
			else
				cout<<" ,";
		}
		cout<<endl;
	}
}



/********    构造优先关系表  *******/
/*
  
      
  
              */

map<char,int> term_pos;//终结符以及其在数组中的位置
vector<vector<char>> table;//算符优先关系表
void table_init(vector<string> s)//初始化算符优先关系表
{
	vector<char> tmp;
	tmp.push_back(' ');
	int len1=s.size();
	int co=0;//计算终结符的个数
	for(int i=0;i<len1;i++)//遍历每一条产生式
	{
		int len2=s[i].size();
		for(int j=4;j<len2;j++)
		{
			if(istermi(s[i][j])&&term_pos.count(s[i][j])==0)
			{
				term_pos[s[i][j]]=++co;
				tmp.push_back(s[i][j]);
			}
		}
	}
	term_pos['#']=co+1;
	//将算符优先关系表的第一行和第一列用于存储对应的终结符
	table.resize(co+2);
	for(int i=0;i<=co+1;i++)
		table[i].resize(co+2);
	for(int i=0;i<=co;i++)
	{
		table[0][i]=tmp[i];
		table[i][0]=tmp[i];
	}
	//将#号加入表中
	table[0][co+1]='#';
	table[co+1][0]='#';
	for(int i=1;i<=co;i++)
	{
		table[co+1][i]='<';
		table[i][co+1]='>';
	}
	table[co+1][co+1]='=';

}

void  Get_Table(vector<string> s)
{
	table_init(s);
	int len=s.size();
	for(int i=0;i<len;i++)//遍历每一条产生式
	{
		int len1=s[i].size();
		int k=4;
		string temp="";
		while(k<=len1)
	    {
			if((k==len1||s[i][k]=='|')&&temp!="")//设产生式为P-->X(1)X(2)....X(n)
			{
				int len2=temp.size();
				for(int j=0;j<len2-1;j++)
				{
					char c_j=temp[j];
					char c_j1=temp[j+1],c_j2;
					if(j<len2-2)
					{
						c_j2=temp[j+2];
					}
					if(istermi(c_j)&&istermi(c_j1))//X(j)和X(j+1)均为终结符,则X(j)=X(j+1)
					{
						int pos_j=term_pos[temp[j]];
					    int pos_j1=term_pos[temp[j+1]];
						table[pos_j][pos_j1]='=';
						table[pos_j1][pos_j]='=';
					}
					if(j<len2-2&&istermi(c_j)&&istermi(c_j2)&&!istermi(c_j1))//X(j)和X(j+2)均为终结符但X(j+1)为非终结符,则X(j)=X(j+2)
					{
						int pos_j=term_pos[temp[j]];
					    int pos_j2=term_pos[temp[j+2]];
						table[pos_j][pos_j2]='=';
					}
					if(istermi(c_j)&&!istermi(c_j1))//X(j)为终结符,X(j+1)为非终结符
					{
						//X(j)<firstvt(X(j+1))
						int pos_j=term_pos[temp[j]];
						vector<char> tmp(firstvt[c_j1].begin(),firstvt[c_j1].end());
						int len3=tmp.size();
						for(int p=0;p<len3;p++)
						{
							table[pos_j][term_pos[tmp[p]]]='<';
						}
					}
					if((istermi(c_j1)&&!istermi(c_j)))//X(j)为非终结符,X(j+1)为终结符
					{
						//lastvt(X(j))>X(j+1)
						vector<char> tmp(lastvt[c_j].begin(),lastvt[c_j].end());
						int pos_j1=term_pos[temp[j+1]];
						int len3=tmp.size();
						for(int p=0;p<len3;p++)
						{
							table[term_pos[tmp[p]]][pos_j1]='>';
						}
					}
				}
				temp="";
			}
			else
				temp+=s[i][k];
			k++;
		}
	}

}

//打印优先关系表
void print_table()
{
	cout<<"优先关系表"<<endl;
	int len=table.size();
	for(int i=0;i<len;i++)
	{
		cout<<endl;
		for(int j=0;j<len;j++)
		{
			cout<<table[i][j]<<"  ";
		}
	}
	cout<<endl;
}


/*******    词法分析  *******/
/*
 

                   */
typedef struct 
{
	int code;//种别码
	string attr;//属性值
}WordType;
bool isdigit(char c);//判断是不是数字
bool ischar(char s);//判断是不是字符
bool isremain(string s);//判断是不是保留字
//判断是不是数字
bool isdigit(char c)
{
	if(c>='0'&&c<='9')
		return 1;
	return 0;
}

//判断是不是字符
bool ischar(char c)
{
	if(c>='a'&&c<='z'||c>='A'&&c<='Z')
		return 1;
	return 0;
}

//判断是不是clear
bool isremain(string s)
{
	if(s=="clear")
		return 1;
	return 0;
}

queue<WordType> res; //存储词法分析的结果
map<string,int> v_table;//符号表,-1表示未赋值
queue<WordType> LEX(string s)
{
	s='#'+s+'#';
	int len=s.length();
	WordType t;
	for(int i=0;i<len;i++)
	{
		if(s[i]!=' ')
		{
			string temp="";
			if(isdigit(s[i]))//判断是否为整型数字
			{
				temp+=s[i];
				i++;
				while(isdigit(s[i]))
				{
					temp+=s[i];
					i++;
				}
				i--;//返回最后字符
				t.code=10;t.attr =temp;
				res.push(t);//插入到返回结果中
			}
			else if(ischar(s[i]))//判断是否是clear或者标识符
			{
				temp+=s[i];
				i++;
				while(ischar(s[i])||isdigit(s[i]))
				{
					temp+=s[i];
					i++;
				}
				i--;//返回最后字符
				if(isremain(temp))
				{
					t.code=11;t.attr ="clear";
					res.push(t);
				}
				else
				{	
					t.code=9;t.attr =temp;
					if(v_table.count(temp)==0)
						v_table[temp]=-1;
					res.push(t);
				}
			}
			else
			{
				switch(s[i])
				{
				case '(':{t.code=7;t.attr ="(";res.push(t);break;}
				case ')':{t.code=8;t.attr =")";res.push(t);break;}
				case '=':{t.code=1;t.attr ="=";res.push(t);break;}
				case '?':{t.code=2;t.attr ="?";res.push(t);break;}
				case '+':{t.code=3;t.attr ="+";res.push(t);break;}
				case '-':{t.code=4;t.attr ="-";res.push(t);break;}
				case '*':{t.code=5;t.attr ="*";res.push(t);break;}
				case '/':{t.code=6;t.attr ="/";res.push(t);break;}
				case '#':{t.code=12;t.attr ="#";res.push(t);break;}
				default:{t.code=14;t.attr ="ERROR";res.push(t);cout<<"输入串中出现未识别单词!"<<endl;exit(1);}
				}
			}
		}
	}
	return res;
}

//打印结果
void print_word(queue<WordType> res)
{
	cout<<"-------------词法分析的结果--------------"<<endl;
	int i=0;//控制输出格式
	while(!res.empty())
	{
		WordType temp;
		temp=res.front();
		res.pop();
		cout<<setw(3)<<"("<<setw(3)<<temp.code<<setw(3)<<","<<setw(3)<<temp.attr <<setw(3)<<")";
		cout<<"  ";
		i++;
		if(i%5==0)
			cout<<endl;
	}
	cout<<endl;
}

void print_v_table()//打印变量表中的信息
{
	cout<<"-------------变量表中的信息------------"<<endl;
	map<string,int>::iterator   iter;     
	cout<<setw(4)<<"变量名"<<setw(4)<<"值"<<endl;
	for(iter=v_table.begin(); iter !=v_table.end(); iter++)
	{          
		cout<<setw(4)<<iter->first<<setw(4) <<iter->second<<endl;
	}
}

/*******     语法分析  *******/
/*


                            */
vector<WordType> Stack;//归约栈
/******    打印栈中元素  *******/
void print_stack()
{
	cout<<"当前归约栈中的元素"<<endl;
	int len=Stack.size();
	for(int i=0;i<len;i++)
	{
		cout<<"( "<<Stack[i].code <<" , "<<Stack[i].attr<<")    ";
	}
	cout<<endl;
}

/*******      归约     *******/

bool handle(int j,int k)
{
	int len=k+1;
	//常量归约
	if(Stack[len-1].code==10)
	{
		Stack[len-1].code=13;
	}
	//变量归约
	else if(Stack[len-1].code==9)
	{
		Stack[len-1].code=13;
		//检查变量是否被定义
		if(v_table.count(Stack[len-1].attr))
		{
			long long tmp=v_table[Stack[len-1].attr];
			Stack[len-1].attr=to_string(tmp);
		}
		else
		{
			cout<<"变量"<<Stack[len-1].attr<<"未定义"<<endl;
			return false;
		}
	}
	//赋值归约
	else if(Stack[len-2].code==1)
	{
		if(Stack[len-3].code==9)
		{
			v_table[Stack[len-3].attr]=stoi(Stack[len-1].attr );
			Stack[len-3].attr =Stack[len-1].attr;
			Stack[len-3].code=13;
		}
		else if(Stack[len-3].code==13)
			Stack[len-3].attr =Stack[len-1].attr;
		else
		{
			cout<<"语法错误!"<<endl;
			return false;
		}
		Stack.pop_back();
		Stack.pop_back();
	}
	//运算归约
	else if(Stack[len-2].code==3)//加法
	{
		if(Stack[len-1].code !=13&&Stack[len-3].code!=13)
		{
			cout<<"+号两边应该都有变量!"<<endl;
			return false;
		}
		long long  a,b;
		a=stoi(Stack[len-1].attr );
		b=stoi(Stack[len-3].attr );
		a=a+b;
		Stack[len-3].attr=to_string(a);
		Stack.pop_back();
		Stack.pop_back();
	}
	else if(Stack[len-2].code==4)//减法
	{
		if(Stack[len-1].code !=13&&Stack[len-3].code!=13)
		{
			cout<<"-号两边应该都有变量!"<<endl;
			return false;
		}
		long long  a,b;
		a=stoi(Stack[len-1].attr );
		b=stoi(Stack[len-3].attr );
		a=a-b;
		Stack[len-3].attr=to_string(a);
		Stack.pop_back();
		Stack.pop_back();
	}
	else if(Stack[len-2].code==5)//乘法
	{
		if(Stack[len-1].code !=13&&Stack[len-3].code!=13)
		{
			cout<<"*号两边应该都有变量!"<<endl;
			return false;
		}
		long long  a,b;
		a=stoi(Stack[len-1].attr );
		b=stoi(Stack[len-3].attr );
		a=a*b;
		Stack[len-3].attr=to_string(a);
		Stack.pop_back();
		Stack.pop_back();
	}
	else if(Stack[len-2].code==3)//除法
	{
		if(Stack[len-1].code !=13&&Stack[len-3].code!=13)
		{
			cout<<"/号两边应该都有变量!"<<endl;
			return false;
		}
		long long  a,b;
		a=stoi(Stack[len-1].attr );
		b=stoi(Stack[len-3].attr );
		a=a/b;
		Stack[len-3].attr=to_string(a);
		Stack.pop_back();
		Stack.pop_back();
	}
	//括号规约
	else if(Stack[len-1].code==8)//归约(N)为N
	{
		if(Stack[len-3].code==7&&Stack[len-2].code==13)//判断前面是不是(N
		{
			WordType tmp;
			tmp.code=13;
			tmp.attr=Stack[len-2].attr;
			//开始归约
			Stack.pop_back();
			Stack.pop_back();
			Stack.pop_back();
			Stack.push_back(tmp);
		}
		else
		{
			cout<<"括号不匹配,句子错误!"<<endl;
			return false;
		}
	}
	//输出语句
	else if (Stack[len-1].code==2)
	{
		if(Stack[len-2].code==13)
		{
			cout<<"表达式的值为:"<<Stack[len-2].attr<<endl;
			Stack.pop_back();
		}
		else
		{
			cout<<"问号前面必须有N!"<<endl;
			return false;
		}
	}
	else
	{
		cout<<"暂时还未定义!"<<endl;
		return false;
	}
	return true;
}

void MainHandle()
{
	//将#入栈
	Stack.push_back(res.front());
	res.pop();
	//检查是否为清除语句
	WordType t=res.front();
	if(t.attr =="clear")
	{
		res.pop();
		t.code =13;
		Stack.push_back(t);
		t=res.front();
		if(t.attr [0]='#')
		{
			v_table.clear ();
	        system("cls");
			Stack.push_back(t);
			print_stack();
			cout<<"归约成功"<<endl;
		}
		else
			cout<<"句子错误!"<<endl;
		return;
	}
	int top=0;//栈顶指针
	WordType a;
	int j;
	do
	{
		a=res.front();//将下一个输入符号读入a
		WordType t=Stack[top];
		if(t.code ==13)//栈顶为N
			j=top-1;
		else
			j=top;
		//计算Stack[j]和a的优先关系
		char a_char,j_char;//获取字符
		if(a.code==9)
			a_char='v';
		else if(a.code==10)
			a_char='c';
		else
			a_char=a.attr[0];
		WordType sj=Stack[j];
		if(sj.code==9)
			j_char='v';
		else if(sj.code==10)
			j_char='c';
		else
			j_char=sj.attr[0];
		char prio_relation=table[term_pos[j_char]][term_pos[a_char]];
		if(prio_relation=='>')//Stack[j]>a
		{
			//寻找最左素短语
			WordType Q,Sj;
			char prio;//用于比较S[j]和Q的优先关系
			do
			{
				Q=Stack[j];
				char q_char,j_char;
				if(Q.code==9)
					q_char='v';
				else if(Q.code==10)
					q_char='c';
				else
					q_char=Q.attr[0];

				if(Stack[j-1].code!=13)
					j-=1;
				else
					j-=2;
			
				if(Stack[j].code==9)
					j_char='v';
				else if(Stack[j].code==10)
					j_char='c';
				else
					j_char=Stack[j].attr[0];
				 prio=table[term_pos[j_char]][term_pos[q_char]];
			}while(prio=='>'||prio=='=');
			//将Stack[j+1]...Stack[top]归约
			cout<<"-----------进行归约-------------"<<endl;
			if(handle(j+1,top))
			{
				print_stack();
			}
			else
			{
				cout<<"语法错误!"<<endl;
				return;
			}
			top=j+1;
		}
		else if(prio_relation=='<'||prio_relation=='=')
		{
			cout<<"---------------压栈--------------"<<endl;
			res.pop();
			Stack.push_back(a);
			print_stack();
			top+=1;
		}
		else
		{
				cout<<"语法错误!"<<endl;
				exit(1);
		}
	}while(!res.empty());

	int len1=Stack.size();
	if(len1==3)
	{
		if(Stack[0].code=12&&Stack[1].code==13&&Stack[2].code==12)
		{	
			cout<<"归约成功"<<endl;
		}
		else
			cout<<"语句不合法!"<<endl;
	}
	else
		cout<<"语句不合法!"<<endl;

}
		
void main()
{
	string s1,s2,s3,s4;
	vector<string> s;
	s1="S-->v=E|E?|l";s2="E-->E+T|E-T|T";s3="T-->T*F|T/F|F",s4="F-->(E)|v|c";
	s.push_back(s1);s.push_back(s2);s.push_back(s3);s.push_back(s4);
	//求firstvt和lastvt集合
	First_VT(s,s1[0]);
	Last_VT(s,s1[0]);     
	print_fv_lv();
	cout<<endl;

	//求优先关系表
	Get_Table(s);
	print_table();

	cout<<endl;
	//归约
	string s5;
	char x='y';
	while(x=='y')
	{
		cout<<"请输入语句"<<endl;
		cin>>s5;
		queue<WordType> t;
		t=LEX(s5);
		cout<<"-----------------词法分析成功----------------"<<endl;
		print_word(t);
		print_v_table();

		MainHandle();
		cout<<"是否继续 y or n?"<<endl;
		cin>>x;
		queue<WordType> empty;
	    swap(empty,res);
		Stack.clear();
	}

}
	









  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
这个里面的都是测试数据,总共得分5分。从控制台输入,不能从文件中读取。实现了基本功能,加分项目都没有去实现,没有函数数组这些的实现。这是用C++语言写的,新建parser类别要选C++,其他对于VS的配置和C语言一样。for语句用的是枚举所有情况,你可以自行修改。 对预备工作中自然语言描述的简化C编译器的语言特性的语法,设计上下文无关文法进行描述 借助Yacc工具实现语法分析器 考虑语法树的构造: 1.语法树数据结构的设计:节点类型的设定,不同类型节点应保存哪些信息,多叉树的实现方式 2.实现辅助函数,完成节点创建、树创建等功能 3.利用辅助函数,修改上下文无关文法,设计翻译模式 4.修改Yacc程序,实现能构造语法树的分析器 考虑符号表处理的扩充 1.完成语法分析后,符号表项应增加哪些标识符的属性,保存语法分析的结果 2.如何扩充符号表数据结构,Yacc程序如何与Lex程序交互,正确填写符号表项 以一个简单的C源程序验证你的语法分析器,可以文本方式输出语法树结构,以节点编号输出父子关系,来验证分析器的正确性,如下例: main() { int a, b; if (a == 0) a = b + 1; } 可能的输出为: 0 : Type Specifier, integer, Children: 1 : ID Declaration, symbol: a Children: 2 : ID Declaration, symbol: b Children: 3 : Var Declaration, Children: 0 1 2 4 : ID Declaration, symbol: a Children: 5 : Const Declaration, value:0, Children: 6 : Expr, op: ==, Children: 4 5 7 : ID Declaration, symbol: a Children: 8 : ID Declaration, symbol: b Children: 9 : Const Declaration, value:1, Children: 10: Expr, op: +, Children: 8 9 11: Expr, op: =, Children: 7 10 12: if statement, Children: 6 11 13: compound statement, Children: 3 12

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Daniel_26_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值