⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 analyze.c

📁 小型编译器,可以用于测试使用
💻 C
字号:
/****************************************************/
/* File: analyze.c                                  */
/* Semantic analyzer implementation                 */
/* for the TINY compiler                            */
/* Compiler Construction: Principles and Practice   */
/* Kenneth C. Louden                                */
/****************************************************/

#include "globals.h"
#include "symtab.h"
#include "analyze.h"

/* counter for variable memory locations */
//static int location = 0;	修改后此变量移至parse.c

/* Procedure traverse is a generic recursive 
 * syntax tree traversal routine:
 * it applies preProc in preorder and postProc 
 * in postorder to tree pointed to by t
 */
static void traverse( TreeNode * t,
               void (* preProc) (TreeNode *),
               void (* postProc) (TreeNode *) )
{ if (t != NULL)
  { preProc(t);
    { int i;
      for (i=0; i < MAXCHILDREN; i++)
        traverse(t->child[i],preProc,postProc);
    }
    postProc(t);
    traverse(t->sibling,preProc,postProc);
  }
}

/* nullProc is a do-nothing procedure to 
 * generate preorder-only or postorder-only
 * traversals from traverse
 */
static void nullProc(TreeNode * t)
{ if (t==NULL) return;
  else 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)
          // not yet in table, so treat as new definition
            symtabError(t->lineno,"undeclared identifier");
          else
          // already in table, so ignore location, add line number of use only
            st_addline(t->attr.name,t->lineno);
          break;
        default:
          break;
      }
      break;
    case ExpK:
      switch (t->kind.exp)
      { case IdK:
          if (st_lookup(t->attr.name) == -1)
          // not yet in table, so treat as new definition
            symtabError(t->lineno,"undeclared identifier");
          else
          // already in table, so ignore location, add line number of use only
            st_addline(t->attr.name,t->lineno);
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
}

//修改
/* Function checkSymtab constructs the symbol 
 * table by preorder traversal of the syntax tree
 */
void checkSymtab(TreeNode * syntaxTree)
{ traverse(syntaxTree,insertNode,nullProc);
  if (TraceAnalyze)
  { fprintf(listing,"\nSymbol table:\n\n");
    printSymTab(listing);
  }
}

static void typeError(TreeNode * t, char * message)
{ fprintf(listing,"Type error at line %d: %s\n",t->lineno,message);
  Error = TRUE;
}

/* Procedure checkNode performs
 * type checking at a single tree node
 */
static void checkNode(TreeNode * t)			//修改
{
	switch (t->nodekind)
	{
	case ExpK:
		switch (t->kind.exp)
		{
		case OpK:
			if (t->attr.op == NOT && t->child[0]->type != Boolean)
				typeError(t,"\'not\' operator needs a boolean expression");
			else if(t->attr.op != NOT && t->child[0]->type != t->child[1]->type)
				typeError(t,"the types of operands are not equal");
			if (t->attr.op == EQ || t->attr.op == LT || t->attr.op == LE || t->attr.op == GT || t->attr.op == GE)
				t->type = Boolean;
			else if(t->attr.op == AND || t->attr.op == OR || t->attr.op == NOT)
				t->type = Boolean;
			else
				t->type = Integer;
			break;
		case ConstK:
			t->type = Integer;
			break;
		case IdK:
			t->type = st_gettype(t->attr.name);
			break;
		case StrK:
			t->type = String;
			break;
		case BoolK:
			t->type = Boolean;
			break;
        default:
          break;
		}
		break;
	case StmtK:
		switch (t->kind.stmt)
		{ 
		case IfK:
          if (t->child[0]->type != Boolean)		//修改
            typeError(t->child[0],"if test is not Boolean");
          break;
        case AssignK:
			t->type = st_gettype(t->attr.name);		//增加
          if (t->child[0]->type != t->type)		//修改
            typeError(t->child[0],"assignment of a different type value");
          break;
		case ReadK:		//增加
			t->type = st_gettype(t->attr.name);
			break;
        case WriteK:
          if (t->child[0]->type != Integer)
            typeError(t->child[0],"write of non-integer value");
          break;
        case RepeatK:
          if (t->child[1]->type != Boolean)
            typeError(t->child[1],"repeat test is not Boolean");
          break;
		case WhileK:
			if(t->child[0]->type != Boolean)
				typeError(t->child[0],"while test is not Boolean");
			break;
        default:
          break;
		}
		break;
    default:
		break;
	}
}

/* Procedure typeCheck performs type checking 
 * by a postorder syntax tree traversal
 */
void typeCheck(TreeNode * syntaxTree)
{ traverse(syntaxTree,nullProc,checkNode);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -