吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2961|回复: 15
收起左侧

[会员申请] 申请会员ID:钟离绝霞

[复制链接]
吾爱游客  发表于 2018-5-15 11:01
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[1] == '\'') 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[1] == '\'') //以撇号结尾的非终结符
    {
     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[LINE_LENGTH + 1];
  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[i - 1];
    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[id - 1];
}
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[50];
  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[0])) {
   tableContent.action = 'G';
   tableContent.num = atoi(content.c_str());
  }
  else if (toupper(content[0] == 'A')) {
   tableContent.action = 'A';
   tableContent.num = 0;
  }
  else {
   tableContent.action = toupper(content[0]);
   tableContent.num = atoi(content.c_str() + 1);
  }
  table[key] = 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.length() - 1] != '#')
   setence.append("#"); //添加上结束符
  pda.AnalyzeSetence(setence);
}
}

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Hmily 发表于 2018-5-15 16:36
这写的啥,看不懂。

点评

看着貌似只是贴了一堆代码上来?  详情 回复 发表于 2018-5-18 15:07
舒克Schuck 发表于 2018-5-15 17:29
先有我后有天 发表于 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
楼主写的看不懂啊
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-3-29 04:12

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表