递归下降语法分析程序设计与实现

制作一个简单的C语言词法分析程序_用c语言编写词法分析程序-CSDN博客文章浏览阅读276次。C语言的程序中,有很单词多符号和保留字。一些单词符号还有对应的左线性文法。所以我们需要先做出一个单词字符表,给出对应的识别码,然后跟据对应的表格来写出程序。_用c语言编写词法分析程序https://blog.csdn.net/lijj0304/article/details/134078944前置程序词法分析器参考这个帖子⬆️

1.程序目标

递归下降实现的语法分析程序,程序可以识别词法分析程序的输出文件中的二元序列,拼凑出用户输入的算式,然后通过递归下降的方式从中识别算术表达式是否正确,在错误位置输出提示。算式的语法如下:

G[S]:S→V=E        E→TE′        E′→ATE|ε        T→FT′        T′→MFT′|ε        F→ (E)|i        A→+|-M→*|/        V→i

2.程序设计

程序会分析analyze文件,根据二元式拼凑出原本的输入str,然后把算式中的变量转换成i,同时在结尾处加上结束符号#,方便运算。同时程序还设计了一个全局变量flag用于标记当前递归下降分析器的状态,如果出错则会把flag置为1。

完整的程序运行顺序如下:

  1. 读入分析的二元式获得用户输入
  2. 转换变量,加上结束符
  3. 递归下降分析,输出结论

3.递归下降详细设计

首先我根据给定的语法,计算处所需要用到的first集和follow集

first

follow

S

i

#

E

