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

📄 cgen.c

📁 一个编译器的实现
💻 C
字号:

#include "globals.h"
#include "symtab.h"
#include "code.h"
#include "cgen.h"



/* prototype for internal recursive code generator */
static void cGen (TreeNode * tree, int isAddr, char * label);

/* Procedure genStmt generates code at a statement node */
static void genStmt( TreeNode * t, char * label)
{
	char codestr[CODESIZE];
	char * lab1, * lab2;
    TreeNode * temp;
	switch(t->kind.stmt){
	case ExK:
		cGen(t->child[0],0,label);
		break;
	case IfK:
		cGen(t->child[0],0,label);
		lab1 = genLabel();
		sprintf(codestr,"%s %s","fjp",lab1);
		emitCode(codestr);
		cGen(t->child[1],0,label);
		if(t->child[2] != NULL)
		{
			lab2 = genLabel();
			sprintf(codestr,"%s %s" ,"ujp" ,lab2);
			emitCode(codestr);
		}
		sprintf(codestr,"%s %s", "lab",lab1);
		emitCode(codestr);
		if(t->child[2]!=NULL)
		{
			cGen(t->child[2],0,label);
			sprintf(codestr,"%s %s","lab",lab2);
			emitCode(codestr);
		}
		break;
	case WhileK:
		lab1 = genLabel();
		sprintf(codestr,"%s %s", "lab",lab1);
		emitCode(codestr);
		cGen(t->child[0],0,label);
		lab2 = genLabel();
		sprintf(codestr,"%s %s","fjp",lab2);
		emitCode(codestr);
		cGen(t->child[1],0,lab2);
		sprintf(codestr,"%s %s" ,"ujp" ,lab1);
		emitCode(codestr);
		sprintf(codestr,"%s %s","lab",lab2);
		emitCode(codestr);
		break;
	case BreakK:
		sprintf(codestr,"%s %s","ujp",label);
		emitCode(codestr);
		break;
	case DeclK:
		temp=t->child[1];
		while(temp!=NULL){
			if(temp->type==Integer){
				if(temp->kind.exp==IdK){
					emitComment("define integer");
					sprintf(codestr,"%s di ?",temp->attr.name);
					emitCode(codestr);
				}
				else{
					emitComment("define integer array");
					sprintf(codestr,"%s di %d dup(?)",temp->attr.name,temp->child[0]->attr.val.i); 
					emitCode(codestr);
			
				}
			}
			else if(temp->type==Float) {
				if(temp->kind.exp==IdK){
					emitComment("define float");
					sprintf(codestr,"%s df ?",temp->attr.name);
					emitCode(codestr);
				}
				else{
					emitComment("define float array");
					sprintf(codestr,"%s df %d dup(?)",temp->attr.name,temp->child[0]->attr.val.i); 
					emitCode(codestr);
			
				}
			}
			else {
				if(temp->kind.exp==IdK){
					emitComment("define char");
					sprintf(codestr,"%s dc ?",temp->attr.name);
					emitCode(codestr);
				}
				else{
					emitComment("define char array");
					sprintf(codestr,"%s dc %d dup(?)",temp->attr.name,temp->child[0]->attr.val.i); 
					emitCode(codestr);
			
				}
			}

			temp=temp->sibling;
		}
		break;
	default:
		emitCode("Error");
		break;
	}
} /* genStmt */

