实验目的与内容
实验目的
- 了解语法分析的设计方法与实现原理:深入理解编译原理中LL(1)文法的语法分析方法,为编译器设计与实现奠定基础。
- 构造LL(1)文法分析表:编写LL(1)分析程序,利用构造的LL(1)文法分析表对输入串进行语法分析,实现分析过程中的控制程序。
- 实现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的原因如下:
- 跨平台支持: Visual Studio Code 支持 Windows、macOS 和 Linux 操作系统,使得开发者可以在不同平台上保持一致的开发环境,提高跨平台开发的效率。
- 轻量高效: VSC 是一款轻量级的代码编辑器,启动速度快,占用系统资源少。
- 强大的扩展生态系统: VSC具有丰富的扩展插件,开发者可以根据自己的需要选择并安装扩展,定制化编辑器,使其满足特定的开发需求。这也促使了VSC的生态系统的不断发展和壮大。
- 语言支持广泛: VSC支持多种编程语言,并且对不同语言的语法高亮、自动补全等功能提供了良好的支持。这使得它适用于多种开发场景,从前端到后端,从移动端到云端。
- 强大的调试功能: VSC提供了强大的调试工具,支持多种语言的调试,并且能够与多种调试器集成,使得开发者能够更轻松地进行代码调试。
图1 IDE界面展示
实验过程
实验步骤
- 构造LL(1)文法分析表:
定义给定文法 G[S]。
计算文法的FIRST集合,包括非终结符和终结符的FIRST集合。
计算文法的FOLLOW集合。
利用FIRST和FOLLOW集合构造LL(1)文法分析表。
- 编写LL(1)语法分析程序:
实现LL(1)分析程序的数据结构,包括文法规则、FIRST集合、FOLLOW集合等。
编写LL(1)分析程序的核心算法,根据文法分析表进行LL(1)语法分析。
实现出错检测机制,确保程序能够发现输入串中的语法错误。
- 准备输入串:
利用专题1词法分析程序的输出,生成输入串,作为LL(1)分析程序的输入。
- 验证LL(1)文法分析程序:
运行LL(1)分析程序,输入专题1词法分析程序的输出作为输入串。
验证LL(1)文法分析程序对给定赋值语句的正确性,确保输出符合LL(1)文法规则。
- 设计测试用例:
设计至少四个测试用例,包括正确的赋值语句和具有语法错误的情况。
测试用例应覆盖文法的不同产生式和可能的错误情况。
- 执行测试用例:
依次执行设计的测试用例,观察LL(1)分析程序的输出。
记录每个测试用例的执行结果,包括正确的情况和出错的情况。
- 分析实验结果:
分析测试用例的执行结果,验证LL(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;
}