Tiny语言编译器之语义分析

来源:互联网 发布:linux压缩文件命令 zip 编辑:程序博客网 时间:2024/05/17 03:30

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);
        fori=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, charmessage)
{
    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);
}

0 0