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

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

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

实验环境
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_OperatorP
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值