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
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);
|
||
|
}
|
||
|
}
|
||
|
}
|