当前位置:网站首页>编译原理研究性学习专题 2——递归下降语法分析设计原理与实现
编译原理研究性学习专题 2——递归下降语法分析设计原理与实现
2022-07-28 21:51:00 【dor.yang】
1 实验内容
完成以下描述赋值语句的 LL(1)文法的递归下降分析程序
G[S]: S→ V=E
E→ TE’
E’→ ATE’ | e
T→ FT’
T’→ MFT’ | E
F→ (E) | i
A→ + | -
M→ * | /
V→ i
设计说明:终结符号 i 为用户定义的简单变量,即标识符的定义。
2 实验要求
(1)输入串应是词法分析的输出二元式序列,即某算术表达式“专题 1” 的输出结果,输出为输入串是否为该文法定义的算术表达式的判断结果;
(2)递归下降分析程序应能发现简单的语法错误;
(3)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果;
(4)选做:如有可能,考虑如何用文法描述 C 语言的 if 语句,使整个文 法仍然为 LL(1)文法,并使得你的递归下降程序可以分析赋值语句和 if 语句
3.程序功能描述
结合实验要求,完成实验二程序,具体实现功能为读取同目录下的实验一输出的词法判别的二元式文件,根据给定文法,按照递归下降分析的方式判断输入的语句是否合理。对于不合理的部分,在判定出错之后输出错误的点。
4.程序结构描述
由于语法是给定的,所以可以先完成first和follow集合的计算:
根据first和follow集合以及给定的文法,可以确定递归向下分析程序的结构。
所以程序的整体表达式结构为:
S的递归分析程序结构如下图
E的递归下降分析程序结构如下图:
E’的递归向下分析的结构图
T的递归下降分析程序结构如下:
T’的递归下降分析程序结构如下:
F的递归下降分析程序结构如下:
A的递归下降分析程序结构如下:
M的递归下降分析程序结构如下:
V的递归下降分析程序结构如下:
5.实现代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include <cassert>
#include<fstream>
#define MAX_LINE 1024
using namespace std;
// 函数声明
void S();
void E();
void E_();
void T();
void T_();
void F();
void A();
void M();
void V();
// 定义一个长度为100的字符数组
char s[100];
// 用来作数组索引,当每次匹配成功存入数据时index自增1
int i;
// 用来标记语句是否正确
int SIGN;
int main()
{
// printf("请输入你的语句(记得在最后带上#)\n");
cout<<"读取文件可知输入语句:"<<endl;
FILE *fp;
char buf[MAX_LINE];
string shizi,like;
if((fp = fopen("text.txt","r"))!=NULL){
while(fgets(buf,MAX_LINE,fp) != NULL)
{
int len = strlen(buf);
buf[len-1] = '\0'; /*去掉换行符*/
printf("%s \n",buf);
int flag=0;
if(buf[1]=='1'){
like+='i';
}
for(int i=0;i<len;i++){
if(buf[i]=='"'&&flag==0){
i++;
while(buf[i]!='"'){
shizi+=buf[i];
if(buf[1]!='1'){
like+=buf[i];
}
i++;
}
}
}
}
}
shizi+='#';
like+='#';
fclose(fp);
cout<<"输入的语句为:"<<shizi<<endl;
cout<<"可以理解为:"<<like<<endl;
SIGN = 0;//语句是否正确用SIGN
i=0;
//将输入的式子按照修改为字符串格式char*
int length=like.length();
for(int i=0;i<length;i++){
s[i]=like[i];
}
// 当输入的第一个字符为#时,程序直接结束
if( s[0] == '#')
return 0;
S();
// 如果最后的字符以#结束则输出下面
if(s[i]=='#'&&SIGN==0){
printf("\n语句合法\n");
}else{
printf("\n语句不合法\n");
}
// printf("请输入你的语句(记得在最后带上#)\n");
// }
return 1;
}
void S()
{
if(SIGN==0)
{
printf("S检查 ");
// 当输入的字符串中首字母为a时
if(s[i]=='i'){
V();
if(SIGN==0&&s[i]=='='){
// printf("(%c) ",s[i]);
i++;
E();
}
else{
SIGN=1;
cout<<"S处出现错误"<<endl;
}
}
else{
SIGN=1;
cout<<"S处出现错误"<<endl;
}
}
}
void E()
{
if(SIGN==0){
printf("E ");
if(s[i]=='('||s[i]=='i'){
T();
if(SIGN==0){
if(s[i]=='+'||s[i]=='-'){
E_();
}
else if(s[i]==')'||s[i]=='#'){
return;
}
else{
SIGN=1;
cout<<"E处出现错误"<<endl;
}
}
}
else{
SIGN=1;
cout<<"E处出现错误"<<endl;
}
}
}
void E_()
{
if(SIGN==0){
printf("E' ");
if(s[i]=='+'||s[i]=='-'){
A();
if(SIGN==0){
if(s[i]=='('||s[i]=='i'){
T();
if(SIGN==0){
if(s[i]=='+'||s[i]=='-'){
E_();
}
else if(s[i]==')'||s[i]=='#') {
return;
}
else{
SIGN=1;
cout<<"E'处出现错误"<<endl;
}
}
}
else{
SIGN=1;
cout<<"E'处出现错误"<<endl;
}
}
}
else if(s[i]==')'||s[i]=='#'){
return;
}
else{
SIGN=1;
cout<<"E'处出现错误"<<endl;
}
}
}
void T()
{
if(SIGN==0){
printf("T ");
if(s[i]=='('||s[i]=='i'){
F();
if(SIGN==0){
if(s[i]=='*'||s[i]=='/'){
T_();
}
else if(s[i]=='+'||s[i]=='-'||s[i]==')'||s[i]=='#') {
return;
}
else{
SIGN=1;
cout<<"T处出现错误"<<endl;
}
}
}
else{
SIGN=1;
cout<<"T处出现错误"<<endl;
}
}
}
void T_()
{
if(SIGN==0){
printf("T' ");
if(s[i]=='*'||s[i]=='/'){
M();
if(SIGN==0){
F();
if(SIGN==0){
T_();
}
}
}
else if(s[i]=='+'||s[i]=='-'||s[i]==')'||s[i]=='#'){
return;
}
else{
SIGN=1;
cout<<"T'处出现错误"<<endl;
}
}
}
void F()
{
if(SIGN==0){
printf("F ");
if(s[i]=='('){
// printf("(%c) ",s[i]);
i++;
if(s[i]=='('||s[i]=='i'){
E();
if(SIGN==0){
if(s[i]==')'){
// printf("(%c) ",s[i]);
i++;
}
else{
SIGN=1;
cout<<"F处出现错误"<<endl;
}
}
}
else{
SIGN=1;
cout<<"F处出现错误"<<endl;
}
}
else if(s[i]=='i'){
// printf("(%c) ",s[i]);
i++;
}
else{
SIGN=1;
cout<<"F处出现错误"<<endl;
}
}
}
void A()
{
if(SIGN==0){
printf("A ");
if(s[i]=='+'||s[i]=='-'){
// printf("(%c) ",s[i]);
i++;
}
else{
SIGN=1;
cout<<"A处出现错误"<<endl;
}
}
}
void M()
{
if(SIGN==0){
printf("M ");
if(s[i]=='*'||s[i]=='/'){
// printf("(%c) ",s[i]);
i++;
}
else{
SIGN=1;
cout<<"M处出现错误"<<endl;
}
}
}
void V()
{
if(SIGN==0){
printf("V ");
if(s[i]=='i'){
// printf("(%c) ",s[i]);
i++;
}
else{
SIGN=1;
cout<<"V处出现错误"<<endl;
}
}
}
6.程序测试
按照实验要求,提供两个测试样例,一个正确一个错误:
首先是正确的测试样例,将a=b*(c+d)输入在input文件中,启动程序lab1,产生对应的二元式,这里为了便于判断和操作,将标识符的二元式输出修改为(1,‘符号’),得到的输出二元式如下:

