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

📄 util.cpp

📁 snl语言是一个简单的具有嵌套过程定义的过程式语言
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/****************************************************/
/* 文件	util.cpp									*/
/* 说明 类PASCAL语言编译器功能函数的实现			*/
/* 主题 编译器结构:原理和实例						*/
/****************************************************/

/* 头文件globals.h定义了全局类型与变量 */
#include "globals.h"

#include "stdio.h"

#include "string.h"

#include "symbTable.h"

#include "code.h"

#include "cgen.h"

int  fp_num=0;    /*输出时记录token个数的变量*/



/*****************************************************************/
/* 函数名 printTokenlist     					        		 */	
/* 功  能 将文件tokenlist中的信息作为返回值                      */							    
/*        一般,listing指向标准输出。                            */
/* 说  明 用于显示词法分析结果                                   */
/*****************************************************************/
void printTokenlist()
{
   TokenType  token;
   int m;
   
   fp=fopen("c:\\Tokenlist","rb");  /*打开文件*/
   
   if(fp==NULL)
   {
	   printf("can not open the file:Tokenlist!\n");
	   Error = TRUE;
	   //exit(0);
   }
   
   for (m=1;m<=Tokennum;m++)
   {     
	   fread(&token,TOKENLEN,1,fp);
	   
	   fprintf(listing,"\t%d: ",token.lineshow);/*打印行号*/
    
	   /* 对函数参数Lex给定单词进行分类处理 */
       switch (token.Lex)
	   { 
	    /* 单词token为保留字,将保留字词元以指定格式写入列表文件listing */
        case PROGRAM:
        case PROCEDURE:
		case TYPE:
		case VAR:
		case IF:
		case THEN:
		case ELSE:
		case FI:
		case INTEGER:
		case CHAR:
		case WHILE:
		case DO:
		case ENDWH:
		case BEGIN:
		case END:
		case READ:
		case WRITE:
		case ARRAY:
		case OF:
		case RECORD:
		case RETURN:

			fprintf(listing,     /*打印保留字*/     
                  "reserved word: %s\n",token.Sem);
            break;

	    /* 单词token为特殊符号:ASSIGN (赋值),将":="写入文件listing */
		case ASSIGN: fprintf(listing,":=\n"); break;
    
		/* 单词token为特殊符号:LT (小于),将"<"写入文件listing */
		case LT: fprintf(listing,"<\n"); break;
  
		/* 单词token为特殊符号:EQ (等于),将"="写入文件listing */
		case EQ: fprintf(listing,"=\n"); break;
    
		/* 单词token为特殊符号:LPAREN (左括号),将"("写入文件listing */
		case LPAREN: fprintf(listing,"(\n"); break;

		/* 单词token为特殊符号:RPAREN (右括号),将")"写入文件listing */
		case RPAREN: fprintf(listing,")\n"); break;
    
		/* 单词token为特殊符号:SEMI (分号),将";"写入文件listing */
		case SEMI: fprintf(listing,";\n"); break;
 
		/* 单词token为特殊符号:PLUS (加号),将"+"写入文件listing */
		case PLUS: fprintf(listing,"+\n"); break;
 
		/* 单词token为特殊符号;MINUS (减号),将"-"写入文件listing */
		case MINUS: fprintf(listing,"-\n"); break;

		/* 单词token为特殊符号:TIMES (乘号),将"*"写入文件listing */
		case TIMES: fprintf(listing,"*\n"); break;

		/* 单词token为特殊符号:OVER (除号),将"/"写入文件listing */
		case OVER: fprintf(listing,"/\n");  break;

		case DOT:  fprintf(listing,".\n"); break;

		case COMMA: fprintf(listing,",\n"); break;

		case LMIDPAREN: fprintf(listing,"[\n"); break;

		case RMIDPAREN: fprintf(listing,"]\n"); break;

		case UNDERANGE: fprintf(listing,"..\n"); break;

		/* 单词token为簿记单词符号:ENDFILE (文件结尾),将EOF写入文件listing */
		case ENDFILE: fprintf(listing,"EOF\n"); break;
    
		/* 单词token为多字符单词符号:NUM (数字),将数值写入文件listing */
		case INTC:
			fprintf(listing,
				"NUM, val= %s\n",token.Sem);
			 break;

		case CHARC:
			fprintf(listing,
				"INCHAR, char=%c\n",token.Sem);
			break;
    
		/* 单词token为多字符单词符号:ID (标识符),将标识符名写入文件listing */
		case ID:
			 fprintf(listing,
				"ID, name= %s\n",token.Sem);
			 break;

		/* 单词token为簿记单词符号:ERROR (错误),将错误信息写入文件listing */
		case ERROR:
			 fprintf(listing,
				 "ERROR: %s\n",token.Sem);
			  break;

		/* 单词token为其他未知单词,未知信息写入文件listing,此种情况不应发生 */
		 default: 
			 fprintf(listing,"Unknown token: %d\n",token.Lex);
			  break;
	  
		}
		fseek(fp,m*TOKENLEN,0);
	}	      
   fprintf(listing,"\n");
   fclose(fp);
}

