?? analyze.cpp
字號:
/****************************************************/
/* 文件 analyze.cpp */
/* 說明 類PASCAL語言編譯器語義分析程序 */
/* 主題 編譯器結(jié)構(gòu):原理和實(shí)例 */
/****************************************************/
/*********** 該文件所包含的頭文件 ****************/
#include "globals.h"
#include "util.h"
#include "symbTable.h"
#include "scanner.h"
#include "parse.h"
#include "analyze.h"
#include "string.h"
/*scope棧的層數(shù)*/
int Level=-1;
/*在同層的變量偏移*/
int Off;
/*主程序的noff偏移*/
int mainOff;
SymbTable * scope[SCOPESIZE]; /*scope棧*/
TypeIR * intPtr = NULL; /*該指針一直指向整數(shù)類型的內(nèi)部表示*/
TypeIR * charPtr = NULL; /*該指針一直指向字符類型的內(nèi)部表示*/
TypeIR * boolPtr = NULL; /*該指針一直指向布爾類型的內(nèi)部表示*/
static TypeIR * arrayVar(TreeNode * t);
/*該函數(shù)用于處理數(shù)組類型變量*/
static TypeIR * recordVar(TreeNode * t);
/*該函數(shù)用于處理記錄類型變量*/
/***********************類型處理*****************************/
/*************************************************************/
/* 函數(shù)名 initialize */
/* 功 能 該函數(shù)初始化整數(shù)類型,字符類型,布爾類型的內(nèi)部表示*/
/* 說 明 由于這三種類型均為基本類型,內(nèi)部表示固定。 */
/*************************************************************/
void initialize(void)
{
intPtr = NewTy(intTy);
charPtr = NewTy(charTy);
boolPtr = NewTy(boolTy);
/*scope棧的各層指針設(shè)為空*/
for (int i=0;i<SCOPESIZE;i++)
scope[i] = NULL;
}
/************************************************************/
/* 函數(shù)名 TypeProcess */
/* 功 能 該函數(shù)用來完成類型分析的工作 */
/* 說 明 處理語法樹的當(dāng)前結(jié)點(diǎn)類型。構(gòu)造出當(dāng)前類型的內(nèi)部表 */
/* 示,并將其地址返回給Ptr類型內(nèi)部表示的地址. */
/************************************************************/
TypeIR * TypeProcess(TreeNode * t,DecKind deckind)
{
TypeIR * Ptr = NULL;
switch (deckind)
{
case IdK:
Ptr = nameType(t);break; /*類型為自定義標(biāo)識符*/
case ArrayK:
Ptr = arrayType(t);break; /*類型為數(shù)組類型*/
case RecordK:
Ptr = recordType(t);break; /*類型為記錄類型*/
case IntegerK:
Ptr = intPtr;break; /*類型為整數(shù)類型*/
case CharK:
Ptr = charPtr;break; /*類型為字符類型*/
}
return Ptr;
}
/************************************************************/
/* 函數(shù)名 nameType */
/* 功 能 該函數(shù)用來在符號表中尋找已定義的類型名字 */
/* 說 明 調(diào)用尋找表項(xiàng)地址函數(shù)FindEntry,返回找到的表項(xiàng)地址*/
/* 指針entry。如果present為FALSE,則發(fā)生無聲明錯(cuò)誤。*/
/* 如果符號表中的該標(biāo)識符的屬性信息不是類型,則非類 */
/* 型標(biāo)識符。該函數(shù)返回指針指向符號表中的該標(biāo)識符的 */
/* 類型內(nèi)部表示。 */
/************************************************************/
TypeIR * nameType(TreeNode * t)
{
TypeIR * Ptr=NULL;
SymbTable * entry = NULL;
int present;
/*類型標(biāo)識符也需要往前層查找*/
present = FindEntry(t->attr.type_name,&entry);
if(present == TRUE)
{
/*檢查該標(biāo)識符是否為類型標(biāo)識符*/
if(entry->attrIR.kind != typeKind)
ErrorPrompt(t->lineno,t->attr.type_name,"used before typed!\n");
else
Ptr = entry->attrIR.idtype;
}
else/*沒有找到該標(biāo)識符*/
{
ErrorPrompt(t->lineno,t->attr.type_name,"type name is not declared!\n");
}
return Ptr;
}
/************************************************************/
/* 函數(shù)名 arrayType */
/* 功 能 該函數(shù)處理數(shù)組類型的內(nèi)部表示 */
/* 說 明 類型為數(shù)組類型時(shí),需要檢查下標(biāo)是否合法。 */
/************************************************************/
TypeIR * arrayType(TreeNode * t)
{
TypeIR * Ptr0 = NULL;
TypeIR * Ptr1 = NULL;
TypeIR * Ptr = NULL;
/*檢查數(shù)組上界是否小于下界*/
if ((t->attr.ArrayAttr.low)>( t->attr.ArrayAttr.up))
{
ErrorPrompt(t->lineno,"","array subscript error!\n");
Error = TRUE;
}
else
{
Ptr0 = TypeProcess(t,IntegerK);
/*調(diào)用類型分析函數(shù),處理下標(biāo)類型*/
Ptr1 = TypeProcess(t,t->attr.ArrayAttr.childtype);
/*調(diào)用類型分析函數(shù),處理元素類型*/
Ptr = NewTy(arrayTy);
/*指向一新創(chuàng)建的類型信息表*/
Ptr->size = ((t->attr.ArrayAttr.up)-(t->attr.ArrayAttr.low)+1)*(Ptr1->size);
/*計(jì)算本類型長度*/
/*填寫其他信息*/
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;
}
/************************************************************/
/* 函數(shù)名 recordType */
/* 功 能 該函數(shù)處理記錄類型的內(nèi)部表示 */
/* 說 明 類型為記錄類型時(shí),是由記錄體組成的。其內(nèi)部節(jié)點(diǎn)需 */
/* 要包括3個(gè)信息:一是空間大小size;二是類型種類標(biāo)志 */
/* recordTy;三是體部分的節(jié)點(diǎn)地址body。記錄類型中的 */
/* 域名都是標(biāo)識符的定義性出現(xiàn),因此需要記錄其屬性。 */
/************************************************************/
TypeIR * recordType(TreeNode * t)
{
TypeIR * Ptr=NewTy(recordTy); /*新建記錄類型的節(jié)點(diǎn)*/
t = t->child[0]; /*從語法數(shù)的兒子節(jié)點(diǎn)讀取域信息*/
fieldChain * Ptr2 = NULL;
fieldChain * Ptr1 = NULL;
fieldChain * body = NULL;
while (t != NULL) /*循環(huán)處理*/
{
/*填寫ptr2指向的內(nèi)容節(jié)點(diǎn)*
*此處循環(huán)是處理此種情況int a,b; */
for(int i=0 ; i < t->idnum ; i++)
{
/*申請新的域類型單元結(jié)構(gòu)Ptr2*/
Ptr2 = NewBody();
if(body == NULL)
body = Ptr1 = Ptr2;
/*填寫Ptr2的各個(gè)成員內(nèi)容*/
strcpy(Ptr2->id,t->name[i]);
Ptr2->UnitType = TypeProcess(t,t->kind.dec);
Ptr2->Next = NULL;
/*如果Ptr1!=Ptr2,那么將指針后移*/
if(Ptr2 != Ptr1)
{
/*計(jì)算新申請的單元off*/
Ptr2->off = (Ptr1->off) + (Ptr1->UnitType->size);
Ptr1->Next = Ptr2;
Ptr1 = Ptr2;
}
}
/*處理完同類型的變量后,取語法樹的兄弟節(jié)點(diǎn)*/
t = t->sibling;
}
/*處理記錄類型內(nèi)部結(jié)構(gòu)*/
/*取Ptr2的off為最后整個(gè)記錄的size*/
Ptr->size = Ptr2->off + (Ptr2->UnitType->size);
/*將域鏈鏈入記錄類型的body部分*/
Ptr->More.body = body;
return Ptr;
}
/************************************************************/
/*********************聲明的語義分析*************************/
/************************************************************/
/* 函數(shù)名 TypeDecPart */
/* 功 能 該函數(shù)處理類型聲明的語義分析 */
/* 說 明 遇到類型T時(shí),構(gòu)造其內(nèi)部節(jié)點(diǎn)TPtr;對于"idname=T"構(gòu)*/
/* 造符號表項(xiàng);檢查本層類型聲明中是否有重復(fù)定義錯(cuò)誤.*/
/************************************************************/
void TypeDecPart(TreeNode * t)
{
int present = FALSE;
AttributeIR attrIr;
SymbTable * entry = NULL;
/*添屬性作為參數(shù)*/
attrIr.kind = typeKind;
/*遍歷語法樹的兄弟節(jié)點(diǎn)*/
while (t!=NULL)
{
/*調(diào)用記錄屬性函數(shù),返回是否重復(fù)聲明錯(cuò)和入口地址*/
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;
}
}
/************************************************************/
/* 函數(shù)名 VarDecPart */
/* 功 能 該函數(shù)處理變量聲明的語義分析 */
/* 說 明 調(diào)用變量處理分析函數(shù) */
/************************************************************/
void VarDecPart(TreeNode * t)
{
varDecList(t);
}
/************************************************************/
/* 函數(shù)名 varDecList */
/* 功 能 該函數(shù)處理變量聲明的語義分析 */
/* 說 明 當(dāng)遇到變量表識符id時(shí),把id登記到符號表中;檢查重 */
/* 復(fù)性定義;遇到類型時(shí),構(gòu)造其內(nèi)部表示。 */
/************************************************************/
void varDecList(TreeNode * t)
{
AttributeIR attrIr;
int present = FALSE;
SymbTable * entry = NULL;
while(t!=NULL) /*循環(huán)過程*/
{
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;
/*計(jì)算形參的偏移*/
attrIr.More.VarAttr.off = Off;
Off = Off+1;
}/*如果是變參,則偏移加1*/
else
{
attrIr.More.VarAttr.access = dir;
attrIr.More.VarAttr.level = Level;
/*計(jì)算值參的偏移*/
if(attrIr.idtype!=NULL)
{
attrIr.More.VarAttr.off = Off;
Off = Off + (attrIr.idtype->size);
}
}/*其他情況均為值參,偏移加變量類型的size*/
/*登記該變量的屬性及名字,并返回其類型內(nèi)部指針*/
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;
}
/*如果是主程序,則記錄此時(shí)偏移,用于目標(biāo)代碼生成時(shí)的displayOff*/
if(Level==0)
{
mainOff = Off;
/*存儲主程序AR的display表的偏移到全局變量*/
StoreNoff = Off;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -