c++详细实现:读取固定位置的文件中的文法,并对文法实现以下具体功能: 1、检测左递归,如果有则进行消除; 2、求解FIRST集和FOLLOW集; 3、构建LL(1)分析表; 4、构建LL分析程序,对于用户输入的句子,能够利用所构造的分析程序进行分析,并显示出分析过程。
时间: 2024-03-25 15:36:32 浏览: 53
c++实现的数据结构-GrammaAnalysis(编译原理(文法的消除左递归、提取左因子).zip
好的,我来一步步为您解答。
首先,我们需要读取文件中的文法。假设我们的文法存储在文件 grammar.txt 中,则可以使用以下代码读取:
```c++
#include <fstream>
#include <string>
#include <vector>
using namespace std;
vector<string> grammar;
void readGrammar() {
ifstream inFile("grammar.txt");
string line;
while (getline(inFile, line)) {
grammar.push_back(line);
}
inFile.close();
}
```
接下来,我们需要实现检测左递归并进行消除。以下是一个简单的左递归消除算法:
```c++
void eliminateLeftRecursion() {
for (int i = 0; i < grammar.size(); i++) {
string left = grammar[i].substr(0, grammar[i].find("->"));
vector<string> right;
string tmp = grammar[i].substr(grammar[i].find("->") + 2);
int pos = 0;
while ((pos = tmp.find("|")) != -1) {
right.push_back(tmp.substr(0, pos));
tmp = tmp.substr(pos + 1);
}
right.push_back(tmp);
for (int j = 0; j < i; j++) {
string prev_left = grammar[j].substr(0, grammar[j].find("->"));
if (prev_left != left) continue;
vector<string> prev_right;
tmp = grammar[j].substr(grammar[j].find("->") + 2);
pos = 0;
while ((pos = tmp.find("|")) != -1) {
prev_right.push_back(tmp.substr(0, pos));
tmp = tmp.substr(pos + 1);
}
prev_right.push_back(tmp);
vector<string> new_right;
for (int k = 0; k < right.size(); k++) {
if (right[k][0] == prev_left) {
for (int l = 0; l < prev_right.size(); l++) {
new_right.push_back(right[k].substr(1) + prev_right[l]);
}
} else {
new_right.push_back(right[k]);
}
}
right = new_right;
}
vector<string> new_grammar;
bool flag = false;
for (int j = 0; j < right.size(); j++) {
if (right[j][0] == left[0]) {
flag = true;
string new_left = left + "'";
new_grammar.push_back(new_left + "->" + right[j].substr(1) + new_left);
} else {
new_grammar.push_back(left + "->" + right[j]);
}
}
if (flag) {
new_grammar.push_back(left + "'->" + "epsilon");
for (int j = 0; j < i; j++) {
string prev_left = grammar[j].substr(0, grammar[j].find("->"));
if (prev_left == left) continue;
new_grammar.push_back(grammar[j]);
}
grammar = new_grammar;
eliminateLeftRecursion();
return;
}
}
}
```
现在我们需要求解 FIRST 集和 FOLLOW 集。以下是一个简单的算法:
```c++
#include <map>
#include <set>
using namespace std;
map<string, set<string>> first_set;
map<string, set<string>> follow_set;
void calculateFirst() {
for (int i = 0; i < grammar.size(); i++) {
string left = grammar[i].substr(0, grammar[i].find("->"));
if (left == "S") first_set[left].insert("$");
vector<string> right;
string tmp = grammar[i].substr(grammar[i].find("->") + 2);
int pos = 0;
while ((pos = tmp.find("|")) != -1) {
right.push_back(tmp.substr(0, pos));
tmp = tmp.substr(pos + 1);
}
right.push_back(tmp);
for (int j = 0; j < right.size(); j++) {
string cur = right[j];
if (cur[0] >= 'a' && cur[0] <= 'z') {
first_set[left].insert(cur.substr(0, 1));
} else {
int k = 0;
while (k < cur.size()) {
if (cur[k] >= 'a' && cur[k] <= 'z') {
first_set[left].insert(cur.substr(k, 1));
break;
} else {
string next = cur.substr(k, 1);
set<string> next_first = first_set[next];
first_set[left].insert(next_first.begin(), next_first.end());
if (next_first.find("epsilon") == next_first.end()) break;
k++;
}
}
if (k == cur.size()) {
first_set[left].insert("epsilon");
}
}
}
}
}
void calculateFollow() {
follow_set["S"].insert("$");
for (int i = 0; i < grammar.size(); i++) {
string left = grammar[i].substr(0, grammar[i].find("->"));
vector<string> right;
string tmp = grammar[i].substr(grammar[i].find("->") + 2);
int pos = 0;
while ((pos = tmp.find("|")) != -1) {
right.push_back(tmp.substr(0, pos));
tmp = tmp.substr(pos + 1);
}
right.push_back(tmp);
for (int j = 0; j < right.size(); j++) {
string cur = right[j];
for (int k = 0; k < cur.size(); k++) {
if (cur[k] >= 'a' && cur[k] <= 'z') continue;
string cur_sym = cur.substr(k, 1);
if (k == cur.size() - 1) {
set<string> follow_left = follow_set[left];
follow_set[cur_sym].insert(follow_left.begin(), follow_left.end());
} else {
int l = k + 1;
bool flag = true;
while (l < cur.size()) {
if (cur[l] >= 'a' && cur[l] <= 'z') {
follow_set[cur_sym].insert(cur.substr(l, 1));
flag = false;
break;
} else {
set<string> next_first = first_set[cur.substr(l, 1)];
if (next_first.find("epsilon") == next_first.end()) {
follow_set[cur_sym].insert(next_first.begin(), next_first.end());
flag = false;
break;
} else {
next_first.erase("epsilon");
follow_set[cur_sym].insert(next_first.begin(), next_first.end());
l++;
}
}
}
if (flag) {
set<string> follow_left = follow_set[left];
follow_set[cur_sym].insert(follow_left.begin(), follow_left.end());
}
}
}
}
}
}
```
接下来,我们需要构建 LL(1) 分析表。以下是一个简单的算法:
```c++
#include <map>
#include <string>
#include <vector>
using namespace std;
map<string, map<string, vector<string>>> ll1_table;
void buildLL1Table() {
for (int i = 0; i < grammar.size(); i++) {
string left = grammar[i].substr(0, grammar[i].find("->"));
vector<string> right;
string tmp = grammar[i].substr(grammar[i].find("->") + 2);
int pos = 0;
while ((pos = tmp.find("|")) != -1) {
right.push_back(tmp.substr(0, pos));
tmp = tmp.substr(pos + 1);
}
right.push_back(tmp);
for (int j = 0; j < right.size(); j++) {
set<string> first = first_set[right[j].substr(0, 1)];
for (set<string>::iterator it = first.begin(); it != first.end(); it++) {
if (*it == "epsilon") {
set<string> follow = follow_set[left];
for (set<string>::iterator it2 = follow.begin(); it2 != follow.end(); it2++) {
ll1_table[left][*it2].push_back(right[j]);
}
} else {
ll1_table[left][*it].push_back(right[j]);
}
}
}
}
}
```
最后,我们需要构建 LL 分析程序,对于用户输入的句子,能够利用所构造的分析程序进行分析,并显示出分析过程。以下是一个简单的算法:
```c++
#include <iostream>
#include <stack>
#include <string>
using namespace std;
void llParse() {
while (true) {
cout << "请输入要分析的句子(以 $ 结尾):" << endl;
string sentence;
cin >> sentence;
if (sentence == "$") break;
stack<string> stk;
stk.push("$");
stk.push("S");
int pos = 0;
string cur_sym = sentence.substr(pos, 1);
while (!stk.empty()) {
string top_sym = stk.top();
if (top_sym == cur_sym) {
stk.pop();
pos++;
if (pos >= sentence.size()) {
cout << "分析成功!" << endl;
break;
}
cur_sym = sentence.substr(pos, 1);
} else if (top_sym[0] >= 'A' && top_sym[0] <= 'Z') {
vector<string> rule = ll1_table[top_sym][cur_sym];
if (rule.empty()) {
cout << "无法匹配 " << cur_sym << endl;
break;
}
stk.pop();
for (int i = rule[0].size() - 1; i >= 0; i--) {
stk.push(rule[0].substr(i, 1));
}
} else {
cout << "无法匹配 " << cur_sym << endl;
break;
}
}
}
}
```
完整的代码如下:
阅读全文