南京邮电大学编译原理实验二(语法分析程序)

news2025/2/3 0:50:42

文章目录

  • 一、文法
  • 二、源代码模块
    • (一)消除文法的左递归
    • (二)求First集
    • (三)求Follow集
    • (四)构建LL(1)分析表
    • (五)符号串分析
    • (六)主函数
  • 三、实验结果
  • 四、视频讲解
  • 五、全部源代码

一、文法

E::=E+T|T
T::=T*F|F
F::=(E)|i

二、源代码模块

(一)消除文法的左递归

#pragma once
#pragma once
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#include <fstream>
#include <stack>
#include <string>

// 1读取文法
void ReadGrammarFile(std::vector<std::string>& grammarList, std::string url)
{
	std::ifstream input(url);
	std::string line;

	if (input)
	{
		while (std::getline(input, line))
		{
			grammarList.push_back(line);
		}
	}
}

// 打印文法
void PrintGrammar(const std::vector<std::string>& grammarList)
{
	for (std::string oneGrammar : grammarList)
	{
		std::cout << oneGrammar << std::endl;
	}
}

void SetToVector(const std::set<std::string>& oneSet, std::vector<std::string>& oneVector)
{
	oneVector.clear();
	for (std::string item : oneSet)
	{
		oneVector.push_back(item);
	}
}

// 3求解终结符号集 和 非终结符号集
void GetTerminator_Nonterminal(const std::vector<std::string>& grammarList, 
	std::vector<std::string>& terminatorList, 
	std::vector<std::string>& nonterminalList)
{
	std::set<std::string> terminator;
	std::set<std::string> nonterminal;
	for (std::string oneGrammar : grammarList)
	{
		int len = oneGrammar.length();
		for (int i = 0; i < len; i++)
		{
			if (oneGrammar[i] == '|')
			{
				continue;
			}
			else if (i < len - 1 && oneGrammar[i] == '-' && oneGrammar[i + 1] == '>')
			{
				i++;
				continue;
			}
			else if (i < len - 2 && oneGrammar[i] == ':' && oneGrammar[i + 1] == ':' && oneGrammar[i + 2] == '=')
			{
				i += 2;
				continue;
			}
			else if (oneGrammar[i] >= 'A' && oneGrammar[i] <= 'Z')
			{
				if (i < len - 1 && oneGrammar[i + 1] == '\'')
				{
					nonterminal.insert(oneGrammar.substr(i, 1) + "'");
					i++;
				}
				else
				{
					nonterminal.insert(oneGrammar.substr(i, 1));
				}
			}
			else
			{
				terminator.insert(oneGrammar.substr(i, 1));
			}
		}
	}
	SetToVector(nonterminal, nonterminalList);
	SetToVector(terminator, terminatorList);
}

// 打印终结符号
void PrintTerminator(const std::vector<std::string>& terminatorList)
{
	std::cout << "终结符号集为" << std::endl;
	for (std::string item : terminatorList)
	{
		std::cout << item << " ";
	}
	std::cout << std::endl;
}

// 打印非终结符号
void PrintNonterminal(const std::vector<std::string>& nonterminalList)
{
	std::cout << "非终结符号集为" << std::endl;
	for (std::string item : nonterminalList)
	{
		std::cout << item << " ";
	}
	std::cout << std::endl;
}

std::string GetFirstChar(const std::string str)
{
	std::string firstChar = str.substr(0, 1);
	if (str.length() > 1 && str.substr(1, 1) == "'")
	{
		firstChar = str.substr(0, 2);
	}
	return firstChar;
}

// 分割一条文法
std::vector<std::string> DivideOneGrammar(const std::string oneGrammar)
{
	std::vector<std::string> oneDividedGrammar;

	std::string part;
	int i = 1;
	part = oneGrammar.substr(0, 1);

	char startChar = oneGrammar[0];

	if (oneGrammar.substr(1, 1) == "'")
	{
		i++;
		part = oneGrammar.substr(0, 2);
	}

	oneDividedGrammar.push_back(part);

	if (oneGrammar.substr(i, 2) == "->")
	{
		oneDividedGrammar.push_back("->");
		part = "";
		i += 2;
	}
	else if (oneGrammar.substr(i, 3) == "::=")
	{
		oneDividedGrammar.push_back("::=");
		part = "";
		i += 3;
	}
	else
	{
		std::cout << "文法错误" << std::endl;
		exit(-1);
	}

	for (; i < oneGrammar.length(); i++)
	{
		if (oneGrammar[i] == '|')
		{
			oneDividedGrammar.push_back(part);
			part = "";
			oneDividedGrammar.push_back("|");
			continue;
		}
		part += oneGrammar[i];
	}

	oneDividedGrammar.push_back(part);
	return oneDividedGrammar;
}

// 获取一条产生式的全部侯选式
void GetOneGrammarAllRight(const std::string oneGrammar, std::map<std::string, std::vector<std::string>>& allRightMap)
{
	std::vector<std::string> oneDividedGrammar = DivideOneGrammar(oneGrammar);

	std::string key = oneDividedGrammar[0];

	for (int i = 2; i < oneDividedGrammar.size(); i++)
	{
		std::string part = oneDividedGrammar[i];
		if (part != "|")
		{
			allRightMap[key].push_back(part);
		}
	}
}

// 获取全部产生式的全部侯选式
void GetAllRightMap(std::map<std::string, std::vector<std::string>>& allRightMap,
	const std::vector<std::string>& grammarList)
{
	for (std::string oneGrammar : grammarList)
	{
		GetOneGrammarAllRight(oneGrammar, allRightMap);
	}
}