/*****************************************************************/
/* 函数名 ReadNextToken							        		 */	
/* 功  能 将文件tokenlist中的信息作为返回值                      */							    
/*        一般,listing指向标准输出。                            */
/* 说  明 返回值为TokenType类型,用于语法分析中                  */
/*****************************************************************/
void ReadNextToken(TokenType *p)
{
	FILE *fp2;
   /*按只读方式打开文件*/
   fp2=fopen("c:\\Tokenlist","rb");
   if (fp==NULL)   
         {  
			printf("cannot create file Tokenlist!\n");
			Error = TRUE;
            //exit(0);
	     }  
   fseek(fp2,fp_num*sizeof(TokenType),0);
   fread(p,sizeof(TokenType),1,fp2);
   fp_num++;
   fclose(fp2);
}

/********************************************************/
/* 函数名 copyString									*/
/* 功  能 字符串复制函数								*/
/* 说  明 该函数为已存在的字串分配内存单元,并将其复制	*/
/********************************************************/
char * copyString(char * s)

{ int n;
  char * t;

  /* 函数参数s所给字串为NULL(空), 函数返回NULL */
  if (s==NULL) return NULL;

  /* 函数参数s所给字串非空,计算字串s长度+1赋给临时变量n */
  n = strlen(s)+1;

  /* 动态分配内存单元,指定单元长度为n,t为指向该单元的指针 */
  t = (char *)malloc(n);

  /* 单元指针t为NULL(空),未能成功分配			*
   * 将出错信息及行号lineno写入列表文件listing  */
  if (t==NULL)
  {
	  fprintf(listing,"Out of memory error at line %d\n",lineno);
	  Error = TRUE;
  }
  /* 调用库函数string.h,复制给定字串s到新字串单元t */
  else strcpy(t,s);

  /* 函数返回复制得到的新字串指针t */
  return t;
}


/*****************************************************************/
/* 函数名 ChainToFile   										 */	
/* 功  能 将链表中的Token结点依次存入文件中                      */							    
/* 说  明  参数p是指针变量,指向Token链表的表头                  */
/*****************************************************************/
void ChainToFile (ChainNodeType *Chainhead)
{ 
  int num=1;
  ChainNodeType  *currentP=Chainhead;
  /*创建一个新的文件"Tokenlist",以存储Token序列*/
  fp=fopen("c:\\Tokenlist","wb+");
  if (fp==NULL)
         {  printf("cannot create file Tokenlist!\n");
             Error = TRUE;
			//exit(0);
	     }  
  
  fp=fopen("c:\\Tokenlist","ab");   /*按追加方式打开文件*/
    if (fp==NULL)
         {  printf("cannot open file Tokenlist!\n");
             Error = TRUE;  
			//exit(0);
	     }  
 /*从表头到表尾,依次将所有的Token写入文件*/ 
	do 
	{  fwrite(currentP,TOKENLEN,1,fp);
       currentP=currentP->nextToken;
       num++;
    }
    while (currentP!=NULL);

  fclose(fp);  /*关闭文件*/
}

/********************************************************
 *********以下是LL1语法分析方法所用到的栈操作************
 ********************************************************/
/*用链表实现栈操作,栈中存放的是终极符和非终极符,上面的两个枚举
  类型*/
void Push(int i,int j)
{ StackNode *p;
  p=(StackNode *)malloc(sizeof(StackNode));
  
  if (i==1)     
    (*p).var.Ntmlvar=(NontmlType)j;
  else if (i==2)
          (*p).var.tmlvar=(TmlType)j;
  
  p->flag=i;
  p->underNode=StackTop;
  StackTop=p;
  STACKEMPTY=false;
}

void  Pop()
{ StackNode *p;
  p=StackTop;
  StackTop=(*StackTop).underNode;
  free(p);
  if (StackTop==NULL)
	  STACKEMPTY=true;
}

/*读栈顶标志,看是终极符还是非终极符*/
int readStackflag()
{ int j;
  j=StackTop->flag ;
  return(j);
}

/*非终极符时*/
NontmlType readstackN()
{
  return ((*StackTop).var.Ntmlvar);
}

/*终极符*/
TmlType readstackT()
{
  return ((*StackTop).var.tmlvar);
}


/*压栈的实现过程,压入的是指向树节点的指针的地址*/
void  PushPA(TreeNode **t)
{
	StackNodePA *p=NULL;
    p=(StackNodePA *)malloc (sizeof(StackNodePA));
	p->pointer= t ;
	p->underNode =StackTopPA;
    StackTopPA=p;
    paSTACKEMPTY=false;
}
/*弹栈的实现过程*/
TreeNode ** PopPA()
{     
  StackNodePA  *p=NULL;
  TreeNode   **backpointer;
  p = StackTopPA;
  backpointer=p ->pointer;
  StackTopPA=StackTopPA->underNode;
  free(p);
  if (StackTopPA==NULL)
	  paSTACKEMPTY=true;

  return backpointer;
}


