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.
58 lines
1.4 KiB
58 lines
1.4 KiB
1 year ago
|
//
|
||
|
// Created by lenfrex on 2023/5/8.
|
||
|
//
|
||
|
|
||
|
#include "Grammar.h"
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
// 求是否有交集
|
||
|
bool hasUnion(const set<char> &a, const set<char> &b) {
|
||
|
for (const auto &selectChars: b) {
|
||
|
if (a.contains(selectChars)) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// 检查是否为LL1文法
|
||
|
bool Grammar::isLL1Grammar() {
|
||
|
// 逐个非终止符检查
|
||
|
for (const auto &nonTerminal: nonTerminals) {
|
||
|
SelectSet select = selectSet[nonTerminal];
|
||
|
|
||
|
// 取一行
|
||
|
for (auto current = select.begin(); current != select.end();) {
|
||
|
const auto &productionSelectSet = current->second;
|
||
|
// 取剩下的行进行比较,注意这里已经++current了,外层for就不要++了
|
||
|
for (auto innerCurrent = ++current; innerCurrent != select.end(); innerCurrent++) {
|
||
|
if (hasUnion(productionSelectSet, innerCurrent->second)) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void Grammar::buildAnalysisTable() {
|
||
|
if (!isLL1Grammar()) {
|
||
|
throw NotSupportedGrammarException("文法定义不符合LL1文法");
|
||
|
}
|
||
|
|
||
|
for (const auto &nonTerminal: nonTerminals) {
|
||
|
SelectSet select = selectSet[nonTerminal];
|
||
|
for (const auto &selectPair: select) {
|
||
|
const auto &prod = selectPair.first;
|
||
|
const auto &selectChars = selectPair.second;
|
||
|
|
||
|
// 填充预测分析表
|
||
|
for (const auto &selectableTerminal: selectChars) {
|
||
|
analysisTable[nonTerminal][selectableTerminal] = prod;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|