// 通过左部求当前产生式在文法当中是第几条产生式
int GetGrammarIndexByLeft(std::string left, const std::vector<std::string>& grammarList)
{
	for (int i = 0; i < grammarList.size(); i++)
	{
		std::string oneGrammar = grammarList[i];
		std::string firstChar = GetFirstChar(oneGrammar);

		if (firstChar == left)
		{
			return i;
		}
	}
}

// 获取产生左递归的索引对,即产生左递归的位置
std::vector<std::pair<std::string, int>> GetPairIndex(const std::vector<std::string>& nonterminalList,
	std::map<std::string, std::vector<std::string>> allRightMap)
{
	std::vector<std::pair<std::string, int>> leftRecursionIndex;
	for (std::string left : nonterminalList)
	{
		std::vector<std::string> oneAllRight = allRightMap[left];
		// 遍历每一条侯选式
		for (int i = 0; i < oneAllRight.size(); i++)
		{
			std::string oneRight = oneAllRight[i];
			std::string startChar = GetFirstChar(oneRight);
			if (left == startChar)
			{
				leftRecursionIndex.push_back(std::make_pair(left, i));
			}
		}
	}
	return leftRecursionIndex;
}


// 消除一条产生式的左递归
void EliminateOneLeftRecursion(std::string left, int rightIndex, std::vector<std::string>& grammarList,
	const std::vector<std::string>& oneAllRight, int grammarIndex)
{
	std::string A = left;
	std::string alpha = oneAllRight[rightIndex].substr(A.length());
	std::string beta = oneAllRight[1 - rightIndex];

	grammarList.erase(grammarList.begin() + grammarIndex);

	std::string grammar1 = A + "::=" + beta + A + "'";
	std::string grammar2 = A + "'::=" + alpha +  A + "'|$";

	grammarList.push_back(grammar1);
	grammarList.push_back(grammar2);
}

// 消除全部产生式的左递归
void EliminateAllLeftRecursion(const std::vector<std::string>& nonterminalList, 
	std::vector<std::string>& grammarList,
	std::map<std::string, std::vector<std::string>> allRightMap)
{
	 // 索引对 <左部,第几个侯选式>
	std::vector<std::pair<std::string, int>> pairIndex = GetPairIndex(nonterminalList, allRightMap);

	for (int i = 0; i < pairIndex.size(); i++)
	{
		std::string left = pairIndex[i].first;
		int rightIndex = pairIndex[i].second;
		std::vector<std::string> oneAllRight = allRightMap[left];
		// 获取当前的产生式是文法的第几条产生式
		int grammarIndex = GetGrammarIndexByLeft(left, grammarList);

		EliminateOneLeftRecursion(left, rightIndex, grammarList, oneAllRight, grammarIndex);
	}
}

// 设置新文法的第一条产生式
void SetFirstGrammar(std::vector<std::string>& grammarList, std::string startChar)
{
	std::string oneGrammar = grammarList[0];
	std::string firstChar = GetFirstChar(oneGrammar);

	if (firstChar == startChar)
	{
		return;
	}

	for (int i = 1; i < grammarList.size(); i++)
	{
		oneGrammar = grammarList[i];
		firstChar = GetFirstChar(oneGrammar);
		if (startChar == firstChar)
		{
			grammarList[i] = grammarList[0];
			grammarList[0] = oneGrammar;
			break;
		}
	}
}

// 消除左递归的主方法
void EliminateLeftRecursion(const std::vector<std::string>& nonterminalList, std::vector<std::string>& grammarList)
{
	// 1 求所有产生式的全部侯选式
	std::map<std::string, std::vector<std::string>> allRightMap;

	GetAllRightMap(allRightMap, grammarList);

	// 文法的开始符号
	const std::string grammarStartChar = GetFirstChar(grammarList[0]);

	EliminateAllLeftRecursion(nonterminalList, grammarList, allRightMap);

	SetFirstGrammar(grammarList, grammarStartChar);
}

(二)求First集

#pragma once
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#include <fstream>
#include <stack>
#include <string>
#include "EliminateLeftRecursion.h"

// 获取全部文法的全部左部和右部
std::vector<std::string> GetAllLeftRightList(std::map<std::string, std::vector<std::string>> allRightMap)
{
	std::vector<std::string> allSentenceList;
	std::set<std::string> allSentenceSet;
	for (auto item: allRightMap)
	{
		
		allSentenceSet.insert(item.first);
		for (auto item2 : item.second)
		{
			allSentenceSet.insert(item2);
		}
	}
	SetToVector(allSentenceSet, allSentenceList);
	return allSentenceList;
}

// 判断是否是终结符号
bool IsTerminator(std::string ch, const std::vector<std::string>& terminator)
{
	for (std::string item : terminator)
	{
		if (ch == item)
		{
			return true;
		}
	}
	return false;
}

// 求一条句型的 First 集
void GetOneFirst(std::string& sentence, 
	std::vector<std::string>& First,
	const std::vector<std::string>& terminator,
	std::map<std::string, std::vector<std::string>> allRightMap)
{
	// 求该句型的开始符号
	std::string firstChar = GetFirstChar(sentence);
	
	// 如果是终结符号,那么 firstChar 就是当前句型 First集 的唯一元素,直接返回
	if (IsTerminator(firstChar, terminator))
	{
		First.push_back(firstChar);
		return;
	}
	// 如果是非终结符号
	else
	{
		// 根据首字符确定 产生式
		std::vector<std::string> oneAllRight = allRightMap[firstChar];
		// 遍历每一条产生式
		for (std::string item : oneAllRight)
		{
			// 新句型 = 用产生式替换原句型的首字符 
			sentence = item + sentence.substr(firstChar.length());
			// 再次递归,直到遇到终结符号,自动结束递归
			GetOneFirst(sentence, First, terminator, allRightMap);
		}
	}
}


