编译器开发系列--Ocelot语言5.表达式的有效性检查
本篇将对“1=3”“&5”这样无法求值的不正确的表达式进行检查。
将检查如下这些问题。
●为无法赋值的表达式赋值(例:1 = 2 + 2)
●使用非法的函数名调用函数(例:"string"("%d\n", i))
●操作数非法的数组引用(例:1[0])
●操作数非法的成员引用(例:1.memb)
●操作数非法的指针间接引用(例:1->memb)
●对非指针的对象取值(例:*1)
●对非左值的表达式取地址
具体例子以及问题的检测方法如表10.1所示,其中包括了刚才列举的问题。
非指针类型取值操作的检查
- /*非指针类型取值操作的检查
- * 表示取值运算符(*)的DereferenceNode的处理。
- * 该方法检查取值运算符的操作数的类型是否为指针。
- */
- // #@@range/DereferenceNode{
- public Void visit(DereferenceNode node) {
- /*
- * 首先,通过super.visit(node) 调用基类Visitor 的方法遍历操作数(node.expr())
- (即检查操作数)。
- */
- super.visit(node);
- /*
- * 接着,调用操作数node.expr() 的isPointer 方法,检查操作数的类型是否是指针,
- 即检查是否可以进行取值。如果无法取值,则调用undereferableError 方法输出编译错误。
- */
- if (! node.expr().isPointer()) {
- undereferableError(node.location());
- }
- /*
- * 最后,调用handleImplicitAddress 方法对数组类型和函数类型进行特别处理。该处
- 理还和接下来AddressNode 的处理相关,
- */
- handleImplicitAddress(node);
- return null;
- }
获取非左值表达式地址的检查
- /*获取非左值表达式地址的检查
- * 检查操作数是否为左值。表示地址运算符的AddressNode 的处理
- */
- // #@@range/AddressNode{
- public Void visit(AddressNode node) {
- super.visit(node);
- /*
- * 首先对node.expr() 调用isLvalue 方法,检查&expr 中的expr 是否是可以进行取
- 址操作的表达式。
- ExprNode#isLvalue 是检查该节点的表达式是否能够获取地址的方法。
- */
- if (! node.expr().isLvalue()) {
- semanticError(node.location(), "invalid expression for &");
- }
- /*
- * 剩余的语句用于确定AddressNode 的类型。通常node.expr().isLoadable() 会
- 返回true,即执行else 部分的处理。&expr 的类型是指向expr 类型的指针,因此指向
- node.expr().type() 的指针类型可以作为节点整体的类型来使用。
- */
- Type base = node.expr().type();
- /*
- * 在将puts 的类型设置为指向函数的指针的同时,还必须将&puts 的类型也设置为指向函
- 数的指针。
- node.expr() 的类型是数组或函数的情况下进行特别处理,使得&puts 的类型
- 和puts 的类型相一致。
- */
- if (! node.expr().isLoadable()) {
- // node.expr.type is already pointer.
- node.setType(base);
- }
- else {
- node.setType(typeTable.pointerTo(base));
- }
- return null;
- }
隐式的指针生成
单个数组类型或函数类型的变量表示数组或函数的地址。例如,假设变量puts 的类型为函数类型(一般称为函数指针),那么puts 和&puts 得到的值是相同的。
- /*
- * handleImplicitAddress 方法将数组类型或函数类型转换为了指向
- 数组或函数类型的指针,即隐式地生成指针类型。
- */
- private void handleImplicitAddress(LHSNode node) {
- if (! node.isLoadable()) {
- Type t = node.type();
- if (t.isArray()) {
- // int[4] ary; ary; should generate int*
- node.setType(typeTable.pointerTo(t.baseType()));
- }
- else {
- node.setType(typeTable.pointerTo(t));
- }
- }
- }
puts 是指向函数的指针,因此它的取值运算*puts 的结果是函数类型,但这样又会隐式地转换为指向函数的指针。*puts 还是指向函数的指针,因此仍然可以进行取值运算,仍然会转换为指向函数的指针。像这样可以无限重复下去。所以C 语言中“&puts”“puts”“*puts”“**puts”“***puts”的值都是相同的。
编译器开发系列--Ocelot语言5.表达式的有效性检查的更多相关文章
- 编译器开发系列--Ocelot语言1.抽象语法树
从今天开始研究开发自己的编程语言Ocelot,从<自制编译器>出发,然后再自己不断完善功能并优化. 编译器前端简单,就不深入研究了,直接用现成的一款工具叫JavaCC,它可以生成抽象语法树 ...
- 编译器开发系列--Ocelot语言7.中间代码
Ocelot的中间代码是仿照国外编译器相关图书Modern Compiler Implementation 中所使用的名为Tree 的中间代码设计的.顾名思义,Tree 是一种树形结构,其特征是简单, ...
- 编译器开发系列--Ocelot语言6.静态类型检查
关于"静态类型检查",想必使用C 或Java 的各位应该非常熟悉了.在此过程中将检查表达式的类型,发现类型不正确的操作时就会报错.例如结构体之间无法用+ 进行加法运算,指针和数值之 ...
- 编译器开发系列--Ocelot语言2.变量引用的消解
"变量引用的消解"是指确定具体指向哪个变量.例如变量"i"可能是全局变量i,也可能是静态变量i,还可能是局部变量i.通过这个过程来消除这样的不确定性,确定所引用 ...
- 编译器开发系列--Ocelot语言3.类型名称的消解
"类型名称的消解"即类型的消解.类型名称由TypeRef 对象表示,类型由Type 对象表示.类型名称的消解就是将TypeRef 对象转换为Type 对象. TypeResolve ...
- 编译器开发系列--Ocelot语言4.类型定义的检查
这里主要介绍一下检查循环定义的结构体.联合体.是对成员中包含自己本身的结构体.联合体进行检查.所谓"成员中包含自己本身",举例来说,就是指下面这样的定义. struct point ...
- iOS开发系列--Swift语言
概述 Swift是苹果2014年推出的全新的编程语言,它继承了C语言.ObjC的特性,且克服了C语言的兼容性问题.Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在 ...
- iOS开发系列--C语言之基础知识
概览 当前移动开发的趋势已经势不可挡,这个系列希望浅谈一下个人对IOS开发的一些见解,这个IOS系列计划从几个角度去说IOS开发: C语言 OC基础 IOS开发(iphone/ipad) Swift ...
- iOS开发系列--C语言之数组和字符串
概览 数组在C语言中有着特殊的地位,它有很多特性,例如它的存储是连续的,数组的名称就是数组的地址等.而在C语言中是没有String类型的,那么如果要表示一个字符串,就必须使用字符数组.今天主要就介绍如 ...
随机推荐
- Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数
上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...
- Jexus 5.8.2 正式发布为Asp.Net Core进入生产环境提供平台支持
Jexus 是一款运行于 Linux 平台,以支持 ASP.NET.PHP 为特色的集高安全性和高性能为一体的 WEB 服务器和反向代理服务器.最新版 5.8.2 已经发布,有如下更新: 1,现在大 ...
- ExtJS 4.2 组件介绍
目录 1. 介绍 1.1 说明 1.2 组件分类 1.3 组件名称 1.4 组件结构 2. 组件的创建方式 2.1 Ext.create()创建 2.2 xtype创建 1. 介绍 1.1 说明 Ex ...
- JQuery easyUI DataGrid 创建复杂列表头(译)
» Create column groups in DataGrid The easyui DataGrid has ability to group columns, as the followin ...
- 【NLP】蓦然回首:谈谈学习模型的评估系列文章(一)
统计角度窥视模型概念 作者:白宁超 2016年7月18日17:18:43 摘要:写本文的初衷源于基于HMM模型序列标注的一个实验,实验完成之后,迫切想知道采用的序列标注模型的好坏,有哪些指标可以度量. ...
- Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级
Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 3.安装Clus ...
- 【开源毕设】一款精美的家校互动APP分享——爱吖校推 [你关注的,我们才推](持续开源更新3)附高效动态压缩Bitmap
一.写在前面 爱吖校推如同它的名字一样,是一款校园类信息推送交流平台,这么多的家校互动类软件,你选择了我,这是我的幸运.从第一次在博客园上写博客到现在,我一次一次地提高博文的质量和代码的可读性,都是为 ...
- 使用RequireJS并实现一个自己的模块加载器 (一)
RequireJS & SeaJS 在 模块化开发 开发以前,都是直接在页面上引入 script 标签来引用脚本的,当项目变得比较复杂,就会带来很多问题. JS项目中的依赖只有通过引入JS的顺 ...
- UVa 122 Trees on the level
题目的意思: 输入很多个节点,包括路径和数值,但是不一定这些全部可以构成一棵树,问题就是判断所给的能否构成一棵树,且没有多余. 网上其他大神已经给出了题目意思:比如我一直很喜欢的小白菜又菜的博客 说一 ...
- [Django]用户权限学习系列之Permission权限基本操作指令
若需建立py文件进行测试,则在文件开始加入以下代码即可 #coding:utf-8 import os os.environ.setdefault("DJANGO_SETTINGS_MODU ...