《编译原理》:LL(1)语法分析设计实现

实验目的与内容

实验目的

  1. 了解语法分析的设计方法与实现原理:深入理解编译原理中LL(1)文法的语法分析方法,为编译器设计与实现奠定基础。
  2. 构造LL(1)文法分析表:编写LL(1)分析程序,利用构造的LL(1)文法分析表对输入串进行语法分析,实现分析过程中的控制程序。
  3. 实现LL(1)语法分析程序:编写LL(1)分析程序,利用构造的LL(1)文法分析表对输入串进行语法分析,实现分析过程中的控制程序。

实验内容

        以专题1词法分析程序的输出为语法分析的输入,实现LL(1)分析中控制程序(表驱动程序);完成以下描述赋值语句的LL(1)文法的LL(1)分析过程。

G[S]: S→V=E

        E→TE′

          E′→ATE′|ε

          T→FT′

          T′→MFT′|ε

          F→ (E)|i

          A→+|-

          M→*|/

          V→i


实验要求

 设计说明

        终结符号i为用户定义的简单变量,即标识符的定义。重点是LL(1)分析方法和LL(1)分析器的实现。

设计要求

(1)构造该文法的LL(1)分析表。

(2)输入串应是词法分析的输出二元式序列,即某算术表达式“专题1”的输出结果。输出为输入串是否为该文法定义的算术表达式的判断结果;

(3)LL(1)分析过程应能发现输入串出错;

(4)设计至少四个测试用例(尽可能完备,正确和出错),并给出测试结果;

(5)选做:考虑根据LL(1)文法编写程序构造LL(1)分析表,包括FIRST集合和FOLLOW集合,并添加到你的LL(1)分析程序中


实验环境和工具

实验背景与环境

        在实验一中,我们已经完成了对输入程序的词法分析,得到了对应的二元式文件。现在的任务是设计一个语法分析器,通过LL(1)分析的方式判断输入的程序语句是否符合给定的文法规则。

语言选择与编译器:C++/g++

编码格式:GBK

IDE

        Visual Studio Code(VSC)作为一款开源、轻量级、跨平台的代码编辑器,具有一系列优势,因此成为许多开发者的首选之一。使用VSC的原因如下:

  1. 跨平台支持: Visual Studio Code 支持 Windows、macOS 和 Linux 操作系统,使得开发者可以在不同平台上保持一致的开发环境,提高跨平台开发的效率。
  2. 轻量高效: VSC 是一款轻量级的代码编辑器,启动速度快,占用系统资源少。
  3. 强大的扩展生态系统: VSC具有丰富的扩展插件,开发者可以根据自己的需要选择并安装扩展,定制化编辑器,使其满足特定的开发需求。这也促使了VSC的生态系统的不断发展和壮大。
  4. 语言支持广泛: VSC支持多种编程语言,并且对不同语言的语法高亮、自动补全等功能提供了良好的支持。这使得它适用于多种开发场景,从前端到后端,从移动端到云端。
  5. 强大的调试功能: VSC提供了强大的调试工具,支持多种语言的调试,并且能够与多种调试器集成,使得开发者能够更轻松地进行代码调试。

图1 IDE界面展示


实验过程

实验步骤

  1. 构造LL(1)文法分析表:

        定义给定文法 G[S]。

        计算文法的FIRST集合,包括非终结符和终结符的FIRST集合。

        计算文法的FOLLOW集合。

        利用FIRST和FOLLOW集合构造LL(1)文法分析表。

  1. 编写LL(1)语法分析程序:

        实现LL(1)分析程序的数据结构,包括文法规则、FIRST集合、FOLLOW集合等。

        编写LL(1)分析程序的核心算法,根据文法分析表进行LL(1)语法分析。

        实现出错检测机制,确保程序能够发现输入串中的语法错误。

  1. 准备输入串:

        利用专题1词法分析程序的输出,生成输入串,作为LL(1)分析程序的输入。

  1. 验证LL(1)文法分析程序:

        运行LL(1)分析程序,输入专题1词法分析程序的输出作为输入串。

        验证LL(1)文法分析程序对给定赋值语句的正确性,确保输出符合LL(1)文法规则。

  1. 设计测试用例:

        设计至少四个测试用例,包括正确的赋值语句和具有语法错误的情况。

        测试用例应覆盖文法的不同产生式和可能的错误情况。

  1. 执行测试用例:

        依次执行设计的测试用例,观察LL(1)分析程序的输出。

        记录每个测试用例的执行结果,包括正确的情况和出错的情况。

  1. 分析实验结果:

        分析测试用例的执行结果,验证LL(1)文法分析程序的准确性和健壮性。

        如有出错情况,分析错误的原因并调整程序。

  1. 总结与报告:

        撰写实验报告,总结实验过程中的关键步骤、问题和解决方案。

        提供测试用例的执行结果,讨论实验的有效性和可能的改进方向。

    1. 程序结构描述