// 打印全部的左部和右部的各个侯选式
void PrintAllSentence(const std::vector<std::string>& allSentence)
{
	std::cout << "全部的左部和右部如下" << std::endl;
	for (std::string item : allSentence)
	{
		std::cout << item << "  " << std::endl;
	}
	std::cout << std::endl;
}


// 打印 First集
void PrintFirst(std::map<std::string, std::set<std::string>>& First)
{
	std::cout << "FIRST 集如下" << std::endl;
	for (std::pair<std::string, std::set<std::string>> item : First)
	{
		std::cout << std::left << std::setw(4) << item.first << ": { ";
		for (std::string ii : item.second)
		{
			std::cout << ii << ", ";
		}
		std::cout << "\b\b }" << std::endl;
	}
	std::cout << std::endl;
}

// 1求 First集 主函数
std::map<std::string, std::set<std::string>> GetFirstSet(
	const std::vector<std::string>& terminatorList,
	const std::vector<std::string>& nonterminalList,
	std::map<std::string, std::vector<std::string>> allRightMap)
{
	// 所有产生式的左部和右部的全部侯选式
	std::vector<std::string> allSentenceList;

	allSentenceList = GetAllLeftRightList(allRightMap);
		
	PrintAllSentence(allSentenceList);


	std::map<std::string, std::set<std::string>> First;

	// 一个句型的 First 集
	std::vector<std::string> oneFirst;

	for (std::string sentence : allSentenceList)
	{
		std::string sentenceTemp = sentence;
		oneFirst.clear();
		GetOneFirst(sentence, oneFirst, terminatorList, allRightMap);
		for (std::string item : oneFirst)
		{
			First[sentenceTemp].insert(item);
		}
	}
	return First;
}

(三)求Follow集

#pragma once
#include "EliminateLeftRecursion.h"
#include "MyFirst.h"

// PairSet 转换为 PairVector
void PairSetToPairVector(const std::set<std::pair<std::string, std::string>>& onePairSet, 
	std::vector<std::pair<std::string, std::string>>& onePairVector)
{
	onePairVector.clear();
	for (std::pair<std::string, std::string> item : onePairSet)
	{
		onePairVector.push_back(item);
	}
}

// 判断某个字符是否是非终结符号
bool IsNonterminal(std::string ch, const std::vector<std::string>& nonterminalList)
{
	for (std::string item : nonterminalList)
	{
		if (ch == item)
		{
			return true;
		}
	}
	return false;
}

// 输入侯选式返回所有可能的产生式的左部 
std::vector<std::string> GetOneCandidateAllLeft(const std::string candidate,
	const std::map<std::string, std::vector<std::string>> allRightMap)
{
	std::vector<std::string> allLeft;

	for (std::pair<std::string, std::vector<std::string>> item : allRightMap)
	{
		std::string left = item.first;
		std::vector<std::string> oneAllRight = item.second;
		for (std::string oneRight : oneAllRight)
		{
			if (oneRight == candidate)
			{
				allLeft.push_back(left);
				break;
			}
		}
	}
	return allLeft;
}


// 获取全部文法的全部右部
std::vector<std::string> GetAllRightList(std::map<std::string, std::vector<std::string>> allRightMap, 
	const std::vector<std::string>& nonterminalList)
{
	std::vector<std::string> allRightList;
	std::set<std::string> allRightSet;
	for (std::string key : nonterminalList)
	{
		for (std::string item : allRightMap[key])
		{
			allRightSet.insert(item);
		}
	}
	SetToVector(allRightSet, allRightList);
	return allRightList;
}

// 获取一条侯选式的全部字符
std::vector<std::string> GetOneCandidateAllCharacter(std::string oneCandidate)
{
	std::vector<std::string> charList;
	std::string oneChar;
	int len = oneCandidate.length();
	for (int i = 0; i < len; i++)
	{
		oneChar = oneCandidate.substr(i, 1);
		if (i < len - 1 && oneCandidate.substr(i + 1, 1) == "'")
		{
			oneChar = oneCandidate.substr(i, 2);
			i++;
		}
		charList.push_back(oneChar);
	}
	return charList;
}

// 寻找一条侯选式的 B 和 Beta             A::=αBβ
std::vector<std::pair<std::string, std::string>> FindOneCandidateBBeta(
	std::string oneCandidate,
	const std::vector<std::string>& nonterminalList, 
	const std::vector<std::string>& oneCandidateCharList)
{
	std::vector<std::pair<std::string, std::string>> oneBBeta;
	int index = 0;
	int charNum = oneCandidateCharList.size();
	std::string beta;
	std::string oneChar;

	// E::=aEFcd
	// B = E
	// B = F

	for (int i = 0; i < charNum; i++)
	{
		oneChar = oneCandidateCharList[i];
		index += oneChar.length();
		// 如果是非终结符号
		if (IsNonterminal(oneChar, nonterminalList))
		{
			std::string B = oneChar;
			beta = oneCandidate.substr(index);
			beta = beta == "" ? "$" : beta;
			oneBBeta.push_back(make_pair(B, beta));
		}
	}
	return oneBBeta;
}

