编译原理 词法分析 算符优先分析法

编译原理 词法分析 算符优先分析法

实验目的
加深对语法分析器工作工程的理解,加强对算符优先分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己辨析的分析程序对简单的程序段进行语法翻译。

实验环境
Microsoft Visual Studio 2019 Community

思路
首先从文件中读取产生式,并进行分割,将包含“|”的产生式分割成单独的一条产生式。
然后根据产生式求Vt和Vn。先获取每条产生式左侧的字符,这些就是所有的Vn,然后在每条产生式右侧中寻找非Vn的字符,就是Vt。
之后根据求到的Vt和Vn求每个Vn的FIRSTVT集和LASTVT集。每个非终结符在Vn中的下标就是在FIRSTVT集和LASTVT集的横坐标。求FIRSTVT集和LASTVT集需要递归求解。要求FIRSTVT集首先求第一个非终结符,若左侧是该非终结符的产生式的右侧第一个字符是终结符,那么该非终结符的FIRSTVT集就是该终结符;如果右侧第一个字符是非终结符,那么第二个字符一定是终结符,该终结符就属于该非终结符的FIRSTVT集,然后右侧第一个非终结符的FIRSTVT集的元素也属于该非终结符,所以递归求右侧第一个非终结符的FIRSTVT集。LASTVT集也是类似的递归求法。
之后求算符优先关系表,对每条产生式,相邻的终结符之间优先级相同;然后寻找每一个终结符的前面的非终结符,这些非终结符的LASTVT集中的终结符的优先级都大于当前终结符;寻找每一个终结符的后面的非终结符,这些非终结符的FIRSTVT集中的终结符的优先级都大于该终结符。
最后开始分析,若字符串第一个字符为非终结符则直接进栈;否则判断栈内第一个终结符与字符串第一个终结符的优先级,若站内的小于等于字符串的,则直接将字符串第一个终结符压入栈,并将其优先关系压入优先关系栈中;否则开始出栈,若出栈的元素是终结符,则优先关系栈也出栈;直到优先关系栈弹出一个‘<’,然后如果栈顶元素是非终结符还需将栈顶的非终结符出栈。此时出栈结束,压入一个非终结符,并且此次操作没有将字符串字符压入栈,所以不能继续读取下一个字符。当字符串所有元素都读取完毕则完成匹配。

产生式
E→E+T|T
T→T*F|F
F→(E)|i

#pragma once
#include <iostream>
#include <ostream>
#include <stack>
#include <fstream>
#include <vector>
#include <set>
#include <sstream>

using namespace std;

/// <summary>
/// 算符优先分析法词法分析
/// </summary>
class SyntexAnalysis_OperatorPrecedenceParsing
{
	static vector<string> productions;//产生式集合
	static vector<char> Vn;//非终结符集
	static vector<char> Vt;//终结符集
	static vector<vector<char>> firstVt;//FIRSTVT集
	static vector<vector<char>> lastVt;//LASTVT集
	static vector<bool> fished;//标志一个非终结符的FIRSTVT集或LASTVT集是否已经求过,下标与Vn中的下标一一对应
	static vector<vector<char>> operatorPrecedenceRelationTable;//算符优先关系表,下标与Vt中的下标一一对应
	static void getVtAndVn();
	static void readProduction(string fileName);
	static int findChar(char ch, vector<char>& v);
	static void divideProduction();
	static void getFirstVt(char vn);
	static void getLastVt(char vn);
	static void removeSame(vector<char>& v);
	static void initFished();
	static void getOperatorPrecedenceRelationTable();
	static void resizeVector2(vector<vector<char>>& v, int size);
	static void printOperatorPrecedenceRelationTable();
	static void printVtSet(vector<vector<char>>& v);
	static void printProductions();
	static void printV(vector<char>& v);
	static void printAll();
	static void printStack(stack<char> S);
	static void analyse(string str);
public:
	static void SyntexAnalyse_OperatorPrecedenceParsing(string str, string fileName);
};
#include "SyntaxAnalysis.h"

using namespace std;