总体程序结构流程图如下:

代码编写

根据读取的文法文件,拆分产生式并判断输出终结符号和非终结符号

 // 记录Vn集合和Vt集合及其在分析表中的下标
    for (map<string, vector<string>>::iterator it = grammar.begin(); it != grammar.end(); ++it) 
    {
        pair<string,vector<string>> temp = *it;

        Vn.insert(temp.first);
        VnIndex[temp.first] = cntVn++;

        vector<string> production = temp.second;
		for(vector<string>::iterator iit = production.begin();iit!=production.end();iit++)
		{
			string ss= *iit;
			for (int j = 0; j < ss.length(); j++) 
        	{            	
                //记录产生式中的非终结符和终结符
                if (ss[j] >= 'A' && ss[j] <= 'Z') 
                { // 大写字母
                    if (ss[j + 1] == '\'') 
                    {          // 有'则读入俩作为一个非终结符
                        Vn.insert(ss.substr(j, 2));                       
                        j++;
                    } 
                    else
                    {
                        Vn.insert(ss.substr(j, 1));                        
                    }
                }
                else
                {   
                    Vt.insert(ss.substr(j, 1)); // 是终结符
                    string v = ss.substr(j, 1) ;
                    if(v != "" && VtIndex[v]==0)
                        VtIndex[v] = cntVt++;                   
                }
            }
        	
		}       
    }

根据读取的文法,获取非终结符号的first集合和follow集合

// 判断是否是终结符
bool isVt(const string& symbol) {
    return Vt.count(symbol);
}

// 计算 First 集
map<string, set<string>> calculateFirstSet() 
{
    map<string, set<string>> firstSet;

    // 初始化非终结符的 First 集
    for (map<string,vector<string>>::iterator entry=grammar.begin();entry!=grammar.end();entry++) 
	{
        firstSet[entry->first] = {};
		for(vector<string>::iterator production = entry->second.begin(); production!=entry->second.end(); production++) //若每个右部第一个字母是终结符则直接加入
		{
			string s = *production;
			if(isVt(s.substr(0,1)))
				firstSet[entry->first].insert(s.substr(0,1));
		}
    }

    bool changes = true;
    while (changes) 
	{
        changes = false;

        for (map<string,vector<string>>::iterator entry=grammar.begin();entry!=grammar.end();entry++) 
		{
            string nonTerminal = entry->first;
			int originalSize = firstSet[nonTerminal].size();
            for (vector<string>::iterator it = entry->second.begin(); it!=entry->second.end(); it++) 
			{
				string production = *it; // 一个产生式右部
				int i;
				for(i=0; i<production.length(); i++)
				{	
					if(isupper(production[i]))// 如果是非终结符
					{
						string vn = " ";
						bool flag = false;
						vn[0] = production[i];

						if(production[i+1] == '\'')
						{
							vn = vn + "\'";
							for(set<string>::iterator fi = firstSet[vn].begin(); fi!= firstSet[vn].end();fi++)
							{
								if(*fi == "")
									flag = true;
								else
									firstSet[nonTerminal].insert(*fi);
							}                    		
							i++;
						}
						else
						{
							for(set<string>::iterator fi = firstSet[vn].begin(); fi!= firstSet[vn].end();fi++)
							{
								if(*fi == "")
									flag = true;
								else
									firstSet[nonTerminal].insert(*fi);
							}
                    		if (firstSet[nonTerminal].size() != originalSize) 
							{
                        		changes = true;
                    		}
						}
						if(!flag) // 如何无ε则跳出
							break;
					}
					else// 如果是终结符
						break;
				}
                if (i == production.length()) 
				{ 	
                    firstSet[nonTerminal].insert("");
                } 				
            }
			if (firstSet[nonTerminal].size() != originalSize) //若first改变,则继续迭代
			{
                changes = true;
            }
        }
		
    }

    return firstSet;
}