// 寻找全部侯选式的 B 和 Beta
std::vector<std::pair<std::string, std::string>> FindAllCandidateBBeta(
	const std::vector<std::string>& allCandidateList,
	const std::vector<std::string>& nonterminalList)
{
	std::vector<std::pair<std::string, std::string>> allBBetaList;
	std::set<std::pair<std::string, std::string>> allBBetaSet;
	std::vector<std::string> oneCandidateAllCharList;
	std::vector<std::pair<std::string, std::string>> oneCandidateBBetaList;
	for (std::string oneCandidate : allCandidateList)
	{
		oneCandidateAllCharList = GetOneCandidateAllCharacter(oneCandidate);
		oneCandidateBBetaList = FindOneCandidateBBeta(oneCandidate, nonterminalList, oneCandidateAllCharList);
		for (std::pair<std::string, std::string> oneBBeta : oneCandidateBBetaList)
		{
			allBBetaSet.insert(oneBBeta);
		}
	}
	PairSetToPairVector(allBBetaSet, allBBetaList);
	return allBBetaList;
}

// 求解 FOLLOW 集合 规则一
void Rule1(std::map<std::string, std::set<std::string>>& Follow, std::string startChar)
{
	Follow[startChar].insert("#");
}

// 求解 FOLLOW 集合 规则二
void Rule2(std::map<std::string, std::set<std::string>>& Follow,
	const std::vector<std::pair<std::string, std::string>> allBBetaList, 
	const std::vector<std::string>& terminatorList, 
	std::map<std::string, std::vector<std::string>> allRightMap)
{
	std::vector<std::string> FirstSetOfBeta;
	for (std::pair<std::string, std::string> oneBBeta : allBBetaList)
	{
		FirstSetOfBeta.clear();
		std::string B = oneBBeta.first;
		std::string beta = oneBBeta.second;

		GetOneFirst(beta, FirstSetOfBeta, terminatorList, allRightMap);
		for (std::string item : FirstSetOfBeta)
		{
			if (item != "$")
			{
				Follow[B].insert(item);
			}
		}
	}
}


// beta 是否能广义推导出 空符号 $
void IsGeneralizedDerivation(std::string lastA,
	std::pair<std::string, std::string>& oneBBeta,
	std::map<std::string, std::vector<std::string>> allRightMap, 
	const std::vector<std::string>& terminatorList, 
	bool& flag, 
	std::set<std::string>& ASet)
{
	std::string beta = oneBBeta.second;

	std::string firstChar = GetFirstChar(beta);

	if (IsTerminator(firstChar, terminatorList))
	{
		if (firstChar == "$")
		{
			flag = true;
			ASet.insert(lastA);
		}
	}
	else
	{
		for (std::string right : allRightMap[firstChar])
		{
			std::string newBeta = right + beta.substr(firstChar.size());
			oneBBeta.second = newBeta;
			lastA = firstChar;
			IsGeneralizedDerivation(lastA, oneBBeta, allRightMap, terminatorList, flag, ASet);
		}
	}
}

// 规则三递归终止条件
bool IsRule3Over(std::map<std::string, std::set<std::string>>& thisFollow,
	std::map<std::string, std::set<std::string>>& lastFollow, 
	const std::vector<std::string>& nonterminalList)
{
	for (std::string key : nonterminalList)
	{
		if (thisFollow[key].size() != lastFollow[key].size())
		{
			return false;
		}
	}
	return true;
}

// 求解 FOLLOW 集合 规则三
void Rule3(std::map<std::string, std::set<std::string>>& Follow,
	const std::vector<std::string>& allRightList,
	const std::map<std::string, std::vector<std::string>> allRightMap,
	const std::vector<std::string>& terminatorList,
	const std::vector<std::string>& nonterminalList)
{
	// 先保存一份 Follow集
	std::map<std::string, std::set<std::string>> tempFollow = Follow;
	std::vector<std::string> allChar;
	std::vector<std::pair<std::string, std::string>> oneCandidateBBetaList;
	std::vector<std::string> oneCandidateAllLeft;
	bool flag;
	for (std::string oneCandidate : allRightList)
	{
		allChar = GetOneCandidateAllCharacter(oneCandidate);
		oneCandidateBBetaList = FindOneCandidateBBeta(oneCandidate, nonterminalList, allChar);
		oneCandidateAllLeft = GetOneCandidateAllLeft(oneCandidate, allRightMap);
		for (std::pair<std::string, std::string> oneBBeta : oneCandidateBBetaList)
		{
			for (std::string left : oneCandidateAllLeft)
			{
				std::set<std::string> ASet;
				flag = false;
				std::string B = oneBBeta.first;
				std::string beta = oneBBeta.second;
				IsGeneralizedDerivation(left, oneBBeta, allRightMap, terminatorList, flag, ASet);
				// 如果能广义推导出 $, 则 FOLLOW(A) 中全部终结符均属于FOLLOW(B)
				if (flag)
				{
					for (std::string key : ASet)
					{
						//std::cout << "A = " << key << "  ";
						//std::cout << key << " ";
						for (std::string item : Follow[key])
						{
							Follow[B].insert(item);
						}
					}
					//std::cout << "属于" << B << std::endl;
				}
			}
		}
	}
	// 如果更新了,则继续递归;否则如果本次没有更新,继续递归
	if (!IsRule3Over(Follow, tempFollow, nonterminalList))
	{
		Rule3(Follow, allRightList, allRightMap, terminatorList, nonterminalList);
	}
}

// 打印 Follow集 
int PrintFollow(std::map<std::string, std::set<std::string>>& Follow)
{
	std::cout << "FOLLOW 集如下" << std::endl;
	for (std::pair<std::string, std::set<std::string>> item : Follow)
	{
		std::cout << std::left << std::setw(3) << item.first << " : { ";
		for (std::string ii : item.second)
		{
			std::cout << ii << ", ";
		}
		std::cout << "\b\b }" << std::endl;
	}
	std::cout << std::endl;
	return 0;
}

