编译器开发系列--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类型的,那么如果要表示一个字符串,就必须使用字符数组.今天主要就介绍如 ...
随机推荐
- 看完SQL Server 2014 Q/A答疑集锦:想不升级都难!
看完SQL Server 2014 Q/A答疑集锦:想不升级都难! 转载自:http://mp.weixin.qq.com/s/5rZCgnMKmJqeC7hbe4CZ_g 本期嘉宾为微软技术中心技术 ...
- .NET 提升教育 第一期:VIP 付费课程培训通知!
为响应 @当年在远方 同学的建议,在年前尝试进行一次付费的VIP培训. 培训的课件:点击下载培训周期:10个课程左右,每晚1个半小时培训价格:1000元/人.报名方式:有意向的请加QQ群:路过秋天.N ...
- 【AutoMapper官方文档】DTO与Domin Model相互转换(上)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...
- 利用bootstrap的carousel.js实现轮播图动画
前期准备: 1.jquery.js. 2.bootstrap的carousel.js. 3.bootstrap.css. 如果大家不知道在哪下载,可以联系小颖,小颖把这些js和css可以发送给你. 一 ...
- OpenCV模板匹配算法详解
1 理论介绍 模板匹配是在一幅图像中寻找一个特定目标的方法之一,这种方法的原理非常简单,遍历图像中的每一个可能的位置,比较各处与模板是否“相似”,当相似度足够高时,就认为找到了我们的目标.OpenCV ...
- 深入学习jQuery自定义插件
原文地址:jQuery自定义插件学习 1.定义插件的方法 对象级别的插件扩展,即为jQuery类的实例增加方法, 调用:$(选择器).函数名(参数); $(‘#id’).myPlugin(o ...
- AbpZero--1.如何开始
1.加群 群号:104390185,下载这个文件并解压 用VS2015打开aspnet-zero-1.9.0.1 2.修改Web项目web.config连接字符串 <add name=" ...
- SharePoint 2013: A feature with ID has already been installed in this farm
使用Visual Studio 2013创建一个可视web 部件,当右击项目选择"部署"时报错: "Error occurred in deployment step ' ...
- NSURLSession详解
导语 现在NSURLConnection在开发中会使用的越来越少,iOS9已经将NSURLConnection废弃,现在最低版本一般适配iOS7,所以也可以使用. NSURLConnection相对于 ...
- 1.Hibernate简介
1.框架简介: 定义:基于java语言开发的一套ORM框架: 优点:a.方便开发; b.大大减少代码量; c.性能稍高(不能与数据库高手相比,较一般数据库使用者 ...