⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 语法分析器.cpp

📁 是用slr(1)法做的一个语法分析器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<fstream>
#include<string>
#include<cmath>
using namespace std;
struct token//token结构体
{
	int code;
	int num;
	token *next;
};
token *token_head,*token_tail;//token队列
struct number//number结构体
{
	int num;
	int value;
	number *next;
};
number *number_head,*number_tail;//number队列
struct str//string结构体
{
	int num;
	string  word;
	str *next;
};
str *string_head,*string_tail;//string队列
struct ivan//表达式结构体
{
	char left;
	string right;
	int len;
};
ivan css[20];//20个表达式
struct pank//action表结构体
{
	char sr;
	int state;
};
pank action[46][18];//action表
int go_to[46][11];//go_to表
struct ike//分析栈结构体,双链
{
	ike *pre;
	int num;
	int word;
	ike *next;
};
ike *stack_head,*stack_tail;//分析栈首尾指针

void scan();//按字符读取源文件
int judge(char ch);//判断输入字符的类型
void out1(char ch);//写入token.txt
void out2(char ch,string word);//写入number.txt
void out3(char ch,string word);//写入string.txt
void input1(token *temp);//插入结点到队列token
void input2(number *temp);//插入结点到队列number
void input3(str *temp);//插入结点到队列string
void output();//输出三个队列的内容
void outfile();//输出三个队列的内容到相应文件中
void yufa_initialize();//初始化语法分析数据结构
int yufa_main(int a);//语法分析主体部分
int ID1(int a);//给输入字符编号,转化成action表列编号
string ID10(int i);//给输入字符反编号
int ID2(char ch);//给非终结状态编号,转化成go_to表列编号
int ID20(char ch);//给非终结状态编号
char ID21(int j);//给非终结状态反编号
void add(ike *temp);//给ike分析栈链表增加一个结点
void del();//给ike分析栈链表删除一个结点

