📄 analyze.cpp
字号:
/****************************************************/
/* 文件 analyze.cpp */
/* 说明 类PASCAL语言编译器语义分析程序 */
/* 主题 编译器结构:原理和实例 */
/****************************************************/
/*********** 该文件所包含的头文件 ****************/
#include "globals.h"
#include "util.h"
#include "symbTable.h"
#include "scanner.h"
#include "parse.h"
#include "analyze.h"
#include "string.h"
/*scope栈的层数*/
int Level=-1;
/*在同层的变量偏移*/
int Off;
/*主程序的noff偏移*/
int mainOff;
SymbTable * scope[SCOPESIZE]; /*scope栈*/
TypeIR * intPtr = NULL; /*该指针一直指向整数类型的内部表示*/
TypeIR * charPtr = NULL; /*该指针一直指向字符类型的内部表示*/
TypeIR * boolPtr = NULL; /*该指针一直指向布尔类型的内部表示*/
static TypeIR * arrayVar(TreeNode * t);
/*该函数用于处理数组类型变量*/
static TypeIR * recordVar(TreeNode * t);
/*该函数用于处理记录类型变量*/
/***********************类型处理*****************************/
/*************************************************************/
/* 函数名 initialize */
/* 功 能 该函数初始化整数类型,字符类型,布尔类型的内部表示*/
/* 说 明 由于这三种类型均为基本类型,内部表示固定。 */
/*************************************************************/
void initialize(void)
{
intPtr = NewTy(intTy);
charPtr = NewTy(charTy);
boolPtr = NewTy(boolTy);
/*scope栈的各层指针设为空*/
for (int i=0;i<SCOPESIZE;i++)
scope[i] = NULL;
}
/************************************************************/
/* 函数名 TypeProcess */
/* 功 能 该函数用来完成类型分析的工作 */
/* 说 明 处理语法树的当前结点类型。构造出当前类型的内部表 */
/* 示,并将其地址返回给Ptr类型内部表示的地址. */
/************************************************************/
TypeIR * TypeProcess(TreeNode * t,DecKind deckind)
{
TypeIR * Ptr = NULL;
switch (deckind)
{
case IdK:
Ptr = nameType(t);break; /*类型为自定义标识符*/
case ArrayK:
Ptr = arrayType(t);break; /*类型为数组类型*/
case RecordK:
Ptr = recordType(t);break; /*类型为记录类型*/
case IntegerK:
Ptr = intPtr;break; /*类型为整数类型*/
case CharK:
Ptr = charPtr;break; /*类型为字符类型*/
}
return Ptr;
}
/************************************************************/
/* 函数名 nameType */
/* 功 能 该函数用来在符号表中寻找已定义的类型名字 */
/* 说 明 调用寻找表项地址函数FindEntry,返回找到的表项地址*/
/* 指针entry。如果present为FALSE,则发生无声明错误。*/
/* 如果符号表中的该标识符的属性信息不是类型,则非类 */
/* 型标识符。该函数返回指针指向符号表中的该标识符的 */
/* 类型内部表示。 */
/************************************************************/
TypeIR * nameType(TreeNode * t)
{
TypeIR * Ptr=NULL;
SymbTable * entry = NULL;
int present;
/*类型标识符也需要往前层查找*/
present = FindEntry(t->attr.type_name,&entry);
if(present == TRUE)
{
/*检查该标识符是否为类型标识符*/
if(entry->attrIR.kind != typeKind)
ErrorPrompt(t->lineno,t->attr.type_name,"used before typed!\n");
else
Ptr = entry->attrIR.idtype;
}
else/*没有找到该标识符*/
{
ErrorPrompt(t->lineno,t->attr.type_name,"type name is not declared!\n");
}
return Ptr;
}
/************************************************************/
/* 函数名 arrayType */
/* 功 能 该函数处理数组类型的内部表示 */
/* 说 明 类型为数组类型时,需要检查下标是否合法。 */
/************************************************************/
TypeIR * arrayType(TreeNode * t)
{
TypeIR * Ptr0 = NULL;
TypeIR * Ptr1 = NULL;
TypeIR * Ptr = NULL;
/*检查数组上界是否小于下界*/
if ((t->attr.ArrayAttr.low)>( t->attr.ArrayAttr.up))
{
ErrorPrompt(t->lineno,"","array subscript error!\n");
Error = TRUE;
}
else
{
Ptr0 = TypeProcess(t,IntegerK);
/*调用类型分析函数,处理下标类型*/
Ptr1 = TypeProcess(t,t->attr.ArrayAttr.childtype);
/*调用类型分析函数,处理元素类型*/
Ptr = NewTy(arrayTy);
/*指向一新创建的类型信息表*/
Ptr->size = ((t->attr.ArrayAttr.up)-(t->attr.ArrayAttr.low)+1)*(Ptr1->size);
/*计算本类型长度*/
/*填写其他信息*/
Ptr->More.ArrayAttr.indexTy = Ptr0;
Ptr->More.ArrayAttr.elemTy = Ptr1;
Ptr->More.ArrayAttr.low = t->attr.ArrayAttr.low;
Ptr->More.ArrayAttr.up = t->attr.ArrayAttr.up;
}
return Ptr;
}
/************************************************************/
/* 函数名 recordType */
/* 功 能 该函数处理记录类型的内部表示 */
/* 说 明 类型为记录类型时,是由记录体组成的。其内部节点需 */
/* 要包括3个信息:一是空间大小size;二是类型种类标志 */
/* recordTy;三是体部分的节点地址body。记录类型中的 */
/* 域名都是标识符的定义性出现,因此需要记录其属性。 */
/************************************************************/
TypeIR * recordType(TreeNode * t)
{
TypeIR * Ptr=NewTy(recordTy); /*新建记录类型的节点*/
t = t->child[0]; /*从语法数的儿子节点读取域信息*/
fieldChain * Ptr2 = NULL;
fieldChain * Ptr1 = NULL;
fieldChain * body = NULL;
while (t != NULL) /*循环处理*/
{
/*填写ptr2指向的内容节点*
*此处循环是处理此种情况int a,b; */
for(int i=0 ; i < t->idnum ; i++)
{
/*申请新的域类型单元结构Ptr2*/
Ptr2 = NewBody();
if(body == NULL)
body = Ptr1 = Ptr2;
/*填写Ptr2的各个成员内容*/
strcpy(Ptr2->id,t->name[i]);
Ptr2->UnitType = TypeProcess(t,t->kind.dec);
Ptr2->Next = NULL;
/*如果Ptr1!=Ptr2,那么将指针后移*/
if(Ptr2 != Ptr1)
{
/*计算新申请的单元off*/
Ptr2->off = (Ptr1->off) + (Ptr1->UnitType->size);
Ptr1->Next = Ptr2;
Ptr1 = Ptr2;
}
}
/*处理完同类型的变量后,取语法树的兄弟节点*/
t = t->sibling;
}
/*处理记录类型内部结构*/
/*取Ptr2的off为最后整个记录的size*/
Ptr->size = Ptr2->off + (Ptr2->UnitType->size);
/*将域链链入记录类型的body部分*/
Ptr->More.body = body;
return Ptr;
}
/************************************************************/
/*********************声明的语义分析*************************/
/************************************************************/
/* 函数名 TypeDecPart */
/* 功 能 该函数处理类型声明的语义分析 */
/* 说 明 遇到类型T时,构造其内部节点TPtr;对于"idname=T"构*/
/* 造符号表项;检查本层类型声明中是否有重复定义错误.*/
/************************************************************/
void TypeDecPart(TreeNode * t)
{
int present = FALSE;
AttributeIR attrIr;
SymbTable * entry = NULL;
/*添属性作为参数*/
attrIr.kind = typeKind;
/*遍历语法树的兄弟节点*/
while (t!=NULL)
{
/*调用记录属性函数,返回是否重复声明错和入口地址*/
present = Enter(t->name[0],&attrIr,&entry);
if (present!=FALSE)
{
ErrorPrompt(t->lineno,t->name[0],"is repetation declared!\n");
entry = NULL;
}
else
entry->attrIR.idtype = TypeProcess(t,t->kind.dec);
t = t->sibling;
}
}
/************************************************************/
/* 函数名 VarDecPart */
/* 功 能 该函数处理变量声明的语义分析 */
/* 说 明 调用变量处理分析函数 */
/************************************************************/
void VarDecPart(TreeNode * t)
{
varDecList(t);
}
/************************************************************/
/* 函数名 varDecList */
/* 功 能 该函数处理变量声明的语义分析 */
/* 说 明 当遇到变量表识符id时,把id登记到符号表中;检查重 */
/* 复性定义;遇到类型时,构造其内部表示。 */
/************************************************************/
void varDecList(TreeNode * t)
{
AttributeIR attrIr;
int present = FALSE;
SymbTable * entry = NULL;
while(t!=NULL) /*循环过程*/
{
attrIr.kind = varKind;
for(int i=0;i<(t->idnum);i++)
{
attrIr.idtype = TypeProcess(t,t->kind.dec);
/*判断识值参还是变参acess(dir,indir)*/
if(t->attr.ProcAttr.paramt == varparamType)
{
attrIr.More.VarAttr.access = indir;
attrIr.More.VarAttr.level = Level;
/*计算形参的偏移*/
attrIr.More.VarAttr.off = Off;
Off = Off+1;
}/*如果是变参,则偏移加1*/
else
{
attrIr.More.VarAttr.access = dir;
attrIr.More.VarAttr.level = Level;
/*计算值参的偏移*/
if(attrIr.idtype!=NULL)
{
attrIr.More.VarAttr.off = Off;
Off = Off + (attrIr.idtype->size);
}
}/*其他情况均为值参,偏移加变量类型的size*/
/*登记该变量的属性及名字,并返回其类型内部指针*/
present = Enter(t->name[i],&attrIr,&entry);
if(present!=FALSE)
{
ErrorPrompt(t->lineno,t->name[i]," is defined repetation!\n");
}
else
t->table[i] = entry;
}
if(t!=NULL)
t = t->sibling;
}
/*如果是主程序,则记录此时偏移,用于目标代码生成时的displayOff*/
if(Level==0)
{
mainOff = Off;
/*存储主程序AR的display表的偏移到全局变量*/
StoreNoff = Off;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -