c++前提:给定预测分析表,见教材 P76 表 4.1(对应文法为文法 4.2) 要求:构造出相关预测分析程序,并返回一个符号串的分析结果,如果是一个合法的符号串输出正确标志并返回 True,否则输出错误标志并返回 False。 参考:教材 P76-78 4.5 预测分析程序
时间: 2023-12-10 16:39:54 浏览: 163
以下是一个简单的 C++ 预测分析程序,用于对给定的符号串进行分析:
```c++
#include <iostream>
#include <stack>
#include <map>
using namespace std;
// 定义文法符号的类型
enum SymbolType {
TERMINAL, // 终结符
NONTERMINAL // 非终结符
};
// 定义文法符号结构体
struct GrammarSymbol {
string name; // 符号名称
SymbolType type; // 符号类型
};
// 文法符号比较函数,用于 map 中的键值比较
bool operator<(const GrammarSymbol& a, const GrammarSymbol& b) {
return a.name < b.name || (a.name == b.name && a.type < b.type);
}
// 定义预测分析表的类型
typedef map<pair<GrammarSymbol, GrammarSymbol>, int> PredictiveTable;
// 定义分析栈的类型
typedef stack<GrammarSymbol> AnalysisStack;
// 预测分析程序函数
bool predictiveAnalysis(string str, const PredictiveTable& table) {
// 初始化分析栈
AnalysisStack stack;
stack.push({"$", TERMINAL});
stack.push({"S", NONTERMINAL});
// 逐个读入输入字符串中的字符
for (int i = 0; i < str.size();) {
// 取出栈顶符号和当前输入字符
GrammarSymbol topSymbol = stack.top();
char curChar = str[i];
// 如果栈顶为终结符,弹出栈顶并继续下一轮循环
if (topSymbol.type == TERMINAL) {
stack.pop();
continue;
}
// 查找预测分析表中对应的产生式编号
int production = table.at({topSymbol, {curChar, TERMINAL}});
// 如果找不到相应的产生式,说明输入串不合法
if (production == 0) {
cout << "Error: Invalid input string." << endl;
return false;
}
// 弹出栈顶符号
stack.pop();
// 将对应的产生式逆序入栈
string productionStr = to_string(production);
for (int j = productionStr.size() - 1; j >= 0; j--) {
char symbolName = productionStr[j];
stack.push({string(1, symbolName), NONTERMINAL});
}
// 如果当前字符为终结符,继续读入下一个字符
if (str[i] != '$') {
i++;
}
}
// 如果分析栈为空且已到达输入串末尾,则输入串合法
if (stack.empty()) {
cout << "Input string is valid!" << endl;
return true;
} else {
cout << "Error: Invalid input string." << endl;
return false;
}
}
int main() {
// 定义文法符号
GrammarSymbol S = {"S", NONTERMINAL};
GrammarSymbol T = {"T", NONTERMINAL};
GrammarSymbol F = {"F", NONTERMINAL};
GrammarSymbol plus = {"+", TERMINAL};
GrammarSymbol times = {"*", TERMINAL};
GrammarSymbol leftParen = {"(", TERMINAL};
GrammarSymbol rightParen = {")", TERMINAL};
GrammarSymbol id = {"i", TERMINAL};
GrammarSymbol dollar = {"$", TERMINAL};
// 定义预测分析表
PredictiveTable table;
table[{S, {leftParen, TERMINAL}}] = 1;
table[{T, {leftParen, TERMINAL}}] = 2;
table[{F, {leftParen, TERMINAL}}] = 3;
table[{S, {id, TERMINAL}}] = 4;
table[{T, {id, TERMINAL}}] = 5;
table[{F, {id, TERMINAL}}] = 6;
table[{S, {leftParen, TERMINAL}}] = 7;
table[{T, {leftParen, TERMINAL}}] = 2;
table[{F, {leftParen, TERMINAL}}] = 3;
table[{S, {rightParen, TERMINAL}}] = 8;
table[{T, {rightParen, TERMINAL}}] = 8;
table[{F, {rightParen, TERMINAL}}] = 8;
table[{S, {dollar, TERMINAL}}] = 9;
table[{T, {plus, TERMINAL}}] = 10;
table[{F, {times, TERMINAL}}] = 11;
table[{S, {plus, TERMINAL}}] = 12;
table[{T, {id, TERMINAL}}] = 13;
table[{F, {id, TERMINAL}}] = 6;
table[{S, {times, TERMINAL}}] = 14;
table[{T, {times, TERMINAL}}] = 15;
table[{F, {id, TERMINAL}}] = 6;
// 输入待分析字符串
cout << "Please input a string to analyze: ";
string str;
cin >> str;
str += '$';
// 进行预测分析
predictiveAnalysis(str, table);
return 0;
}
```
上述程序中,我们首先定义了文法符号的类型和结构体,并重载了 `<` 运算符,以便在预测分析表中使用 map 进行查找。然后,我们定义了预测分析表的类型和分析栈的类型,并实现了预测分析程序的主函数 `predictiveAnalysis`。该函数首先初始化分析栈,然后逐个读入输入字符串中的字符,对于每个字符,它从分析栈的栈顶取出一个符号进行分析。
如果栈顶为终结符,则直接弹出栈顶并继续下一轮循环;如果栈顶为非终结符,则在预测分析表中查找对应的产生式编号,并将对应的产生式逆序入栈。如果在预测分析表中找不到相应的产生式,说明输入串不合法。最后,如果分析栈为空且已到达输入串末尾,则输入串合法;否则,输入串不合法。
在 main 函数中,我们首先定义了文法符号,并根据文法 4.2 的预测分析表填充了预测分析表。然后,我们输入待分析字符串,并调用 `predictiveAnalysis` 函数进行预测分析。
阅读全文