发表于 2018-5-15 11:01

申请会员ID:钟离绝霞

1. 申请ID:钟离绝霞
2. 个人邮箱:1004789224@qq.com
3. 原创技术文章:
LR(1)分析法实验
一个编译原理实验...LR(1)分析法实验,大家如果学过编译原理肯定对LR 分析法印象很深,它很麻烦不是我说直到我写完这个程序才真正理解了LR分析法 .下面分析以下LR分析法
vs2017编译通过
分析表是那个压缩包解压后的.csv文件
// LR分析程序.cpp: 定义控制台应用程序的入口点。
//
#include<iostream>
#include<map>
#include<vector>
#include<string>
#include<fstream>
using namespace std;
struct StackContent {
int state; //状态栏
string sign; //符号栏
};
struct tableContent {
char action; //动作:A 接受, S 移进,R 归约,G 转向
int num; //动作后附加的字数
};
class Production
{
public:
int id; //产生式的编号
string left; //左侧非终结符,为直观起见考虑到有些非终结符是两个字符构成,如 E',以字符串为单位
vector<string> right; //右侧符号串
Production(const string &s) :producerString(s) { //产生式的构造函数
if (s == "")
   return;
int i = 1;
if (s == '\'') i++; //以撇号结尾的非终结符
left = s.substr(0, i);
i += 2; //跳过箭头
while (i < s.length())
{
   //查双字符(汉字和希腊字母均为双字)
   if (i < s.length() - 1) {
    string next = s.substr(i, 2);
    if (next == "ε") //右侧为空串
    {
   right.clear();
   break;
    }
    else if (next == '\'') //以撇号结尾的非终结符
    {
   right.push_back(next);
   i += 2;
   continue;
    }
   }
   //单个符号
   right.push_back(s.substr(i, 1));
   i++;
}
}//构造函数
bool operator==(const string &s) {
return producerString == s;
} //比较是否是指定产生式
bool operator!=(const string &s) {
return producerString != s;
} //比较是否是指定产生式
private:
string producerString; //产生式原始字符串
};
class AnalysisTable
{
public:
// 由文本文件创建分析表,文件格式将分析表做成 Excel 文件,然后另存为 CSV 格式文件,箭头使用中文箭头→
bool CreateTable(string filename) {
ifstream fin(filename.c_str());
if (!fin)return false;
table.clear();
const int LINE_LENGTH = 0xff;
char buf;
vector<string> signs;
vector<string>::size_type i;
while (fin.getline(buf, LINE_LENGTH))
{
   vector<string>words = SplitLineOfCVS(buf);
   if (!producers.size()) {
    for (i = 0; i<words.size(); i++) {
   producers.push_back(Production(words));
   producers.id = i + 1;
    }
    continue;
   }
   if (!signs.size()) {
    for (i = 1; i<words.size() && words.length(); i++) {
   signs.push_back(words);
    }
    continue;
   }
   int state;//当前状态编号
   for (i = 0; i<words.size(); i++) {
    string word = words;
    if (i == 0) {
   state = atoi(word.c_str());
   continue;
    }
    string sign = signs;
    SettableContent(state, sign, word);
   }
}
fin.close();
return true;
}
// 根据状态和符号查 LR 分析表,如果是空白(ERROR)的,返回 flase,否则返回 true,并将查到的结果填充到 result 中
bool Lookup(int state, string sign, tableContent &result) {
string key = CreateKey(state, sign.c_str());
map<string, tableContent>::iterator it;
it = table.find(key);
if (it == table.end())return false;
result = it->second;
return true;
}
// 获取指定编号的生成式
const Production &GetProducer(int id) {
return producers;
}
private:
vector<string> SplitLineOfCVS(char *s) {
vector<string> result;
char *p = s;
while (*s) {
   if (*s == ',') {
    *s = '\0';
    result.push_back(string(p));
    p = s + 1;
   }
   s++;
}
result.push_back(string(p));
return result;
} //分割 CVS 行
string CreateKey(int state, string sign) {
char buf;
sprintf_s(buf, "%04d\%s", state, sign.c_str());//转换为四位整数|符号
return buf;
} //创建表的关键字
void SettableContent(int state, string sign, string content) {
if (content.length() == 0)return;
string key = CreateKey(state, sign);
tableContent tableContent;
if (isdigit(content)) {
   tableContent.action = 'G';
   tableContent.num = atoi(content.c_str());
}
else if (toupper(content == 'A')) {
   tableContent.action = 'A';
   tableContent.num = 0;
}
else {
   tableContent.action = toupper(content);
   tableContent.num = atoi(content.c_str() + 1);
}
table = tableContent;
} //设置表的内容
private:
vector<Production> producers; //产生式表
map<string, tableContent> table; //LR 分析表
};
class PushDownStack : public vector<StackContent>
{
public:
void push(int state, string sign) {
StackContent sc; sc.state = state; sc.sign = sign;
vector<StackContent>::push_back(sc);
}
void pop() { vector<StackContent>::pop_back(); }
StackContent top() { return vector<StackContent>::back(); }
};
//下推自动机
class PushDownAutomachine
{
public:
PushDownAutomachine(AnalysisTable &at) : at(at) {}
void AnalyzeSetence(const string &setence) {
stepNum = 0;
readPos = 0;
pds.clear();
outline.clear();
pds.push(0, "#");
instring = setence;
int &i = readPos;
cout << "步骤\t状态栏\t符号栏\t输入串\t输出带\t下步动作\n";
while (i<setence.length()) {
   if (pds.empty())return;
   int state = pds.top().state;
   string a(1, setence);
   tableContent result;
   if (!at.Lookup(state, a, result)) {
    Output("出错");
    break;
   }
   else if (result.action == 'A') {
    Output("成功");
    break;
   }
   else if (result.action == 'S') {
    Output("移进");
    pds.push(result.num, a);
    i++;
   }
   else {
    Output("归约");
    Production p = at.GetProducer(result.num);
    outline.push_back(p.id);
    int count = p.right.size();
    if (count>pds.size()) {
   cout << "分析表错误\n";
   break;
    }
    while (count--)pds.pop();
    if (!at.Lookup(pds.top().state, p.left, result)) {
   Output("出错");
   break;
    }
    else {
   pds.push(result.num, p.left);
    }
   }
}
} //语法分析
private:
void Output(string nextAction) {
int i;
//输出当前步骤
cout << stepNum++ << "\t";
//输出栈内状态栏的情况
for (i = 0; i < pds.size(); i++) {
   if (i > 0) cout << ",";
   cout << pds.state;
}
cout << "\t";
//输出栈内符号栏的情况
for (i = 0; i < pds.size(); i++) {
   cout << pds.sign;
}
cout << "\t";
//输出输入串情况
for (i = 0; i < instring.length(); i++)
{
   if (i < readPos)
    cout << " "; //已读过的输出空格
   else
    cout << instring;
}
cout << "\t";
//输出输出带的情况
for (i = 0; i < outline.size(); i++)
{
   if (i > 0) cout << ",";
   cout << outline;
}
//输出下一步的动作
cout << "\t" << nextAction << endl;
} //输出分析过程,nextAction 下一步的动作
private:
AnalysisTable & at; //分析表
int stepNum; //步骤数
int readPos; //读头位置
string instring; //输入带
vector<int> outline; //输出带
PushDownStack pds; //下推栈
};
void main()
{
string filename; //文件名
AnalysisTable at; //分析表
PushDownAutomachine pda(at); //下推自动机
cout << "===================================\n";
cout << "| LR 语法分析程序 |\n";
cout << "===================================\n";
while (1)
{
cout << "请输入分析表路径:";
cin >> filename;
if (at.CreateTable(filename))
   break; //创建分析表成功
cout << "创建分析表失败,请确认文件格式是符合要求的,路径是正确的。" << endl;
}
string setence; //待分析的句子
while ((cout << "请输入语句(单个\"#\"退出程序):"),
(cin >> setence),
setence != "#")
{
if (setence != '#')
   setence.append("#"); //添加上结束符
pda.AnalyzeSetence(setence);
}
}

Hmily 发表于 2018-5-15 16:36

这写的啥,看不懂。

舒克Schuck 发表于 2018-5-15 17:29

我也看不懂0.0

先有我后有天 发表于 2018-5-15 19:07

同意了没

陌上寒烟薄雪 发表于 2018-5-15 19:10

哈哈,看不懂很绝望

BE一诺 发表于 2018-5-15 19:14

支持原创,虽然看不懂

Milovehickey 发表于 2018-5-15 20:07

这种就跟我大二课设一样,混混就过去了,没必要搞懂这个

实习 发表于 2018-5-15 22:16

不明觉厉

nmsl 发表于 2018-5-16 07:29

没看明白

省委书记 发表于 2018-5-16 17:18

楼主写的看不懂啊
页: [1] 2
查看完整版本: 申请会员ID:钟离绝霞