// 计算 Follow 集
map<string, set<string>> calculateFollowSet() 
{
    map<string, set<string>> followSet;
	map<string,int> originalSize; //前一次迭代follow集大小

    // 初始化非终结符的 Follow 集
    for (auto const& entry : grammar) 
	{
        followSet[entry.first] = {};
    }
	followSet["S"].insert("#");

    bool changes = true;
    while (changes) 
	{
        changes = false;		
        for (map<string,vector<string>>::iterator entry=grammar.begin();entry!=grammar.end();entry++) 
		{
            string nonTerminal = entry->first;
			originalSize[nonTerminal] = followSet[nonTerminal].size();
            for (vector<string>::iterator it = entry->second.begin(); it!=entry->second.end(); it++) 
			{
				string production = *it;
                for (int i = 0; i < production.size(); i++) 
				{
                    if(isupper(production[i]))// 如果是非终结符
					{
						string vn = " ";						
						vn[0] = production[i];

						if(production[i+1] == '\'')
						{
							vn = vn + "\'";							              		
							i++;
						}

						string las = production.substr(i+1);
						if(las != "")
						{
							int j ;
							for(j = 0 ;j< las.length();j++)
							{
								if(isupper(las[j])) // 如果是非终结符
								{
									string vnn = " ";
									bool flag = false;
									vnn[0] = las[j];

									if(las[j+1]=='\'')
									{
										vnn = vnn + "\'";
										j++;
									}

									for(set<string>::iterator fi = first[vnn].begin(); fi!= first[vnn].end();fi++)
									{
										if(*fi == "")
											flag= true;
										else
											followSet[vn].insert(*fi);
									}

									if(!flag)
										break;

								}
								else
								{									
									followSet[vn].insert(string(1,las[j]));
									break;
								}
							}

							if(j == las.length())
							{
								for(set<string>::iterator fo = followSet[nonTerminal].begin(); fo!= followSet[nonTerminal].end();fo++)
									followSet[vn].insert(*fo);
							}
						}
						else
						{
							for(set<string>::iterator fo = followSet[nonTerminal].begin(); fo!= followSet[nonTerminal].end();fo++)
								followSet[vn].insert(*fo);
						}
					}
                }
            }	
        }
		for (map<string,vector<string>>::iterator entry=grammar.begin();entry!=grammar.end();entry++) 
		{
			if (followSet[entry->first].size() != originalSize[entry->first]) //若follow改变,则继续迭代
			{
                changes = true;
				break;
            }
		}		
    }

    return followSet;
}

根据计算完成的first集合和follow集合,结合产生式,输出分析表

// 构造LL(1)分析表
void parseTable() 
{
    for (map<string, vector<string>>::iterator it = grammar.begin(); it != grammar.end(); it++) 
    {
        int vnidx = VnIndex[it->first];
        for (vector<string>::iterator tmp = it->second.begin(); tmp != it->second.end(); tmp++) 
        {
            string str = *tmp; // 右部
            if(str == "")    //为空则将follow(left)中元素填入left->^
            {
                for(set<string>::iterator b=follow[it->first].begin();b!=follow[it->first].end();b++)
                {
                    if (isVt(*b)) 
                    {
                        table[vnidx][VtIndex[*b]] = "";                               
                    }
                }
            }
            else if (isVt(str.substr(0, 1))) //产生式右部第一个字符是终结符
                table[vnidx][VtIndex[str.substr(0, 1)]] = str;
            else //产生式右部第一个字符是非终结符,遍历其first集
            {
                string::iterator iit;
                for(iit = str.begin();iit != str.end();)
                {
                    string vn = " ";
                    bool flag=false;
                    vn[0] = *iit;
                    iit++;
                    if(*iit == '\'')
                    {
                        vn = vn+ "\'";
                        iit++;
                    }
                    
                    for(set<string>::iterator fi=first[vn].begin();fi!=first[vn].end();fi++)
                    {
                        if(*fi =="")
                            flag= true;
                        else
                            table[vnidx][VtIndex[*fi]] = str;
                    }
                    if(!flag)
                        break;
                }

                if(iit == str.end())//遍历其follow集合
                {
                    for(set<string>::iterator b=follow[it->first].begin();b!=follow[it->first].end();b++)
                    {
                        if (isVt(*b)) 
                        {
                            table[vnidx][VtIndex[*b]] = "";                               
                        }
                    }
                }                
                
            }
        }
    }
}