FILE *fp;//文件
int wordcount;//标志符计数
int numcount;//整型常数计数
int err;//标志词法分析结果正确或错误
int nl;//读取行数
void main()
{
	token_head=new token;
	token_head->next=NULL;
	token_tail=new token;
	token_tail->next=NULL;
	number_head=new number;
	number_head->next=NULL;
	number_tail=new number;
	number_tail->next=NULL;
	string_head=new str;
	string_head->next=NULL;
	string_tail=new str;
	string_tail->next=NULL;//初始化三个队列的首尾指针
	wordcount=0;//初始化字符计数器
	numcount=0;//初始化常数计数器
	err=0;//初始化词法分析错误标志
	nl=1;//初始化读取行数
	scan();
	if(err==0)
	{
		char m;
		cout<<"词法分析正确完成!"<<endl<<endl<<"下边将输出结果,如果将结果保存到文件中请输入 y ,否则请输入其它键:";
		cin>>m;
		output();
		if(m=='y')
		{
			cout<<"结果同时保存在token.txt、number.txt和sting.txt三个文件中,请打开查看"<<endl;
			outfile();
		}
	}
	yufa_initialize();//初始化语法分析数据结构
	token *temp;
	temp=new token;
	temp=token_head->next;
	int p,q;
	p=0;
	q=0;
	cout<<endl<<"下面开始语法分析:"<<endl;
	while(temp!=NULL)
	{
		int w;
		w=ID1(temp->code);
		p=yufa_main(w);
		if(p==1) break;
		if(p==0)
			temp=temp->next;
		if(temp==NULL) q=1;
	}//语法分析
	if(q==1)
		while(1)
		{
			p=yufa_main(17);
			if(p==3) break;
		}//最后输入$来完成语法分析
	cout<<endl;
	system("pause");
}
void scan()
{
	char ch;
	string word;
	char document[50];
	int flag=0;
	cout<<"请输入源文件路径及名称:";
	cin>>document;
	cout<<endl;
	if((fp=fopen(document,"rt"))==NULL)
	{
		err=1;
		cout<<"无法找到该文件!"<<endl;
		return;
	}
	while(!feof(fp))
	{
		word="";
		ch=fgetc(fp);
		flag=judge(ch);
		if(flag==1)
			out1(ch);
		else if(flag==2)
			out2(ch,word);
		else if(flag==3)
			out3(ch,word);
		else if(flag==4 || flag==5 ||flag==6)
			continue;
		else
		{
			cout<<nl<<"行  "<<"错误:非法字符!  "<<ch<<endl;
			err=1;
		}
	}
	fclose(fp);
}
int judge(char ch)
{
	int flag=0;
	if(ch=='=' || ch=='+' || ch=='*' || ch=='>' || ch==':' || ch==';' || ch=='{' || ch=='}' || ch=='(' || ch==')')
		flag=1;//界符
	else if('0'<=ch && ch<='9')
		flag=2;//数字
	else if(('a'<=ch && ch<='z') || ('A'<=ch && ch<='Z'))
		flag=3;//字母
	else if(ch==' ')
		flag=4;//空格
	else if(feof(fp))
		flag=5;//结束
	else if(ch=='\n')
	{
		flag=6;//换行
		nl++;
	}
	else
		flag=0;//非法字符
	return(flag);
}
void out1(char ch)
{
	int id;
	switch(ch)
	{
	case '=' : id=1;break;
	case '+' : id=2;break;
	case '*' : id=3;break;
	case '>' : id=4;break;
	case ':' : id=5;break;
	case ';' : id=6;break;
	case '{' : id=7;break;
	case '}' : id=8;break;
	case '(' : id=9;break;
	case ')' : id=10;break;//界符编码
	default : id=0;
	}
	token *temp;
	temp=new token;
	temp->code=id;
	temp->num=-1;
	temp->next=NULL;
	input1(temp);
	return;
}
void out2(char ch,string word)
{
	token *temp;
	temp=new token;
	temp->code=-1;
	temp->num=-1;
	temp->next=NULL;
	number *temp1;
	temp1=new number;
	temp1->num=-1;
	temp1->value=-1;
	temp1->next=NULL;
	int flag=0;
	word=word+ch;
	ch=fgetc(fp);
	flag=judge(ch);
	if(flag==1)
	{
		numcount++;
		temp->code=26;
		temp->num=numcount;
		input1(temp);
		temp1->num=numcount;
		int i,num_value=0,num_length;//字符串转化为数字
		char *num_head;
		num_head=&word[0];
		num_length=strlen(num_head);
		for(i=num_length-1;i>=0;i--)
			num_value=num_value+(int(word[i])-48)*pow(10,(num_length-i-1));
		temp1->value=num_value;//把数字的值赋给结点
		input2(temp1);
		out1(ch);
	}
	else if(flag==2)
		out2(ch,word);//形成字符串
	else if(flag==3)
	{
		err=1;
		cout<<nl<<"行  "<<"错误:数字后面跟字母!"<<endl;
		return;
	}
	else if(flag==4 || flag==5 || flag==6)
	{
		numcount++;
		temp->code=26;
		temp->num=numcount;
		input1(temp);
		temp1->num=numcount;
		int i,num_value=0,num_length;//字符串转化为数字
		char *num_head;
		num_head=&word[0];
		num_length=strlen(num_head);
		for(i=num_length-1;i>=0;i--)
			num_value=num_value+(int(word[i])-48)*pow(10,(num_length-i-1));
		temp1->value=num_value;//把数字的值赋给结点
		input2(temp1);
		return;
	}
	else
	{
		err=1;
		cout<<nl<<"行  "<<"错误:非法字符!  "<<ch<<endl;
		return;
	}
}
void out3(char ch,string word)
{
	token *temp;
	temp=new token;
	temp->code=-1;
	temp->num=-1;
	temp->next=NULL;
	str *temp1;
	temp1=new str;
	temp1->num=-1;
	temp1->word="";
	temp1->next=NULL;
	int flag=0;
	word=word+ch;
	ch=fgetc(fp);
	flag=judge(ch);
	if(flag==1 || flag==4 || flag==5 || flag==6)
	{
		if(word=="and" || word=="if" || word=="then" /*|| word=="else"*/ || word=="while" || word=="do" || word=="int")
		{
			if(word=="and")
				temp->code=31;
			else if(word=="if")
				temp->code=32;
			else if(word=="then")
				temp->code=33;
			//else if(word=="else")
			//	temp->code=34;
			else if(word=="while")
				temp->code=35;
			else if(word=="do")
				temp->code=36;
			else if(word=="int")
				temp->code=37;//关键字编码
			input1(temp);
			if(flag==1)
				out1(ch);
			else if(flag==4 || flag==5 || flag==6)
				return;
		}
		else if(flag==1)
		{
			wordcount++;
			temp->code=25;
			temp->num=wordcount;
			input1(temp);
			temp1->num=wordcount;
			temp1->word=word;
			input3(temp1);
			out1(ch);
		}
		else if(flag==4 || flag==5 || flag==6)
		{
			wordcount++;
			temp->code=25;
			temp->num=wordcount;
			input1(temp);
			temp1->num=wordcount;
			temp1->word=word;
			input3(temp1);
		}
		return;
	}
	else if(flag==2 || flag==3)
		out3(ch,word);//形成字符串
	else
	{
		err=1;
		cout<<nl<<"行  "<<"错误:非法字符!  "<<ch<<endl;
		return;
	}
}
void input1(token *temp)
{
	if(token_head->next == NULL)
	{
		token_head->next=temp;
		token_tail->next=temp;
	}
	else
	{
		token_tail->next->next=temp;
		token_tail->next=temp;
	}
}
void input2(number *temp)
{
	if(number_head->next == NULL)
	{
		number_head->next=temp;
		number_tail->next=temp;
	}
	else
	{
		number_tail->next->next=temp;
		number_tail->next=temp;
	}
}
void input3(str *temp)
{
	if(string_head->next == NULL)
	{
		string_head->next=temp;
		string_tail->next=temp;
	}
	else
	{
		string_tail->next->next=temp;
		string_tail->next=temp;
	}
}
void output()
{
	cout<<"token表内容如下:"<<endl;
	token *temp1;
	temp1=new token;
	temp1=token_head->next;
	while(temp1!=NULL)
	{
		cout<<temp1->code;
		if(temp1->num == -1)
		{
			cout<<endl;
		}
		else
		{
			cout<<"   "<<temp1->num<<endl;
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -