赞
踩
首先可能要检查程序中标识符的声明问题,程序设计语言可以分为强类型语言和弱类型语言。强类型:要求所有用到的表示符必须经过声明,而且在一个程序的作用域内只声明一次,因此需要检查有没有变量的声明、标识符有没有重复声明。
处理后的是没有错误的token序列,token序列被分成3类:常量、标识符、特殊符。
newtoken和token相比,常量、特殊符都没有发生变化,但是标识符发生了变化。标识符在这里被分为两部分一部分仍然是原来的标识符另一部分指向一个符号表,符号表中还含有标识符的语义,记录了有关标识符的信息。
const n=100
来定义,不能被赋值只能代表100的值,常量标识符不对应存储单元,而是对应一个值,所以不能被赋值
在进行处理的时候一些语义信息要把他体现出来,要不然可能会出现一些错误,比如T是一个类型标识符,T+1的运算从语法的角度来说标识符加常数没有错误,但是语义上有错误,所以一个标识符的语义信息要把他的一些主要的内容区分开。
这些信息缺一不可,缺少某一项翻译工作无法进行
TypePtr执行类型信息表的指针
Value可以直接写上具体的值,也可以一个指向常量表的指针
常量标识符不能被赋值,因为在内存中不保存常量标识符,实际上常量标识符是不存在的(不在内存中分配空间,因为已经在编译的时候把常量全部替换成真正的“常量”了)
类型本身不对应内存空间的
intPtr指向类型信息表中的int部分。t2指向内存中的数组类型,而数组类型中的每个元素的基本类型再指向int类型
Access:直接取址还是间接取址(存的是地址还是值)
Level:层数,实际上与语言是嵌套式语言还是并行式语言相关
每一个函数在程序真正要运行的过程中要对应一块存储单元,我们把这个存储单元叫做过程活动记录。定义的函数活动记录存储在Activity Record(AR)中(一般程序中会将内存按照一定的规则划分,划分成常量区、堆栈区等,AR即存储在栈区,进行到一个函数就将它的AR存储到栈区。后面需要一个变量的Level来对使用性变量进行说明。
Off:表示当前过程中的变量存储在AR的哪部分,对应内存块的起始位置的偏移量
int g(param seris){ //在函数名之前的属于L层,则后面括号中的参数一直到下一个函数的函数名都是L+1层,依次类推k int i; int g1(){ int j; int g2(){ int k = i+j; } } } //这里一般在最内层函数中是可以调用外层函数中的变量的 //这里f和g属于并列关系,g和g1、g2属于嵌套关系 //g函数可以调用f函数但是不能调用f1和f2,不能调用定义在函数f里面的函数 int f(){ ... int f1(){ ... int f2(){ ... } } }
偏移量是针对记录类型的偏移量,一个记录可能有多个域,每一个域都要占用一定的存储单元,而这个偏移就是我们这个域名针对记录的偏移,域名的宿主类型,因为一个域在不同的记录中都可能声明,比方说学生可以声明一个name,工人声明一个name,一旦出现一个name,我们需要知道他是哪个记录中定义的,所以要保存它的宿主类型。
一个函数被调用的时候本身就是一个AR,Off部分为nullptr
正常函数没有Off,为默认值nullptr
,但如果是虚参函数,作为另一个函数的参数存在,这个时候Off不为nullptr
Code:函数目标代码的地址,在函数调用之后一定需要一个语句返回函数体内的固定位置,需要知道目标代码的初始位置。创建符号表的时候,目标代码的地址是不确定的,但是空间要保留出来,待后续确定之后写回Code。如果要形成一条转移指令,则到Code部分找到目标地址回填。
Size:存储AR表的大小,Size多大对应天多大的内存空间,但是这里存在一个问题就是实际上所需的内存空间不是程序中定义的变量等需要的那么大的内存空间,实际上在编译过程中(未涉及优化)会产生大量的中间变量,中间变量也需要内存空间,需要动态调整,根据生成的中间变量的大小增加Size的值。
int p = k+i+j;
//首先取i的值送入Reg,然后和j相加送入中间变量t1
//然后将t1值取出放入Reg,然后和k相加送入中间变量t2
//都得先放入Reg(考虑一般情况)
//这里的t1和t2就是临时变量
Forward:前向声明
int f1(){
g1();
}
int g1(){
f1();
}
//这里函数f1和g1都是函数定义,但是定义都不完整,无法直接进行二者的调用
//使用前置声明可以解决这个问题
//前置声明只包括函数名和返回值以及参数不包括函数体
//只是在未完全定义时写在所有使用的地方前面,则可以使用未定义函数
类型信息有什么作用呢?他的作用主要有两类:
1、做类型的检查,不同类型的数在计算机中的表示形式是不同的
2、要根据类型的大小为每一个变量分配存储空间的,一个简单变量和一个数组他们占用的存储空间的大小是不同的
枚举类型是一种特殊的数据类型,定义的数据通过枚举的方式都把它给出来,
枚举类型的语义信息,元素的大小,以后这种枚举变量,给他开多大的空间,
第二就是种类表示他是一个枚举类型,
第三他要按照表的方式给他存放起来,要记录一个表头,后面是长度表示枚举类型应该有几个元素。
(内部计算的时候枚举的内容按整形存储)
Size = (up-low+1)* Typelength
一维数组和二维数组的表示如下:
按照最长的类型size开辟空间
集合类型,大小 种类,基类型,这个集合是定义在哪一个类型上面的。集合的大小怎么来确定,因为集合可能是一个无穷极,怎么来确定他的大小呢?程序设计语言中设定一个集合的时候都是设定成一个有限的集合,用2的n次方来确定,假如有1000个元素是不是要给他1000个存储单元呢? 用一个二进制码来表示这个集合,按位来表示,所以集合变量占用的空间并不是很大,好处是关于集合的运算就很好做了,集合的并就是二进制数的逻辑加,交就是逻辑乘
文件类型,大小指的是缓冲区的大小, 通常文件是这样处理的,数据文件是每次读入是按照缓冲区的大小读入一个记录,缓冲区类型
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。