// 求解 Follow集 主函数
std::map<std::string, std::set<std::string>> GetFollowSet(
	const std::vector<std::string>& terminatorList,
	const std::vector<std::string>& nonterminalList,
	std::map<std::string, std::vector<std::string>> allRightMap,
	std::string grammarStartChar)
{
	std::map<std::string, std::set<std::string>> Follow;

	std::vector<std::pair<std::string, std::string>> allBBeta;

	std::vector<std::string> allCandidateList = GetAllLeftRightList(allRightMap);

	allBBeta = FindAllCandidateBBeta(allCandidateList, nonterminalList);

	Rule1(Follow, grammarStartChar);
	std::cout << "规则一" << std::endl;
	PrintFollow(Follow);

	Rule2(Follow, allBBeta, terminatorList, allRightMap);
	std::cout << "规则二" << std::endl;
	PrintFollow(Follow);

	Rule3(Follow, allCandidateList, allRightMap, terminatorList, nonterminalList);
	std::cout << "规则三" << std::endl;

	return Follow;
}


(四)构建LL(1)分析表

#pragma once
#include "MyFirst.h"
#include "MyFollow.h"

// 输入非空侯选式,返回左部
std::string GetSartCharByCandidate(std::string candidate, std::map<std::string, std::vector<std::string>> allRightMap)
{
	std::string left;
	for (std::pair<std::string, std::vector<std::string>> oneLeftAllRight : allRightMap)
	{
		left = oneLeftAllRight.first;
		for (std::string oneCandidate : oneLeftAllRight.second)
		{
			// 如果此产生式存在侯选式与目标侯选式相匹配,就返回此产生式的左部
			if (oneCandidate == candidate)
			{
				return left;
			}
		}
	}
	std::cout << "出错了" << std::endl;
	return "Error";
}

// 打印 LL1 分析表
void PrintAnalysisTable(std::map<std::string, std::map<std::string, std::string>> analysisTable,
	const std::vector<std::string>& terminatorList,
	const std::vector<std::string>& nonterminalList)
{
	std::vector<std::string> ROW = nonterminalList;
	std::vector<std::string> COL = terminatorList;
	for (int i = 0; i < COL.size(); i++)
	{
		if (COL[i] == "$")
		{
			COL[i] = "#";
			break;
		}
	}
	std::cout << "LL(1) 分析表如下" << std::endl;
	std::string j;
	std::cout << std::left << "     |" << std::left << std::setw(6) << "";
	for (int k = COL.size() - 1; k >= 0; k--)
	{
		std::cout << std::left << std::setw(10) << COL[k];
	}
	std::cout << std::endl;
	int num = COL.size() + 1;
	std::string space = "----------";
	for (int i = 0; i < num; i++)
	{
		std::cout << std::left << std::setw(10) << space;
	}
	std::cout << std::endl;
	for (std::string i : ROW)
	{
		std::cout << std::left << std::setw(5) << i << std::left << std::setw(5) << "|";
		for (int k = COL.size() - 1; k >= 0; k--)
		{
			j = COL[k];
			std::cout << std::left << std::setw(10) << analysisTable[i][j];
		}
		std::cout << std::endl;
	}
	std::cout << std::endl;
}


// 由 FIRST 集构造分析表
void ConstructorAnalysisTableByFirst(
	std::map<std::string, std::map<std::string, std::string>>& analysisTable,
	const std::map<std::string, std::set<std::string>>& First,
	const std::map<std::string, std::vector<std::string>>& allRightMap,
	const std::vector<std::string>& nonterminalList)
{																					   
	// 遍历每一个句型的 First集
	for (std::pair<std::string, std::set<std::string>> onefirstSet : First)
	{
		// 一个句型
		std::string oneSentence = onefirstSet.first;
		// 如果该句型是非终结符号 或者 空符号,因为分析表的第一行是终结符号
		if (IsNonterminal(oneSentence, nonterminalList) || oneSentence == "$")
		{
			continue;
		}
		// 句型是终结符号
		for (std::string item : onefirstSet.second)
		{
			std::string left = GetSartCharByCandidate(oneSentence, allRightMap);
			std::string i = left;
			std::string j = item;
			std::string grammar = left + "->" + oneSentence;
			analysisTable[i][j] = grammar;
		}
	}
}


// 由 FOLLOW 集构造分析表
void ConstructorAnalysisTableByFollow(
	std::map<std::string, std::map<std::string, std::string>>& analysisTable,
	std::map<std::string, std::set<std::string>> Follow,
	const std::map<std::string, std::vector<std::string>>& allRightMap,
	const std::vector<std::string>& nonterminalList)
{

	for (std::pair<std::string, std::vector<std::string>> oneLeftAllRight : allRightMap)
	{
		std::string left = oneLeftAllRight.first;
		std::vector<std::string> oneAllRight = oneLeftAllRight.second;
		for (std::string oneCandidate : oneAllRight)
		{
			if (oneCandidate == "$")
			{
				std::string i = left;
				auto COL = Follow[left];
				for (std::string j : COL)
				{
					std::string grammar = left + "->$";
					analysisTable[i][j] = grammar;
				}
			}
		}
	}
}

// 初始化 LL(1) 分析表
void InitAnalysisTable(std::map<std::string, std::map<std::string, std::string>>& analysisTable,
	const std::vector<std::string>& ROW, const std::vector<std::string>& COL)
{
	for (std::string i : ROW)
	{
		for (std::string j : COL)
		{
			analysisTable[i][j] = "";
		}
	}
}


