www.pudn.com > subpas.rar > analyze.c
/****************************************************/
/* File: analyze.c */
/* Semantic analyzer implementation */
/* for the SubPas compiler */
/****************************************************/
#include "globals.h"
#include "util.h"
#include "parse.h"
#include "analyze.h"
/* 当前检查所在的子函数或过程*/
static TreeNode * currentPro=NULL;
TreeNode * syntaxTree;
/* 返回变量的声明节点
* @param name 变量名
8 @return 该变量的声明的节点指针
*/
TreeNode * lookUpVar(char * name)
{
TreeNode * t;
if(currentPro!=NULL){
t = currentPro->child[0]; //是否在函数的参数中?
while (t!=NULL){
if(strcmp(t->name,name)==0) return t;
t = t->sibling;
}
t = currentPro -> child[1]; //是否在函数的局部变量声明中?
while (t!=NULL){
if(strcmp(t->name,name)==0) return t;
t = t->sibling;
}
}
t = syntaxTree->child[1]; //是否在全局变量声明中?
while (t!=NULL){
if(strcmp(t->name,name)==0) return t;
t = t->sibling;
}
return NULL; //找不到,返回NULL
}
/* 返回函数的声明节点
* @param name 函数名
* @return 函数声明的节点指针
*/
TreeNode * lookUpPro(char * name)
{
TreeNode * t = syntaxTree->sibling;
while(t!=NULL && (currentPro != NULL && t != currentPro->sibling)){
if(strcmp(t->name,name)==0) return t;
t = t->sibling;
}
return NULL;
}
/* 检查是否有重复变量声明,方法是将参数和局部变量声明逐一比较
* @param proNode 函数或过程的声明节点
* @return 若有重复声明,返回第二个声明变量的节点,否则返回NULL
*/
TreeNode * idCheck(TreeNode * proNode)
{
TreeNode * t1 = proNode->child[0]; //检查参数
TreeNode * t2;
while(t1!=NULL){
int flag = TRUE;
t2 = t1->sibling;
while(t2!=NULL){ //先跟参数比较
if(strcmp(t1->name,t2->name)==0) return t2;
t2 = t2->sibling;
if(t2==NULL && flag==TRUE){
t2 = proNode->child[1]; //再跟局部变量比较
flag = FALSE;
}
}
t1 = t1->sibling;
}
t1 = proNode->child[1]; //检查局部变量
while(t1!=NULL){
t2 = t1->sibling;
while(t2!=NULL){
if(strcmp(t1->name,t2->name)==0) return t2;
t2 = t2->sibling;
}
t1 = t1->sibling;
}
return NULL;
}
/* 错误信息种类*/
typedef enum {type_mismatch , op_err, dec_again , undec_id , test_err , param_must_be_id,
param_num_err , array_overflow , array_index_err } ErrorType;
/* 打印语法错误信息
* @param t 发生错误的节点
* @param err 错误信息种类
*/
void printError(TreeNode * t,ErrorType err)
{
switch (err) {
case type_mismatch:
if (t->child[1])
printf("Error:(line %d) Incompatible types:%s and %s.\n",
t->lineno,getType(t->child[0]),getType(t->child[1]));
else printf("Error:(line %d) Incompatible types.\n",t->lineno);
break;
case op_err:
if(t->kind.exp==SignK)
printf("Error:(line %d) Type of Signed-Operation must be Integer or Real.\n",t->lineno);
else
printf("Error:(line %d) Type of NOT-Operation must be Boolean.\n",t->lineno);
break;
case dec_again:
printf("Error:(line %d) Identifier redeclared:%s.\n",t->lineno,t->name);
break;
case undec_id:
printf( "Error:(line %d) Undeclared identifier:%s.\n",t->lineno,t->name);
break;
case test_err:
printf( "Error:(line %d) Type of expression must be BOOLEAN.\n",t->lineno);
break;
case param_must_be_id:
printf( "Error:(line %d) Wrong parameter:the parameter must be variable identifier.\n",t->lineno);
break;
case param_num_err:
printf( "Error:(line %d) The number of parameters is mismatched:%s.\n",t->lineno,t->name);
break;
case array_overflow:
printf( "Error:(line %d) Array index overflow:%s.\n",t->lineno,t->name);
break;
case array_index_err:
printf( "Error:(line %d) Array index must be integer:%s.\n",t->lineno,t->name);
break;
}
Error = TRUE;
}
static TreeNode * ReadlnParam = NULL; //readln语句的参数
static TreeNode * WritelnParam = NULL; //writeln语句的参数
static TreeNode * ReadlnDec = NULL; //readln语句的声明
static TreeNode * WritelnDec = NULL; //writeln的声明
//是否用到Readln语句
int ReadlnUsed = FALSE;
//是否用到Writeln语句
int WritelnUsed = FALSE;
/* 进行错误检查,若有错误,打印出错误信息
* @param t 树节点
*/
void errorCheck(TreeNode * t)
{
TreeNode * tree;
if(t==NULL) return;
switch (t->nodekind)
{
case Pro:
if (t->kind.pro == SubP) currentPro = t;
tree=idCheck(t); //检查全局变量是否有重复声明
if(tree!=NULL) printError(tree,dec_again);
if (t->kind.pro ==MainP){ //若是主过程,则
errorCheck(t->sibling); //先对子过程和子函数进行检查
errorCheck(t->child[2]); //再检查主过程语句
}else{
errorCheck(t->child[2]); //否则,先检查子过程(函数)的语句
errorCheck(t->sibling); //再检查下一个子过程(函数)
}
break;
case Stmt:
errorCheck(t->child[0]);
errorCheck(t->child[1]);
errorCheck(t->child[2]);
switch (t->kind.stmt)
{
case IfK:
case WhileK:
if (t->child[0]->type != Boolean)
printError(t->child[0],test_err);
break;
case CallK:
if (!strcmp(t->name,"readln")) {
TreeNode * realp = t->child[0];
if (realp->type != Integer)
printError(realp,type_mismatch);
else if (realp->kind.exp != IdK && realp->kind.exp != ArrayK)
printError(realp,param_must_be_id);
else if (realp->sibling)
printError(t,param_num_err);
else {
ReadlnUsed = TRUE;
if (!ReadlnParam) {
ReadlnParam = newExpNode(IdK);
ReadlnParam ->type = Integer;
ReadlnParam ->attr.paramkind = ByRefer;
ReadlnDec = newStmtNode(CallK);
ReadlnDec ->child[0]=ReadlnParam;
ReadlnDec ->name = (char *)malloc(8);
strcpy(ReadlnDec->name,"_readln");
}
t->child[2] = ReadlnDec;
}
}else if (!strcmp(t->name,"writeln")){
TreeNode * realp = t->child[0];
if (realp->type != Integer)
printError(realp,type_mismatch);
else if (realp->sibling)
printError(t,param_num_err);
else {
WritelnUsed = TRUE;
if(!WritelnParam) {
WritelnParam = newExpNode(IdK);
WritelnParam ->type = Integer;
WritelnParam ->attr.paramkind = ByVal;
WritelnDec = newStmtNode(CallK);
WritelnDec ->child[0] = WritelnParam;
WritelnDec ->name = (char *)malloc(12);
strcpy(WritelnDec->name,"_writeln");
}
t->child[2] = WritelnDec;
}
}else{
tree = lookUpPro(t->name);
if(tree==NULL) printError(t , undec_id);
else{
TreeNode * formp; //形参,
TreeNode * realp; //实参
t->type = tree->type;
for (formp = tree->child[0],realp = t->child[0];
formp != NULL && realp != NULL;
formp = formp->sibling, realp = realp->sibling){
if (formp->type != realp->type && !(formp->type==Real && realp->type==Integer))
printError( realp , type_mismatch);
else if(formp->attr.paramkind == ByRefer && realp->kind.exp!=IdK)
printError(realp , param_must_be_id);
}
if (formp != NULL || realp != NULL)
printError( t , param_num_err);
t->child[2] = tree; //指向声明节点
}
}
break;
case AssignK:
if (t->child[0]->type != t->child[1]->type) {
if (t->child[0]->type == Real && t->child[1]->type == Integer)
t->type = t->child[1]->type = Real;
else
printError( t,type_mismatch);
}
if( t->child[0]->kind.stmt == CallK){ //由于是先Check child[0],故可能为CallK
if (strcmp(t->child[0]->name,currentPro->name) == 0) //判断是否为返回语句
t->kind.stmt = ReturnK; //赋值语句转为返回语句
else printError( t->child[0],undec_id);
}
break;
}
if(t->sibling) errorCheck(t->sibling);
break;
case Exp:
switch (t->kind.exp)
{
case OpK:
errorCheck(t->child[0]);
errorCheck(t->child[1]);
switch(t->attr.op) {
case PLUS: case MINUS: case TIMES: case OVER: case MOD: case DIV:
if ((t->child[0]->type != Integer && t->child[0]->type != Real) ||
(t->child[1]->type != Integer && t->child[1]->type != Real))
printError(t, type_mismatch);
else if (t->child[0]->type == Real || t->child[1]->type == Real)
t->type = Real;
else if (t->attr.op == OVER) t->type = Real;
else t->type = Integer;
break;
case EQ: case NE:
if(t->child[0]->type == Boolean && t->child[1]->type == Boolean){
t->type = Boolean;
break;
}
case LT: case LE: case GT: case GE:
if ((t->child[0]->type != Integer && t->child[0]->type != Real) ||
(t->child[1]->type != Integer && t->child[1]->type != Real))
printError(t, type_mismatch);
else
t->type = Boolean;
break;
case AND: case OR:
if ((t->child[0]->type != Boolean) ||( t->child[1]->type != Boolean))
printError(t, type_mismatch);
else
t->type = Boolean;
break;
case NOT:
if (t->child[0]->type != Boolean)
printError(t, op_err);
else
t->type = Boolean;
break;
}
break;
case SignK:
errorCheck(t->child[0]);
if(t->child[0]->kind.exp==NumK){
t->kind.exp =NumK;
t->attr.intval = -(t->child[0]->attr.intval);
t->type = Integer;
t->child[0] = NULL;
}else if( t->child[0]->kind.exp==RealNumK ){
t->kind.exp =RealNumK;
t->attr.realval = -(t->child[0]->attr.realval);
t->type = Real;
t->child[0] = NULL;
}else if(t->child[0]->type != Integer && t->child[0]->type != Real)
printError(t, op_err);
else t->type = t->child[0]->type;
break;
case IdK:
tree = lookUpVar(t->name);
if(tree!=NULL) {
if(tree->type==Array){
if(!t->child[0]) {
printError(t , array_index_err);
break;
}
errorCheck(t->child[0]);
if(t->child[0]->kind.exp == NumK){ //检查数组上下界
int i = t->child[0]->attr.intval;
if(i < tree->attr.arrayattr->low || i > tree->attr.arrayattr->high)
printError(t,array_overflow);
}
else if(t->child[0]->type!=Integer)
printError(t , array_index_err);
t->kind.exp = ArrayK; //转为ArrayK
t->type = tree->attr.arrayattr->type;
t->attr.arrayattr = tree->attr.arrayattr;
}
else t->type=tree->type;
}else{
tree = lookUpPro(t->name); //检查是否为函数调用(这时只有函数没有括号)或返回赋值
if(tree!=NULL && tree->type!=Void) {
t->nodekind = Stmt;
t->kind.stmt = CallK;
t->type = tree->type;
}
}
if (tree == NULL)
printError(t , undec_id);
else t->child[2] = tree; //指向声明节点
break;
}
if (t->sibling) errorCheck(t->sibling); //若该节点为参数时有兄弟节点
break;
}
}