c++实现: 1、检测左递归,如果有则进行消除; 2、求解FIRST集和FOLLOW集; 3、构建LL(1)分析表; 4、构建LL分析程序,对于用户输入的句子,能够利用所构造的分析程序进行分析,并显示出分析过程。
时间: 2024-03-25 19:36:05 浏览: 101
以下是一个简单的 C++ 实现,包括检测和消除左递归,求解FIRST和FOLLOW集,构建LL(1)分析表,以及利用所构造的分析程序对用户输入的句子进行分析并显示出分析过程。
```c++
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
// 定义产生式结构体
struct Production {
char left; // 产生式左部
vector<string> right; // 产生式右部
};
// 检测左递归
void eliminate_left_recursion(vector<Production>& productions) {
for (int i = 0; i < productions.size(); i++) {
Production& p = productions[i];
vector<string> new_right;
vector<string> old_right = p.right;
bool has_left_recursion = false;
for (string& s : old_right) {
if (s[0] == p.left) {
has_left_recursion = true;
break;
}
}
if (!has_left_recursion) {
continue;
}
char new_left = p.left + 1;
while (find_if(productions.begin(), productions.end(), [&](const Production& p) { return p.left == new_left; }) != productions.end()) {
new_left++;
}
// 消除左递归
for (string& s : old_right) {
if (s[0] == p.left) {
new_right.push_back(s.substr(1) + new_left);
} else {
new_right.push_back(s + new_left);
}
}
new_right.push_back("$");
// 生成新的产生式
p.right.clear();
for (string& s : new_right) {
p.right.push_back(s);
}
Production new_p = {new_left, {}};
for (string& s : old_right) {
if (s[0] != p.left) {
new_p.right.push_back(s + new_left);
}
}
new_p.right.push_back("$");
productions.push_back(new_p);
}
}
// 求解FIRST集
void compute_first_sets(vector<Production>& productions, map<char, set<char>>& first_sets) {
bool changed = true;
while (changed) {
changed = false;
for (Production& p : productions) {
char left = p.left;
vector<string>& right = p.right;
for (string& s : right) {
if (s.empty()) { // 空产生式
if (first_sets[left].insert('@').second) {
changed = true;
}
} else if (islower(s[0])) { // 终结符
if (first_sets[left].insert(s[0]).second) {
changed = true;
}
} else { // 非终结符
bool has_epsilon = true;
for (char& c : s) {
if (first_sets[c].find('@') == first_sets[c].end()) {
has_epsilon = false;
if (first_sets[left].insert(*first_sets[c].begin()).second) {
changed = true;
}
break;
}
}
if (has_epsilon && first_sets[left].insert('@').second) {
changed = true;
}
}
}
}
}
}
// 求解FOLLOW集
void compute_follow_sets(vector<Production>& productions, map<char, set<char>>& first_sets, map<char, set<char>>& follow_sets) {
bool changed = true;
while (changed) {
changed = false;
for (Production& p : productions) {
char left = p.left;
vector<string>& right = p.right;
for (int i = 0; i < right.size(); i++) {
string& s = right[i];
for (int j = 0; j < s.length(); j++) {
if (!isupper(s[j])) { // 终结符
continue;
}
bool has_epsilon = true;
for (int k = j + 1; k < s.length(); k++) {
if (first_sets[s[k]].find('@') == first_sets[s[k]].end()) {
has_epsilon = false;
if (follow_sets[s[j]].insert(*first_sets[s[k]].begin()).second) {
changed = true;
}
break;
}
}
if (has_epsilon && follow_sets[s[j]].insert(follow_sets[left].begin(), follow_sets[left].end()).second) {
changed = true;
}
if (has_epsilon && i == right.size() - 1 && follow_sets[s[j]].insert(follow_sets[left].begin(), follow_sets[left].end()).second) {
changed = true;
}
}
}
}
}
}
// 构建LL(1)分析表
void build_ll1_table(vector<Production>& productions, map<char, set<char>>& first_sets, map<char, set<char>>& follow_sets, map<pair<char, char>, vector<string>> &ll1_table) {
for (Production& p : productions) {
char left = p.left;
vector<string>& right = p.right;
for (int i = 0; i < right.size(); i++) {
string& s = right[i];
set<char> first;
if (s.empty() || first_sets[s[0]].find('@') != first_sets[s[0]].end()) { // 空产生式或以非终结符开头的产生式
first = follow_sets[left];
} else {
first = first_sets[s[0]];
}
for (char& c : first) {
ll1_table[{left, c}].push_back(s);
}
}
}
}
// 执行LL分析
vector<string> ll_analyze(map<pair<char, char>, vector<string>>& ll1_table, string input) {
vector<string> output;
input += "$";
vector<char> stack = {'$', 'S'};
int i = 0;
while (!stack.empty()) {
char c = stack.back();
stack.pop_back();
if (c == input[i]) {
output.push_back(string("match: ") + c);
i++;
} else if (isupper(c)) {
auto it = ll1_table.find({c, input[i]});
if (it == ll1_table.end()) {
output.push_back("error");
break;
} else {
vector<string>& s = it->second;
output.push_back(string("predict: ") + s[0]);
stack.insert(stack.end(), s[0].rbegin(), s[0].rend());
}
} else {
output.push_back("error");
break;
}
}
return output;
}
int main() {
// 输入文法
vector<Production> productions = {
{'S', {"aBC"}},
{'B', {"bB", "@"}},
{'C', {"cC", "@"}}
};
// 消除左递归
eliminate_left_recursion(productions);
// 求解FIRST集
map<char, set<char>> first_sets;
compute_first_sets(productions, first_sets);
// 求解FOLLOW集
map<char, set<char>> follow_sets;
follow_sets['S'].insert('$');
compute_follow_sets(productions, first_sets, follow_sets);
// 构建LL(1)分析表
map<pair<char, char>, vector<string>> ll1_table;
build_ll1_table(productions, first_sets, follow_sets, ll1_table);
// 执行LL分析
vector<string> output = ll_analyze(ll1_table, "abccc$");
// 输出分析过程
for (string& s : output) {
cout << s << endl;
}
return 0;
}
```
这个实现只是一个简单的例子,实际应用中可能需要更复杂的算法和数据结构来处理更复杂的语法。
阅读全文