vector<char> SyntexAnalysis_OperatorPrecedenceParsing::Vn;
vector<char> SyntexAnalysis_OperatorPrecedenceParsing::Vt;
vector<string> SyntexAnalysis_OperatorPrecedenceParsing::productions;
vector<vector<char>> SyntexAnalysis_OperatorPrecedenceParsing::firstVt;
vector<vector<char>> SyntexAnalysis_OperatorPrecedenceParsing::lastVt;
vector<bool> SyntexAnalysis_OperatorPrecedenceParsing::fished;
vector<vector<char>> SyntexAnalysis_OperatorPrecedenceParsing::operatorPrecedenceRelationTable;

/// <summary>
/// 从文件读取产生式
/// </summary>
/// <param name="fileName">文件名</param>
void SyntexAnalysis_OperatorPrecedenceParsing::readProduction(string fileName)
{
	fstream file(fileName);
	while (!file.eof())
	{
		string s;
		file >> s;
		productions.push_back(s);
	}
	file.close();
}

/// <summary>
/// 划分产生式,将包含“|”的产生式划分成单独的一条产生式
/// </summary>
void SyntexAnalysis_OperatorPrecedenceParsing::divideProduction()
{
	for (int i = 0; i < productions.size(); i++)
	{
		for (int j = 0; j < productions[i].length(); j++)
		{
			if (productions[i][j] == '|')
			{
				productions.push_back(productions[i].substr(0, 3) + productions[i].substr(j + 1));
				productions[i] = productions[i].substr(0, j);
			}
		}
	}
}

/// <summary>
/// 寻找ch在v中的下标,未找到则返回-1
/// </summary>
/// <param name="ch">要查找的字符</param>
/// <param name="v">要查找的向量</param>
/// <returns>ch在v中的下标,未找到返回-1</returns>
int SyntexAnalysis_OperatorPrecedenceParsing::findChar(char ch, vector<char>& v)
{
	for (int i = 0; i < v.size(); i++)
	{
		if (v[i] == ch)
		{
			return i;
		}
	}
	return -1;
}

/// <summary>
/// 去掉v中重复的元素
/// </summary>
/// <param name="v">要去重的向量</param>
void SyntexAnalysis_OperatorPrecedenceParsing::removeSame(vector<char>& v)
{
	set<char> s(v.begin(), v.end());
	v.assign(s.begin(), s.end());
}

/// <summary>
/// 求Vt和Vn
/// </summary>
void SyntexAnalysis_OperatorPrecedenceParsing::getVtAndVn()
{
	for (int i = 0; i < productions.size(); i++)//获取所有非终结符
	{
		Vn.push_back(productions[i][0]);
	}
	for (int i = 0; i < productions.size(); i++)//获取所有终结符,但是会重复
	{
		string& s = productions[i];
		for (int j = 3; j < s.size(); j++)
		{
			if (findChar(s[j], Vn) == -1)//不在非终结符中,即找到终结符
			{
				Vt.push_back(s[j]);
			}
		}
	}
	removeSame(Vt);
	removeSame(Vn);
}

/// <summary>
/// 求FIRSTVT集
/// </summary>
/// <param name="vn">要求FIRSTVT集的非终结符</param>
void SyntexAnalysis_OperatorPrecedenceParsing::getFirstVt(char vn)
{
	int index = findChar(vn, Vn);
	for (int i = 0; i < productions.size(); i++)
	{
		if (fished[index] == false && productions[i][0] == vn)
		{
			if (findChar(productions[i][3], Vt) != -1)//如果产生式右侧第一个字母是终结符
			{
				firstVt[index].push_back(productions[i][3]);
			}
			else
			{
				if (productions[i].length() > 4)//如果产生式右侧不止一个字母
				{
					firstVt[index].push_back(productions[i][4]);//第二个字母一定是终结符
				}
				for (int j = 0; j < productions.size(); j++)
				{//开始求该非终结符所有产生式右侧第一个字母是非终结符时的FIRSTVT集
					if (productions[i][0] == productions[j][0] && productions[i][0] != productions[j][3])
					{//产生式左侧和右侧第一个字母不能一样,否则无限递归
						getFirstVt(productions[j][3]);//求产生式右侧第一个字母,即非终结符的FIRSTVT集
						for (int k = 0; k < firstVt[findChar(productions[j][3], Vn)].size(); k++)
						{//将产生式右侧第一个字母的FIRSTVT集中的元素加入该非终结符的FIRSTVT集
							firstVt[index].push_back(firstVt[findChar(productions[j][3], Vn)][k]);
						}
					}
				}
			}
		}
	}
	removeSame(firstVt[index]);
	fished[index] = true;
}

