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

📄 compiler.cpp

📁 上课时老师用过的SNL编译器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// compiler.cpp : implementation file
//

#include "stdafx.h"
#include "face.h"

#include "compiler.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// compiler
 
compiler::compiler()
{
	//在构造函数中初始化变量值:
	lineno = 0;
    linepos = 0;
    bufsize = 0;
	Tokennum=0;
	EOF_flag = FALSE;
	EchoSource = TRUE;

	static struct Reserve  reservedWords[MAXRESERVED]
	= {
		{"program" ,  PROGRAM },{"type"   , TYPE   },{"var"   , VAR   },
		{"procedure",PROCEDURE},{"begin"  , BEGIN  },{"end"   , END   },
	    {"array"   ,  ARRAY   },{"of"     , OF     },{"record", RECORD},
        {"if"      ,  IF      },{"then"   , THEN   },{"else"  , ELSE  },
		{"fi"      ,  FI      },{"while"  , WHILE  },{"do"    , DO    },
		{"endwh"   ,  ENDWH   },{"read"   , READ   },{"write" , WRITE },
		{"return"  ,  RETURN  },{"integer", INTEGER},{"char"  , CHAR  }
	  };

}

compiler::~compiler()
{
}

BEGIN_MESSAGE_MAP(compiler, CEdit)
	//{{AFX_MSG_MAP(compiler)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// compiler message handlers

/****************************************************/
/* 文件	zscanner.cpp								*/
/* 说明 TINY编译器的词法扫描器实现					*/
/* 主题 编译器结构:原理和实例						*/
/****************************************************/

/*******************************************************************/
/* 函数名 getNextChar											   */
/* 功  能 取得下一非空字符函数									   */	
/* 说  明 该函数从输入缓冲区lineBuf中取得下一个非空字符		       */
/*        如果lineBuf中的字串已经读完,则从源代码文件中读入一新行   */
/*******************************************************************/
int compiler::getNextChar(void)
{ 
   /* 当前代码输入行缓冲器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 compiler::ungetNextChar(void)
{
  /* 如果EOF_flag标志为FALSE,不是处于源文件末尾  *
   * 输入行缓冲区lineBuf中当前字符位置linepos减1 */
  if (!EOF_flag) 
	   linepos-- ;
}

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

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


/****************************************************************/
/* 函数名 printToken											*/	
/* 功  能 输出单词函数											*/
/* 说  明 该函数将单词及其词元写入列表文件listing				*/
/*        参数token指定了输出单词,参数tokenString指定了其词元	*/
/****************************************************************/
 void compiler::printToken( TokenType token )

{
  /* 对函数参数token给定单词进行分类处理 */
  switch (token.Lex)

  { 
	/* 单词token为保留字,将保留字词元以指定格式写入列表文件listing */
    case  PROGRAM:   
    case  PROCEDURE:  
    case  TYPE:     
    case  VAR:      
    case  IF:        
    case  THEN:      
    case  ELSE:     
    case  FI:        
	case  WHILE:    
    case  DO:        
    case  ENDWH:    
    case  BEGIN:     
    case END:        
    case READ:       
    case WRITE:      
    case ARRAY:      
    case OF:         
    case RECORD:     
    case RETURN:    
    /*后来添加的*/
	case INTEGER:  
	case CHAR1:       
      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为特殊符号: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;

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

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

	/* 单词token为特殊符号:LMIDPAREN (左中括号),将"["写入文件listing */
    case LMIDPAREN: fprintf(listing,"[\n"); break;    
	
	/* 单词token为特殊符号:RMIDPAREN (右中括号),将"]"写入文件listing */
    case RMIDPAREN: fprintf(listing,"]\n"); break; 

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

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

	/* 单词token为特殊符号:COMMA (逗号),将","写入文件listing */
    case COMMA: fprintf(listing,",\n"); break;	
		
	/* 单词token为特殊符号:DOT (程序结束符),将"."写入文件listing */
    case DOT: fprintf(listing,".\n"); break;	
	
    /* 单词token为特殊符号:UNDERANGE (下标界限),将".."写入文件listing */
	case UNDERANGE: fprintf(listing,";\n"); break;

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

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

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

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

/*****************************************************************/
/* 函数名 printTokenlist										 */	
/* 功  能 将文件"Tokenlist"中保存的Token序列写入列表文件listing中*/							    
/*        一般,listing指向标准输出。                            */
/* 说  明                                                        */
/*****************************************************************/
void compiler::printTokenlist()
{  int num;
   TokenType currentToken;

   fprintf(listing, " \n>>scanner result :\n");
 /*按只读方式打开文件*/
   FILE *fp=fopen("c:\\Tokenlist","rb");
   if (fp==NULL)   
   {   fprintf(listing,"cannot create file Tokenlist!\n");
       exit(0);
   }  
/*从文件中依次读Token,并输出到listing指向的列表文件中去*/
 for (num=1;num<=Tokennum;num++)
   {/*从文件中读一个Token存入变量currentToken中*/  
	   fread(&currentToken,TOKENLEN,1,fp);
	   fprintf(listing,"\t%d:  ",currentToken.lineshow);
       printToken(currentToken);
    /*文件指针移到下一个Token的位置*/
       fseek(fp,num*TOKENLEN,0);
   }
 
 fclose(fp);  /*关闭文件*/

 fclose(listing);

}


/****************************************
 ********* 词法扫描器基本函数  **********
 ****************************************/

/************************************************************/
/* 函数名 getTokenlist										*/
/* 功  能 取得单词函数										*/
/* 说  明 函数从源文件字符串序列中获取下一个单词符号		*/
/*        使用确定性有限自动机DFA,采用直接转向法    		*/
/*        超前读字符,对保留字采用查表方式识别    			*/
/*        产生词法错误时候,仅仅略过产生错误的字符,不加改正  */
/************************************************************/
 void  compiler::getTokenList(CString  pgm)

{ 
   
	source =fopen(pgm ,"r");

   if (source==NULL)
   { fprintf(listing,"File %s not found\n",pgm);
      exit(1);
   }

   listing = fopen("c:\\result.txt","w+");

   if (source==NULL)
   { fprintf(listing,"File %s not found\n",pgm);
      exit(1);
   }
   ChainNodeType *chainHead;    /*链表的表头指针*/
  
   ChainNodeType *currentNode;  /*指向处理当前Token的当前结点*/

⌨️ 快捷键说明

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