📄 xunh.java
字号:
else if(p.nodekind.equals("ProcDecK") )
procDecPart(p);
else
AnalyzeError(t,"no this node kind in syntax tree!",null);
p = p.sibling ;/*循环处理*/
}
/*程序体*/
t = t.child[2];
if(t.nodekind.equals("StmLK"))
BodyA(t);
/*撤销符号表*/
if (Level!=-1)
DestroySymbTable();
/*输出语义错误*/
if(Error)
AnalyzeError(null," Analyze Error ",null);
}
/****************************************************/
/* 函数名 TypeDecPart */
/* 功 能 处理一个类型声明 */
/* 说 明 根据语法树中的类型声明节点,取相应内容, */
/* 将类型标识符添入符号表. */
/****************************************************/
void TypeDecPart(TreeNode t)
{
boolean present=false;
AttributeIR Attrib=new AttributeIR(); /*存储当前标识符的属性*/
SymbTable entry = new SymbTable();
Attrib.kind="typekind";
while (t!=null)
{
/*调用记录属性函数,返回是否重复声明错和入口地址*/
present = Enter(t.name[0],Attrib,entry);
if (present)
{
AnalyzeError(t," id repeat declaration ",t.name[0]);
entry = null;
}
else
entry.attrIR.idtype = TYPEA(t,t.kind);
t = t.sibling;
}
}
/****************************************************/
/* 函数名 TYPEA */
/* 功 能 建立类型的内部表示 */
/* 说 明 调用具体类型处理完成类型内部表示的构造 */
/* 返回指向类型内部表示的指针. */
/****************************************************/
TypeIR TYPEA(TreeNode t,String kind)
{
TypeIR typeptr=null;
/*根据不同类型信息,调用相应的类型处理函数*/
if (kind.equals("IdK"))
typeptr= NameTYPEA(t);
else if (kind.equals("IntegerK"))
typeptr= intptr;
else if (kind.equals("CharK"))
typeptr= charptr;
else if (kind.equals("ArrayK"))
typeptr= ArrayTYPEA(t);
else if (kind.equals("RecordK"))
typeptr= RecordTYPEA(t);
else
{
AnalyzeError(t,"bug: no this type in syntax tree ",null);
return null;
}
return typeptr;
}
/****************************************************/
/* 函数名 NameTYPEA */
/* 功 能 处理类型为类型标识符时的情形 */
/* 说 明 不构造新的类型,返回此类型标识符的类型, */
/* 并检查语义错误 */
/****************************************************/
TypeIR NameTYPEA(TreeNode t)
{
SymbTable Entry=new SymbTable();
TypeIR temp=null;
boolean present;
present= FindEntry(t.attr.type_name,Entry);
/*检查类型标识符未声明错*/
if (!present)
AnalyzeError(t," id use before declaration ",t.attr.type_name);
/*检查非类型标识符错*/
else if (!(Entry.attrIR.kind.equals("typekind")))
AnalyzeError(t," id is not type id ",t.attr.type_name);
/*返回标识符的类型的内部表示*/
else
{
temp= Entry.attrIR.idtype;
return temp;
}
return temp;
}
/****************************************************/
/* 函数名 ArrayTypeA */
/* 功 能 构造数组类型的内部表示 */
/* 说 明 处理下标类型,成员类型,计算数组大小, */
/* 并检查下标超界错误 */
/****************************************************/
TypeIR ArrayTYPEA(TreeNode t)
{
TypeIR tempforchild;
/*建立一个新的数组类型的内部表示*/
TypeIR typeptr=new TypeIR();
typeptr.array=new Array();
typeptr.kind="arrayTy";
/*下标类型是整数类型*/
typeptr.array.indexTy=intptr;
/*成员类型*/
tempforchild=TYPEA(t,t.attr.arrayAttr.childtype);
typeptr.array.elementTy=tempforchild;
/*检查数组下标出界错误*/
int up=t.attr.arrayAttr.up;
int low=t.attr.arrayAttr.low;
if (up < low)
AnalyzeError(t," array up smaller than under ",null);
else /*上下界计入数组类型内部表示中*/
{
typeptr.array.low = low;
typeptr.array.up = up;
}
/*计算数组的大小*/
typeptr.size= (up-low+1)*(tempforchild.size);
/*返回数组的内部表示*/
return typeptr;
}
/****************************************************/
/* 函数名 RecordTYPEA */
/* 功 能 构造记录类型的内部表示 */
/* 说 明 构造域表,指针存储在记录的内部表示中, */
/* 并计算记录的大小 */
/****************************************************/
TypeIR RecordTYPEA(TreeNode t)
{
TypeIR Ptr=new TypeIR(); /*新建记录类型的节点*/
Ptr.body=new FieldChain();
Ptr.kind="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 = new FieldChain();
if(body == null)
{
body = Ptr2;
Ptr1 = Ptr2;
}
/*填写Ptr2的各个成员内容*/
Ptr2.id=t.name[i];
Ptr2.unitType = TYPEA(t,t.kind);
/*如果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部分*/
Fcopy(Ptr.body,body);
return Ptr;
}
/****************************************************/
/* 函数名 VarDecPart */
/* 功 能 变量声明序列分析函数 */
/* 说 明 处理所有的变量声明 */
/****************************************************/
void VarDecPart(TreeNode t)
{
varDecList(t);
}
/****************************************************/
/* 函数名 varDecList */
/* 功 能 处理一个变量声明或形参声明 */
/* 说 明 处理一个声明节点中声明的所有标识符, */
/* 将相关信息添入符号表中,若是形参,还要 */
/* 构造一个参数信息表,各个标识符在符号表的 */
/* 位置存储在表中,返回参数表的表头指针 */
/****************************************************/
void varDecList(TreeNode t)
{
boolean present = false;
SymbTable Entry=new SymbTable();
/*纪录变量的属性*/
AttributeIR Attrib=new AttributeIR();
while(t!=null) /*循环过程*/
{
Attrib.kind="varkind";
for(int i=0;i<(t.idnum);i++)
{
Attrib.idtype=TYPEA(t,t.kind);
/*判断识值参还是变参acess(dir,indir)*/
if((t.attr.procAttr!=null)&&(t.attr.procAttr.paramt.equals("varparamType")))
{
Attrib.var = new Var();
Attrib.var.access = "indir";
Attrib.var.level = Level;
/*计算形参的偏移*/
Attrib.var.off = Off;
Off = Off+1;
}/*如果是变参,则偏移加1*/
else
{
Attrib.var = new Var();
Attrib.var.access = "dir";
Attrib.var.level = Level;
/*计算值参的偏移*/
if(Attrib.idtype.size!=0)
{
Attrib.var.off = Off;
Off = Off + (Attrib.idtype.size);
}
}/*其他情况均为值参,偏移加变量类型的size*/
/*登记该变量的属性及名字,并返回其类型内部指针*/
present = Enter(t.name[i],Attrib,Entry);
if(present)
AnalyzeError(t," id repeat declaration ",t.name[0]);
else
t.table[i] = Entry;
}
if(t!=null)
t = t.sibling;
}
/*如果是主程序,则记录此时偏移,用于目标代码生成时的displayOff*/
if(Level==0)
{
mainOff = Off;
/*存储主程序AR的display表的偏移到全局变量*/
StoreNoff = Off;
}
/*如果不是主程序,则记录此时偏移,用于下面填写过程信息表的noff信息*/
else
savedOff = Off;
}
/****************************************************/
/* 函数名 procDecPart */
/* 功 能 一个过程声明的语义分析 */
/* 说 明 处理过程头,声明,过程体 */
/****************************************************/
void procDecPart(TreeNode t)
{
TreeNode p =t;
SymbTable entry = HeadProcess(t); /*处理过程头*/
t = t.child[1];
/*如果过程内部存在声明部分,则处理声明部分*/
while (t!=null)
{
if ( t.nodekind.equals("TypeK") )
TypeDecPart(t.child[0]);
else if ( t.nodekind.equals("VarK") )
VarDecPart(t.child[0]);
/*如果声明部分有函数声明,则跳出循环,先填写noff和moff等信息,*
*再处理函数声明的循环处理,否则无法保存noff和moff的值。 */
else if ( t.nodekind.equals("ProcDecK") ) {}
else
AnalyzeError(t,"no this node kind in syntax tree!",null);
if(t.nodekind.equals("ProcDecK"))
break;
else
t=t.sibling ;
}
entry.attrIR.proc.nOff = savedOff;
entry.attrIR.proc.mOff = entry.attrIR.proc.nOff + entry.attrIR.proc.level+1;
/*过程活动记录的长度等于nOff加上display表的长度*
*diplay表的长度等于过程所在层数加一 */
/*处理程序的声明部分*/
while(t!=null)
{
procDecPart(t);
t = t.sibling;
}
t = p;
BodyA(t.child[2]);/*处理Block*/
/*函数部分结束,删除进入形参时,新建立的符号表*/
if ( Level!=-1)
DestroySymbTable();/*结束当前scope*/
}
/****************************************************/
/* 函数名 HeadProcess */
/* 功 能 形参处理函数 */
/* 说 明 循环处理各个节点,并将处理每个节点得到 */
/* 的参数表连接起来,组成整个形参链表,返回 */
/* 这个表的指针 */
/****************************************************/
SymbTable HeadProcess(TreeNode t)
{
AttributeIR attrIr = new AttributeIR();
boolean present = false;
SymbTable entry = new SymbTable();
/*填属性*/
attrIr.kind = "prockind";
attrIr.idtype = null;
attrIr.proc = new Proc();
attrIr.proc.param = new ParamTable();
attrIr.proc.level = Level+1;
if(t!=null)
{
/*登记函数的符号表项*/
present = Enter(t.name[0],attrIr,entry);
t.table[0] = entry;
/*处理形参声明表*/
}
entry.attrIR.proc.param = ParaDecList(t);
return entry;
}
/****************************************************/
/* 函数名 ParaDecList */
/* 功 能 处理一个形参节点 */
/* 说 明 根据参数是形参还是变参,分别调用变量声明 */
/* 节点的处理函数,另一个实参是Add,表示处理*/
/* 的是函数的形参。 */
/****************************************************/
ParamTable ParaDecList(TreeNode t)
{
TreeNode p=null;
ParamTable Ptr1=null;
ParamTable Ptr2=null;
ParamTable head=null;
if(t!=null)
{
if(t.child[0]!=null)
p = t.child[0]; /*程序声明节点的第一个儿子节点*/
CreatSymbTable(); /*进入新的局部化区*/
Off = 7; /*子程序中的变量初始偏移设为8*/
VarDecPart(p); /*变量声明部分*/
SymbTable Ptr0 = scope[Level];
while(Ptr0 != null) /*只要不为空,就访问其兄弟节点*/
{
/*构造形参符号表,并使其连接至符号表的param项*/
Ptr2 = new ParamTable();
if(head == null)
{
head = Ptr2;
Ptr1 = Ptr2;
}
//Ptr0.attrIR.var.isParam = true;
copy(Ptr2.entry,Ptr0);
if(Ptr2 != Ptr1)
{
Ptr1.next = Ptr2;
Ptr1 = Ptr2;
}
Ptr0 = Ptr0.next;
}
}
return head; /*返回形参符号表的头指针*/
}
/****************************************************/
/* 函数名 BodyA */
/* 功 能 语句序列处理函数 */
/* 说 明 用于处理过程体或者程序体, */
/* 循环处理各个语句 */
/****************************************************/
void BodyA(TreeNode t)
{
/*令指针指向第一条语句*/
if (t.nodekind.equals("StmLK"))
t=t.child[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -