合工大 编译原理实验二 LL(1)文法
本实验为必做实验,使用C++开发,利用Windows API制作了简易的界面。
基本功能:
- 支持自定义文法
- 多个显示窗口,支持显示FIRST集、FOLLOW集、状态转换表、分析表
- 支持直接/间接左递归文法转化为LL(1)文法后识别
详细功能,示例截图、项目代码请见GitHub页面:LL(1)文法
部分核心代码如下:
- 消除直接/间接左递归
/******************************************************************************
* 函数名: ChecktoEraseRecursion
* 函数功能: 计算是否文法含有直间接左递归,并得出消去左递归后的文法
* 传入参数: void
* 传出参数: result ChecktoEraseRecursion_result
*******************************************************************************/
ChecktoEraseRecursion_result CheckLL1class::ChecktoEraseRecursion() {
ChecktoEraseRecursion_result result;
//非终结符集合
std::map<std::string, std::string> CheckGrammarFormula;
int stepcounter = 4000;
result.isNeedToTransfer = false;
result.CheckGrammarFormula.clear();
CheckGrammarFormula.insert(GrammarFormula.begin(), GrammarFormula.end());
bool record = 1;
for (auto i = CheckGrammarFormula.begin(); i != CheckGrammarFormula.end(); i++) {
VnSet.insert(i->second.at(0));
}
//auto mosti = VnSet.rend(); //最高终结符
//mosti--;
for (auto i = VnSet.rbegin(); i != VnSet.rend()/*mosti*/; i++) { //按顺序排列非终结符,并指定一非终结符,消去其余非终结符,从而观察是否含有左递归
if (*i == mostcharacter)
continue;
for (auto ii = CheckGrammarFormula.begin(); ii != CheckGrammarFormula.end() && stepcounter>0; ii++, stepcounter--) {
std::string tmp="";
int catchpos=(int)ii->first.find(*i);
if (catchpos >= 0) {
for (auto formulaofi = CheckGrammarFormula.begin(); formulaofi != CheckGrammarFormula.end() && stepcounter>0; stepcounter--) {
if (formulaofi->second.at(0) == *i) {
tmp = ii->first.substr(0, catchpos);
tmp += formulaofi->first;
tmp += ii->first.substr((int)catchpos + 1, tmp.length());
CheckGrammarFormula.insert(std::make_pair(tmp,ii->second));
//auto oldformulaofi = formulaofi; //临时变量,要消除的变量
formulaofi++;
//CheckGrammarFormula.erase(oldformulaofi);
}
else {
formulaofi++;
}
}
}
}
}
if (stepcounter <= 0) {
return result;
}
auto i = VnSet.rbegin();
for (; i != VnSet.rend()/*mosti*/; i++) {
if (*i == mostcharacter)
continue;
for (auto ii = CheckGrammarFormula.begin(); ii != CheckGrammarFormula.end();) { //删除含其他符号的多余表达式
int thepos =ii->first.find(*i);
if (thepos >= 0 || ii->second.at(0)==*i) {
auto oldii = ii;
ii++;
CheckGrammarFormula.erase(oldii);
}
else {
ii++;
}
}
}
char newchar; //新增的非终结符
for (newchar = 'A'; newchar <= 'Z'; newchar++) {
if (newchar != CheckGrammarFormula.begin()->second.at(0)) {
break;
}
}
for (auto i = CheckGrammarFormula.begin(); i != CheckGrammarFormula.end();) { //查看是否含有左递归
if (i->first.at(0) == i->second.at(0)) {
result.isNeedToTransfer = true;
std::string tmpstring = i->first.substr(1, i->first.length());
tmpstring += newchar;
result.CheckGrammarFormula.insert(std::make_pair(tmpstring, std::string{ newchar }));
result.CheckGrammarFormula.insert(std::make_pair(std::string{ NULLCHARACTER }, std::string{ newchar }));
auto oldi = i;
i++;
CheckGrammarFormula.erase(oldi);
}
else {
std::string tmpstring = i->first;
tmpstring += newchar;
result.CheckGrammarFormula.insert(std::make_pair(tmpstring, i->second));
auto oldi = i;
i++;
CheckGrammarFormula.erase(oldi);
}
}
return result;
}
- FOLLOW集计算
/******************************************************************************
* 函数名: getFOLLOWsets
* 函数功能: 获取FOLLOW集
* 传入参数: void
* 传出参数: void
*******************************************************************************/
void CheckLL1class::getFOLLOWsets() {
std::set<std::string> tmptotalbuildsymbol;
for (auto i = GrammarFormula.begin(); i != GrammarFormula.end(); i++) {
tmptotalbuildsymbol.insert(i->second);
}
std::map<char, std::map<char, bool>> FirstLinear, FollowLinear; //First集约束条件, Follow集约束条件
for (auto i = GrammarFormula.begin(); i != GrammarFormula.end(); i++) {
auto theend = i->first.rend();
theend--;
for (auto t = i->first.rbegin(); t != theend; t++) {
if (tmptotalbuildsymbol.find(std::string{ *(t + 1) }) != tmptotalbuildsymbol.end()) {
if(tmptotalbuildsymbol.find(std::string{ *(t) }) != tmptotalbuildsymbol.end())
//FirstLinear[*t][*(t + 1)] = true;
FOLLOWset[*(t + 1)].insert(FIRSTset[*t].begin(), FIRSTset[*t].end());
else
FOLLOWset[*(t+1)].insert(*t);
FOLLOWset[*(t + 1)].erase(NULLCHARACTER);
}
}
}
for (auto i = GrammarFormula.begin(); i != GrammarFormula.end(); i++) {
for (auto t = i->first.rbegin(); t != i->first.rend(); t++) {
if (tmptotalbuildsymbol.find(std::string{ *t }) != tmptotalbuildsymbol.end() || *t ==NULLCHARACTER) {
if(*t != NULLCHARACTER && i->second.at(0) != *t)
FollowLinear[i->second.at(0)][*t] = true;
if (*t != NULLCHARACTER && FIRSTset[*t].find(NULLCHARACTER) == FIRSTset[*t].end()) { //不包含空集
break;
}
}
else {
break;
}
}
}
while (FollowLinear.size() > 0) {
for (auto i = tmptotalbuildsymbol.begin(); i != tmptotalbuildsymbol.end();) {
bool isOK = true;
for (auto ii = FollowLinear.begin(); ii != FollowLinear.end(); ii++) {
if (ii->second.find(i->at(0)) != ii->second.end()) {
isOK = false;
}
}
if (isOK == true) {
//for (auto ii = FirstLinear[i->at(0)].begin(); ii != FirstLinear[i->at(0)].end(); ii++) {
// FOLLOWset[i->at(0)].insert(FIRSTset[ii->first].begin(), FIRSTset[ii->first].end());
//}
for (auto ii = FollowLinear[i->at(0)].begin(); ii != FollowLinear[i->at(0)].end(); ii++) {
FOLLOWset[ii->first].insert(FOLLOWset[i->at(0)].begin(), FOLLOWset[i->at(0)].end());
}
auto tmp = i;
i++;
FollowLinear.erase(tmp->at(0));
}
else {
i++;
}
}
}
}