/// <summary>
/// 求LASTVT集
/// </summary>
/// <param name="vn">要求LASTVT集的非终结符</param>
void SyntexAnalysis_OperatorPrecedenceParsing::getLastVt(char vn)
{
	int index = findChar(vn, Vn);
	for (int i = 0; i < productions.size(); i++)
	{
		if (fished[index] == false && productions[i][0] == vn)
		{
			if (findChar(productions[i][productions[i].length() - 1], Vt) != -1)//如果产生式右侧最后的字母是终结符
			{
				lastVt[index].push_back(productions[i][productions[i].length() - 1]);
			}
			else
			{
				if (productions[i].length() > 4)//产生式右侧不止一个字母
				{
					lastVt[index].push_back(productions[i][productions[i].length() - 2]);//倒数第二个字母一定是终结符
				}
				for (int j = 0; j < productions.size(); j++)
				{//开始求该非终结符所有产生式右侧最后一个字母是非终结符时的LASTVT集
					if (productions[i][0] == productions[j][0] && productions[i][0] != productions[j][productions[j].length() - 1])
					{//产生式左侧和右侧最后一个字母不能一样,否则无限递归
						getLastVt(productions[j][productions[j].length() - 1]);//求产生式右侧最后一个字母,即非终结符的LASTVT集
						for (int k = 0; k < lastVt[findChar(productions[j][productions[j].length() - 1], Vn)].size(); k++)
						{//将产生式右侧最后一个字母的LASTVT集中的元素加入该非终结符的LADTVT集
							lastVt[index].push_back(lastVt[findChar(productions[j][productions[j].length() - 1], Vn)][k]);
						}
					}
				}
			}
		}
	}
	removeSame(lastVt[index]);
	fished[index] = true;
}

/// <summary>
/// 初始化fished
/// </summary>
void SyntexAnalysis_OperatorPrecedenceParsing::initFished()
{
	for (int i = 0; i < fished.size(); i++)
	{
		fished[i] = false;
	}
}

/// <summary>
/// 求算符优先关系表
/// </summary>
void SyntexAnalysis_OperatorPrecedenceParsing::getOperatorPrecedenceRelationTable()
{
	for (int i = 0; i < productions.size(); i++)
	{
		int x = 3;
		int index = findChar(productions[i][x], Vt);//产生式右侧第一个字符
		if (index == -1)//该字符是非终结符
		{
			x++;//x指向第一个终结符
		}
		for (int y = x; y < productions[i].length(); y += 2)//遍历该产生式所有终结符
		{
			if (y > 3)//该终结符不是第一个字符
			{
				for (int j = 0; j < lastVt[findChar(productions[i][y - 1], Vn)].size(); j++)
				{//寻找当前终结符前面的非终结符的lastVt集里的所有字符,优先级都大于当前终结符
					operatorPrecedenceRelationTable
						[findChar(lastVt[findChar(productions[i][y - 1], Vn)][j], Vt)]//前面的非终结符的lastVt集中的第j个元素对应的下标
					[findChar(productions[i][y], Vt)]//当前终结符对应的关系表的下标,与其在Vt中的下标相同
					= '>';
				}
			}
			if (y + 1 < productions[i].length())//该终结符不是该产生式的最后一个字符
			{
				for (int j = 0; j < firstVt[findChar(productions[i][y + 1], Vn)].size(); j++)
				{//寻找当前终结符后面的非终结符的firstVt集里的所有字符,优先级都大于当前终结符
					operatorPrecedenceRelationTable
						[findChar(productions[i][y], Vt)]//当前终结符对应的关系表的下标,与其在Vt中的下标相同
					[findChar(firstVt[findChar(productions[i][y + 1], Vn)][j], Vt)]//后面的非终结符的firstVt集中的第j个元素对应的下标
					= '<';
				}
			}
			if (y + 2 < productions[i].length())//该终结符后面还有终结符
			{//该终结符与后一个终结符优先级相等
				operatorPrecedenceRelationTable
					[findChar(productions[i][y], Vt)]//当前终结符
				[findChar(productions[i][y + 2], Vt)]//后一个终结符
				= '=';
			}
		}
	}
}

