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

📄 analyze.c

📁 SIP软件开发记录 由于通信网的封闭性
💻 C
字号:
/* analyze.c
 * Semantic analyzer implementation for TINY compiler
 *
 * Compiler Construction: Principles and Practice
 * Kenneth C. Louden
 * 编译原理及实践
 * (美) Kenneth C. Louden 著
 * 冯博琴 冯岚 等译
 * 机械工业出版社 IBSN 7-111-07703-2
 * 源代码:zwf编辑并修订
 * 
 */
#include "globals.h"
#include "symtab.h"
#include "analyze.h"

/* counter for variable memory location */
static int location = 0;

/* Procedure traverse is a generic recursive
 * syntax tree traversal rountine:
 * 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;
}

/* Procedure insertNode inserts
 * identifiers stores in t into
 * the symbol table
 */
static void insertNode(TreeNode * t)
{
	switch (t->nodekind) {
	case StmtK:
		switch (t->kind.stmt) {
		case AssignK:
		case ReadK:
			/* not yet in table, so treat as new definition */
			if (st_lookup(t->attr.name) == -1)
				st_insert(t->attr.name, t->lineno, location++);
			else
				/* alraedy in table, so ignore location,
				 * add line number of use only
				 */
				st_insert(t->attr.name, t->lineno, 0);
			break;
		default:
			break;
		}
		break;
	case ExpK:
		switch (t->kind.exp) {
		case IdK:
			/* not yet in table, so treat as new definition */
			if (st_lookup(t->attr.name) == -1)
				st_insert(t->attr.name, t->lineno, location++);
			else
				/* already in table, so ignore location,
				 * add line number of use only
				 */
				st_insert(t->attr.name, t->lineno, 0);
			break;
		default:
			break;
		}
		break;
	}
}

/* Function buildSymtab constructs the symbol
 * table by preorder traversal of the syntax tree
 */
void buildSymtab(TreeNode * syntaxTree)
{
	traverse(syntaxTree, insertNode, nullProc);
	if (TraceAnalyze) {
#ifdef CHINESE
		fprintf(listing, "\n符号表:\n\n");
#else
		fprintf(listing, "\nSymbol table:\n\n");
#endif
		printSymTab(listing);
	}
}

static void typeError(TreeNode * t, char *msg)
{
#ifdef CHINESE
	fprintf(listing, "类型错误, %d 行: %s\n", t->lineno, msg);
#else
	fprintf(listing, "Type error at line %d: %s\n", t->lineno, msg);
#endif
	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->child[0]->type != Integer)
				|| (t->child[1]->type != Integer))
#ifdef CHINESE
				typeError(t, "操作符未使用整数变量");
#else
				typeError(t, "Op applied to non-integer");
#endif
			if ((t->attr.op == EQ) || (t->attr.op == LT)
				|| (t->attr.op == GT)
				|| (t->attr.op == NE) || (t->attr.op == LE)
				|| (t->attr.op == GE))
				t->type = Boolean;
			else
				t->type = Integer;
			break;
		case ConstK:
		case IdK:
			t->type = Integer;
			break;
		default:
			break;
		}
		break;
	case StmtK:
		switch (t->kind.stmt) {
		case IfK:
			if (t->child[0]->type != Boolean)
#ifdef CHINESE
				typeError(t->child[0], "如果判断语句未使用布尔变量");
#else
				typeError(t->child[0], "if test is not Boolean");
#endif
			break;
		case AssignK:
			if (t->child[0]->type != Integer)
#ifdef CHINESE
				typeError(t->child[0], "赋值语句未使用整数变量");
#else
				typeError(t->child[0], "assignment of non-integer value");
#endif
			break;
		case WriteK:
			if (t->child[0]->type != Integer)
#ifdef CHINESE
				typeError(t->child[0], "输出语句未使用整数变量");
#else
				typeError(t->child[0], "write of non-integer vlue");
#endif
			break;
		case RepeatK:
			if (t->child[1]->type != Boolean)
#ifdef CHINESE
				typeError(t->child[0], "循环判断语句未使用布尔变量");
#else
				typeError(t->child[0], "repeat test is not Boolean");
#endif
			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 + -