#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. poj 1797(并查集)

    http://poj.org/problem?id=1797 题意:就是从第一个城市运货到第n个城市,最多可以一次运多少货. 输入的意思分别为从哪个城市到哪个城市,以及这条路最多可以运多少货物. 思路 ...

  2. linux mysql查看安装信息

    ps -ef|grep mysql root               ?        :: /bin/sh /usr/bin/mysqld_safe --datadir=/var/lib/mys ...

  3. android一句话搞定图片加载

    http://square.github.io/picasso/ Picasso.with(context).load("http://i.imgur.com/DvpvklR.png&quo ...

  4. java 入门 第二季3

    1.继承 1.java是单继承的,一个子类只有一个父类 父类,基类 子类,派生类 2.继承的好处:子类拥有父类的所有属性和方法,属性的修饰符不能是private 3.语法规则: class 子类 ex ...

  5. Python~Outlook

    用python处理outlook邮件 按季度将邮件分类,归入新建文件夹2016Q1,2015Q4等等 http://www.tuicool.com/articles/Fra22mq Python读取O ...

  6. 【C语言】pragma

    ① #pragma comment (lib, "libgsl.a") 这是告诉编译器在编译形成的.obj文件和.exe文件中加一条信息,使得 链接器在链接库的时候要去找libgs ...

  7. 20145213《Java程序设计》第一周学习总结

    20145213<Java程序设计>第一周学习总结 教材学习内容总结 期待了一个寒假,终于见识到了神秘的娄老师和他的Java课.虽说算不上金风玉露一相逢,没有胜却人间无数也是情理之中,但娄 ...

  8. 解决 The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement

    这个时候我们只需要flush privileges 一下就OK了,mysql> flush privileges;Query OK, 0 rows affected (0.01 sec)

  9. rabbitmq_hearbeat

    heartbeat[心跳检测],用于报告客户端与服务器之间连接的一种检测机制.在rabbitmq中有Sender和consumer. 为了确保rabbitmq与客户端的状态,需启用heartbeat. ...

  10. 使用DateUtils和DateFormatUtils处理时间日期转换与SimpleDateFormat的区别

    在Apache Commons项目的Lang里面,有两个类:DateUtils和DateFormatUtils,专门用于处理时间日期转换.它们在 org.apache.commons.lang.tim ...