- LR来实现-简单算数表达式语法分析器设计
【问题描述】
1.设计简单算数表达式语法分析器算法;(LR来实现)
2.编写代码并上机调试运行通过。
【输入形式】
简单算数表达式
【输出形式】
正确/错误
【样例输入】
x+y*(3*a+7)-b/5 x+y*(3*a+7-b/5
【样例输出】
true false
【样例说明】
【评分标准】
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <list>
using namespace std;
// 判断某个非终结符的FIRST集是否含空
bool contain_null(char m, map<char, string> FIRST) {
string p = FIRST[m];
for (size_t i = 0; i < p.length(); i++) {
if (p[i] == 'k') return true;
}
return false;
}
// 打印map
template<class T>
void Printmap(T a, T b) {
for (; a != b; a++) cout << (*a).first << ":" << (*a).second << endl;
}
// 判断是不是终结符
bool isTerminal(char p) {
if (p == '*' || p == '(' || p == ')' || p == '+' || p == '^' || p == 'k' || p == '+' || p == '/' || p == '-' || p == 'i') {
return true;
}
else {
return false;
}
}
// 找某个非终结符是哪个产生式左边的符号
int find_next(char p, vector<string> production) {
for (vector<string>::iterator i = production.begin(); i != production.end(); i++) {
if ((*i)[0] == p) return i - production.begin();
}
}
// 找某行产生式每个子产生式出现的第一个位置
vector<int> find_firstright(string s) {
vector<int> p;
for (size_t i = 0; i < s.length(); i++) {
if (s[i] == '>' || s[i] == '|') p.push_back(i + 1);
}
return p;
}
// 求某个非终结符的FIRST集
string solveFirst(string s, vector<string> production, map<char, string>& FIRST) {
vector<int> fr = find_firstright(s);
string result;
for (auto i = fr.begin(); i != fr.end(); i++) {
if (!isTerminal(s[*i])) {
int p = find_next(s[*i], production);
FIRST[s[*i]] = solveFirst(production[p], production, FIRST);
result += FIRST[s[*i]];
for (size_t j = *i; j < s.size(); j++) {
if (contain_null(s[j], FIRST)) {
if (s[j] == '|') break;
j++;
if (isTerminal(s[j])) {
result += s[j];
break;
}
p = find_next(s[j], production);
FIRST[s[j]] = solveFirst(production[p], production, FIRST);
result += FIRST[s[j]];
}
}
}
else {
result += s[*i];
}
}
return result;
}
// 求非终结符在其他产生式后面的非终结符,或判断是不是其它产生式的末尾
vector<string> find_follow(char p, vector<string> production) {
vector<string> follow;
string follow1, follow2;
for (auto i = production.begin(); i != production.end(); i++) {
for (size_t j = 0; j < (*i).length(); j++) {
if ((*i)[j] == p) {
if ((j == (*i).length() - 1) || (*i)[j + 1] == '|') follow1 += (*i)[0];
else follow2 += (*i)[j + 1];
}
}
}
follow.push_back(follow1);
follow.push_back(follow2);
return follow;
}
// 求非终结符的FOLLOW集
void solveFollow(int pos, vector<string> production, map<char, string> FIRST, map<char, string>& FOLLOW, bool flag) {
string result;
if (pos == 0) result += "#";
vector<string> m = find_follow(production[pos][0], production);
for (size_t i = 0; i < m[0].length(); i++) {
vector<string> p = find_follow(m[0][i], production);
if ((FOLLOW.count(m[0][i]) == 0) && (flag == 0) || p[0].find(production[pos][0]) == string::npos && flag == 1) {
int x = find_next(m[0][i], production);
solveFollow(x, production, FIRST, FOLLOW, 1);
}
result += FOLLOW[m[0][i]];
}
for (size_t i = 0; i < m[1].length(); i++) {
if (isTerminal(m[1][i])) result += m[1][i];
else {
if (contain_null(m[1][i], FIRST)) {
if (FOLLOW.count(m[1][i]) == 0) {
int x = find_next(m[1][i], production);
solveFollow(x, production, FIRST, FOLLOW, 1);
}
result += FOLLOW[m[1][i]];
string p = FIRST[m[1][i]];
for (size_t i = 0; i < p.length(); i++) {
if (p[i] != 'k') result += p[i];
}
}
else {
result += FIRST[m[1][i]];
}
}
}
sort(result.begin(), result.end());
result.erase(unique(result.begin(), result.end()), result.end());
if (FOLLOW.count(production[pos][0]) == 0) FOLLOW.insert(make_pair(production[pos][0], result));
else FOLLOW[production[pos][0]] = result;
}
// 求每个产生式的SELECT集
vector<string> solveselect(int x, vector<string> production, map<char, string> FIRST, map<char, string> FOLLOW) {
vector<string> r;
vector<int> p = find_firstright(production[x]);
for (size_t i = 0; i < p.size(); i++) {
string select;
if (isTerminal(production[x][p[i]]) && production[x][p[i]] != 'k') select = production[x][p[i]];
else {
if ((FIRST[production[x][p[i]]].find('k') == string::npos) && production[x][p[i]] != 'k') select = FIRST[production[x][p[i]]];
else {
for (size_t j = p[i]; j < production[x].size(); j++) {
if (isTerminal(production[x][j]) && production[x][p[i]] != 'k') {
select += production[x][j];
break;
}
else {
if (FIRST[production[x].at(j)].find('k') != string::npos)
{
select += FIRST[production[x][j]];
}
else {
if ((production[x][j] == '|') || j == production[x].length() - 1) {
select += FOLLOW[production[x][0]];
break;
}
}
}
}
}
}
select.erase(remove(select.begin(), select.end(), 'k'), select.end());
r.push_back(select);
}
return r;
}
// 根据当前终结符和式子行数判断当前应该选哪个产生式
int run_LL(char b, int a, vector<string> slect, string t, list<pair<int, int>>& f, bool m) {
unsigned int i;
int flag = 0;
for (i = 0; i < slect.size(); i++) {
for (size_t j = 0; j < slect[i].length(); j++) {
if (slect[i][j] == b) {
flag = 1;
break;
}
}
if (flag == 1) break;
}
if (flag == 0) {
i = -1;
return i;
}
if (!f.empty()) f.pop_front();
vector<int> p = find_firstright(t);
if (m == 0) {
for (size_t j = p[i]; j < t.length(); j++) {
if (t[j] == '|') break;
f.push_back(make_pair(a, j)); // 保存的是行数和接下来元素的位置
}
}
int h = t.length() - 1;
for (size_t j = p[i]; j < t.length(); j++) { // 找这个子产生式的结尾
if (t[j] == '|') {
h = j;
break;
}
}
if (m == 1) {
if (h == t.length() - 1) {
for (size_t j = (int)t.length() - 1; j >= p[i]; j--) {
f.push_front(make_pair(a, j));
}
}
else {
for (int j = h - 1; j >= p[i]; j--) {
f.push_front(make_pair(a, j));
}
}
}
return i; // 返回:这行选择了什么产生式子
}
int main() {
string m;
vector<char> px;
map<int, vector<string>> SELECT;
map<char, string> FIRST;
map<char, string> FOLLOW;
vector<string> production = { "E->TG",
"G->+TG|-TG|k",
"T->FH",
"H->*FH|/FH|k",
"F->i|(E)" };
int kuohao = 0;
// 找出所有出现过的终结符
for (size_t i = 0; i < production.size(); i++) {
for (size_t j = 0; j < production[i].length(); j++) {
if (isTerminal(production[i][j])) px.push_back(production[i][j]);
}
}
sort(px.begin(), px.end());
px.erase(unique(px.begin(), px.end()), px.end());
// 求FIRST, FOLLOW和SELECT集
for (auto i = production.begin(); i != production.end(); i++) {
string p = solveFirst(*i, production, FIRST);
sort(p.begin(), p.end());
p.erase(unique(p.begin(), p.end()), p.end());
FIRST.insert(make_pair((*i)[0], p));
}
for (size_t i = 0; i < production.size(); i++) solveFollow(i, production, FIRST, FOLLOW, 0);
for (size_t i = 0; i < production.size(); i++) {
SELECT.insert(make_pair(i, solveselect(i, production, FIRST, FOLLOW)));
}
// 实际测试
int flag = 0;
int run = 0;
string test;
cin >> test;
for (size_t i = 0; i < test.length(); i++) {
if ((test[i] >= '0' && test[i] <= '9') || (test[i] >= 'a' && test[i] <= 'z')) test[i] = 'i';
if (test[i] == '(') kuohao += 1;
if (test[i] == ')') kuohao -= 1;
}
for (size_t i = 0; i < test.length(); i++) {
auto t = find(px.begin(), px.end(), test[i]);
if (t == px.end()) {
cout << "False" << endl;
return 0;
}
}
unsigned int time = 0;
list<pair<int, int>> f;
bool tst = 0;
while (time < test.length()) {
int c = -2;
if (time == test.length()) {
flag = 0;
break;
}
c = run_LL(test[time], run, SELECT[run], production[run], f, tst); // time当前要推导出的终结符,run是当前选用产生式的行
if (c == -1) {
cout << "False" << endl;
flag = 1;
return -1;
}
if ((production[f.front().first][f.front().second] == test[time]) || production[f.front().first][f.front().second] == 'k') {
int a, b;
do {
a = f.front().first;
b = f.front().second;
if (production[a][b] != 'k') {
time++;
}
if (time == test.length()) break;
f.pop_front();
if (f.empty()) {
if (time == test.length()) {
flag = 0;
cout << "True" << endl;
}
else {
cout << "False" << endl;
return -1;
}
}
} while (isTerminal(production[f.front().first][f.front().second])); // 考虑到空产生式,可能出现连续多个终结符在一起的情况,要把所有终结符都出队,然后对非终结符找下一个产生式
if (time == test.length()) {
flag = 0;
break;
}
run = find_next(production[f.front().first][f.front().second], production);
continue;
}
else {
run = find_next(production[f.front().first][f.front().second], production);
}
tst = 1;
}
if (kuohao != 0) {
cout << "False" << endl;
return 0;
}
if (flag == 0) {
cout << "True" << endl;
}
return 0;
}