/*操作符栈的压栈实现过程,压入的是指向树节点的指针*/
void  PushOp(TreeNode *t)
{
	StackNodeP *p=NULL;
    p=(StackNodeP *)malloc (sizeof(StackNodeP));
	p->pointer= t ;
	p->underNode =OpStackTop;
    OpStackTop=p;
	OpSTACKEMPTY=FALSE;
}

/*操作符栈的弹栈实现过程*/
TreeNode * PopOp()
{     
  StackNodeP *p=NULL;
  TreeNode   *backpointer;
  p=OpStackTop;
  backpointer=p->pointer;
  OpStackTop=OpStackTop->underNode;
  free(p);
  if (OpStackTop==NULL)
	  OpSTACKEMPTY= TRUE;

  return backpointer;
}

LexType ReadOpStack()
{
	TreeNode *t1;
	t1=OpStackTop->pointer;
    return (t1->attr.ExpAttr.op);
}
/*操作数栈的压栈实现过程,压入的是指向树节点的指针*/
void  PushNum(TreeNode *t)
{
	StackNodeP *p=NULL;
    p =(StackNodeP *)malloc (sizeof(StackNodeP));
	p->pointer= t ;
	p->underNode =NumStackTop;
    NumStackTop=p;
	NumSTACKEMPTY=false;
}
/*操作数栈的弹栈实现过程*/
TreeNode * PopNum()
{     
  StackNodeP  *p=NULL;
  TreeNode    *backpointer;
  p =NumStackTop;
  backpointer=p->pointer;
  NumStackTop=NumStackTop->underNode;
  free(p);
  if (NumStackTop==NULL)
	  NumSTACKEMPTY=true;

  return backpointer;
}
 



/********************************************************
 *********以下是创建语法树所用的各类节点的申请***********
 ********************************************************/

/********************************************************/
/* 函数名 newRootNode									*/	
/* 功  能 创建语法树根节点函数			        		*/
/* 说  明 该函数为语法树创建一个新的根结点      		*/
/*        并将语法树节点成员初始化						*/
/********************************************************/
TreeNode * newRootNode(void)

{
  /* 在内存中动态申请分配单元,返回指向该单元的语法树结点类型指针t */
  TreeNode * t = (TreeNode *) malloc(sizeof(TreeNode));

  int i;
  
  /* 语法树节点指针t为NULL,未能成功分配内存单元 *
   * 将出错信息及行号lineno写入列表文件listing  */
  if (t==NULL)
  {
	  fprintf(listing,"Out of memory error at line %d\n",lineno);
	   Error = TRUE;
  }
  /* 语法树节点指针t不是NULL,成功分配内存单元 */
  else {

	/* 初始化新语法树节点t各子节点child[i]为NULL */
    for (i=0;i<MAXCHILDREN;i++) t->child[i] = NULL;

	/* 初始化新语法树节点t兄弟节点sibling为NULL */
	t->sibling = NULL;
    
	/* 指定新语法树节点t成员:结点类型nodekind为语句类型ProK */
	t->nodekind = ProK;
    
	/* 指定新语法树节点t成员:源代码行号lineno为全局变量lineno */
	t->lineno = lineno;

	for(i=0;i<10;i++) 
	{
		strcpy(t->name[i],"\0");
		t->table[i] = NULL;
	}

  }
  /* 函数返回语法树根节点指针t */
  return t;
}


/********************************************************/
/* 函数名 newPheadNode									*/	
/* 功  能 创建程序头类型语法树节点函数					*/
/* 说  明 该函数为语法树创建一个新的程序头类型结点		*/
/*        并将语法树节点成员初始化						*/
/********************************************************/
TreeNode * newPheadNode(void)

{
  /* 在内存中动态申请分配单元,返回指向该单元的语法树结点类型指针t */
  TreeNode * t = (TreeNode *) malloc(sizeof(TreeNode));

  int i;
  
  /* 语法树节点指针t为NULL,未能成功分配内存单元 *
   * 将出错信息及行号lineno写入列表文件listing  */
  if (t==NULL)
  {
	  fprintf(listing,"Out of memory error at line %d\n",lineno);
	   Error = TRUE;
  }
  /* 语法树节点指针t不是NULL,成功分配内存单元 */
  else {

	/* 初始化新语法树节点t各子节点child[i]为NULL */
    for (i=0;i<MAXCHILDREN;i++) t->child[i] = NULL;

	/* 初始化新语法树节点t兄弟节点sibling为NULL */
	t->sibling = NULL;
    
	/* 指定新语法树节点t成员:结点类型nodekind为语句类型PheadK */
	t->nodekind = PheadK;
    
	/* 指定新语法树节点t成员:源代码行号lineno为全局变量lineno */
	t->lineno = lineno;
    
	t->idnum = 0;

	for(i=0;i<10;i++) 
	{

⌨️ 快捷键说明

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