对表达式进行LL(1)分析(TEST1合法)

// 读取二元式文件并进行LL(1)分析
void analyzeExpression(const char* expressionFile) 
{
    cout<<"读取文件可知输入语句:"<<endl;
	FILE *fp;
	char buf[1024];
	string shizi,like;
	if((fp = fopen(expressionFile,"r"))!=NULL)
	{
		while(fgets(buf,1024,fp) != NULL)
		{
			int len = strlen(buf);
		 	buf[len-1] = '\0';  /*去掉换行符*/
		 	printf("%s \n",buf);
		 	
		 	if(buf[2]=='0') // 说明为标识符
			{
		 		like += 'i';		 		
			}			
		 	for(int i=5;i<len-2;i++)
			{
				shizi= shizi + buf[i];
		 		if(buf[2]!='0')
				{
		 			like+=buf[i];
				}
			}
		}
	}
	shizi += '#';
	like += '#';
	fclose(fp);
	
	cout<<"输入的语句为:"<<shizi<<endl;
	cout<<"可以理解为:"<<like<<endl;

    cout << "LL(1)分析结果:" << endl;

    string expression = like;
    string result = "ACCEPT";
    string topOfStack = "S#";

    while (topOfStack.size()>1 && result == "ACCEPT") 
    {
        char nextSymbol = expression[0];
        
        if (isVt(topOfStack.substr(0,1))) 
        {
            if (nextSymbol == topOfStack[0]) 
            {
                cout << "Match: " << nextSymbol << endl;
                expression = expression.substr(1);
                topOfStack = topOfStack.substr(1);
            } 
            else 
            {
                result = "REJECT";
                cout << "Error: Mismatch for symbol " << nextSymbol << endl;
            }
        } 
        else 
        {
            string vn = " ",vt=" ";
            int idx = 0;

            vn[0] = topOfStack[idx++];
            vt[0] = nextSymbol;
            if(topOfStack[idx] =='\'')
                vn = vn+topOfStack[idx++];

            string production = table[VnIndex[vn]][VtIndex[vt]];
            cout << "Apply production: " << production << endl;

            if (production != "") 
            {
                // 非空产生式,将产生式右部压入栈
                topOfStack = topOfStack.substr(idx);
                for (int i = production.length() - 1; i >= 0; i--) 
                {                        
                    cout << "Push: " << production[i] << endl;
                    topOfStack = production[i] + topOfStack;
                }
            }
            else
                topOfStack = topOfStack.substr(idx);
        }
        cout<<topOfStack<<"\t\t\t"<<expression<<endl;
    }

    if (topOfStack.size()==1&&expression.size()==1&&result == "ACCEPT") 
    {
        cout << "Expression Accepted" << endl;
    } 
    else 
    {
        cout << "Expression Rejected" << endl;
    }

    cout << "--------------------------" << endl;
}


完整代码 

#include <iostream>
#include <fstream>
#include <set>
#include <map>
#include <vector>
#include <string>
#include<cstring>

using namespace std;

string line;
set<string> Vt; // 终结符集合
set<string> Vn; // 非终结符集合
map<string, set<string>> first; // FIRST集合
map<string, set<string>> follow; // FOLLOW集合
map<string,int>VnIndex; //分析表中Vn的下标
map<string,int>VtIndex; //分析表中Vt的下标
vector<vector<string>> table; // LL(1)分析表

// 定义文法规则
map<string, vector<string>> grammar = {
    {"S", {"V=E"}},
    {"E", {"TE\'"}},
    {"E\'", {"ATE\'", ""}},
    {"T", {"FT\'"}},
	{"T\'",{"MFT\'",""}},
	{"F",{"(E)","i"}},
    {"A", {"+", "-"}},
    {"M", {"*", "/"}},
    {"V", {"i"}}
};

// 判断是否是非终结符
bool isVn(const string& symbol) {
    return Vn.count(symbol);
}

// 判断是否是终结符
bool isVt(const string& symbol) {
    return Vt.count(symbol);
}