// 构建 LL(1) 分析表主函数
std::map<std::string, std::map<std::string, std::string>> AnalysisTableConstructor(
	std::map<std::string, std::set<std::string>> First,
	std::map<std::string, std::set<std::string>> Follow,
	const std::vector<std::string>& terminatorList,
	const std::vector<std::string>& nonterminalList,
	std::map<std::string, std::vector<std::string>> allRightMap)
{
	std::map<std::string, std::map<std::string, std::string>>  analysisTable;

	std::vector<std::string> ROW = nonterminalList;
	std::vector<std::string> COL = terminatorList;

	for (int i = 0; i < COL.size(); i++)
	{
		if (COL[i] == "$")
		{
			COL[i] = "#";
			break;
		}
	}

	InitAnalysisTable(analysisTable, ROW, COL);

	ConstructorAnalysisTableByFirst(analysisTable, First, allRightMap, nonterminalList);
	ConstructorAnalysisTableByFollow(analysisTable, Follow, allRightMap, nonterminalList);

	return analysisTable;
}

(五)符号串分析

#pragma once
#include "AnalysisTable.h"


//************************符号串分析函数定义**********************************************************

void MyPush(std::stack<std::string>& analysisStack, std::string string0)
{
	std::vector<std::string> charList;
	std::string ch;
	int len = string0.length();
	for (int i = 0; i < len; i++)
	{
		ch = string0.substr(i, 1);
		if (i + 1 < len && string0.substr(i + 1, 1) == "'")
		{
			ch = string0.substr(i, 2);
			i++;
		}
		charList.push_back(ch);
	}
	for (int i = charList.size() - 1; i >= 0; i--)
	{
		analysisStack.push(charList[i]);
	}
}

std::string GetAnalysisByStack(const std::stack<std::string>& analysisStack)
{
	std::stack<std::string> tempAnalysisStack = analysisStack;
	std::vector<std::string> charList;
	std::string string0;
	int size = tempAnalysisStack.size();
	for (int i = 0; i < size; i++)
	{
		charList.push_back(tempAnalysisStack.top());
		tempAnalysisStack.pop();
	}
	for (int i = charList.size() - 1; i >= 0; i--)
	{
		string0 += charList[i];
	}
	return string0;

}

std::string GetStringByStack(const std::stack<std::string>& stringStack)
{
	std::stack<std::string> tempStringStack = stringStack;
	std::string string0;
	int size = tempStringStack.size();
	for (int i = 0; i < size; i++)
	{
		string0 += tempStringStack.top();
		tempStringStack.pop();
	}
	return string0;
}

void PrintStack(const std::stack<std::string>& analysisStack)
{
	std::stack<std::string> tempStack = analysisStack;
	while (tempStack.size() != 0)
	{
		std::string ch = tempStack.top();
		tempStack.pop();
		std::cout << ch << std::endl;
	}
}



void InitStringStack(std::stack<std::string>& stringStack, std::string string0)
{
	stringStack.push("#");
	MyPush(stringStack, string0);
}

void InitAnalysisStack(std::stack<std::string>& analysisStack, std::string startChar)
{
	analysisStack.push("#");
	analysisStack.push(startChar);
}

// 
std::string GetGrammar(std::string analysisTop, std::string stringTop, std::map<std::string, std::map<std::string, std::string>> analysisTable)
{
	return analysisTable[analysisTop][stringTop];
}


void PrintAllStep(const std::vector<std::vector<std::string>>& allStep, std::string string0)
{
	std::cout << "符号串 " << string0 << " 的分析过程" << std::endl;
	for (std::vector<std::string> oneStep : allStep)
	{
		std::cout << std::left << std::setw(6) << oneStep[0]
			<< std::left << std::setw(10) << oneStep[1]
			<< std::right << std::setw(10) << oneStep[2] << "     "
			<< std::left << std::setw(10) << oneStep[3]
			<< std::endl;

	}
}

// 获取一条产生式的右部
std::string GetRight(std::string oneGrammar)
{
	std::string firstChar = GetFirstChar(oneGrammar);
	std::string right;
	if (oneGrammar.substr(firstChar.length(), 3) == "::=")
	{
		right = oneGrammar.substr(firstChar.length() + 3);
		return right;
	}
	else if (oneGrammar.substr(firstChar.length(), 2) == "->")
	{
		right = oneGrammar.substr(firstChar.length() + 2);
		return right;
	}
	else
	{
		std::cout << "right 出错了" << std::endl;
		return "";
	}

}

std::vector<std::vector<std::string>> Func(std::stack<std::string>& analysisStack, std::stack<std::string>& stringStack, std::map<std::string, std::map<std::string, std::string>> analysisTable, int& step)
{
	std::string analysisTop;
	std::string stringTop;
	std::string oneGrammar;
	std::string right;

	bool sucess = true;

	std::vector<std::vector<std::string>> allStep;
	std::vector<std::string> oneStep;
	std::string  analysisStackList;
	std::string  stringStackList;

	while (!(analysisStack.top() == "#" && stringStack.top() == "#") || step >= 100)
	{
		step++;
		oneStep.clear();

		oneStep.push_back(std::to_string(step));
		analysisStackList = GetAnalysisByStack(analysisStack);
		stringStackList = GetStringByStack(stringStack);
		oneStep.push_back(analysisStackList);
		oneStep.push_back(stringStackList);
		analysisTop = analysisStack.top();
		stringTop = stringStack.top();
		if (analysisTop == stringTop)
		{
			oneStep.push_back("");
			allStep.push_back(oneStep);
			analysisStack.pop();
			stringStack.pop();
			continue;
		}
		oneGrammar = GetGrammar(analysisTop, stringTop, analysisTable);

		oneStep.push_back(oneGrammar);
		allStep.push_back(oneStep);
		if (oneGrammar == "")
		{
			sucess = false;
			break;
		}
		right = GetRight(oneGrammar);
		analysisStack.pop();
		if (right != "$")
		{
			MyPush(analysisStack, right);
		}
	}

	std::vector<std::string> successStep = { std::to_string(++step), "#", "#", "SUCCESS" };
	std::vector<std::string> failStep = { std::to_string(++step), "?", "?", "FAIL" };

	allStep.push_back(sucess ? successStep : failStep);
	//std::cout << "Success" << std::endl;
	return 	allStep;


}

