Tiny语言的语义分析非常简单,第一步先遍历语法树建立符号表,但是这个符号表本身并没有太大的用处,只是为变量分配了内存的地址,为代码生成做准备;第二步是类型检查,主要对if语句、repeat语句的条件进行检查,必须是Boolean类型的,另外有些表达式要求是Integer类型,类型检查采用后序遍历的方式。语义分析的源代码如下:
#include "globals.h"
#include "symtab.h"
#include "analyze.h"
typedef void (*traverseFunc)(TreeNode*);
//变量的内存地址
static int location = 0;
//遍历函数
static void traverse(TreeNode*t,traverseFunc preProc,traverseFunc postProc)
{
int i;
if(t!=NULL)
{
preProc(t);
for( i=0; i< MAXCHILDREN; i++)
traverse(t->child[i], preProc, postProc);
postProc(t);
traverse(t->sibling, preProc, postProc);
}
}
//空遍历函数
static void nullProc(TreeNode* t)
{
return;
}
//根据节点类型,建立符号表
static void insertNode(TreeNode* t)
{
switch(t->nodekind)
{
case Stmtk:
switch(t->kind.stmt)
{
case AssignK:
case ReadK:
if(st_lookup(t->attr.name)==-1)
st_insert(t->attr.name, t->lineno, location++);
else
st_insert(t->attr.name, t->lineno, 0);
break;
default:
break;
}
break;
case ExpK:
switch(t->kind.exp)
{
case IdK:
if(st_lookup(t->attr.name)==-1)
st_insert(t->attr.name, t->lineno, location++);
else
st_insert(t->attr.name, t->lineno, 0);
break;
default:
break;
}
break;
default:
break;
}
}
static void typeError(TreeNode* t, char* message)
{
fprintf(listing, "Type error at line %d: %s\n", t->lineno, message);
Error = TRUE;
}
//根据节点类型进行类型检查
static void checkNode(TreeNode* t)
{
switch(t->nodekind)
{
case Stmtk:
switch(t->kind.stmt)
{
case IfK: //if语句条件必须是Boolean类型
if(t->child[0]->type==Integer)
typeError(t->child[0], "if test is not Boolean");
break;
case AssignK:
if(t->child[0]->type!=Integer)
typeError(t->child[0], "assignment of non-integer value");
break;
//不用对Read语句进行类型检查了,因为语法分析已经保证了这一点
case WriteK:
if(t->child[0]->type!=Integer)
typeError(t->child[0], "write of non-integer value");
break;
case RepeatK: //if语句条件必须是Boolean类型
if(t->child[1]->type==Integer)
typeError(t->child[1], "repeat test is not Boolean");
break;
default:
break;
}
break;
case ExpK:
switch(t->kind.exp)
{
case opK:
if((t->child[0]->type!=Integer) || (t->child[1]->type!=Integer))
typeError(t, "Op applied to non-integer");
if((t->attr.op==EQ)||(t->attr.op==LT))
t->type=Boolean;
else
t->type=Integer;
break;
case ConstK:
case IdK:
t->type = Integer;
break;
default:
break;
}
break;
default:
break;
}
}
//遍历语法树,创建符号表
void buildSymtab(TreeNode* syntaxTree)
{
traverse(syntaxTree, insertNode, nullProc);
printSymTab(listing);
}
//遍历语法树,进行类型检查
void typeCheck(TreeNode* syntaxTree)
{
traverse(syntaxTree, nullProc, checkNode);
}