www.pudn.com > subpas.rar > util.c
/****************************************************/
/* File: util.c */
/* Utility function interface */
/* for the SubPas compiler */
/****************************************************/
#include "globals.h"
#include "util.h"
#include "parse.h"
/* 返回树节点的数据类型
* @param tree 指向该节点的指针
* @return 类型的字符表达式,如"integer","boolean","real"等
*/
char * getType(TreeNode *tree)
{
static char * datatype[] = {"integer","real","boolean","array","void","unkown type"};
if (!tree || tree->type < Integer || tree->type > Void)
return datatype[5];
return datatype[tree->type];
}
/* 在listing文件中打印出一个token的识别
* @param token 该token的类别
* @param tokenString 该token在源文件中的字符串表示
*/
void printToken(TokenType token, const char* tokenString )
{ switch (token)
{
case ARRAY:
case BOOLEAN:
case DO:
case ELSE:
case END:
case MYFALSE:
case FUNCTION:
case IF:
case INTEGER:
case MYBEGIN:
case OF:
case PROCEDURE:
case PROGRAM:
case REAL:
case THEN:
case MYTRUE:
case VAR:
case WHILE:
fprintf(listing,"reserved word: %s\n",tokenString);
break;
case PLUS: fprintf(listing,"+\n"); break;
case MINUS: fprintf(listing,"-\n"); break;
case TIMES: fprintf(listing,"*\n"); break;
case DIV: fprintf(listing,"DIV\n"); break;
case MOD: fprintf(listing,"MOD\n");break;
case LT: fprintf(listing,"<\n"); break;
case LE: fprintf(listing,"<=\n"); break;
case GT: fprintf(listing,">\n"); break;
case GE: fprintf(listing,">=\n"); break;
case EQ: fprintf(listing,"=\n"); break;
case NE: fprintf(listing,"<>\n"); break;
case AND: fprintf(listing,"and\n"); break;
case OR: fprintf(listing,"or\n"); break;
case NOT: fprintf(listing,"not\n"); break;
case ASSIGNOP: fprintf(listing,":=\n"); break;
case LP: fprintf(listing,"(\n"); break;
case RP: fprintf(listing,")\n"); break;
case LSP: fprintf(listing,"[\n"); break;
case RSP: fprintf(listing,"]\n"); break;
case SEMI: fprintf(listing,";\n"); break;
case COMMA: fprintf(listing,",\n"); break;
case COLON: fprintf(listing,":\n"); break;
case DOT: fprintf(listing,".\n"); break;
case NUM: fprintf(listing,"NUM, val= %s\n",tokenString); break;
case REALNUM:fprintf(listing,"REALNUM,val=%s\n",tokenString);break;
case ID: fprintf(listing,"ID, name= %s\n",tokenString); break;
case ERROR:fprintf(listing,"ERROR: %s\n",tokenString); break;
case 0: fprintf(listing,"End of file.\n");break;
default: /* should never happen */
fprintf(listing,"Unknown token: %d\n",token);
}
}
/* 建立一个过程的节点
* @param kind 过程的小类别:MainP或SubP
* @return 指向该节点的指针
*/
TreeNode * newProNode(ProKind kind)
{
TreeNode * t = (TreeNode *) malloc(sizeof(TreeNode));
int i;
if (t==NULL)
fprintf(listing,"Out of memory error at line %d\n",lineno);
else {
for (i=0;ichild[i] = NULL;
t->sibling = NULL;
t->nodekind = Pro;
t->lineno = lineno;
t->kind.pro = kind;
t->offset = 0;
t->name = NULL;
}
return t;
}
/* 建立一个语句的节点
* @param kind 语句的小类别,IfK,WhileK,AssignK等
* @return 指向该节点的指针
*/
TreeNode * newStmtNode(StmtKind kind)
{ TreeNode * t = (TreeNode *) malloc(sizeof(TreeNode));
int i;
if (t==NULL)
fprintf(listing,"Out of memory error at line %d\n",lineno);
else {
for (i=0;ichild[i] = NULL;
t->sibling = NULL;
t->nodekind = Stmt;
t->lineno = lineno;
t->kind.stmt = kind;
t->offset = 0;
t->name = NULL;
t->ltrue = NULL;
t->lfalse = NULL;
}
return t;
}
/* 建立一个表达式的节点
* @param kind 表达式的小类别:OpK,IdK,NumK等
* @return 指向该节点的指针
*/
TreeNode * newExpNode(ExpKind kind)
{ TreeNode * t = (TreeNode *) malloc(sizeof(TreeNode));
int i;
if (t==NULL)
fprintf(listing,"Out of memory error at line %d\n",lineno);
else {
for (i=0;ichild[i] = NULL;
t->sibling = NULL;
t->nodekind = Exp;
t->lineno = lineno;
t->kind.exp = kind;
t->offset = 0;
t->name = NULL;
t->ltrue = NULL;
t->lfalse = NULL;
}
return t;
}
/* 分配相应空间,将一个字符串复制到该空间中,再返回
* 复制后的字符串指针
* @param s 要复制的字符串
* @return 指向新空间的字符串指针
*/
char * copyString(char * s)
{ size_t n;
char * t;
if (s==NULL) return NULL;
n = strlen(s)+1;
t = malloc(n);
if (t==NULL)
fprintf(listing,"Out of memory error at line %d\n",lineno);
else strcpy(t,s);
return t;
}
/* 用一个链表来模拟堆栈*/
typedef struct savedFunName{
char * name;
struct savedFunName * next;
} SavedFunName;
/* savedfunname是一个链表,用于保存函数的名字*/
static SavedFunName * savedfunname = NULL;
/* 将一个字符串指针压入栈
* @param name 要入栈的字符串指针
*/
void pushName(char * name)
{
SavedFunName * temp = (SavedFunName *)malloc(sizeof(SavedFunName));
temp->name = name;
temp->next = savedfunname;
savedfunname = temp;
}
/* 将栈顶的字符串指针出栈
* @return 指向出栈后的字符串指针
*/
char * popName(void)
{
char * name;
SavedFunName * temp = savedfunname;
savedfunname = savedfunname->next;
name = temp->name;
free(temp);
return name;
}
/* 变量indentno用来格式化打印语法树(主要是tab缩进表示)
*/
static int indentno = 0;
/* macros to increase/decrease indentation */
#define INDENT indentno++
#define UNDENT indentno--
/* 打印indentno个tab */
static void printTab(void)
{ int i;
for (i=0;inodekind) {
case Pro:
switch(tree ->kind.pro){
case MainP:
if (tree->child[1]){
fprintf(listing,"\n\nPROGRAM NAME:%s\n",tree->name);
fprintf(listing,"*****************Print Tree Start:********************\n");
fprintf(listing,"Global Declarations:\n");
t = tree->child[1];
while(t){
fprintf(listing,"\tname:%s\ttype:%s \n",t->name,getType(t));
t=t->sibling;
}
}
printTree(tree->sibling);
INDENT;printTree(tree->child[2]);UNDENT;
fprintf(listing,"*****************Print Tree Ends.*********************\n\n");
break;
case SubP:
fprintf(listing,"==================================\n");
if(tree->type==Void)
fprintf(listing,"Procedure name: %s\n ",tree->name);
else fprintf(listing,"Function name:%s\n",tree->name);
fprintf(listing,"\tParameters:\n");
t = tree->child[0];
if(t==NULL) fprintf(listing,"\t\tNone.\n");
else while(t){
fprintf(listing,"\t\tname:%s\ttype:%s\n",t->name,getType(t));
t=t->sibling;
}
if(tree->type !=Void)
fprintf(listing,"\treturn type:%s\n",getType(tree));
fprintf(listing,"\tLocal Declarations:\n");
t = tree->child[1];
if(t==NULL) fprintf(listing,"\t\tNone.\n");
else while(t){
fprintf(listing,"\t\tname:%s\ttype:%s\n",t->name,getType(t));
t=t->sibling;
}
INDENT;printTree(tree->child[2]); UNDENT;
fprintf(listing,"=================================\n");
printTree(tree->sibling);
break;
}
break;
case Stmt:
switch(tree ->kind.stmt){
case IfK:
printTab();fprintf(listing,"If-statement:\n");
printTab();fprintf(listing,"\tcondition:\n");
INDENT;printTree(tree->child[0]);UNDENT;
printTab();fprintf(listing,"\n\t\ttrue:\n");
INDENT;printTree(tree->child[1]);UNDENT;
printTab();fprintf(listing,"\n\t\tfalse:\n");
INDENT;printTree(tree->child[2]);UNDENT;
printTab();fprintf(listing,"If-statement ends.\n");
break;
case WhileK:
printTab();fprintf(listing,"While-statement:\n");
printTab();fprintf(listing,"\tcondition:\n");
INDENT;printTree(tree->child[0]);UNDENT;
printTab();fprintf(listing,"\tloop:\n");
INDENT;printTree(tree->child[1]);UNDENT;
printTab();fprintf(listing,"While-statement ends.\n");
break;
case AssignK:
printTab();fprintf(listing,"Assign-statement:\n");
printTab();fprintf(listing,"\t%s assigned to\n",tree->child[0]->name);
INDENT;printTree(tree->child[1]);UNDENT;
printTab();fprintf(listing,"Assign-statement ends.\n");
break;
case CallK:
printTab();fprintf(listing,"Call-statement:\n");
printTab();fprintf(listing,"\tCalls:%s\n",tree ->name);
printTab();fprintf(listing,"\tparams:\n");
t = tree->child[0];
if(t==NULL){printTab();fprintf(listing,"\t\tNone.\n");}
else {INDENT;printTree(t);UNDENT;}
printTab();fprintf(listing,"Call-statement ends.\n");
break;
}
printTree(tree->sibling);
break;
case Exp:
switch(tree->kind.exp){
case NumK:
printTab();fprintf(listing,"Num_Const: %d\n",tree->attr.intval);
break;
case RealNumK:
printTab();fprintf(listing,"Real_Const: %f\n",tree->attr.realval);
break;
case BoolK:
printTab();
if(tree->attr.intval==0) fprintf(listing,"BoolValue:false\n");
else fprintf(listing,"BoolValue:true\n");
break;
case IdK:
printTab();fprintf(listing,"Variable: %s\n",tree->name);
break;
case SignK:
printTab();
if(tree->attr.op==MINUS)
fprintf(listing,"-(inverse):\n");
INDENT;printTree(tree->child[0]);UNDENT;
break;
default:
printTab();fprintf(listing,"Op: ");
printToken(tree->attr.op,"\0");
INDENT;printTree(tree->child[0]);UNDENT;
INDENT;printTree(tree->child[1]);UNDENT;
break;
}
printTree(tree->sibling);
break;
default:
printTab();fprintf(listing,"Unknown treenode kind!\n");
break;
}
}
}