用c语言编译递归下降翻译器,Java实现C语言语义分析(递归下降)

article/2025/10/15 6:06:35

说起这次的语义分析,不得不说的是我的重大的改变。上一次的语法分析是利用了预测分析法来实现的,经过多方考证,发现用预测分析法的语法分析器基础来实现语义分析的困难重重,例如在语法指导翻译的时候那个栈的变化和各种属性的传递就已经让我头晕脑胀了。无奈之下,只好重写语法分析,用了递归下降来实现语法分析进而实现我的语义分析。

使用递归下降的最大好处就是思路特别清晰,一旦开始写了,就特别明确接下来要做什么。这就是我选择递归下降的原因。

简单的说一下,递归下降语法分析的思想。一个递归下降的语法分析程序由一堆的过程组成,每个非终结符号都有一个对应的过程。程序的执行从开始符号对应的过程开始,如果这个过程的过程体扫描了整个输入串,它就停止执行,并且语法分析结束。

而要在递归下降语法分析的过程中进行翻译:在语法分析中对应于每个非终结符A都有一个函数A,在函数A的函数体中,可以进行语法分析和处理继承属性和综合属性。

1.决定用哪一个产生式来展开A

2.当需要读入一个终结符号时,在输入中检查这些符号是否出现。

3.在局部变量中保存所有必要的属性值。这些属性可以用来计算产生式体中的非终结符号的继承属性,或产生式左部的非终结符号的综合属性。

4.调用对应于被选定产生式体中的非终结符号的函数,向他们提供正确的参数。

实现语义分析很关键的一点是语义动作的书写。我的语义动作都嵌入到了每个非终结符所对应的类中的某些方法来实现的。

例如在类Expression中有如下几个方法:

/**

* 返回一个可以成为某个三地址指令的右部

* @return 一个项

*/

public Expression gen() {

return this;

}

/**

* 把一个表达式规约成一个地址

* @return 一个地址

*/

public Expression reduce(){

return this;

}

/**

* 调用jumps()方法,生成跳转代码

* @param t true出口

* @param f false出口

*/

public void jumping(int t,int f){

jumps(toString(),t,f);

}

/**

* 生成跳转代码

* @param string

* @param t

* @param f

*/

public void jumps(String string,int t,int f){

if (t != 0 && f != 0){

emit("if " + string + " goto L" + t);

emit("goto L"+ f);

}else if(t != 0){

emit("if " + string + " goto L" + t);

}else if (f != 0){

emit("iffalse " + string + " goto L" + f);

}

}

在Expression的子类中通常会实现gen()方法和reduce()方法。

而在类Or中,也有jumps()方法与此相关,如下:

/**

* 为布尔表达式B = B1 || B2生成跳转代码

* 如果B1为真,那么B必然为真,所以B1的true出口是B的true出口

* 如果B1为假,那么B1的false出口则是B2的第一条指令

* B2的true出口和false出口与B的相同

*/

public void jumping(int t,int f) {

int label = t != 0 ? t : newLabel();

expression1.jumping(label, 0);

expression2.jumping(t, f);

if (t == 0){

label(label);

}

}

在类And中,也有也有jumps()方法与此相关,如下:

/**

* 为布尔表达式B = B1 & B2生成跳转代码

* 如果B1为假,那么B必然为假,所以B1的false出口是B的false出口

* 如果B1为真,那么B1的true出口则是B2的第一条指令

* B2的true出口和false出口与B的相同

*/

public void jumping(int t,int f) {

int label = f != 0 ? f : newLabel();

expression1.jumping(0,label);

expression2.jumping(t, f);

if (f == 0){

label(label);

}

}

还有一些方法,如label()和newLabel()方法也都与语义动作相关,newLabel()方法是用来生成一个新的标号,label()方法是用给接下来的一句三地址码标号。

关于符号表的处理:

我的符号表是一个HashMap,其定义是HashMap。其中key是变量名,value是一个ID类的对象。在ID类中,保存了变量的名字,类型,类型的长度,偏移量,入口地址等多个属性。如果变量是一个数组,则包含更加复杂的属性,如数组元素个数,数组元素的类型等等。

在变量声明阶段,程序每读到一个新的声明语句,都会将其加入到符号表中。当在赋值语句中使用这些变量的时候,首先从符号表中寻找是否已经存在这样一个已经被声明过的变量,否则不可使用。

我的测试程序如下:

0818b9ca8b590ca3270a3433284dd417.png

根据这个测试程序,生成的符号表如下:

0818b9ca8b590ca3270a3433284dd417.png

简要的说一下我的语义分析可识别的错误类型:

1.if或while的条件必须是布尔语句

2.变量必须要先声明后使用

3.相同变量名的变量不得重复声明

好像主要能识别的错误就是以上的三类了,其中还要说明的一点是,我的语义分析支持简单的类型转换,例如把float类型的值赋给int型变量是不会出错的。

总体来说,这次的语义分析实现的不大好。没有坚持用预测分析的方法来实现语义分析一直是我的一个遗憾,却转向较为简单递归下降的实现。并且在递归下降的实现中仍然有缺陷,例如不支持函数调用,符号表对于函数没有处理,指针运算的不支持,数组赋值只适用于a[i] = x这类的赋值,错误处理不完备等等。

最后,语义分析结果(仍然是针对上述测试程序)如下:

0818b9ca8b590ca3270a3433284dd417.png


http://chatgpt.dhexx.cn/article/1PesZv1f.shtml

相关文章

递归下降分析法

介绍: 递归下降分析法是针对LL(1)文法的一种语法分析方法; 通过对文法的消除左递归,提取左公因子,对各个产生式和非终结符求first()和follow()集,通过first()和follow()集构造该文法的预测分析表,当这个预…

编译原理实验-递归下降语法分析

具体代码已放至Github(仅供参考): qxpBlog/Compiler_UESTC: 电子科技大学编译原理实验 (github.com) 具体实验过程如下: 一、实验目的、原理、内容及步骤: (1)目的:通过本实验加深…

编译原理实验--实验二 递归下降法判断算术表达式的正确性--Python实现

目录 一、实验目的和要求 二、实验内容 三、实验环境 四、实验步骤 1、语法分析所依据的文法; 2、给出消除左递归及提取左公因子的文法; 五、测试要求 六、实验步骤 1、语法分析所依据的文法 2、给出消除左递归及提取左公因子的文法&#xff1…

递归下降语法分析

一、实验目的 递归下降语法分析 二、实验题目 三、分析与设计 四、源代码 #include <iostream> #include <fstream> #include <cstring> #include <string> #include <conio.h> #define digit 1 // 1数字 #define op 2 // -*/()# #define Hh …

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);//设置不允许更改大小…