编译器开发系列--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类型的,那么如果要表示一个字符串,就必须使用字符数组.今天主要就介绍如 ...
随机推荐
- 《Web 前端面试指南》1、JavaScript 闭包深入浅出
闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...
- 超大 Cookie 拒绝服务攻击
有没有想过,如果网站的 Cookie 特别多特别大,会发生什么情况? 不多说,马上来试验一下: for (i = 0; i < 20; i++) document.cookie = i + '= ...
- TODO:macOS上ThinkPHP5和Semantic-UI集成
TODO:macOS上ThinkPHP5和Semantic-UI集成 1. 全局安装 (on OSX via homebrew)Composer 是 homebrew-php 项目的一部分 2. 把X ...
- .NET Core的日志[4]:将日志写入EventLog
面向Windows的编程人员应该不会对Event Log感到陌生,以至于很多人提到日志,首先想到的就是EventLog.EventLog不仅仅记录了Windows系统自身针对各种事件的日志,我们的应用 ...
- 安装eclipse的maven插件
我们团队用maven来管理项目需要的库文件,其实以前都没听过maven,第一次接触这个,师兄要我直接去装下这个,开始以为还挺简单的,没想到中间遇到了一些小麻烦,现在把我成功安装maven的过程分享下, ...
- IE8/9 JQuery.Ajax 上传文件无效
IE8/9 JQuery.Ajax 上传文件有两个限制: 使用 JQuery.Ajax 无法上传文件(因为无法使用 FormData,FormData 是 HTML5 的一个特性,IE8/9 不支持) ...
- 微信小程序初探
做为码农相信大家最近肯定都会听到微信小程序,虽然现阶段还没有正式开放注册,但大家可以还是可以开发测试. 到微信的WIKI(http://mp.weixin.qq.com/wiki?t=resource ...
- CSS学习笔记
CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...
- 简历生成平台项目开发-STEP1问卷设计
周五课程结束完后,小组建立QQ群和微信群,着手讨论项目问题.一开始的大概想法:就业信息平台,收集企业招聘信息和就业生资料,提供给学生和企业的校企对接平台.后来发现群里谭卓同学也有个相关的思路,经过商量 ...
- Alwayson的IP冲突
Alwayson的IP冲突 https://social.technet.microsoft.com/Forums/office/en-US/4d50cb1c-eef7-4dcc-b937-3c8eb ...