某个编译原理的实验代码存档
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
2.9 KiB

2 years ago
//
// Created by lenfrex on 2023/5/8.
//
#include "Grammar.h"
using namespace std;
#define isEmptyStr(c) (c == '~')
void Grammar::generateSelectSet() {
// 处理每一个非终止符,以取得产生式
for (const auto &leftNonTerminal: nonTerminals) {
if (!productionsMap.contains(leftNonTerminal)) {
continue;
}
const set<string> &productions = productionsMap.at(leftNonTerminal);
// 解析非终止符的每个产生式
for (const auto &production: productions) {
ExpressSelectSet productionSelectSet = ExpressSelectSet();
productionSelectSet.first = production;
productionSelectSet.second = set<char>();
// 解析产生式,一个一个字符处理
for (auto currPos = production.begin(); currPos != production.end(); currPos++) {
char currChar = *currPos;
// 如果当前字符是终止符
// - 是空串,把产生式左部非终止符(即A->a...中的A, 此处即为leftNonTerminal)的follow加到当前产生式的select中(productionSelectSet);
// - 不是空串,就直接把这个符号加入到当前产生式的select
//
// 如果是非终结符把,则把当前字符的first删去空串之后加入当前产生式的select中
// - 当前非终止符可以推出空串,就继续往后解析处理当前非终止符为空时的情况;
// - 如果是最后一个字符,把产生式左部follow加当前产生式的select中;
// - 如果不是最后一个字符,则继续看下一个字符(continue)
// - 不能推出空串,说明该条产生式select集合的计算结束(break)
if (terminals.contains(currChar)) {
if (isEmptyStr(currChar)) {
productionSelectSet.second.insert(followSet[leftNonTerminal].begin(), followSet[leftNonTerminal].end());
} else {
productionSelectSet.second.insert(currChar);
}
break;
} else {
// 前字符的first删去空串之后加入到产生式的select中
set<char> currFirst = firstSet[currChar];
currFirst.erase('~');
productionSelectSet.second.insert(currFirst.begin(), currFirst.end());
// 如果当前字符能推出空串,就看看下一个字符怎么样
// 不能推出空串就break退出
if (canDeducedEmpty(productionsMap.at(currChar))) {
// 如果现在的这个字符已经是产生式末尾了,就把产生式左部follow加进去
// 否则转到下一个字符
auto next = currPos + 1;
if (next == production.end()) {
productionSelectSet.second.insert(followSet[leftNonTerminal].begin(), followSet[leftNonTerminal].end());
} else {
continue;
}
} else {
break;
}
}
}
selectSet[leftNonTerminal].insert(productionSelectSet);
}
}
}