/* Procedure genExp generates code at an expression node */
static void genExp( TreeNode * t, int isAddr)
{ 
	char codestr[CODESIZE];
	switch(t->kind.exp){
	case OpK:
		switch(t->attr.op){
		case PLUS:
			if(isAddr) emitCode("Error");
			else{
				cGen(t->child[0],FALSE,NULL);
				cGen(t->child[1],FALSE,NULL);
				if(t->type==Integer)
					emitCode("addi");
				else
                    emitCode("addf");
			}
			break;
		case MINUS:
			if(isAddr) emitCode("Error");
			else{
				cGen(t->child[0],FALSE,NULL);
				cGen(t->child[1],FALSE,NULL);
				if(t->type==Integer)
					emitCode("subi");
				else
                    emitCode("subf");
			}
			break;
		case TIMES:
			if(isAddr) emitCode("Error");
			else{
				cGen(t->child[0],FALSE,NULL);
				cGen(t->child[1],FALSE,NULL);
				if(t->type==Integer)
					emitCode("muli");
				else
                    emitCode("mulf");
			}
			break;
		case OVER:
			if(isAddr) emitCode("Error");
			else{
				cGen(t->child[0],FALSE,NULL);
				cGen(t->child[1],FALSE,NULL);
				if(t->type==Integer)
					emitCode("divi");
				else
                    emitCode("divf");
			}
			break;
		case AND:
			if(isAddr) emitCode("Error");
			else{
				cGen(t->child[0],FALSE,NULL);
				cGen(t->child[1],FALSE,NULL);
				emitCode("and");
			}
			break;
		case OR:
			if(isAddr) emitCode("Error");
			else{
				cGen(t->child[0],FALSE,NULL);
				cGen(t->child[1],FALSE,NULL);
				emitCode("or");
			}
			break;
		case EQ:
			if(isAddr) emitCode("Error");
			else{
				cGen(t->child[0],FALSE,NULL);
				cGen(t->child[1],FALSE,NULL);
				emitCode("eq");
			}
			break;
		case NE:
			if(isAddr) emitCode("Error");
			else{
				cGen(t->child[0],FALSE,NULL);
				cGen(t->child[1],FALSE,NULL);
				emitCode("ne");
			}
			break;
		case LT:
			if(isAddr) emitCode("Error");
			else{
				cGen(t->child[0],FALSE,NULL);
				cGen(t->child[1],FALSE,NULL);
				emitCode("lt");
			}
			break;
		case MT:
			if(isAddr) emitCode("Error");
			else{
				cGen(t->child[0],FALSE,NULL);
				cGen(t->child[1],FALSE,NULL);
				emitCode("mt");
			}
			break;
		case LE:
			if(isAddr) emitCode("Error");
			else{
				cGen(t->child[0],FALSE,NULL);
				cGen(t->child[1],FALSE,NULL);
				emitCode("le");
			}
			break;
		case ME:
			if(isAddr) emitCode("Error");
			else{
				cGen(t->child[0],FALSE,NULL);
				cGen(t->child[1],FALSE,NULL);
				emitCode("me");
			}
			break;
		case NOT:
			if(isAddr) emitCode("Error");
			else{
				cGen(t->child[0],FALSE,NULL);
				emitCode("not");
			}
			break;
		default:
			emitCode("error");
			break;
		}
		break;
	case IK:
		if(isAddr) emitCode("error");
		else{
			sprintf(codestr,"%s %d","ldci",t->attr.val.i);
			emitCode(codestr);
		}
		break;
	case FK:
		if(isAddr) emitCode("error");
		else{
			sprintf(codestr,"%s %f","ldcf",t->attr.val.f);
			emitCode(codestr);
		}
		break;
	case CK:
		if(isAddr) emitCode("error");
		else{
			sprintf(codestr,"%s %c","ldcc",t->attr.val.c);
			emitCode(codestr);
		}
		break;
	case IdK:
		if(isAddr)
			sprintf(codestr,"%s %s","lda",t->attr.name);
		else{
			if(t->type==Integer)
				sprintf(codestr,"%s %s","lodi",t->attr.name);
			else if(t->type==Float)
				sprintf(codestr,"%s %s","lodf",t->attr.name);
			else
                sprintf(codestr,"%s %s","lodc",t->attr.name);
		}
		emitCode(codestr);
		break;
	case ArrK:
		sprintf(codestr,"%s %s","lda",t->attr.name);
		emitCode(codestr);
		cGen(t->child[0],FALSE,NULL);
		if(t->type==Integer)
			sprintf(codestr,"%s %d","ixa",sizeof(int));
		else if(t->type==Float)
			sprintf(codestr,"%s %d","ixa",sizeof(float));
		else 
			sprintf(codestr,"%s %d","ixa",sizeof(char));
		emitCode(codestr);
		if(!isAddr) emitCode("ind 0");
        break;
	case AssignK:
		cGen(t->child[0],TRUE,NULL);
		cGen(t->child[1],FALSE,NULL);
		emitCode("stn");
		break;
	default:
		emitCode("error");
		break;
	}

} /* gen*/

/* Procedure cGen recursively generates code by
 * tree traversal
 */
static void cGen( TreeNode * tree, int isAddr, char * label)
{ if (tree != NULL)
  { switch (tree->nodekind) {
      case StmtK:
        genStmt(tree,label);
        break;
      case ExpK:
        genExp(tree,isAddr);
        break;
      default:
        break;
    }
  
	cGen(tree->sibling,isAddr,label);
  }
}

/**********************************************/
/* the primary function of the code generator */
/**********************************************/
/* Procedure codeGen generates code to a code
 * file by traversal of the syntax tree. The
 * second parameter (codefile) is the file name
 * of the code file, and is used to print the
 * file name as a comment in the code file
 */
void codeGen(TreeNode * syntaxTree, char * codefile)
{  char * s = malloc(strlen(codefile)+7);
   strcpy(s,"File: ");
   strcat(s,codefile);
   emitComment("C Compilation to P-Code");
   emitComment(s);
   /* generate standard prelude */
   /* generate code for TINY program */
   cGen(syntaxTree, FALSE, NULL);
   /* finish */
   emitComment("End of execution.");
   emitCode("ret");
   
}

⌨️ 快捷键说明

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