/// <summary>
/// 重新设置大小
/// </summary>
/// <param name="v">要重置大小的向量</param>
/// <param name="size">大小</param>
void SyntexAnalysis_OperatorPrecedenceParsing::resizeVector2(vector<vector<char>>& v, int size)
{
	v.resize(size);
	for (int i = 0; i < size; i++)
	{
		v[i].resize(size);
	}
}

/// <summary>
/// 打印算符优先关系表
/// </summary>
void SyntexAnalysis_OperatorPrecedenceParsing::printOperatorPrecedenceRelationTable()
{
	cout << "  ";
	for (int i = 0; i < Vt.size(); i++)
	{
		cout << Vt[i] << " ";
	}
	cout << endl;
	for (int i = 0; i < operatorPrecedenceRelationTable.size(); i++)
	{
		cout << Vt[i] << " ";
		for (int j = 0; j < operatorPrecedenceRelationTable[i].size(); j++)
		{
			char ch = operatorPrecedenceRelationTable[i][j];
			if (ch == '\0')
			{
				ch = ' ';
			}
			cout << ch << ' ';
		}
		cout << endl;
	}
}

/// <summary>
/// 打印向量
/// </summary>
/// <param name="v">要打印的向量</param>
void SyntexAnalysis_OperatorPrecedenceParsing::printVtSet(vector<vector<char>>& v)
{
	for (int i = 0; i < v.size(); i++)
	{
		cout << Vn[i] << ": ";
		for (int j = 0; j < v[i].size(); j++)
		{
			cout << v[i][j];
		}
		cout << endl;
	}
}

/// <summary>
/// 打印产生式集合
/// </summary>
void SyntexAnalysis_OperatorPrecedenceParsing::printProductions()
{
	for (int i = 0; i < productions.size(); i++)
	{
		cout << productions[i] << endl;
	}
}

/// <summary>
/// 打印终结符集或非终结符集
/// </summary>
/// <param name="v">要打印的集合</param>
void SyntexAnalysis_OperatorPrecedenceParsing::printV(vector<char>& v)
{
	for (int i = 0; i < v.size(); i++)
	{
		cout << v[i];
	}
	cout << endl;
}

/// <summary>
/// 打印
/// </summary>
void SyntexAnalysis_OperatorPrecedenceParsing::printAll()
{
	cout << "---------------" << endl;
	cout << "转换后的文法" << endl;
	printProductions();
	cout << "---------------" << endl;
	cout << "-------Vt------" << endl;
	printV(Vt);
	cout << "---------------" << endl;
	cout << "-------Vn------" << endl;
	printV(Vn);
	cout << "---------------" << endl;
	cout << "----FIRSTVT----" << endl;
	printVtSet(firstVt);
	cout << "---------------" << endl;
	cout << "-----LASTVT----" << endl;
	printVtSet(lastVt);
	cout << "---------------" << endl;
	cout << "---------------" << endl;
	cout << "算符优先分析表" << endl;
	printOperatorPrecedenceRelationTable();
	cout << "---------------" << endl;
}

/// <summary>
/// 打印栈
/// </summary>
/// <param name="S">要打印的栈</param>
void SyntexAnalysis_OperatorPrecedenceParsing::printStack(stack<char> S)
{
	stack<char> T;
	while (!S.empty())
	{
		char top = S.top();
		S.pop();
		T.push(top);
	}
	while (!T.empty())
	{
		cout << T.top();
		T.pop();
	}
}

