编译器一日一练(DIY系列之语义分析)

news/2024/4/26 13:12:21/文章来源:https://blog.csdn.net/feixiaoxing/article/details/127626631

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

          代码地址:https://github.com/feixiaoxing/DIYCompiler

          语义分析一般是跟在语法分析后面进行的。语义分析的内容比较广。它的输入是语法树,并且在这过程当中会生成符号表,利用符号表的意义去检测语义是否正确。记录的符号表一般有全局变量、函数名、局部变量、参数名这些。此外,除了检测符号表之外,还会检测一些关键字的合理性,比如break外面是否有switch或者循环、continue是否外面有循环、goto是否真的有label与之匹配等等。总之,在中间代码生成前,所有的错误都要在这个阶段来被发现。

        如果大家读到这里,还是不能明白语义分析的话,接下来可以举几个例子来说明,分析下哪些语句是符合语法,但是不符合语义的,比如

        1)全局标识符重名;

        2)局部标识符重名;

        3)调用函数不存在;

        4)调用函数参数不匹配等等。

        当然,因为我们做的是四则运算,并且挑了一个除法来做运算。而除法里面最不能做的,就是除数不能等于0。基于这一点,我们就可以做一个简单的除法分析检测。

	public int check_value() {if(get_right_node() != null){if( 0 == ((value_node)get_right_node()).get_value()){System.out.println("Div by Zero");return -1;}}if(get_left_node().get_node_type() == "/"){return ((div_node)(get_left_node())).check_value();}return 1;}

        因为检测的是一个除法运算,或者是连续除法运算,所以除数只能出现在右子树。检测的方法是自顶而下进行的。如check_value函数所示,首先检测右子树是否为空,如果不为空,并且发现除数为0,那么打印出来并且报警。接着继续检测左子树,判断左子树是否是递归语法树,如果是则继续检测递归语法树,反之则返回为1。整个流程还是比较清晰的。

        语义分析和语法分析基本是一一对应的,比如有一个if-statement的语法树,就会一个check_if_statement的语义分析。其他语法以此类推。

        说了这么多,大家还没有看到添加check_value后的效果是什么,我们可以编译测试下,

C:\Users\feixiaoxing\Desktop\DIYCompiler\day08>java Parse 1/0
Div by Zero
-1C:\Users\feixiaoxing\Desktop\DIYCompiler\day08>java Parse 2/1/0
Div by Zero
-1C:\Users\feixiaoxing\Desktop\DIYCompiler\day08>java Parse 2/0/1
Div by Zero
-1C:\Users\feixiaoxing\Desktop\DIYCompiler\day08>java Parse 6/2/0/3/1
Div by Zero
-1

        从运行结果看,基本还是符合我们要求的。为了便于大家理解整个过程,这里给出完整的jj文件,可以实际操作动手做一下试验。

