递归下降语法分析

article/2025/10/15 6:09:58

一、实验目的

递归下降语法分析

二、实验题目

在这里插入图片描述

三、分析与设计

四、源代码

#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#include <conio.h>
#define digit 1 // 1数字
#define op 2 // +-*/()#
#define Hh 3 // 3Hh
#define AF 4 // 4A-F
#define letter 5 // 5其它字母
using namespace std;char sym; // 保存当前读入字符 
string line; // 保存读入的一行表达式
int cur; // 表达式字符串中的当前下标
int error; // 错误标志。0:正确; -1:错误
char q; // 指向输入符号串中当前的字符
char word[20]; // 存储当前识别的单词
int state; // 表示所处的状态
int i; // 单词的下标int E(), E1(), T(), T1(), F(); // 函数声明
char read(string line, int k);
string change_i(string words); // 将含有十进制或十六进制数的表达式转换为用i代替的表达式
int isDigitOrChar(char ch);int main() {ifstream fin("test.txt");if (!fin.is_open()) {cout << "open file error." << endl;_getch();return -1;}while (getline(fin, line)) {puts("------------------------------------");cur = 0;error = 0;string temp = line;line = change_i(line);if (line == "-1") {cout << temp << " is not a valid express." << endl;continue;}cout << "Output string is: " << line << endl;sym = read(line, cur); // 读取第一个字符E();if (error == -1)cout << temp << " is not valid." << endl;else if (error == 0) {if (cur + 1 < line.size()) { // 未成功匹配提前退出认定为无效cout << temp << " is not valid." << endl;}else {cout << temp << " is valid." << endl;}}}fin.close();_getch();return 0;
}// 递归分析函数实现
int E() {  // E->TE'T();E1();return 0;
}int E1() { // E'->+TE'|-TE'|εif (sym == '+' || sym == '-') {cur++;sym = read(line, cur);T();E1();}else if (sym == '#' || sym == ')')return 0;elseerror = -1;return 0;
}int T() { // T->FT'F();T1();return 0;
}int T1() { // T'->*FT'|/FT'|εif (sym == '*' || sym == '/') {cur++;sym = read(line, cur);F();T1();}else {if (sym == '#' || sym == ')' || sym == '+' || sym == '-')return 0;elseerror = -1;}return 0;
}int F() { // F->(E)|iif (sym == 'i') {cur++;sym = read(line, cur);}else if (sym == '(') {cur++;sym = read(line, cur);E();if (sym == ')') {cur++;sym = read(line, cur);}elseerror = -1;}elseerror = -1;return 0;
}char read(string line, int k) {return line[k];
}int isDigitOrChar(char ch) {if (ch >= 48 && ch <= 57) // 数字return digit;else if (ch == 72 || ch == 104) // H or hreturn Hh;else if ((ch >= 65 && ch <= 70) || (ch >= 97 && ch <= 102)) // 字母A,B,C,D,E,Freturn AF;else if ((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122)) // 除A~F外的其它字母return letter;else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')' || ch == '#')return op;
}// 将含有十进制或十六进制数的表达式转换为用i代替的表达式
string change_i(string words) {memset(word, 0, sizeof word);state = 0;i = 0;cout << "Input string is: " << words << endl;string result = "";int cnt = 0;q = words[cnt++];while (cnt <= words.size()) {// 先判断状态,再判断字符switch (state) {case 0: // 0状态switch (isDigitOrChar(q)) {case digit: // 数字word[i++] = q;state = 2; // 转移到2状态break;case Hh: // H or hcase AF: // 字母A,B,C,D,E,F or a,b,c,d,e,fcase letter: // 字母word[i++] = q;state = 1;break;case op: // 操作符result += q;state = 0;break;default: // 其它(非法字符 )word[i++] = q;state = 5;}break;case 1: // 1状态switch (isDigitOrChar(q)) {case Hh: // 当前状态遇到字母、数字往下读入case AF:case digit:case letter:word[i++] = q;state = 1;break;case op: // 读入完毕,识别为标识符word[i] = '\0';printf("%s is an identifier.\n", word);//result += "i";memset(word, 0, sizeof word);i = 0;state = 0;break;default:word[i++] = q;state = 5;}break;case 2: // 2状态switch (isDigitOrChar(q)) {case digit: // 若为数字,不改变状态往下读入word[i++] = q;state = 2;break;case Hh: // 若为Hh,转移至状态3word[i++] = q;state = 3;break;case AF: // 若为AF,则有可能是16进制,转移至状态4word[i++] = q;state = 4;break;case op: // 成功识别为整数word[i] = '\0';printf("%s is an Integer.\n", word);result += "i";result += q;//cout << result << endl;memset(word, 0, sizeof word);i = 0;state = 0;break;default:word[i++] = q;state = 5;}break;case 3: // 3状态switch (isDigitOrChar(q)) {case op: // 识别为16进制数word[i] = '\0';printf("%s is a Hex digit.\n", word);result += "i";result += q;//cout << result << endl;memset(word, 0, sizeof word);i = 0;state = 0;break;default:word[i++] = q;state = 5;}break;case 4: // 4状态switch (isDigitOrChar(q)) {case digit: // 若为数字或A~F,仍为状态4,往下读入case AF:word[i++] = q;state = 4;break;case Hh:word[i++] = q;state = 3;break;case op: // 如果16进制没有以h或H结尾,转移至错误状态state = 5;cnt--;break;default:word[i++] = q;state = 5;}break;case 5: // 出错状态if (isDigitOrChar(q) == op) { // 若为空格,则识别为非标识符word[i] = '\0';printf("%s is not an identifier.\n", word);memset(word, 0, sizeof word);i = 0;state = 0;result = "-1";return result;}else { // 出错序列还未读取完毕,往下读入word[i++] = q;q = words[cnt++];continue;}break;}q = words[cnt++]; // 指针下移(指向输入符号串中的下一个字符)}return result;
}

五、实验结果(运行截屏)

在这里插入图片描述

六、实验总结

(1)重点与难点
如何将字符转为i
1c(中如何避免(的输入

(2)存在的不足
本来是将字符的替换与判断单独封装为了一个函数justice,但是在主函数调用的时候,运行不出结果,找了一个多小时的原因,没找出来,所以只好让他成为主函数,递归分析直接加到了字符判断函数的后面,显得十分冗长
实验要求没理解透,将实验分成了两个编写,并且在转换为i表达式时,()的更改发生了错误,后续经同学提示发现错误并改正

(3)未来改进方案
继续查找资料,解决上述提到的运行失败的问题

(4)结论(开发体验、收获、感想等)
通过本次实验,我学会了先改写文法,再判断是否符合文法要求的方法编写一个简单的自顶向下语法分析器。本次实验我还学会了如何通过c语言语法,识别一个txt文件,并进行逐行语句的输入。此外,我通过与实验1的联合实验,巩固复习了词法分析器的分析与编写。最后,通过本次实验的实践,我初步学会了strcat语句的使用法则。

七、测试用例

7+9*2#
80+5eH+(6+1)*2+4h#
95eah+3*(5+10)+35h#
9*6+(5+2)*5+80bh#
59h+((3+9ah)*3+4#
6+(5+2))*5+80bh#

http://chatgpt.dhexx.cn/article/nCaXvGbv.shtml

相关文章

Java递归下降分析器_递归下降语法分析器

用java语言编写的递归下降语法分析器&#xff0c;是一种适合手写语法编译器的方法&#xff0c;且非常简单。递归下降法对语言所用的文法有一些限制&#xff0c;但递归下降是现阶段主流的语法分析方法&#xff0c;因为它可以由开发人员高度控制&#xff0c;在提供错误信息方面也…

递归下降算法

递归下降算法 算法模型&#xff1a; Term Term Expr ExprExprFactor Factor 单个元素。最小单位。 实现原理&#xff1a; 一个程式进入算法及被看作是一个项&#xff0c;分解成项加表达式的形式&#xff0c;表达式被分解成 表达式加因子的形式&#xff0c;因子是这个算法…

实验二:递归下降语法分析

文章目录 一、实验目的二、实验原理与要求 1、原理 2、要求 三、实验设备四、实验内容五、实验步骤 1. 单词内码表 2. 定义语言文法 3. 语法分析器的实现&#xff08;编码&#xff09; 4. 测试 六、配套资源 一、实验目的 理解自顶向下语法分析的基本模式&#xff0c;熟悉…

编译原理递归下降语法分析器C++实现

编译原理递归下降语法分析器C简单实现 1.递归下降分析法的功能 语法分析器的功能是利用函数之间的递归调用模拟语法树自上而下的构造过程。 2.递归下降分析法的前提 改造文法&#xff1a;消除二义性、消除左递归、提取左因子&#xff0c;判断是否为LL&#xff08;1&#xff0…

编译原理(九)——递归下降法

背景&#xff1a; 自定向下的语法分析方法&#xff0c;LL(1)是一种非常直观的方法&#xff0c;它的分析过程是按照句子的定义来进行的&#xff0c;也就是说从开始符出发对要分析的串进行推导&#xff0c;如果推导成功就证明这个被分析的串是一个合法的句子&#xff0c;否则的话…

【编译原理】【C语言】实验三:递归下降分析法

C语言 实验环境&#xff1a;Visual Studio 2019 author&#xff1a;zoxiii 递归下降分析法 1、实验内容2、前期准备2.1 递归下降分析法原理2.2 要实现的文法2.3 需要的函数 3、分析过程3.1 递归下降分析法设计思想及算法3.2 分析栈的分析过程3.3 流程图3.4 源代码3.5 运行结果 …

JAVA游戏开发-超炫酷贪吃蛇游戏源码及教程

一&#xff0e;前言 某日&#xff0c;看见隔壁家的小朋友在玩一款网络爆款贪吃蛇游戏&#xff0c;感觉很好玩。自己刚好正在学习JAVA编程&#xff0c;也想实现一个类似功能的游戏Demo练手&#xff0c;在网上查看了不少源码案例&#xff0c;全都是很古老的方块式贪吃蛇游戏案例…

Java实现贪吃蛇游戏【代码】

Java实现贪吃蛇游戏【代码】 花了两个下午写了一个贪吃蛇小游戏&#xff0c;本人想写这游戏很长时间了。作为以前诺基亚手机上的经典游戏&#xff0c;贪吃蛇和俄罗斯方块一样&#xff0c;都曾经在我们的童年给我们带来了很多乐趣。世间万物斗转星移&#xff0c;诺基亚曾经作为手…

JavaSE项目 | 纯Java实现贪吃蛇小游戏

目录 一&#xff1a;贪吃蛇游戏的实现步骤 1. 画出窗口 2. 在窗口上添加画布 3. 在画布上添加黑色游戏区 4. 放静态蛇 5. 定义蛇的数据结构 6. 控制蛇头方向 7. 放上开始提示信息 8. 按空格键开始游戏 9. 让蛇动起来 10. 实现暂停 11. 实现转向功能 12. 添加食物 …

java 贪吃蛇 源码+图片

本人也是个初学者&#xff0c;有什么不对的地方&#xff0c;请大佬指点&#xff01;&#xff01;&#xff01; 一、涉及到的知识点如下&#xff1a; 循环&#xff0c;分支方法的抽取数组的使用面向对象继承&#xff0c;子类方法的重写接口&#xff0c;接口的实现 二、游戏图形…

JAVA贪吃蛇代码(带注释)

贪吃蛇 这是游戏效果图片是代码里面的素材游戏数据类 package com.tang.retor_snaker;import javax.swing.*; import java.net.URL;public class Data {private static URL bodyURL Data.class.getResource("/com/tang/retor_snaker/statics/body.png");private st…

JAVA贪吃蛇小游戏源代码系列

欢迎关注公众号&#xff1a; 获取贪吃蛇小游戏的源代码。 贪吃蛇小游戏运行结果如下&#xff1a; 启动界面&#xff1a; 运行界面&#xff1a; 重启界面&#xff1a; 源代码框架如下&#xff1a; 注&#xff1a;在运行程序的时候&#xff0c;得重新设计窗体的大小&#x…

JAVA 实现《贪吃蛇大作战》游戏|CSDN创作打卡

前言 贪吃蛇&#xff08;也叫做贪食蛇&#xff09;游戏是一款休闲益智类游戏&#xff0c;有PC和手机等多平台版本。既简单又耐玩。该游戏通过控制蛇头方向吃东西&#xff0c;从而使得蛇变得越来越长。 本程序是通过java的swing来实现《贪吃蛇大作战》这款游戏。 主要需求 1…

java贪吃蛇源码

欢迎访问我的个人博客 https://jialaner.cn/​​​​​​​ java是一种面向对象的语言&#xff0c;有着其中不用质疑的优点。学习java将近三个月了&#xff0c;一直在琢磨着“万物皆对象”的意义&#xff0c;却总是只知其表不知其意&#xff0c;做完这个java贪吃蛇后才有了那么…

贪吃蛇 java实现超简单的贪吃蛇(附源代码)

贪吃蛇游戏 贪吃蛇是个非常经典的游戏&#xff0c;希望对初学Java的小伙伴有一定帮助。希望大家喜欢&#xff0c;因为写得简单&#xff0c;希望大家都能看得懂。 游戏界面&#xff08;游戏背景素材不喜欢的话可以自己换&#xff0c;就别在乎我选的素材&#xff08;&#x1f9…

java实现贪吃蛇小游戏(源码+注释)

一.工程文件 二.Main.java package com.company;import javax.swing.*;public class Main {public static void main(String[] args) {//创建窗体对象JFrame frame new JFrame();//创建窗体参数&#xff08;&#xff09;frame.setBounds(10,10,900,720);//设置不允许更改大小…

使用Java实现一个简单的贪吃蛇小游戏

基于java实现贪吃蛇小游戏&#xff0c;主要通过绘制不同的图片并以一定速度一帧一帧地在窗体上进行展示。 开发工具&#xff1a;eclipse java工具包&#xff1a;jdk1.8 一、创建新项目 创建一个新的项目&#xff0c;并命名。创建一个名为images的文件夹用来存放游戏相关图片…

Java贪吃蛇全代码

用Java编写精典小游戏——贪吃蛇&#xff01; 前言 我想贪吃蛇应该是不少90后和00后的童年&#xff08;我本人是01年的&#xff09;&#xff0c;回想起从前偷偷拿着我爹的诺基亚在被窝里玩贪吃蛇&#xff0c;不禁感慨万分&#xff0c;时间飞逝&#xff0c;没想到10年后的我也可…

JAVA小项目(四)—— 贪吃蛇【轻松入门,附源码】

目录 &#xff08;一&#xff09;效果图 &#xff08;二&#xff09;代码实现 &#xff08;1&#xff09;将图片加载到程序中 &#xff08;2&#xff09;创建窗体 &#xff08;3&#xff09;创建面板 &#xff08;4&#xff09;绘制静态的小蛇 &#xff08;5&#xff09; 加入监…

Java贪吃蛇大作战

作为Java新手小白&#xff0c;渴望学习一些好玩有趣的java程序 废话不多说&#xff0c;接下来我会一步一步实现java小程序&#xff1a;贪吃蛇大作战哦&#xff01; 实现 Java贪吃蛇一共分四个步骤&#xff1a; 1、画出窗体对象 2、绘制静态ui 3、使用鼠标监听器事件和定时器事…