实验目的:
针对给定的上下文无关文法,编制一个递归下降分析程序。

分析:

  • 递归下降语法分析的前提是保证LL(1)文法

递归下降的思路就是暴力dfs。对每个程序直接不管三七二十一搜进去,只要能搜到就继续搜。搜不到就return搜其他的。

先看文法:

①    : lexp->atom|list
②   :atom->number|identifier
③   :list->(lexp-seq)
④   :lexp-seq->lexp-seq lexp|lexp

很明显左递归,先消除一下


①   : lexp->atom|list
②   :atom->number|identifier
③   :list->(lexp-seq)
④   :lexp-seq->lexp lexp-seq’
⑤   : lexp-seq’->lexp lexp-seq’|ε

然后直接对input字符流开始递归调用。

#include<stdio.h>
#include<cstdlib>
#include<string.h>
#define maxn 1000
using namespace std;
int idx=0;
char str[maxn];
int lexp();
void atom();
void list();
void lexp_sep();
void lexp_sep_();
int lexp(){if( (str[idx]>='0'&&str[idx]<='9')||(str[idx]>='a'&&str[idx]<='z') ){printf("lexp->atom\n");atom();return 1;}else if(str[idx]=='('){printf("lexp->list\n");list();return 1;}else return 0;
}
void atom(){if(str[idx]>='0'&&str[idx]<='9'){printf("atom->number\n");idx++;}else if(str[idx]>='a'&&str[idx]<='z'){printf("atom->identifier\n");idx++;}
}
void list(){if(str[idx]!='('){printf("list()error!\n");exit(-1);}printf("list->(lexp_seq)\n");idx++;lexp_sep();if(str[idx]!=')'){printf("list()error!\n");exit(-1);}idx++;
}
void lexp_sep(){printf("lexp_sep->lexp lexp_seq'\n");lexp();lexp_sep_();
}
void lexp_sep_(){if(lexp()==1){lexp_sep_();}else return;
}
int main(int argc,char* argv[]){scanf("%s",str);int len=strlen(str);str[len++]='$';str[len]='\0';lexp(); if(str[idx]=='$') printf("accept!\n");else printf("wrong answer!\n");return 0;
}

测试数据:

(a(b(2))c)

输出结果:

lexp->list
list->(lexp_seq)
lexp_sep->lexp lexp_seq'
lexp->atom
atom->identifier
lexp->list
list->(lexp_seq)
lexp_sep->lexp lexp_seq'
lexp->atom
atom->identifier
lexp->list
list->(lexp_seq)
lexp_sep->lexp lexp_seq'
lexp->atom
atom->number
lexp->atom
atom->identifier
accept!

可以看到匹配是能成功的,但是对于想要我们输出该语法树就存在问题了。

经过思考发现,直接递归下降分析是无法完成语法树的构建输出的,虽然能匹配正确结果。
原因在于其需要判定递归有效才会输出,因此在决定是否进入的时候不能保证输出此次进去还是不进去。单纯一次递归有效可以用栈判定,但是多次就不行了。
因此需要构建first集合和follow集合来构建预测分析表。

当然cyc给每个token额外加了括号来直接dfs搜保证了正确的输出。在这里膜一下



#include<iostream>
#include<stack>
#include<algorithm>
#include<string>
using namespace std;
stack<string>input;
stack<string>st;
bool number(const string& s){for(int i=0;i<(int)s.size();i++){if(!(s[i]>='0'&&s[i]<='9')) return false;}return true;
}
bool identifier(const string& s){for(int i=0;i<(int)s.size();i++){if(!(s[i]>='a'&&s[i]<='z')) return false;}return true;
}
int main(){input.push("$");string s;cin>>s;for(int i=(int)s.size()-1;i>=0;i--){string tmp;tmp+=s[i];input.push(tmp);}st.push("$");st.push("lexp");while(st.size()>1){string now=st.top();st.pop();string cnt=input.top();if(now=="lexp"){if(cnt=="("){cout<<"lexp  -> list"<<endl;st.push("list");} else if(number(cnt)){cout<<"lexp -> atom"<<endl;st.push("atom");}else if(identifier(cnt)){cout<<"lexp -> atom"<<endl; st.push("atom");}else{cout<<"lexp()->next error!"<<endl;exit(-1);}}else if(now=="atom"){if(number(cnt)){cout<<"atom -> number"<<endl;input.pop();  }else if(identifier(cnt)){cout<<"atom -> identifier"<<endl;input.pop();}else{cout<<"atom()->next error!"<<endl;exit(-1);}}else if(now=="list"){if(cnt=="("){cout<<"list -> ( lexp-seq )"<<endl;input.pop(); st.push(")");st.push("lexp-seq");}else{cout<<"list()-> next errpr!"<<endl;exit(-1);}}else if(now=="lexp-seq"){if(cnt=="("||number(cnt)||identifier(cnt)){cout<<"lexp-seq -> lexp lexp-seq'"<<endl;st.push("lexp-seq'");st.push("lexp");} else{cout<<"lexp-seq()->next error!"<<endl;exit(-1);}}else if(now=="lexp-seq'"){if(cnt=="("||number(cnt)||identifier(cnt)){cout<<"lexp-seq'  -> lexp lexp-seq'"<<endl; st.push("lexp-seq'");st.push("lexp");}else{cout<<"lexp-seq'  -> NULL"<<endl; }}else if(now==")"&&cnt==")"){input.pop(); }else{cout<<"Wrong answer"<<endl;exit(-1);}}cout<<"Accept!"<<endl;
}

