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

📄 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"

static void typeError(TreeNode * t, char * message);
/* counter for variable memory locations */
static int location = 0;

/* 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);
  }
}

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

/* 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 stored in t into 
 * the symbol table 
 */
static void insertNode( TreeNode * t)
{ 
	TreeNode*s=NULL;
	switch (t->nodekind)
	{ 
	case StmtK:
		switch (t->kind.stmt)
		{ 
		case IntK:
		case BoolK:
		case StringK:
			if(st_lookup(t->child[0]->attr.name) == -1)
				st_insertd(t->child[0]->attr.name,location++,t->type);
			else
				defineError(t->child[0],"Identifier redefined!");
			for(s=t->child[0]->sibling;s!=NULL;s=s->sibling)
			{
				if(st_lookup(s->attr.name)==-1)
					st_insertd(s->attr.name,location++,t->type);
				else
					defineError(s,"Identifier redefined!");
			}
			break;
		case AssignK:
        case ReadK:
			if (st_lookup(t->attr.name) == -1)
				defineError(t,"Identifier undefined!");
			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)
				defineError(t,"Identifier undefined!");
			else
				st_insert(t->attr.name,t->lineno,0);
			break;
		default:
			break;
		}
		break;
	default:
		break;
	}
}

/* Function buildSymtab constructs the symbol 
 * table by preorder traversal of the syntax tree
 */
void buildSymtab(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->child[0]!=NULL&&t->child[1]!=NULL)
			{
				if (t->child[0]->type != t->child[1]->type)
					typeError(t,"Types are not the same!");
			}
			if ((t->attr.op == EQ) || (t->attr.op == LT) || (t->attr.op == GT) 
				|| (t->attr.op == NGT) || (t->attr.op == NLT) || (t->attr.op == NOT)
				|| (t->attr.op == AND) || (t->attr.op == OR))
				t->type = Boolean;
			else
				t->type = Integer;
			break;
        case ConstK:
			t->type = Integer;
			break;
        case IdK:
			t->type = getType(t->attr.name);
			break;
		case StrK:
			t->type = String;
			break;
		case BK:
			t->type = Boolean;
			break;
        default:
			break;
		}
		break;
    case StmtK:
		switch (t->kind.stmt)
		{ 
		case ReadK:
			t->type = getType(t->attr.name);
			if (t->type != Integer&&t->type != String&&t->type != Boolean)
				typeError(t,"read of ID of illegal type!");
			break;
		case WhileK:
			if (t->child[1]->type != Boolean)
				typeError(t->child[1],"while test is not Boolean");
			break;
		case IfK:
			if (t->child[0]->type != Boolean)
				typeError(t->child[0],"if test is not Boolean");
			break;
        case AssignK:
			t->type = getType(t->attr.name);
			if (t->type != Integer&&t->type != String&&t->type != Boolean)
				typeError(t,"assignment of ID of illegal type!");
			if(t->type != t->child[0]->type)
				typeError(t,"assignment of ID of different types!");
			break;
        case WriteK:
			t->type = getType(t->child[0]->attr.name);
			if (t->type != Integer&&t->type != String&&t->type != Boolean)
				typeError(t,"write of ID of illegal type!");
			break;
        case RepeatK:
			if (t->child[1]->type != Boolean)
				typeError(t->child[1],"repeat 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 + -