/// <summary>
/// 分析
/// </summary>
/// <param name="str">要分析的字符串</param>
void SyntexAnalysis_OperatorPrecedenceParsing::analyse(string str)
{
	if (*(--str.end()) != '#')//判断是否以#结尾
	{
		cout << "不以#结尾,不符合规则" << endl;
		return;
	}

	stack<char> S;//存放所有输入的栈
	stack<char> precedenceRelation;//存放优先关系的栈
	stack<char> preVt;//存放输入的终结符的栈
	S.push('#');
	preVt.push('#');
	char curV = '#';//当前读取的字符
	cout << "栈\t\t当前字符串\t操作" << endl;
	for (int i = 0; i < str.length(); i++)
	{
		curV = str[i];
		int curIndex = findChar(curV, Vt);
		if (curIndex != -1)//当前字符为终结符
		{
			char relation = operatorPrecedenceRelationTable[findChar(preVt.top(), Vt)][curIndex];//前一终结符与当前终结符的优先关系
			if (relation == '<' || relation == '=')//直接移进
			{
				printStack(S);
				precedenceRelation.push(relation);
				S.push(curV);
				preVt.push(curV);
				cout << "\t\t" << str.substr(i) << "\t\t移进" << endl;
			}
			else if (relation == '>')//需要规约
			{
				printStack(S);
				//<==...==>的情况时需要规约
				char topV;
				for (char topR = precedenceRelation.top(); topR != '<'; topR = precedenceRelation.top())
				{//弹出所有'='的情况
					topV = S.top();
					S.pop();
					if (findChar(topV, Vt) != -1)//栈顶为终结符
					{
						precedenceRelation.pop();
						preVt.pop();
					}
				}
				//此时优先关系栈顶一定是'<'
				topV = S.top();
				S.pop();
				if (findChar(topV, Vn) != -1)//若弹出的是非终结符
				{
					topV = S.top();
					S.pop();//弹出终结符
				}
				topV = S.top();
				if (findChar(topV, Vn) != -1)//该终结符后面是非终结符
				{
					S.pop();//弹出后面的非终结符
				}
				precedenceRelation.pop();
				preVt.pop();
				S.push(Vn[0]);//压入一个非终结符
				i--;//不能向后移
				cout << "\t\t" << str.substr(i + 1) << "\t\t规约" << endl;
			}
			else//即算符优先关系表中的空白区域
			{
				cout << "#" << str << "匹配失败" << endl;
				break;
			}
		}
		else//当前字符为非终结符
		{
			printStack(S);
			S.push(curV);
			cout << "\t\t" << str.substr(i) << "\t\t移进" << endl;
		}
	}
	if (curV == '#' && preVt.top() == '#')
	{
		cout << "#" << str << "匹配成功" << endl;
	}
}

/// <summary>
/// 算符优先分析
/// </summary>
/// <param name="str">要分析的字符串</param>
/// <param name="fileName">产生式所在的文件</param>
void SyntexAnalysis_OperatorPrecedenceParsing::SyntexAnalyse_OperatorPrecedenceParsing(string str, string fileName)
{
	productions.push_back("");
	readProduction(fileName);//读取产生式
	stringstream ss;
	ss << productions[1][0];
	productions[0] = ("$->#" + ss.str() + "#");//增加第一条产生式,即$->#...#,$视为新的文法开始符
	Vt.push_back('#');
	Vn.push_back('$');
	cout << "---------------" << endl;
	cout << "转换前的文法" << endl;
	printProductions();
	cout << "---------------" << endl;
	divideProduction();//划分产生式
	getVtAndVn();//求Vt和Vn
	firstVt.resize(Vn.size());
	lastVt.resize(Vn.size());
	fished.resize(Vn.size());
	resizeVector2(operatorPrecedenceRelationTable, Vt.size());
	initFished();
	for (int i = 0; i < Vn.size(); i++)
	{
		getFirstVt(Vn[i]);//求FIRSTVT集
	}
	initFished();
	for (int i = 0; i < Vn.size(); i++)
	{
		getLastVt(Vn[i]);//求LASTVT集
	}
	getOperatorPrecedenceRelationTable();//求算符优先关系表
	printAll();
	cout << "----------------规约过程--------------" << endl;
	analyse(str);//分析
	cout << "--------------------------------------" << endl;
}
	cout << "------Syntax Analysis------" << endl;
	string str;
	cout << "输入要分析的字符串:";
	cin >> str;
	SyntexAnalysis_OperatorPrecedenceParsing::SyntexAnalyse_OperatorPrecedenceParsing(str, "OperatorPrecedenceParsingProductions.txt");
	cout << "--------------------------" << endl << endl;

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

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值