某个编译原理的实验代码存档
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.
 
 
compile-work/parser/Checker.cpp

143 lines
4.5 KiB

#include <iomanip>
#include <utility>
#include "iostream"
#include "Checker.h"
using namespace std;
#define isEmptyStr(c) (c == '~')
// 能否推导出空串
bool Checker::canDeducedEmpty(const set<string> &productions) {
for (const auto &production: productions) {
for (const auto &c: production) {
if (isEmptyStr(c)) {
return true;
}
}
}
return false;
}
string Checker::getStackContent(stack<char> source) {
string str;
while (!source.empty()) {
str.push_back(source.top());
source.pop();
}
std::reverse(str.begin(), str.end());
return str;
}
void printTableHeader() {
cout << setw(16) << left << setfill(' ') << "";
cout << setw(20) << left << setfill(' ') << "分析栈情况";
cout << setw(23) << left << setfill(' ') << "待分析字符串";
cout << setw(25) << left << setfill(' ') << "使用产生式与匹配情况" << endl;
}
bool Checker::identifyString(std::string input) {
printTableHeader();
// 添加#到输入字符串尾部
input.push_back('#');
stack<char> analysisStack = stack<char>();
// #先入栈
analysisStack.push('#');
// 开始符号入栈, S
analysisStack.push(grammar.getStartChar());
int step = 0;
string remain = input;
string status = "分析中";
cout << setw(16) << left << setfill(' ') << step;
cout << setw(16) << left << setfill(' ') << getStackContent(analysisStack);
cout << setw(16) << left << setfill(' ') << remain;
const set<char> &terminals = grammar.getTerminals();
const auto &productionsMap = grammar.getGrammarExpresses();
const auto &analysisTable = grammar.getAnalysisTable();
for (auto pos = input.begin(); pos != input.end();) {
char currentChar = *pos;
char stackTopChar = analysisStack.top();
// 如果当前栈顶是终结符,对比当前输入字符和栈顶终结符是否匹配
// 匹配则进行规约,否则判定不匹配
if (terminals.contains(stackTopChar)) {
if (currentChar == stackTopChar) {
analysisStack.pop();
for (const auto &c: remain) {
if (c == currentChar) {
remain = remain.substr(1);
break;
}
}
status.clear();
status.push_back('\'');
status.push_back(currentChar);
status += "': 匹配";
pos++;
} else {
cout << "匹配失败。期望输入:" << stackTopChar;
cout << ",得到输入:" << currentChar << endl;
return false;
}
} else if (stackTopChar == '#') {
return currentChar == '#';
} else {
/* 对非终结符的处理 */
// 预测分析表中找不到对应的规则,但是当前的非终止符能推出空串,就退栈,该非终止符作为空串推测处理
// 否则就判定不接受
bool foundInTable = analysisTable.at(stackTopChar).contains(currentChar);
if (!foundInTable) {
if (canDeducedEmpty(productionsMap.at(stackTopChar))) {
cout << "找不到" << stackTopChar << "" << currentChar << "相匹配的规则" << endl;
return false;
} else {
analysisStack.pop();
status.clear();
status.push_back(stackTopChar);
status += "->~";
}
} else {
analysisStack.pop();
status.clear();
status.push_back(stackTopChar);
string production = analysisTable.at(stackTopChar).at(currentChar);
status += "-> " + production;
for (int i = (int) production.size() - 1; i >= 0; --i) {
char c = production[i];
if (c != '~') {
analysisStack.push(c);
}
}
}
}
step++;
cout << setw(16) << left << setfill(' ') << status << endl;
cout << setw(16) << left << setfill(' ') << step;
cout << setw(16) << left << setfill(' ') << getStackContent(analysisStack);
cout << setw(16) << left << setfill(' ') << remain;
}
cout << endl;
return true;
}
Checker::Checker(Grammar grammar) : grammar(std::move(grammar)){}