std::vector<std::vector<std::string>> StringAnalysis(std::string string0,
	std::string startChar, std::map<std::string, std::map<std::string,
	std::string>> analysisTable)
{

	std::stack<std::string> analysisStack;
	std::stack<std::string> stringStack;


	InitAnalysisStack(analysisStack, startChar);
	InitStringStack(stringStack, string0);

	int step = 0;

	std::vector<std::vector<std::string>> allStep = Func(analysisStack, stringStack, analysisTable, step);

	return allStep;
}

(六)主函数

#include "EliminateLeftRecursion.h"
#include "MyFirst.h"
#include "MyFollow.h"
#include "AnalysisTable.h"
#include "StringAnalysis.h"

int main()
{
	std::vector<std::string> grammarList;
	std::vector<std::string> terminatorList;
	std::vector<std::string> nonterminalList;

	ReadGrammerFile(grammarList, "code.txt");

	std::cout << "原始文法如下" << std::endl;
	PrintGrammerList(grammarList);

	GetTerminator_Nonterminal(grammarList, terminatorList, nonterminalList);

	EliminateLeftRecursion(nonterminalList, grammarList);

	std::cout << "消除左递归文法如下" << std::endl;
	PrintGrammerList(grammarList);

	//********************************************************************


	std::map<std::string, std::set<std::string>> First;
	std::map<std::string, std::vector<std::string>> allRightMap;

	GetTerminator_Nonterminal(grammarList, terminatorList, nonterminalList);

	//PrintTerminator(terminatorList);

	GetAllRightMap(allRightMap, grammarList);

	

	// **2 求解全部左部和右部的 First 集合
	First = GetFirstSet(terminatorList, nonterminalList, allRightMap);
	PrintFirst(First);

	//*********************************************************************

	std::string grammarStartChar = GetFirstChar(grammarList[0]);

	std::map<std::string, std::set<std::string>> Follow;
	Follow = GetFollowSet(terminatorList, nonterminalList, allRightMap, grammarStartChar);
	PrintFollow(Follow);

	// *************************************************************************
	std::map<std::string, std::map<std::string, std::string>> analysisTable;
	analysisTable = AnalysisTableConstructor(First, Follow, terminatorList, nonterminalList, allRightMap);
	PrintAnalysisTable(analysisTable, terminatorList, nonterminalList);

	std::string string0 = "i+i*i";

	// **5 符号串分析
	auto allStep = StringAnalysis(string0, grammarStartChar, analysisTable);

	PrintAllStep(allStep, string0);

	return 0;
}

三、实验结果

原始文法如下
E::=E+T|T
T::=T*F|F
F::=(E)|i

消除左递归文法如下
E::=TE'
F::=(E)|i
E'::=+TE'|$
T::=FT'
T'::=*FT'|$