// 计算 First 集
map<string, set<string>> calculateFirstSet() 
{
    map<string, set<string>> firstSet;

    // 初始化非终结符的 First 集
    for (map<string,vector<string>>::iterator entry=grammar.begin();entry!=grammar.end();entry++) 
	{
        firstSet[entry->first] = {};
		for(vector<string>::iterator production = entry->second.begin(); production!=entry->second.end(); production++) //若每个右部第一个字母是终结符则直接加入
		{
			string s = *production;
			if(isVt(s.substr(0,1)))
				firstSet[entry->first].insert(s.substr(0,1));
		}
    }

    bool changes = true;
    while (changes) 
	{
        changes = false;

        for (map<string,vector<string>>::iterator entry=grammar.begin();entry!=grammar.end();entry++) 
		{
            string nonTerminal = entry->first;
			int originalSize = firstSet[nonTerminal].size();
            for (vector<string>::iterator it = entry->second.begin(); it!=entry->second.end(); it++) 
			{
				string production = *it; // 一个产生式右部
				int i;
				for(i=0; i<production.length(); i++)
				{	
					if(isupper(production[i]))// 如果是非终结符
					{
						string vn = " ";
						bool flag = false;
						vn[0] = production[i];

						if(production[i+1] == '\'')
						{
							vn = vn + "\'";
							for(set<string>::iterator fi = firstSet[vn].begin(); fi!= firstSet[vn].end();fi++)
							{
								if(*fi == "")
									flag = true;
								else
									firstSet[nonTerminal].insert(*fi);
							}                    		
							i++;
						}
						else
						{
							for(set<string>::iterator fi = firstSet[vn].begin(); fi!= firstSet[vn].end();fi++)
							{
								if(*fi == "")
									flag = true;
								else
									firstSet[nonTerminal].insert(*fi);
							}
                    		if (firstSet[nonTerminal].size() != originalSize) 
							{
                        		changes = true;
                    		}
						}
						if(!flag) // 如何无ε则跳出
							break;
					}
					else// 如果是终结符
						break;
				}
                if (i == production.length()) 
				{ 	
                    firstSet[nonTerminal].insert("");
                } 				
            }
			if (firstSet[nonTerminal].size() != originalSize) //若first改变,则继续迭代
			{
                changes = true;
            }
        }
		
    }

    return firstSet;
}

// 计算 Follow 集
map<string, set<string>> calculateFollowSet() 
{
    map<string, set<string>> followSet;
	map<string,int> originalSize; //前一次迭代follow集大小

    // 初始化非终结符的 Follow 集
    for (auto const& entry : grammar) 
	{
        followSet[entry.first] = {};
    }
	followSet["S"].insert("#");

    bool changes = true;
    while (changes) 
	{
        changes = false;		
        for (map<string,vector<string>>::iterator entry=grammar.begin();entry!=grammar.end();entry++) 
		{
            string nonTerminal = entry->first;
			originalSize[nonTerminal] = followSet[nonTerminal].size();
            for (vector<string>::iterator it = entry->second.begin(); it!=entry->second.end(); it++) 
			{
				string production = *it;
                for (int i = 0; i < production.size(); i++) 
				{
                    if(isupper(production[i]))// 如果是非终结符
					{
						string vn = " ";						
						vn[0] = production[i];

						if(production[i+1] == '\'')
						{
							vn = vn + "\'";							              		
							i++;
						}

						string las = production.substr(i+1);
						if(las != "")
						{
							int j ;
							for(j = 0 ;j< las.length();j++)
							{
								if(isupper(las[j])) // 如果是非终结符
								{
									string vnn = " ";
									bool flag = false;
									vnn[0] = las[j];

									if(las[j+1]=='\'')
									{
										vnn = vnn + "\'";
										j++;
									}

									for(set<string>::iterator fi = first[vnn].begin(); fi!= first[vnn].end();fi++)
									{
										if(*fi == "")
											flag= true;
										else
											followSet[vn].insert(*fi);
									}

									if(!flag)
										break;

								}
								else
								{									
									followSet[vn].insert(string(1,las[j]));
									break;
								}
							}

							if(j == las.length())
							{
								for(set<string>::iterator fo = followSet[nonTerminal].begin(); fo!= followSet[nonTerminal].end();fo++)
									followSet[vn].insert(*fo);
							}
						}
						else
						{
							for(set<string>::iterator fo = followSet[nonTerminal].begin(); fo!= followSet[nonTerminal].end();fo++)
								followSet[vn].insert(*fo);
						}
					}
                }
            }	
        }
		for (map<string,vector<string>>::iterator entry=grammar.begin();entry!=grammar.end();entry++) 
		{
			if (followSet[entry->first].size() != originalSize[entry->first]) //若follow改变,则继续迭代
			{
                changes = true;
				break;
            }
		}		
    }

    return followSet;
}