(, i

#, )

E’

+, -, ε

#, )

T

(, i

+, -, #, )

T’

*, /, ε

+, -, #, )

F

(, i

*, /, +, -, #, )

A

+, -

(, i

M

*, /

(, i

V

i

=

S的递归下降分析程序设计:

E的递归下降分析程序设计:

E’的递归下降分析程序设计:

T的递归下降分析程序设计:

T’的递归下降程序设计:

F的递归下降程序设计:

A的递归下降程序设计:

M的递归下降程序设计:

V的递归下降程序设计:

4.完整程序 

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX_LEN 1000
char str[MAX_LEN];
int i, j, flag;
void S();
void E();
void E1();
void T();
void T1(); 
void F();
void A(); 
void M(); 
void V();

void S() {
    if(flag == 0) {
        printf("S->");
        if(str[i] == 'i') {
            V();
			if(flag == 0 && str[i] == '=') {
				i++;
				E();
			}
			else {
				flag = 1;
				printf("error\n"); 
			}
        }	
		else {
            flag = 1;
            printf("error\n"); 
        }
    }
}

void E() {
    if(flag == 0) {
        printf("E->");
        if(str[i] == '(' || str[i] == 'i') {
            T();
            if(flag == 0) {
				if(str[i] == '+' || str[i] == '-')
					E1();
				else if(str[i] == ')' || str[i] == '#')
                    return;
				else {
					flag = 1;
					printf("error\n"); 
				}
			}
        }
        else {
			flag = 1;
			printf("error\n"); 
		}
    }
}

void E1() {
    if(flag == 0) {
		printf("E'->");
        if(str[i] == '+' || str[i] == '-') {
            A();
            if(flag == 0) {
				if(str[i] == '(' || str[i] == 'i') {
					T();
					if(flag == 0){
						if(str[i] == '+' || str[i] == '-')
							E1();
						else if(str[i] == ')' || str[i] == '#')
							return;
						else {
							flag = 1;
							printf("error\n"); 
						}
					}
				}
				else{
					flag = 1;
					printf("error\n"); 
				}
			}
        }
        else if(str[i] == ')' || str[i] == '#')
			return;
        else {
			flag = 1;
			printf("error\n"); 
		}
    }
}

void T() {
    if(flag == 0) {
		printf("T->");
        if(str[i] == '(' || str[i] == 'i') {
            F();
            if(flag == 0) {
				if(str[i] == '*' || str[i] == '/')
					T1();
				else if(str[i] == '+' || str[i] == '-' || str[i] == ')' || str[i] == '#')
					return;
				else {
					flag = 1;
					printf("error\n"); 
				}
			}
        }
        else {
			flag = 1;
			printf("error\n"); 
		}
    }
}

void T1() {
	if(flag == 0) {
		printf("T'->");
		if(str[i] == '*' || str[i] == '/') {
			M();
			if(flag == 0) {
				F();
				if(flag == 0)
					T1();
			}
		}
		else if(str[i] == '+' || str[i] == '-' || str[i] == ')' || str[i] == '#')
			return;			
		else {
			flag = 1;
			printf("error\n"); 
		}
	}
}

void F() {
	if(flag == 0){
		printf("F->");
		if(str[i] == '(') {
			i++;
			if(str[i] == '(' || str[i] == 'i') {
				E();
				if(flag == 0) {
					if(str[i] == ')')
						i++;
					else {
						flag = 1;
						printf("error\n"); 
					}
				}
			}
			else {
				flag = 1;
				printf("error\n");
			}
		}
		else if(str[i] == 'i') {
			i++;
		}
		else {
			flag = 1;
			printf("error\n");
		}
	}
}

void A() {
	if(flag == 0) {
		printf("A->");
		if(str[i] == '+' || str[i] == '-')
			i++;
		else {
			flag = 1;
			printf("error\n");
		}
	}
}

void M() {
	if(flag == 0) {
		printf("M->");
		if(str[i] == '*' || str[i] == '/')
			i++;
		else {
			flag=1;
			printf("error\n");
		}
	}
}

void V() {
	if(flag == 0){
		printf("V->");
		if(str[i] == 'i')
			i++;
		else{
			flag = 1;
			printf("error\n");
		}
	}
}

int main() {
	for(int m = 1; m <= 4; m++) {
		printf("test%d:\n", m);
		char txt[] = "./lexical/analyze";
		char num[6];
		sprintf(num, "%d.txt", m);
		strcat(txt, num);
		FILE *fp = fopen(txt, "r");
		char buf[MAX_LEN] = "";
		char input[MAX_LEN] = "";
		fgets(buf, MAX_LEN, fp);
		i = 0, j = 0;

		for(int k = 0; k < strlen(buf); k++) {
			if(buf[k] == '1' && buf[k+1] == ',') {
				str[i++] = 'i';
				k += 3;
				while(1) {
					if(buf[k] == ')' && buf[k+1] == ' ')
						break;
					input[j++] = buf[k++];
				}
				continue;
			}
			if(buf[k] == ',' && buf[k+1] == ' ') {
				k += 2;
				while(1) {
					if(buf[k] == ')' && buf[k+1] == ' ')
						break;
					str[i++] = buf[k];
					input[j++] = buf[k++];
				}
			}
		}
		printf("Input scentence: %s\n", input);
		str[i] = '#', input[j] = '#';
		fclose(fp);
		flag = 0, i = 0;
		S();
		if(str[i] == '#' && flag == 0) {
			printf("end\n");
			printf("Gramma legal: %s\n", str);
		}
		else
			printf("Gramma illegal\n");
	}
    return 0;
}

5.运行示例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/127645.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于单片机的土壤温湿度控制系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、温湿度控制系统的整体规划2.3系统的总体构架 二、温度湿度控制系统硬件设计3.1系统硬件概述 三、 温湿度系统软件…

Redis学习(十)RedisTemplate 对各种数据类型的支持

目录 一、SpringDataRedis 简介1.1 什么是 Redis&#xff1f;1.2 什么是 Jedis&#xff1f;1.3 什么是 Spring Data Redis&#xff1f; 二、RedisTemplate 中 API 使用2.1 pom.xml 依赖2.2 配置文件2.3 RedisTemplate 的直接方法2.4 String 类型相关操作2.5 Hash 类型相关操作2…

APP安全测试详解

在工作过程中&#xff0c;我接触到了一些SDL安全提测的工作。原来我是学web端渗透比较多的&#xff0c;移动端这块基本没怎么试过手&#xff0c;结果刚开始一直踩坑&#xff0c;连抓包都抓不到(&#xff34;▽&#xff34;)。 下面记录下我遇到的部分问题和解决方法&#xff0…

《QT从基础到进阶·十八》QT中的各种鼠标事件QEvent

1、界面标题栏事件&#xff1a; NonClientAreaMouseButtonPress 标题栏点击事件 NonClientAreaMouseButtonRelease 标题栏释放事件 bool CustomPopDialog::event(QEvent* event) {switch (event->type()){case QEvent::MouseButtonRelease://Event of mouse releasing wind…

Python爬虫抓取微博数据及热度预测

首先我们需要安装 requests 和 BeautifulSoup 库&#xff0c;可以使用以下命令进行安装&#xff1a; pip install requests pip install beautifulsoup4然后&#xff0c;我们需要导入 requests 和 BeautifulSoup 库&#xff1a; import requests from bs4 import BeautifulSou…

奇异矩阵、非奇异矩阵

对于一个方阵A&#xff1a; 如果A的行列式等于0&#xff0c;称矩阵A为奇异矩阵如果A的行列式不等于0&#xff0c;称A 非奇异矩阵 也就是说&#xff0c;对于方阵A&#xff0c;如果它是满秩的&#xff0c;即它的秩等于矩阵的阶数&#xff0c;就是非奇异矩阵&#xff1b;如果秩小…

【 云原生 | K8S 】kubectl 详解

目录 1 kubectl 2 基本信息查看 2.1 查看 master 节点状态 2.2 查看命名空间 2.3 查看default命名空间的所有资源 2.4 创建命名空间app 2.5 删除命名空间app 2.6 在命名空间kube-public 创建副本控制器&#xff08;deployment&#xff09;来启动Pod&#xff08;nginx-wl…

Intel x86_64 LBR功能

文章目录 前言一、CPUID指令1.1 CPUID功能简介1.2 输入参数01H返回结果1.2.1 ECX返回结果1.2.2 EDX返回结果 1.3 Linux中CPUID指令1.3.1 应用层调用cpid指令1.3.2 linux内核中调用cpuid指令 二、MSR寄存器2.1 MSR 寄存器简介2.2 RDMSR,WRMSR指令介绍2.3 IA32_DEBUGCTL MSR 寄存…

OSG交互:选中场景模型并高亮显示

1、目的 可以在osg视图中选中指定模型实体,并高亮显示。共分为两种,一种鼠标点选,一种框选。 2、鼠标点选 2.1 功能说明 生成两组对象,一组cow对象可以被选中,另一组robot不能被选中;点击cow对象被选中高亮,点击robot被选中不高亮;点击空白处,弹出“select nothing!…

匹配不同应用场景,玩转HyperBDR的两种同步模式!

HyperBDR云容灾是万博智云打造的云原生业务级别容灾工具&#xff0c;实现20云的自动化对接&#xff0c;适配云上、云下、云间多种场景容灾&#xff0c;尤其在容灾上云的场景上&#xff0c;由于大幅节约了容灾过程中的计算资源&#xff0c;以更普惠的方案打造云容灾新场景&#…

React构建组件的方式有哪些?区别?

一、是什么 组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念&#xff08;组件&#xff09;来实现开发的模式 在React中&#xff0c;一个类、一个函数都可以视为一个组件 在之前文章中&#xff0c;我们了解到组件所存在的优势&#xff1a; 降低整个系统的耦合度&am…

文件重命名自动化:批量处理让生活更简单

在我们的日常生活和工作中&#xff0c;需要处理大量的文件&#xff0c;无论是文档、图片、音频还是视频。很多时候&#xff0c;为了更好地管理和查找&#xff0c;我们都需要对文件进行重命名。然而&#xff0c;一个一个地重命名文件既耗时又容易出错。幸运的是&#xff0c;随着…

多路转接(中)——poll和epoll

目录 一、poll 1.select的缺点 2.认识poll系统调用 3.poll的优点 二、poll服务器 三、epoll 1.poll的缺点 2.认识epoll的三个接口 3.epoll的原理 四、epoll服务器 一、poll 1.select的缺点 select虽然可以增加IO的效率&#xff0c;但是它有两个问题&#xff1a; &…

高级算法复习

时间代价 主定理 递归树 排序 贪心算法 贪心选择性&#xff08;Greedy-choice property&#xff09;&#xff1a; 通过做出局部最优&#xff08;贪婪&#xff09;选择&#xff0c;可以得出全局最优解——这是贪心算法可行的第一个基本要素&#xff0c;也是贪心算法与动态规划…

使用 Redis 实现生成分布式全局唯一ID(使用SpringBoot环境实现)

目录 一、前言二、如何通过Redis设计一个分布式全局唯一ID生成工具2.1、使用 Redis 计数器实现2.2、使用 Redis Hash结构实现 三、通过代码实现分布式全局唯一ID工具3.1、编写获取工具3.2、测试获取工具 四、总结 一、前言 在很多项目中生成类似订单编号、用户编号等有唯一性数…

创建云端服务器

1.申请云端服务器 每个账户有三个月的免费试用 我的服务器选择是centos7 &#xff0c;别选成win了。 2.创建实例 创建实例的步骤&#xff0c;阿里云有文档 介绍 大致就是 左边点实例 -》 顶部选你申请服务器时的地区-》下面就出现一条实例-》点更多 -》要重置实例密码 -》同一…

Docker安装ewomail

ewomail相关链接 官网官方安装文档gitee 开始安装 快速安装 wget -c https://down.ewomail.com/install-03.sh && sh install-03.sh 域名docker安装 创建docker容器 docker run -idt \-p 25:25 \-p 110:110 \-p 143:143 \-p 465:465 \-p 587:587 \-p 993:993 \-…

【带头学C++】----- 三、指针章 ---- 3.10 函数指针(补充基础知识)

1.函数指针 1.1 函数的返回值类型为指针类型 将函数内部的合法地址通过返回值 返回给函数外部使用 注意:函数不要返回普通局部变量的地址 分析&#xff1a; 在这段代码中&#xff0c;函数getAddr()返回一个指向局部变量data地址&#xff08;作用域是函数内部&#xff09;的指…

DevOps简介

DevOps简介 1、DevOps的起源2、什么是DevOps3、DevOps的发展现状4、DevOps与虚拟化、容器 1、DevOps的起源 上个世纪40年代&#xff0c;世界上第一台计算机诞生。计算机离不开程序&#xff08;Program&#xff09;驱动&#xff0c;而负责编写程序的人&#xff0c;被称为程序员&…

Django ModelSerializer 实现自定义验证详解

随着 Web 开发的日益复杂化&#xff0c;对数据验证的需求也日益增加。Django REST framework 提供了一套强大的、灵活的验证系统&#xff0c;帮助开发者轻松处理各种复杂情况。本文将重点探讨 Django ModelSerializer 中如何实现自定义验证。 1. 简介 Django ModelSerializer…