输入:

(a(b(2))c)

python生成图片:

编译原理实验-递归下降语法分析器的构建相关推荐

  1. 《编译原理》实验报告——递归下降语法分析器的构建

    一.实验要求 运用递归下降法,针对给定的上下文无关文法,给出实验方案.预估实验中可能出现的问题. 二.实验方案 1.构造LL(1),通过设计.编制.调试递归下降语法分析程序,对输入的符号串进行分析匹配 ...

  2. 从0开始的python学习:编译原理实验4:语法分析器1--预测分析器构造

    这里刚开始试用python的函数功能,可能把局部变量和全局变量给写乱了,后期交之前还想再优化的时候发现越改越乱,太真实的hhh 实验四:语法分析器1–预测分析器构造 实验目的: 通过编写一个预测分析器 ...

  3. 《编译原理》实验预习报告——递归下降语法分析器的构建

    一.实验目的 根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析.本次实验的目的主要是加深对递归下降分析法的理解. 二.实验预习提示 1.递归下降分析法的功能 词法分析器的功能是利用 ...

  4. 递归下降语法分析器的构建_一文了解函数式查询优化器Spark SQL Catalyst

    大数据技术与架构点击右侧关注,大数据开发领域最强公众号! 暴走大数据点击右侧关注,暴走大数据!记录一下个人对sparkSql的catalyst这个函数式的可扩展的查询优化器的理解,目录如下: 0. O ...

  5. 递归下降文法C语言实验报告,递归下降语法分析器实验报告.doc

    递归下降语法分析器实验报告 编译原理实验报告 题目: 递归下降语法分析器 学 院 计算机科学与技术 专 业 xxxxxxxxxxxxxxxx 学 号 xxxxxxxxxxxx 姓 名 宁剑 指导教师 ...

  6. 编译原理课程设计:语法分析器

    配套代码: 编译原理课程设计:语法分析器-Python文档类资源-CSDN下载所使用的开发环境:Windows10.python(PyCharm)环境注意:expression更多下载资源.学习资料请 ...

  7. 编译原理 - 实验三 - 递归下降语法分析器的调试及扩展

    一. 语法分析介绍 语法分析是编译过程的核心部分,它的主要任务是按照程序语言的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行语法检查,为语义分析和代码生成做准备.执行语法分析任 ...

  8. 编译原理:LL(1)语法分析器的实现(内含代码详细注释)

     自顶向下语法分析器的设计与实现 目录 一.说明 二.程序功能及运行截图 功能 运行截图 三.算法逻辑和程序流程图 定义的主要变量或存储结构 (1)消除直接左递归 (2)求FIRST集合 (3)求FO ...

  9. c语言语法分析源程序,深入浅出编译原理-5-一个简单语法分析器的C语言实现

    引言 前面已经介绍了编译器的预处理,词法分析,词法分析器的实现,也在其中说到了语法分析的任务和过程. 语法分析的输入是词法单元序列,然后根据语言的文法表示(展开式),利用有限状态机理论,生成抽象语法树 ...

最新文章

  1. 滑动平均滤波_11种滤波算法程序大全(含源代码分享)
  2. t-SNE(t-distributed stochastic neighbor embedding)
  3. eclipse maven创建web项目
  4. 编写JUnit测试的另一种方法(Jasmine方法)
  5. mysql 5.7 pxc_mysql5.7 PXC安装记录
  6. threejs指定对象旋转中心
  7. list排序(Collections.sort())
  8. 数据结构知识点大汇总(三)
  9. c语言程序设计网络作业,北语网院17春《C语言程序设计》作业_2满分答案
  10. 微课|《Python编程基础与案例集锦(中学版)》第3章(1)
  11. Spring + MyBatis配置整合
  12. 数据库的使用(SQL)
  13. Centos7 搭建 Socks 服务
  14. 程序人生之六:写在 2010 年最后一晚,我这两年的工作总结
  15. october php,php – 如何调用组件内的组件[OctoberCMS]
  16. 110款表白网站源码,搭建表白网站必备,总有一款适合你
  17. 贪玩蓝月服务器维护需多少时间,贪玩蓝月合区维护一次多久 | 手游网游页游攻略大全...
  18. 如何从零开始搭建自己的博客(通俗易懂)
  19. 美 DISA 发布数据战略实施计划
  20. 无人便利店代理的系统用于其他行业是否可以

热门文章

  1. Mysql学习之constraint/key/primary key/unique/foreign key/constraint的关系
  2. hough变换检测直线 matlab,Matlab实现Hough变换检测图像中的直线
  3. 项目管理工具 Open Project 介绍
  4. 通信运营商在信息化路上举步维艰
  5. VC2012下MFC程序各控件的常用方法
  6. 移动端开发框架选择及实践
  7. 友盟推送小米手机通知栏图标显示问题
  8. 如何查看Chrome浏览器曾经使用过的账号和密码?查看方法分享
  9. 内蒙古大学考研复试计算机,内蒙古大学计算机考研复试题
  10. 服务程序使用OutputDebugString,DbgView接收不到调试信息问题