// 构造LL(1)分析表
void parseTable() 
{
    for (map<string, vector<string>>::iterator it = grammar.begin(); it != grammar.end(); it++) 
    {
        int vnidx = VnIndex[it->first];
        for (vector<string>::iterator tmp = it->second.begin(); tmp != it->second.end(); tmp++) 
        {
            string str = *tmp; // 右部
            if(str == "")    //为空则将follow(left)中元素填入left->^
            {
                for(set<string>::iterator b=follow[it->first].begin();b!=follow[it->first].end();b++)
                {
                    if (isVt(*b)) 
                    {
                        table[vnidx][VtIndex[*b]] = "";                               
                    }
                }
            }
            else if (isVt(str.substr(0, 1))) //产生式右部第一个字符是终结符
                table[vnidx][VtIndex[str.substr(0, 1)]] = str;
            else //产生式右部第一个字符是非终结符,遍历其first集
            {
                string::iterator iit;
                for(iit = str.begin();iit != str.end();)
                {
                    string vn = " ";
                    bool flag=false;
                    vn[0] = *iit;
                    iit++;
                    if(*iit == '\'')
                    {
                        vn = vn+ "\'";
                        iit++;
                    }
                    
                    for(set<string>::iterator fi=first[vn].begin();fi!=first[vn].end();fi++)
                    {
                        if(*fi =="")
                            flag= true;
                        else
                            table[vnidx][VtIndex[*fi]] = str;
                    }
                    if(!flag)
                        break;
                }

                if(iit == str.end())//遍历其follow集合
                {
                    for(set<string>::iterator b=follow[it->first].begin();b!=follow[it->first].end();b++)
                    {
                        if (isVt(*b)) 
                        {
                            table[vnidx][VtIndex[*b]] = "";                               
                        }
                    }
                }                
                
            }
        }
    }
}

// 读取二元式文件并进行LL(1)分析
void analyzeExpression(const char* expressionFile) 
{
    cout<<"读取文件可知输入语句:"<<endl;
	FILE *fp;
	char buf[1024];
	string shizi,like;
	if((fp = fopen(expressionFile,"r"))!=NULL)
	{
		while(fgets(buf,1024,fp) != NULL)
		{
			int len = strlen(buf);
		 	buf[len-1] = '\0';  /*去掉换行符*/
		 	printf("%s \n",buf);
		 	
		 	if(buf[2]=='0') // 说明为标识符
			{
		 		like += 'i';		 		
			}			
		 	for(int i=5;i<len-2;i++)
			{
				shizi= shizi + buf[i];
		 		if(buf[2]!='0')
				{
		 			like+=buf[i];
				}
			}
		}
	}
	shizi += '#';
	like += '#';
	fclose(fp);
	
	cout<<"输入的语句为:"<<shizi<<endl;
	cout<<"可以理解为:"<<like<<endl;

    cout << "LL(1)分析结果:" << endl;

    string expression = like;
    string result = "ACCEPT";
    string topOfStack = "S#";

    while (topOfStack.size()>1 && result == "ACCEPT") 
    {
        char nextSymbol = expression[0];
        
        if (isVt(topOfStack.substr(0,1))) 
        {
            if (nextSymbol == topOfStack[0]) 
            {
                cout << "Match: " << nextSymbol << endl;
                expression = expression.substr(1);
                topOfStack = topOfStack.substr(1);
            } 
            else 
            {
                result = "REJECT";
                cout << "Error: Mismatch for symbol " << nextSymbol << endl;
            }
        } 
        else 
        {
            string vn = " ",vt=" ";
            int idx = 0;

            vn[0] = topOfStack[idx++];
            vt[0] = nextSymbol;
            if(topOfStack[idx] =='\'')
                vn = vn+topOfStack[idx++];

            string production = table[VnIndex[vn]][VtIndex[vt]];
            cout << "Apply production: " << production << endl;

            if (production != "") 
            {
                // 非空产生式,将产生式右部压入栈
                topOfStack = topOfStack.substr(idx);
                for (int i = production.length() - 1; i >= 0; i--) 
                {                        
                    cout << "Push: " << production[i] << endl;
                    topOfStack = production[i] + topOfStack;
                }
            }
            else
                topOfStack = topOfStack.substr(idx);
        }
        cout<<topOfStack<<"\t\t\t"<<expression<<endl;
    }

    if (topOfStack.size()==1&&expression.size()==1&&result == "ACCEPT") 
    {
        cout << "Expression Accepted" << endl;
    } 
    else 
    {
        cout << "Expression Rejected" << endl;
    }

    cout << "--------------------------" << endl;
}