接下来启动Lab2,可以得到如下结果:
将上图的输出部分单独显示:
读取文件可知输入语句:
(1,“a”)
(运算符,“=”)
(1,“b”)
(运算符,"“)
(分隔符,”(“)
(1,“c”)
(运算符,”+“)
(1,“d”)
(分隔符,”)")
输入的语句为:a=b(c+d)#
可以理解为:i=i*(i+i)#
S检查 V E T F T’ M F E T F E’ A T F T’
语句合法
其中倒数第二行的输出是进行递归下降分析的过程中,每一个非终结符号对应函数的使用的输出。
接下来是错误的测试样例:将a=b*(c+d输入在input文件中,启动程序lab1,产生对应的二元式,得到的输出二元式如下:
启动Lab2的程序之后得到的结果如下:
将程序输出部分单独显示:
读取文件可知输入语句:
(1,“a”)
(运算符,“=”)
(1,“b”)
(运算符,"“)
(分隔符,”(“)
(1,“c”)
(运算符,”+")
(1,“d”)
输入的语句为:a=b(c+d#
可以理解为:i=i*(i+i#
S检查 V E T F T’ M F E T F E’ A T F
F处出现错误
语句不合法
边栏推荐
- 2022年G2电站锅炉司炉考试题库模拟考试平台操作
- VR全景创业如何开拓市场?如何让创业之路更加顺畅?
- 2022 R2 mobile pressure vessel filling test question simulation test platform operation
- MyCms 自媒体商城 v3.6 发布,兼容微擎应用开发(Laravel框架)
- Array array object
- Custom MVC principle and framework
- 苹果官网正在更新维护 Apple Store,国行 iPhone 13 / Pro 等产品将最高优惠 600 元
- 金仓数据库KingbaseES 客户端编程接口指南 - ODBC (2. 概述)
- Intel data center GPU is officially shipped to provide strong computing power with openness and flexibility
- 2022年R2移动式压力容器充装考题模拟考试平台操作
猜你喜欢
![Trivy [2] tool vulnerability scanning](/img/7a/c1012c75b23076f5a9b09e5756adba.png)
Trivy [2] tool vulnerability scanning

How to add the index of a set in mongodb to another set in mongodb

Meet the outbreak period with the integration of transportation and parking, rush for mass production or build a technical moat?

How to open a profitable gym? I tell you from one year's experience that don't fall in love

MySQL log management, backup and recovery

【自】-刷题-集合

网络流量监控工具iftop

Shenkaihong: on the river of Zhilian of all things, there is a bright moon of open source

可视化全链路日志追踪
Object object
随机推荐
Array array object
Programmer growth Chapter 30: artifact of identifying true and false needs
「行泊一体」放量,福瑞泰克高性能域控制器领跑新赛道
这款全网热评的无线路由器,到底有什么特别?
1314_串口技术_RS232通信基础的信息
2022g3 boiler water treatment test simulation 100 questions simulation test platform operation
深度剖析集成学习Xgboost
二舅火了,全网刷屏,他凭什么能治好我的精神内耗?
金仓数据库 KingbaseES 与 Oracle 的兼容性说明(3. 常用函数)
零念科技完成Pre-A轮融资,推动智能驾驶平台软件国产替代
Win11找不到DNS地址怎么办?Win11找不到DNS无法访问网页解决方法
Arduino uno driver universe 1.8 'TFT SPI screen example demonstration (including data package)
Development of small programs ①
Why did "you" become a test / development programmer? The value of your existence
集火全屋智能“后装市场”,真正玩得转的没几个
wget什么意思
Solve the problem of using anonymous users in pod due to the failure of attaching ciphertext token files for serviceaccount user authentication
Intel data center GPU is officially shipped to provide strong computing power with openness and flexibility
以流量为主导的数字零售的发展模式,仅仅只是一个开始
解决线程安全问题&&单例模式