c++前提:给定预测分析表,见教材 P76 表 4.1(对应文法为文法 4.2) 要求:构造出相关预测分析程序,并返回一个符号串的分析结果,如果是一个合法的符号串输出正确标志并返回 True,否则输出错误标志并返回 False。 参考:教材 P76-78 4.5 预测分析程序。
时间: 2023-12-10 15:39:21 浏览: 137
以下是一份可能的 C++ 代码实现:
```c++
#include <iostream>
#include <stack>
#include <unordered_map>
#include <vector>
using namespace std;
// 定义文法符号类型,包括终结符和非终结符
enum class SymbolType {
Terminal,
Nonterminal
};
// 定义文法符号结构体
struct Symbol {
string name;
SymbolType type;
bool operator==(const Symbol& other) const {
return name == other.name && type == other.type;
}
};
// 定义哈希函数,用于 unordered_map
struct SymbolHash {
size_t operator()(const Symbol& symbol) const {
return hash<string>()(symbol.name) ^ hash<int>()(static_cast<int>(symbol.type));
}
};
// 定义预测分析表类型
using ParsingTable = unordered_map<Symbol, unordered_map<Symbol, vector<Symbol>, SymbolHash>, SymbolHash>;
// 定义文法类型
struct Grammar {
Symbol startSymbol;
vector<Symbol> nonterminals;
vector<Symbol> terminals;
ParsingTable parsingTable;
};
// 判断一个符号是否为终结符
bool isTerminal(const Symbol& symbol) {
return symbol.type == SymbolType::Terminal;
}
// 判断一个符号是否为非终结符
bool isNonterminal(const Symbol& symbol) {
return symbol.type == SymbolType::Nonterminal;
}
// 从控制台读入一个符号串,以 $ 结尾
vector<Symbol> readSymbolString() {
vector<Symbol> symbolString;
cout << "请输入一个符号串,以 $ 结尾:" << endl;
string name;
while (cin >> name && name != "$") {
Symbol symbol{name, SymbolType::Terminal};
symbolString.push_back(symbol);
}
// 添加 $ 符号
Symbol endSymbol{"$", SymbolType::Terminal};
symbolString.push_back(endSymbol);
return symbolString;
}
// 根据给定的文法和预测分析表,对一个符号串进行语法分析
bool parseSymbolString(const Grammar& grammar, const ParsingTable& parsingTable, const vector<Symbol>& symbolString) {
stack<Symbol> symbolStack;
vector<Symbol>::const_iterator inputIterator = symbolString.begin();
// 初始化符号栈
symbolStack.push(grammar.startSymbol);
while (!symbolStack.empty() && inputIterator != symbolString.end()) {
Symbol symbolOnTop = symbolStack.top();
if (isTerminal(symbolOnTop)) { // 如果栈顶是终结符
if (symbolOnTop == *inputIterator) { // 匹配成功,弹出栈顶符号和输入符号
symbolStack.pop();
++inputIterator;
} else { // 匹配失败,分析结束
cout << "Error: 无法匹配输入符号 " << inputIterator->name << endl;
return false;
}
} else { // 如果栈顶是非终结符
// 查找预测分析表,获取产生式
auto it1 = parsingTable.find(symbolOnTop);
if (it1 == parsingTable.end()) { // 如果找不到该非终结符对应的行
cout << "Error: 无法匹配栈顶非终结符 " << symbolOnTop.name << endl;
return false;
}
auto it2 = it1->second.find(*inputIterator);
if (it2 == it1->second.end()) { // 如果找不到该终结符对应的列
cout << "Error: 无法匹配输入符号 " << inputIterator->name << endl;
return false;
}
vector<Symbol> production = it2->second;
// 弹出栈顶符号
symbolStack.pop();
// 将产生式右部所有符号推入符号栈中
for (auto it = production.rbegin(); it != production.rend(); ++it) {
symbolStack.push(*it);
}
}
}
if (symbolStack.empty() && inputIterator == symbolString.end()) { // 如果符号栈为空且输入符号串已经分析完毕
cout << "Success: 输入符号串是一个合法的文法符号串" << endl;
return true;
} else { // 如果符号栈不为空或者输入符号串没有分析完毕
cout << "Error: 输入符号串不是一个合法的文法符号串" << endl;
return false;
}
}
int main() {
// 定义文法
Grammar grammar{
Symbol{"E", SymbolType::Nonterminal},
{
Symbol{"E", SymbolType::Nonterminal},
Symbol{"T", SymbolType::Nonterminal},
Symbol{"F", SymbolType::Nonterminal},
},
{
Symbol{"+", SymbolType::Terminal},
Symbol{"*", SymbolType::Terminal},
Symbol{"(", SymbolType::Terminal},
Symbol{")", SymbolType::Terminal},
Symbol{"id", SymbolType::Terminal},
},
{
{
Symbol{"E", SymbolType::Nonterminal},
{
{Symbol{"(", SymbolType::Terminal}, {Symbol{"T", SymbolType::Nonterminal}, Symbol{"E'", SymbolType::Nonterminal}}},
{Symbol{"id", SymbolType::Terminal}, {Symbol{"T", SymbolType::Nonterminal}, Symbol{"E'", SymbolType::Nonterminal}}},
}
},
{
Symbol{"E'", SymbolType::Nonterminal},
{
{Symbol{"+", SymbolType::Terminal}, {Symbol{"+", SymbolType::Terminal}, Symbol{"T", SymbolType::Nonterminal}, Symbol{"E'", SymbolType::Nonterminal}}},
{Symbol{")", SymbolType::Terminal}, {}},
{Symbol{"$", SymbolType::Terminal}, {}},
}
},
{
Symbol{"T", SymbolType::Nonterminal},
{
{Symbol{"(", SymbolType::Terminal}, {Symbol{"F", SymbolType::Nonterminal}, Symbol{"T'", SymbolType::Nonterminal}}},
{Symbol{"id", SymbolType::Terminal}, {Symbol{"F", SymbolType::Nonterminal}, Symbol{"T'", SymbolType::Nonterminal}}},
}
},
{
Symbol{"T'", SymbolType::Nonterminal},
{
{Symbol{"+", SymbolType::Terminal}, {}},
{Symbol{"*", SymbolType::Terminal}, {Symbol{"*", SymbolType::Terminal}, Symbol{"F", SymbolType::Nonterminal}, Symbol{"T'", SymbolType::Nonterminal}}},
{Symbol{")", SymbolType::Terminal}, {}},
{Symbol{"$", SymbolType::Terminal}, {}},
}
},
{
Symbol{"F", SymbolType::Nonterminal},
{
{Symbol{"(", SymbolType::Terminal}, {Symbol{"(", SymbolType::Terminal}, Symbol{"E", SymbolType::Nonterminal}, Symbol{")", SymbolType::Terminal}}},
{Symbol{"id", SymbolType::Terminal}, {Symbol{"id", SymbolType::Terminal}}},
}
},
}
};
// 读入符号串
vector<Symbol> symbolString = readSymbolString();
// 进行语法分析
parseSymbolString(grammar, grammar.parsingTable, symbolString);
return 0;
}
```
该程序的大致流程如下:
1. 定义文法符号类型(终结符和非终结符)和文法符号结构体。
2. 定义哈希函数和预测分析表类型。
3. 定义文法类型,并初始化文法和预测分析表。
4. 从控制台读入一个符号串。
5. 根据给定的文法和预测分析表,对符号串进行语法分析。
6. 输出分析结果。
在语法分析过程中,程序使用了一个栈来维护符号栈,同时使用一个迭代器来遍历输入符号串。对于每一个符号栈顶符号,程序首先判断该符号是终结符还是非终结符,然后进行不同的处理:
- 如果该符号是终结符,程序比较该符号和输入符号串当前位置的符号是否相同,如果相同则弹出该符号和输入符号,否则输出错误信息并结束分析。
- 如果该符号是非终结符,程序查找预测分析表中该非终结符和输入符号对应的产生式,然后将产生式右部的所有符号推入符号栈中。
在分析过程中,如果符号栈为空且输入符号串已经分析完毕,则表示输入符号串是一个合法的文法符号串;否则,表示输入符号串不是一个合法的文法符号串。
阅读全文