FIRST 集如下
$: {$}
(E): {(}
*FT': {*}
+TE': {+}
E: {(, i}
E': {$, +}
F: {(, i}
FT': {(, i}
T: {(, i}
T': {$, *}
TE': {(, i}
i: {i}

规则一
FOLLOW 集如下
E: {#}

规则二
FOLLOW 集如下
E: {#, )}
F: {*}
T: {+}

规则三
FOLLOW 集如下
E: {#, )}
E': {#, )}
F: {#, ), *, +}
T: {#, ), +}
T': {#, ), +}

LL(1) 分析表如下
     |      i         +         *         )         (         #
----------------------------------------------------------------------
E    |    E->TE'                                  E->TE'
E'   |              E'->+TE'            E'->$               E'->$
F    |    F->i                                    F->(E)
T    |    T->FT'                                  T->FT'
T'   |              T'->$     T'->*FT'  T'->$               T'->$

符号串 i+i*i 的分析过程
1     #E            i+i*i#     E->TE'
2     #E'T          i+i*i#     T->FT'
3     #E'T'F        i+i*i#     F->i
4     #E'T'i        i+i*i#
5     #E'T'          +i*i#     T'->$
6     #E'            +i*i#     E'->+TE'
7     #E'T+          +i*i#
8     #E'T            i*i#     T->FT'
9     #E'T'F          i*i#     F->i
10    #E'T'i          i*i#
11    #E'T'            *i#     T'->*FT'
12    #E'T'F*          *i#
13    #E'T'F            i#     F->i
14    #E'T'i            i#
15    #E'T'              #     T'->$
16    #E'                #     E'->$
17    #                  #     SUCCESS

在这里插入图片描述

四、视频讲解

B站详细讲解
在这里插入图片描述

五、全部源代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/103891.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

破解色带现象(下)

编者按&#xff1a;本文是“破解色带现象”文章的第二部分&#xff0c;Fabio Sonnati进一步 分析了色带现象产生的原因&#xff0c;并提供了新的检测办法。本文已获得作者授权转载。翻译&#xff1a;Argus原文链接&#xff1a;https://sonnati.wordpress.com/2022/09/16/defea…

Flink实战案例四部曲

Flink实战案例四部曲 第一部曲:统计5分钟内用户修改创建删除文件的操作日志数量 输入 1001,delete 1002,update 1001,create 1002,delte 输出 1001&#xff0c;2 1002&#xff0c;2代码如下。 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironmen…

Anlios装grouplist 组件之后报错,安装tiger-vncserver

因为之前升级了一个epel-release源&#xff0c;然后containerd也装进去了&#xff0c;但是版本太低 然后以为是runc挡住了&#xff0c;发现没有runc 删完了containerd就可以装了 rpm -ivh http://mirrors.wlnmp.com/centos/wlnmp-release-centos.noarch.rpm dnf install wntp…

【性能篇】30 # 怎么给WebGL绘制加速?

说明 【跟月影学可视化】学习笔记。 常规绘图方式的性能瓶颈 例子&#xff1a;在一个画布上渲染 3000 个不同颜色的、位置随机的三角形&#xff0c;并且让每个三角形的旋转角度也随机。 <!DOCTYPE html> <html lang"en"><head><meta charse…

SpringBoot+Vue实现前后端分离的高校思政课实践教学管理系统

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue.js 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JD…

基于SSM的大学生心理健康系统设计与实现

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 网站前台&#xff1a;关于我们、联系信息、文章信息、咨询师信息、服务信息、测试信喜 管理员功能&#xff1a; 1、管理…

继续谈谈从Rxjava迁移到Flow的背压策略

前言 对于背压问题不久前就讨论过了&#xff0c;这里就不过多介绍了&#xff0c;总之它是一个非常复杂的话题&#xff0c;本文的主要目的是分析我们如何从Rxjava迁移到Flow并且使用其背压方案&#xff0c;由于本身技术的限制以及协程内部的复杂性&#xff0c;不会做过多的深入…

下载安装PyTorch

1、下载并安装Visual Studio Code选择合适版本安装 2、下载安装conda并配置环境 下载方式一&#xff1a;官网下载 下载方式二&#xff1a;清华镜像安装 3、conda配置环境 打开电脑高级系统配置点开系统环境变量&#xff1a; 找到path然后点击Edit或者直接双击&#xff1a; 之后…

利用LSTM识别篇章关系实战代码+数据

1.显式篇章关系分类概述 案例知识点: 任务描述:篇章关系分析是自然语言中处理篇章级基础语言分析任务,其目的是利用规则或机器学习等计算机处理手段判别篇章各组成成分之间的修辞逻辑关系,从而从整体上理解篇章。其中论元之间有连接词连接的此类关系称为显式篇章关系。本教…

实验七、MOS管分压式偏置共源放大电路的静态和动态参数

一、题目 搭建MOS管分压式偏置共源放大电路。利用Multisim研究下列问题&#xff1a; &#xff08;1&#xff09;确定一组电路参数&#xff0c;使电路的 QQQ 点合适。 &#xff08;2&#xff09;若输出电压波形底部失真&#xff0c;则可采取哪些措施&#xff1f;若输出电压波形…

Mysql概念知识

Mysql数据库基础知识为什么要使用数据库数据保存在内存数据保存在文件数据保存在数据库什么是SQL&#xff1f;什么是MySQL?数据库三大范式是什么mysql有关权限的表都有哪几个MySQL的binlog有几种录入格式&#xff1f;分别有什么区别&#xff1f;数据类型mysql有哪些数据类型引…

计算机毕设Python+Vue学生资源管理系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

websocket使用方法

前言 最近项目用到了websocket接口&#xff0c;用来做长连接&#xff0c;监听服务器数据变化&#xff0c;保持各终端数据同步。 用下来发现确实很好用&#xff0c;避免了轮询&#xff0c;开销小&#xff0c;而且最重要的是没有同源策略限制。 websocket WebSocket 是一种在…

Nginx-安装和部署全过程

前言 OpenResty是一个基于Nginx与 Lua 的高性能 Web 平台&#xff0c;其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。openresty官网&#xff1a;OpenResty - 中文官方站 …

软件著作权到底享有哪些权利?

根据《计算机软件保护条例》相关规定 软件著作权人享有下列各项权利: &#xff08;一&#xff09;发表权&#xff0c;即决定软件是否公之于众的权利&#xff1b; &#xff08;二&#xff09;署名权&#xff0c;即表明开发者身份&#xff0c;在软件上署名的权利&#xff1b; &a…

iOS的启动优化

应用的启动优化 当我们参与到大型应用的时候 会遇到一些启动时间过长的情况 这时候就需要使用到相关的操作。 总结来说&#xff0c;main()方法调用前&#xff0c;启动过程大体分为如下步骤&#xff1a; 先是LLVM把项目翻译成IR文件然后到backend&#xff0c;PRE_MAIN,main。 …

感冒咳嗽土法子

目录介绍 01.常见的感冒药02.止咳的土方法03.感冒的土方法 01.常见的感冒药 感冒是生活中最常见的疾病 患者往往会有&#xff1a;头昏、发烧、浑身酸痛、鼻塞、流鼻涕等症状 注意点 注意休息&#xff0c;适当补充水分&#xff0c;保持室内空气流通。 常见感冒药 主要成分的作…

CSS规范

CSS规范 命名规范 页面外围控制整体布局宽度&#xff1a;wrapper、页头&#xff1a;header、页面主体&#xff1a;main、内容&#xff1a;content、页脚&#xff1a;footer、导航&#xff1a;nav、主导航&#xff1a;mainbav、子导航&#xff1a;subnav、顶导航&#xff1a;t…

利用FormData上传本地文件

前言 最近接了个小项目&#xff0c;有个用客户端本地文件的需求。 正常这种需求都是前台传文件&#xff0c;后台去解析。 但这次C的老哥非让我给文件路径&#xff0c;说公司平台有解析文件的能力。 我说web不是桌面端&#xff0c;拿不到真实路径&#xff0c;他还不信&#…

已解决1. Downgrade the protobuf package to 3.20.x or lower.

已解决TypeError: Descriptors cannot not be created directly. If this call came from a _pb2.py file, your generated code is out of date and must be regenerated with protoc > 3.1.0If you cannot immediately regenerate your protos, some other possible worka…