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

📄 func.cpp

📁 SNL语言编译器源码 小语言的编译器C++实现 包括词法分析
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/************ 该代码文件所包含的头文件 **************/

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

#include "ctype.h"      /* 用到了该库中的isalnum,isalpha,isdigit函数 */

#include "math.h"       /* 用到了这个库里的取模运算 */

#include "func.h"

#include "compiler.h"

#include "iostream.h"

int Level=-1;  /*scope栈的层数*/

TypeIR * intPtr = NULL;			/*该指针一直指向整数类型的内部表示*/

TypeIR * charPtr = NULL;		/*该指针一直指向字符类型的内部表示*/

TypeIR * boolPtr = NULL;		/*该指针一直指向布尔类型的内部表示*/

/*记录当前层的displayOff*/
int savedOff = 0;

/*保存主程序的display表的偏移*/
int StoreNoff ;
/*=============词法分析部分=============*/

/*******************************************************************/
/* 函数名 getNextChar											   */
/* 功  能 取得下一非空字符函数									   */	
/* 说  明 该函数从输入缓冲区lineBuf中取得下一个非空字符		       */
/*        如果lineBuf中的字串已经读完,则从源代码文件中读入一新行   */
/*******************************************************************/
int scanner::getNextChar(FILE* source)
{ 
    
	
	/* 当前代码输入行缓冲器lineBuf已经耗尽 */
   if (!(linepos < bufsize))				

   {
	/* 源代码行号lineno加1 */
    lineno++;
    
    /* 从源文件source中读入BUFLEN-2(254)个字符到行缓冲区lineBuf中      *
	 * fgets在的lineBuf末尾保留换行符.并在末尾加了一个NULL字符表示结束 */
	if (fgets(lineBuf,BUFLEN-1,source))	
    
	{ 	 
	  /* 如果源文件追踪标志EchoSource为TRUE                               *
	   * 将源程序行号lineno及行内容lineBuf在词法扫描时写入列表文件listing */
	  //if (EchoSource) fprintf(listing,"%4d: %s",lineno,lineBuf);
	  
	  /* 取得当前输入源代码行的实际长度,送给变量bufsize */
	  bufsize = strlen(lineBuf);

	  /* 输入行缓冲区lineBuf中当前字符位置linepos指向lineBuf开始位置 */
	  linepos = 0;

	  /* 取得输入行缓冲区lineBuf中下一字符 */
      return lineBuf[linepos++];

    }
    else
	{ 
	  /* 未能成功读入新的代码行,fget函数返回值为NULL *
	   * 已经到源代码文件末尾,设置EOF_flag标志为TRUE */
	  EOF_flag = TRUE;					

   	  /* 函数返回EOF */
	  return EOF;
    }
  }

  /* 行输入缓冲区lineBuf中字符还未读完,直接取其中下一字符,函数返回所取字符 */
  else return lineBuf[linepos++];
}

/********************************************************/
/* 函数名 ungetNextChar									*/		
/* 功  能 字符回退函数									*/
/* 说  明 该过程在行输入缓冲区lineBuf中回退一个字符		*/
/*        用于超前读字符后不匹配时候的回退				*/
/********************************************************/
void scanner::ungetNextChar(void)

{
  /* 如果EOF_flag标志为FALSE,不是处于源文件末尾  *
   * 输入行缓冲区lineBuf中当前字符位置linepos减1 */
  if (!EOF_flag) linepos-- ;
}
/**************************************************************/
/* 函数名 reservedLookup								      */
/* 功  能 保留字查找函数									  */
/* 说  明 使用线性查找,查看一个标识符是否是保留字			  */
/*		  标识符如果在保留字表中则返回相应单词,否则返回单词ID */
/**************************************************************/
LexType  scanner::reservedLookup (char * s)

{ 
  int i;

  /* 在保留字表中查找,MAXRESERVED已经定义为8,为保留字数 */
  for (i=0;i<MAXRESERVED;i++)				

	/* 线性查保留字表,察看函数参数s指定标识符是否在表中 *
	 * 当两字符串匹配的时候,函数strcmp返回值为0(FALSE)	*/ 
    if (!strcmp(s,reservedWords[i].str))	

		/* 字符串s与保留字表中某一表项匹配,函数返回对应保留字单词 */
		return reservedWords[i].tok;			

  /* 字符串s未在保留字表中找到,函数返回标识符单词ID */
  return ID;								
}



/*=============语法分析部分=============*/
TokenType Syntax::getToken()
{
 return token;
}

char * Syntax::getTemp_name()
{
return temp_name;
}

