#include<iostream>
#include<fstream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<set>
#include<queue>
#include<stack>
#include<map>
using namespace std; typedef pair<char, string>PP;
typedef pair<char, pair<string, string> >PPP; //*代表弧
//~代表空
//输入:
/*
S*MH
S*a
H*LSo
H*~
K*dML
K*~
L*eHf
M*K
M*bLM
*/ class Set{ private:
multimap<char, string >Grammars;//文法
multimap<string, char >Re_Grammars; //反向映射
vector<PP >FIRST; //FIRST集
vector<PP >FOLLOW; //FOLLOW集
set<char >Ok; //能推出空的非终结符的集合
set<char >Non_terminal; //非终结符集合
vector<string >Right; //产生式右部
vector<PPP >SELECT; //SELECT集
vector<char >Sentence; //要识别的句子 public:
Set();
~Set();
bool Judge_Ok(char); //判断一个非终结符是否能推出空
void Get_Ok(); //求出那些能推出空的非终结符集合
void First_Solve(); //求解FIRST集
void Show_First(); //输出FIRST集合
void Get_First(char, set<char>&); //求解某个非终结符的FIRST集
void Follow_Solve(); //求解FOLLOW集
void Show_Follow(); //输出FOLLOW集
void Get_Follow(char, set<char>&); //求解某个非终结符的FOLLOW集
void Select_Solve(); //求解SELECT集
void Show_Select(); //输出SELECT集
void Analysis(); //预测分析程序 }; Set::Set()
{
ifstream infile;
infile.open("data.txt");
if (!infile){
cout << "can't open the file" << endl;
return;
}
string str;
while (infile >> str){
char ch = str[];
string ss = "";
for (int i = ; i < (int)str.size(); i++)ss += str[i];
Grammars.insert(make_pair(ch, ss)); //所给文法
Re_Grammars.insert(make_pair(ss, ch)); //反向映射集合
Right.push_back(ss); //得到右部产生式
for (int i = ; i < (int)str.size(); i++){
if (isupper(str[i]))Non_terminal.insert(str[i]); //求非终结符集合
}
}
infile.close();
} Set::~Set()
{
Grammars.clear();
Re_Grammars.clear();
Right.clear();
Ok.clear();
FIRST.clear();
FOLLOW.clear();
SELECT.clear();
Non_terminal.clear();
} //判断一个非终结符是否能推出空
bool Set::Judge_Ok(char ch)
{
if (Grammars.find(ch) == Grammars.end())return false;//如果找不到这个非终结符所能推出的符号,则返回false. multimap<char, string>::iterator iter = Grammars.find(ch);
int Count =(int)Grammars.count(iter->first);
for (int i = ; i < Count; i++){
bool flag = true;
for (int j = ; j < (int)iter->second.size(); j++){
//如果是大写字母,那么就继续递归
if (isupper(iter->second[j])){
//避免重复递归
if (iter->second[j] == ch){
flag = false;
break;
}
else if (!Judge_Ok(iter->second[j])){
flag = false;
break;
}
}
//如果不是大写字母,就判断是否是空,如果不是,则也是直接break;
else if (iter->second[j] != '~'){
flag = false;
break;
}
}
if (flag)return true; //在某个非终结符的多重集合中,只要有某个能产生空,那么这个非终结符就能推出空,返回true;
iter++;
}
//如果都不能推出空,那么就返回false;
return false; } //求出那些能推出空的非终结符集合
void Set::Get_Ok()
{
set<char>::iterator iter;
for (iter = Non_terminal.begin(); iter != Non_terminal.end(); iter++){
if(Judge_Ok((*iter))){
Ok.insert(*iter);
}
}
} //求某一个非终结符的FIRST集
void Set::Get_First(char ch, set<char>&st)
{
if (Grammars.find(ch) == Grammars.end())return; //如果没有找到非终结符可以转化的符号,则直接返回 multimap<char, string>::iterator iter = Grammars.find(ch);
int Count = (int)Grammars.count(iter->first);
for (int i = ; i < Count; i++){
for (int j = ; j < (int)(iter->second.size()); j++){
//此时碰到的是终结符,找到后将其插入到set集合中,并且立马跳出循环,找下一个
if (!isupper(iter->second[j])){
st.insert(iter->second[j]);
break;
}
else if (isupper(iter->second[j])){
//避免重复递归
if (iter->second[j] == ch){
break;
}
//如果不重复,那么就从这个非终结符继续找
Get_First(iter->second[j], st); //如果这个非终结符不能推出空,那么就直接break寻找下一个映射
if (Ok.find(iter->second[j]) == Ok.end()){
break;
}
}
}
iter++;
}
} //求所有非终结符的FIRST集
void Set::First_Solve()
{
set<char >First;
for (set<char >::iterator iter = Non_terminal.begin(); iter != Non_terminal.end(); iter++){
First.clear();
Get_First(*iter, First); //求某一个非终结符的FIRST集
string str = "";
for (set<char>::iterator it = First.begin(); it != First.end(); it++)str += (*it);
FIRST.push_back(make_pair(*iter, str));
}
} //输出FIRST集
void Set::Show_First()
{
cout << " " << "FIRST集" << " " << endl << endl;
for (int i = ; i <(int) FIRST.size(); i++){
cout << FIRST[i].first << " : ";
for (int j = ; j <(int) FIRST[i].second.size(); j++){
cout << FIRST[i].second[j] << " ";
}
cout << endl;
}
cout << endl;
} //求某一个非终结符的FOLLOW集
void Set::Get_Follow(char ch, set<char>&st)
{
if (ch == 'S')st.insert('#');//如果是开始符;
for (int i = ; i < (int)Right.size(); i++){
string str = Right[i];
for (int j = ; j < (int)Right[i].size(); j++){
//如果不是当前产生式的最后一个
if (Right[i][j] == ch&&j !=(int) Right[i].size() - ){
//如果后面紧跟着的是终结符
if (!isupper(Right[i][j + ])){
if (Right[i][j + ] != '~'){
st.insert(Right[i][j + ]);
}
}
else{
//后面紧跟着是非终结符,就把这个非终极符的FIRST集(除了空)加入到当前ch的FOLLOW集中
vector<PP>::iterator iter = FIRST.begin();
while (iter != FIRST.end()){
if (iter->first == Right[i][j+]){
break;
}
iter++;
}
for (int k = ; k < (int)iter->second.size(); k++){
if (iter->second[k] != '~')st.insert(iter->second[k]);
}
//如果对形如“…UP”(P是非终结符的组合)的组合;
//如果这些非终结符都能推出空,就么就要把左部(假设是S)的Follow(S)送入到Follow(U)中
bool flag = true;
for (int pos = j + ; pos < (int)Right[i].size(); pos++){
if (isupper(Right[i][pos]) && Ok.find(Right[i][pos]) != Ok.end()){
vector<PP>::iterator ii = FIRST.begin();
while (ii != FIRST.end()){
if (ii->first == Right[i][pos]){
break;
}
ii++;
}
for (int k = ; k < (int)ii->second.size(); k++){
if (ii->second[k] != '~')st.insert(ii->second[k]);
}
continue;
}
flag = false;
break;
}
if (flag){
multimap<string, char>::iterator it = Re_Grammars.find(str);
int Count = Re_Grammars.count(it->first);
while (Count--){
if (it->second != ch){
Get_Follow(it->second, st);
}
}
}
}
}
//如果刚好是当前产生式的最后一个字符
else if (Right[i][j] == ch&&j == (int)Right[i].size() - ){
//反向映射找到推出str这个产生式的左部字符
multimap<string, char>::iterator iter = Re_Grammars.find(str);
int Count = Re_Grammars.count(iter->first);
while (Count--){
if (iter->second != ch){
Get_Follow(iter->second, st);
}
}
}
}
}
} //求所有非终结符的FOLLOW集
void Set::Follow_Solve()
{
set<char>Follow;
for (set<char>::iterator iter = Non_terminal.begin(); iter != Non_terminal.end(); iter++){
Follow.clear();
if (*iter == 'S')Follow.insert('#'); //如果是开始符
Get_Follow(*iter, Follow);
string str = "";
for (set<char>::iterator it = Follow.begin(); it != Follow.end(); it++)str += (*it);
FOLLOW.push_back(make_pair(*iter, str));
}
} //输出所有非终结符的FOLLOW集
void Set::Show_Follow()
{
cout << " " << "FOLLOW集" << " " << endl << endl;
for (int i = ; i < (int) FOLLOW.size(); i++){
cout << FOLLOW[i].first << " : ";
for (int j = ; j <(int) FOLLOW[i].second.size(); j++){
cout << FOLLOW[i].second[j] << " ";
}
cout << endl;
}
cout << endl;
} //求解SELECT集
void Set::Select_Solve()
{
multimap<char, string>::iterator iter;
vector<PP >::iterator it;
set<char >st;
for (iter = Grammars.begin(); iter != Grammars.end(); iter++){
char ch = iter->first;
string str = iter->second;
bool flag = true;
st.clear();
for (int i = ; i < (int)str.size(); i++){
if (Ok.find(str[i]) == Ok.end()&& str[i] != '~'){
flag = false;
}
}
//求FIRST(a)
int pos = ;
while (pos < (int)str.size() && Ok.find(str[pos]) != Ok.end()){
for (it = FIRST.begin(); it != FIRST.end(); it++){
if (str[pos] == it->first)break;
}
for (int j = ; j < (int)it->second.size(); j++){
st.insert(it->second[j]);
}
pos++;
}
if (pos < (int)str.size()){
if (isupper(str[pos])){
for (it = FIRST.begin(); it != FIRST.end(); it++){
if (str[pos] == it->first)break;
}
for (int j = ; j < (int)it->second.size(); j++){
st.insert(it->second[j]);
}
}else
st.insert(str[pos]);
}
//如果产生式A->a并且a能推出空,则SELECT(A->a)=(FIRST(a)-{~})U(FOLLOW(A)
if (flag){
for (it = FOLLOW.begin(); it != FOLLOW.end(); it++){
if (ch == it->first)break;
}
for (int j = ; j < (int)it->second.size(); j++){
st.insert(it->second[j]);
}
for (set<char>::iterator ii = st.begin(); ii != st.end(); ){
if ((*ii) == '~'){
ii = st.erase(ii);
break;
}
ii++;
}
string ss = "";
for (set<char>::iterator ii = st.begin(); ii != st.end(); ii++)ss += (*ii);
SELECT.push_back(make_pair(ch, make_pair(str,ss)));
}
//否则SELECT(A->a)=(FIRST(a)
else {
string ss = "";
for (set<char>::iterator ii = st.begin(); ii != st.end(); ii++)ss += (*ii);
SELECT.push_back(make_pair(ch, make_pair(str,ss)));
}
}
} //输出SELECT集
void Set::Show_Select()
{
cout << " " << "SELECT集" << " " << endl << endl;
for (int i = ; i < (int) SELECT.size(); i++){
cout << SELECT[i].first << " ->";
cout << setw() << SELECT[i].second.first << " : ";
for (int j = ; j < (int) SELECT[i].second.second.size(); j++){
cout << SELECT[i].second.second[j] << " ";
}
cout << endl;
}
cout << endl;
} //预测分析程序
void Set::Analysis()
{
cout << "请输入要识别的串: " << endl;
string str;
cin >> str;
for (int i = ; i < (int)str.size(); i++){
Sentence.push_back(str[i]);
}
Sentence.push_back('#');
vector<char>::iterator iter = Sentence.begin(), ii;
stack<char>S;
vector<char>vet;
S.push('#');
S.push('S');
vet.push_back('#');
vet.push_back('S');
cout << "分析栈" << " " << "剩余输入串" << " " << "推倒所用的产生式或匹配" << endl;
int EMPTY = ;
while (!S.empty()){
for (int i = ; i < (int)vet.size(); i++){
cout << vet[i] << " ";
}
for (int i = (int)vet.size(); i <= EMPTY+; i++)cout << " ";
int count = ;
for (ii = iter; ii != Sentence.end(); ii++){
cout << (*ii) << " ";
count++;
}
for (; count <= EMPTY; count++)cout << " ";
char ch = S.top();
if (ch == (*iter)){
S.pop();
vet.pop_back();
iter++;
for (int i = ; i <= EMPTY; i++)cout << " ";
cout << "匹配" << endl;
}
else {
vector<PPP >::iterator it;
string ss = "";
bool flag = false;
for (it = SELECT.begin(); it != SELECT.end(); it++){
if (it->first == ch){
ss = it->second.first;
for (int i = ; i < (int)it->second.second.size(); i++){
if (it->second.second[i] == (*iter)){
flag = true;
break;
}
}
if (flag)break;
}
}
for (int i = ; i <= EMPTY; i++)cout << " ";
if (!flag){
cout << "ERROR!!!" << endl;
return;
}
cout << ch << "->" << ss << endl;
reverse(ss.begin(), ss.end()); //反转
if (ss == "~"){
S.pop();
vet.pop_back();
}
else {
S.pop();
vet.pop_back();
for (int i = ; i < (int)ss.size(); i++){
S.push(ss[i]);
vet.push_back(ss[i]);
}
}
}
}
cout << "SUCCESS" << endl;
} int main()
{
Set obj;
obj.Get_Ok();
obj.First_Solve();
obj.Show_First();
obj.Follow_Solve();
obj.Show_Follow();
obj.Select_Solve();
obj.Show_Select();
obj.Analysis();
return ;
}

编译原理实习(应用预测分析法LL(1)实现语法分析)的更多相关文章

  1. 编译原理学习笔记·语法分析(LL(1)分析法/算符优先分析法OPG)及例子详解

    语法分析(自顶向下/自底向上) 自顶向下 递归下降分析法 这种带回溯的自顶向下的分析方法实际上是一种穷举的不断试探的过程,分析效率极低,在实际的编译程序中极少使用. LL(1)分析法 又称预测分析法, ...

  2. 编译原理实验之SLR1文法分析

    ---内容开始--- 这是一份编译原理实验报告,分析表是手动造的,可以作为借鉴. 基于  SLR(1) 分析法的语法制导翻译及中间代码生成程序设计原理与实现1 .理论传授语法制导的基本概念,目标代码结 ...

  3. Compiler Theory(编译原理)、词法/语法/AST/中间代码优化在Webshell检测上的应用

    catalog . 引论 . 构建一个编译器的相关科学 . 程序设计语言基础 . 一个简单的语法制导翻译器 . 简单表达式的翻译器(源代码示例) . 词法分析 . 生成中间代码 . 词法分析器的实现 ...

  4. 《编译原理》-用例题理解-自顶向下语法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法

    <编译原理>-用例题理解-自顶向下语法分析及 FIRST,FOLLOW,SELECT集,LL(1)文法 此编译原理确定某高级程序设计语言编译原理,理论基础,学习笔记 本笔记是对教材< ...

  5. 【编译原理】语法分析LL(1)分析法的FIRST和FOLLOW集

    近来复习编译原理,语法分析中的自上而下LL(1)分析法,需要构造求出一个文法的FIRST和FOLLOW集,然后构造分析表,利用分析表+一个栈来做自上而下的语法分析(递归下降/预测分析),可是这个FIR ...

  6. 编译原理(六)自底向上分析之LR分析法

    自底向上分析之LR分析法 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 基本概念 1. LR分析:从左到右扫描(L)自底向上进行规约(R),是规范规约,也即最右推导(规范推导) ...

  7. 《编译原理》LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析

    <编译原理>LR 分析法与构造 LR(1) 分析表的步骤 - 例题解析 笔记 直接做题是有一些特定步骤,有技巧.但也必须先了解一些基本概念,本篇会通过例题形式解释概念,会容易理解和记忆,以 ...

  8. 语法设计——基于LL(1)文法的预测分析表法

    实验二.语法设计--基于LL(1)文法的预测分析表法 一.实验目的 通过实验教学,加深学生对所学的关于编译的理论知识的理解,增强学生对所学知识的综合应用能力,并通过实践达到对所学的知识进行验证.通过对 ...

  9. AX中四种库存ABC分析法原理研究

    库存ABC分类,简单的说就是抓大放小,是为了让我们抓住重点,用最大精力来管理最重要的物料,而对于不太重要的物料则可以用较少的精力进行管理.它和我们平常说的八二法则有异曲同工之妙. 既然要应用库存ABC ...

随机推荐

  1. 外键约束 以及 数据库中实体的对应关系(1==1,1==n,n==n)

    1.1.1 外键约束 Create database day16; Use day16; 创建部门表: create table dept( did int primary key auto_incr ...

  2. Oracle java.sql.SQLException: 数字溢出

    六月 30, 2016 5:47:47 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinit ...

  3. PHP输出Excel两种方法

    2016年3月23日 16:43:51 星期三 第一种: 输出html+css格式, 打开后用Excel软件的"另存为"功能保存为正规的表格格式 public function e ...

  4. win8开发wpf程序遇到的无语问题

    在设置wpf程序全屏后,点击某个listbox列表,发现程序下面出现了任务栏. 查找解决答案未果.仔细一想可能是win8系统的问题. 最后试着把listbox的滚动条去掉了,问题解决. 原因:当程序中 ...

  5. [转]finished with non-zero exit value 2

    Error:Execution failed for task ':phoneacompany:dexDebug'. > com.android.ide.common.process.Proce ...

  6. nyoj756_重建二叉树_先序遍历

    重建二叉树 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 题目很简单,给你一棵二叉树的后序和中序序列,求出它的前序序列(So easy!).   输入 输入有多组数 ...

  7. Spring@Autowired注解与自动装配

    1   配置文件的方法 我们编写spring 框架的代码时候.一直遵循是这样一个规则:所有在spring中注入的bean 都建议定义成私有的域变量.并且要配套写上 get 和 set方法. Boss ...

  8. 20145213《Java程序设计》实验二Java面向对象程序设计实验报告

    20145213<Java程序设计>实验二Java面向对象程序设计实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装,继承,多态 初步掌握UML建模 熟悉S.O. ...

  9. .Net如何在后台设置日期格式,并显示在前台页面上

    其实方法比较老咯,有比这个简单的朋友请留言哈,我的思路是先将数据库中的日期格式读出来,在后台转化成DatetTime类型,然后在使用DateTime的内部方法设置日期格式,代码如下: DateTime ...

  10. php字符串处理函数相关操作

    <?php//获取tech和98426这两个字符串