int main() 
{
    int cntVt = 0,cntVn = 0;

    // 记录Vn集合和Vt集合及其在分析表中的下标
    for (map<string, vector<string>>::iterator it = grammar.begin(); it != grammar.end(); ++it) 
    {
        pair<string,vector<string>> temp = *it;

        Vn.insert(temp.first);
        VnIndex[temp.first] = cntVn++;

        vector<string> production = temp.second;
		for(vector<string>::iterator iit = production.begin();iit!=production.end();iit++)
		{
			string ss= *iit;
			for (int j = 0; j < ss.length(); j++) 
        	{            	
                //记录产生式中的非终结符和终结符
                if (ss[j] >= 'A' && ss[j] <= 'Z') 
                { // 大写字母
                    if (ss[j + 1] == '\'') 
                    {          // 有'则读入俩作为一个非终结符
                        Vn.insert(ss.substr(j, 2));                       
                        j++;
                    } 
                    else
                    {
                        Vn.insert(ss.substr(j, 1));                        
                    }
                }
                else
                {   
                    Vt.insert(ss.substr(j, 1)); // 是终结符
                    string v = ss.substr(j, 1) ;
                    if(v != "" && VtIndex[v]==0)
                        VtIndex[v] = cntVt++;                   
                }
            }
        	
		}       
    }

    Vt.insert("#");
    VtIndex["#"] = cntVt++;
    table.resize(Vn.size(), vector<string>(Vt.size(), ""));

    // 求first集合
	first = calculateFirstSet();
	// 求follow集合
	follow = calculateFollowSet();

	// 输出Vn集合
    cout << "Vn集合: ";
    for (set<string>::iterator it = Vn.begin(); it != Vn.end(); it++) 
		cout << *it << ' ';
	cout<<endl;

	// 输出Vt集合
	cout << "Vt集合: ";
	for (set<string>::iterator it = Vt.begin(); it != Vt.end(); it++) 
		cout << *it << ' ';
	cout<<endl;	

	// 输出First集合
    cout << "First集合: " << endl;
    for (map<string, set<string>>::iterator it = first.begin(); it != first.end(); it++) 
	{
        cout << it->first << ": ";
        for (set<string>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) {
            cout << '\"'<< *it2 <<'\"'<< " ";
        }
        cout << endl;
    }

    // 输出Follow集合
    cout << "Follow集合: " << endl;
    for (map<string, set<string>>::iterator it = follow.begin(); it != follow.end(); it++) {
        cout << it->first << ": ";
        for (set<string>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) {
            cout << '\"'<< *it2 <<'\"'<< " ";
        }
        cout << endl;
    }

    // 构造LL(1)分析表
    parseTable();

    // 输出LL(1)分析表
    cout << "-------------LL(1)分析表------------------" << endl;
    cout<<"--------------------------------------------"<<endl;
    cout<<"\t|";
    for(set<string>::iterator vt=Vt.begin();vt!=Vt.end();vt++)
    {
        cout<<*vt<<"\t|";
    }
    cout<<endl;
    for (map<string, vector<string>>::iterator it = grammar.begin(); it != grammar.end(); it++)
    {
        cout<<it->first<<"\t|";
        for (int j = 0; j < Vt.size(); j++) 
        {
            cout << table[VnIndex[it->first]][j] << "\t|";
        }
        cout << endl;
    }


    // 读取二元式文件并进行LL(1)分析
    analyzeExpression("lab3_4_out.txt");

    return 0;
    
}

  • 25
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

天之交子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值