int Syntax::getLine0()
{
return line0;
}

void Syntax::setCurrentP(ChainNodeType * tokenl)
{

	currentP=tokenl;
}



/********************************************************************/
/* 函数名 syntaxError												*/
/* 功  能 语法错误处理函数											*/
/* 说  明 将函数参数message指定的错误信息格式化写入列表文件listing	*/
/*		  设置错误追踪标志Error为TRUE								*/
/********************************************************************/
void Syntax::syntaxError(char * message)
{
	cout<<" error :   "<<endl;
    cout<<"Syntax error at line"<<token.lineshow<<":"<<message<<endl;
	Error = TRUE;
}
/********************************************************************/
/* 函数名 match														*/
/* 功  能 终极符匹配处理函数										*/
/* 说  明 函数参数expected给定期望单词符号与当前单词符号token相匹配	*/
/*        如果不匹配,则报非期望单词语法错误							*/
/********************************************************************/
void Syntax::match(LexType expected)

{ 
  if (token.Lex == expected)   
  {
	  ReadNextToken();
	  
	  line0 = token.lineshow;
  }
  else 
  {
	  syntaxError("not match error ");
	  cout<<token.Sem<<endl;
	  ReadNextToken();
	  //exit(0);
  }
  
}
/********************************************************/
/* 函数名 copyString									*/
/* 功  能 字符串复制函数								*/
/* 说  明 该函数为已存在的字串分配内存单元,并将其复制	*/
/********************************************************/
char * Syntax::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 = new char[n];

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

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

/*****************************************************************/
/* 函数名 ReadNextToken							        		 */	
/* 功  能 将文件tokenlist中的信息作为返回值                      */							    
/*        一般,listing指向标准输出。                            */
/* 说  明 返回值为TokenType类型,用于语法分析中                  */
/*****************************************************************/
void Syntax::ReadNextToken()
{

    token=currentP->Token;
	currentP=currentP->nextToken;


  
}


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

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

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

  int i;
  
  /* 语法树节点指针t为NULL,未能成功分配内存单元 *
   * 将出错信息及行号lineno写入列表文件listing  */
  if (t==NULL)
  {
	  cout<<"Out of memory error at line"<<lineno<<endl;
	   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 * Syntax::newPheadNode(void)

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

  int i;
  
  /* 语法树节点指针t为NULL,未能成功分配内存单元 *
   * 将出错信息及行号lineno写入列表文件listing  */
  if (t==NULL)
  {
	  cout<<"Out of memory error at line"<<lineno<<endl;
	   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++) 
	{
		strcpy(t->name[i],"\0");
		t->table[i] = NULL;
	}

	
  }
  /* 函数返回程序头类型语法树节点指针t */
  return t;
}


/********************************************************/
/* 函数名 newDecANode									*/	
/* 功  能 创建声明语法树节点函数,没有指明具体的节点声明 */
/*        类型,在语法树的第二层			                */
/* 说  明 该函数为语法树创建一个新的结点      	     	*/
/*        并将语法树节点成员初始化						*/
/********************************************************/
TreeNode * Syntax::newDecANode(NodeKind kind)

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

  int i;
  
  /* 语法树节点指针t为NULL,未能成功分配内存单元 *
   * 将出错信息及行号lineno写入列表文件listing  */
  if (t==NULL)
  {
	  cout<<"Out of memory error at line"<<lineno<<endl;
	  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为参数kind */
	t->nodekind = kind;
	
	/* 指定新语法树节点t成员:源代码行号lineno为全局变量lineno */
	t->lineno = lineno;

	for(i=0;i<10;i++) 
	{
		strcpy(t->name[i],"\0");
		t->table[i] = NULL;
	}
  }
  /* 函数返回语法树根节点指针t */
  return t;
}





/********************************************************/
/* 函数名 newTypeNode									*/
/* 功  能 类型标志语法树节点创建函数					*/
/* 说  明 该函数为语法树创建一个新的类型标志结点,      */
/*        表示在它之下的声明都为类型声明,        		*/
/*        并将语法树节点的成员初始化					*/
/********************************************************/
TreeNode * Syntax::newTypeNode()

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

  /* 语法树节点指针t为NULL,未能成功分配内存单元		*
   * 将出错信息及行号lineno写入列表文件listing		*/
  if (t==NULL)
	  cout<<"Out of memory error at line"<<lineno<<endl;

  /* 语法树节点指针t不是NULL,内存单元已经成功分配 */
  else {

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

	/* 初始化新语法树节点t兄弟节点sibling为NULL(空) */
   	t->sibling = NULL;

⌨️ 快捷键说明

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