options {STATIC = false;
}PARSER_BEGIN(Parse)
import java.io.*;class node
{public node left;public node right;public String node_type;node() {this.left = this.right = null;}public void set_left_node(node left) { this.left = left;}public node get_left_node() { return this.left;}public void set_right_node(node right) { this.right = right;}public node get_right_node() {return this.right;}public void set_node_type(String node_type) {this.node_type = node_type;}public String get_node_type() {return this.node_type;}
}class value_node extends node
{public int value;value_node() { set_node_type("value_node");}public int get_value() { return this.value;}public void set_value(int value) {this.value = value;}
}class div_node extends node
{div_node() { set_node_type("/");}public int get_value() {int left = 0, right = 0;// get left nodeif(get_left_node().get_node_type() == "/"){left = ((div_node)get_left_node()).get_value();}else{left = ((value_node)get_left_node()).get_value();}// get right nodeif(get_right_node() == null){return left;}else{right = ((value_node)get_right_node()).get_value();return left/right;}}// add semantic checkpublic int check_value() {if(get_right_node() != null){if( 0 == ((value_node)get_right_node()).get_value()){System.out.println("Div by Zero");return -1;}}if(get_left_node().get_node_type() == "/"){return ((div_node)(get_left_node())).check_value();}return 1;}
}public class Parse {public static void main(String[] args) {for (String arg : args) {try {System.out.println(evaluate(arg).check_value());} catch (ParseException ex) {System.err.println(ex.getMessage());}}}public static div_node evaluate(String src) throws ParseException {Reader reader = new StringReader(src);return  new Parse(reader).expr();}
}
PARSER_END(Parse)SKIP: { <[" ", "\t", "\r", "\n"]> }
TOKEN: {<INTEGER: (["0"-"9"])+>
}div_node expr() throws NumberFormatException :
{Token a ;Token b ;div_node div;
}
{a = <INTEGER> { value_node node_a = new value_node();node_a.set_value(Integer.parseInt( a.image ));div = new div_node();div.set_left_node(node_a);}("/" b = <INTEGER>{value_node node_b = new value_node();node_b.set_value(Integer.parseInt( b.image ));// important code about node addingif(div.get_right_node() == null){div.set_right_node(node_b);}else{div_node prev = div;div = new div_node();div.set_left_node(prev);div.set_right_node(node_b);}})*<EOF>{ return div ; }
}

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

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

相关文章

fscan:一键自动化、全方位漏洞扫描的开源工具

https://blog.csdn.net/osfront/article/details/116049846 打开服务器看到了一个软件fscan64,并有运行页面。因为没见过,吓了我一跳,搜索了下是什么,记录下。 简介 fscan 是一个内网综合扫描工具,方便一键自动化、全方位漏洞扫描。 它支持主机存活探测、端口扫描、常见服务…

【Java数据结构】顺序表

我们不过是普通人&#xff0c;只不过在彼此眼中闪闪发光 目录 1.模拟实现顺序表 1.1 顺序的结构 1.2 顺序表的成员属性 1.3 顺序表的构造方法 1.4 顺序表的成员方法 1.4.1 扩容 1.4.2 打印顺序表 1.4.3 尾插 1.4.4 在指定位置插入 1.4.5 判断数组中是否有这个元素…

SSH婴幼儿产品销售系统电商购物系统(含源码+论文+答辩PPT等)

该项目采用技术JSP、strust2、Spring、Hibernate、Tomcat服务器、MySQL数据库 &#xff0c;项目含有源码、论文、配套开发软件、软件安装教程、项目发布教程 本系统结构如下&#xff1a; 1&#xff0c;游客访问 |–系统首页&#xff0c;查看所有的商品信息和相关的菜单信息 |–…

每日一记:笔记工具使用、计算机基础知识、编程语言认识

1、笔记工具的使用 我现在使用的是typora这个文档工具 markdown语法 常见操作有&#xff1a;标题、代码块、引用、列表等 typora工具的主页面 我们可以编辑内容 做笔记 。。。 标题分类&#xff1a; 和html&#xff08;超文本标记语言 前端部分一样&#xff09;分为六级标题…

拉卡拉第三季营收13.45亿:净利8372万 同比降73%

雷递网 雷建平 10月31日拉卡拉支付股份有限公司&#xff08;证券代码&#xff1a;300773&#xff0c;证券简称&#xff1a;拉卡拉&#xff09;日前发布财报&#xff0c;财报显示&#xff0c;拉卡拉2022年前三季营收43.55亿元&#xff0c;同比降11.83%&#xff1b;拉卡拉2022年前…

Shell编程从看懂到看开②(字符串、数组、注释、流程控制、read读取控制台输入)

文章目录Shell字符串单引号双引号拼接字符串获取字符串长度提取子字符串查找子字符串Shell数组定义数组读取数组获取数组的长度Shell注释流程控制if判断case语句for 循环while 循环read 读取控制台输入Shell字符串 字符串是shell编程中最常用最有用的数据类型&#xff08;除了…

【DDR3 控制器设计】(5)DDR3 的仲裁读写操作设计

写在前面 本系列为 DDR3 控制器设计总结&#xff0c;此系列包含 DDR3 控制器相关设计&#xff1a;认识 MIG、初始化、读写操作、FIFO 接口等。通过此系列的学习可以加深对 DDR3 读写时序的理解以及 FIFO 接口设计等&#xff0c;附上汇总博客直达链接。 【DDR3 控制器设计】系列…

爆破校园网的宽带

前提&#xff1a;学校的手机号前7位相同&#xff0c;宽带密码都是手机号后六位。仅供学习。 准备工作&#xff1a;电脑一台&#xff0c;把校园网的宽带水晶头插在电脑上&#xff0c; 步骤&#xff1a; winR输入Rasphone点击新建&#xff0c;宽带&#xff0c;输入宽带名称&am…

Kubernetes(31):kubeasz单主机模式

前言 有时候&#xff0c;我们只需要k8s集群进行项目测试&#xff0c;能够使用的主机可能只有一台&#xff0c;那么如何构建一台单机的k8s集群&#xff1f; 单机版的k8s集群可以用于本地测试&#xff0c;或者内部测试环境&#xff0c;或者个人电脑上的项目测试。 那么我们可以使…

Html保留空格和换行

效果&#xff1a; 代码&#xff1a; <pre> 这是一段文本这是一段文本这是一段文 本这是一 段文本这是一段文本 </pre>

会话技术(Session、Cookie)详细介绍

会话技术 request&#xff1a;接收请求 接收请求行 接收请求方式&#xff1a;request.getMethod()接收项目路径&#xff1a;request.getContextPath() 接收请求头 request.getHeader(String name) 接收请求参数 中文参数&#xff1a; get方式&#xff1a;不乱码。因为tomcat8.…

NIO Buffer类的重要方法

1 allocate()创建缓冲区 在使用Buffer&#xff08;缓冲区&#xff09;之前&#xff0c;我们首先需要获取Buffer子类的实例对象&#xff0c;并且分配内存空间。为了获取一个Buffer实例对象&#xff0c;这里并不是使用子类的构造器new来创建一个实例对象&#xff0c;而是调用子类…

带你走入C++动态多态的底层

多态按字面的意思就是多种形态&#xff0c;相同的方法调用&#xff0c;但是有不同的实现方式。多态性可以简单地概括为“一个接口&#xff0c;多种方法&#xff0c;实现接口与实现的分离。 C有两种多态形式&#xff1a; 静态多态动态多态而本文主要介绍动态多态的应用。 动态…

力扣1662(javapython)-检查两个字符串数组是否相等(简单)

题目: 给你两个字符串数组 word1 和 word2 。如果两个数组表示的字符串相同,返回 true ;否则,返回 false 。 数组表示的字符串 是由数组中的所有元素 按顺序 连接形成的字符串。示例 1: 输入:word1 = ["ab", "c"], word2 = ["a", "bc…

SpringBoot:ssm和springboot整合

目录 一、整合Mybatis 因为要使用逆向生成代码 pom.xml generatorConfig.xml application.yml 测试 BookController SpringbootmybatisApplication jdbc.properties 二、整合mybatisplus 简介 application.yml MPGenerator SpringbootmpApplication 三、使用my…

ensp华为配置NAT

ensp华为配置NAT 文章目录ensp华为配置NAT1 对PC进行地址、掩码及网关配置2 对路由器进行初始配置3 ART配置3.1 静态NAT配置3.2 动态NAT配置3.3 端口NAT (NAPT) 的配置3.4 Easy IP的配置3.5 NAT Server的配置4 总结拓扑图如图&#xff1a;1 对PC进行地址、掩码及网关配置 略 …

计算机毕设(附源码)JAVA-SSM佳音大学志愿填报系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

计算机毕设(附源码)JAVA-SSM蓟县农家乐网站

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

通俗易懂!一文看懂手机Root的操作与防护

Root&#xff0c;对于任何手机发烧友、玩机客、从事移动设备研发的人员来说&#xff0c;并不陌生&#xff0c;它代表绝大部分移动设备的使用者能够掌握到的最高权限。 从技术层次来讲&#xff0c;用户拥有了修改系统文件的权限&#xff0c;甚至可以控制账户、增加或删除硬件等…

java毕业设计——基于java+JSP+sqlserver的智能在线考试信息管理系统设计与实现(毕业论文+程序源码)——智能在线考试信息管理系统

基于javaJSPsqlserver的智能在线考试信息管理系统设计与实现&#xff08;毕业论文程序源码&#xff09; 大家好&#xff0c;今天给大家介绍基于javaJSPsqlserver的智能在线考试信息管理系统设计与实现&#xff0c;文章末尾附有本毕业设计的论文和源码下载地址哦。 文章目录&a…