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

📄 main.cpp

📁 snl语言是一个简单的具有嵌套过程定义的过程式语言
💻 CPP
字号:
/****************************************************/
/* 文件 main.cpp									*/
/* 说明 类PASCAL语言编译器主程序					*/
/* 主题 编译器结构:原理和实例						*/	
/****************************************************/

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

/*头文件scan.h定义了词法分析程序的界面*/
#include "scanner.h"  

/*头文件util.h定义了语法分析程序的界面*/
#include "util.h"

#include "symbTable.h"


#include "string.h"


/*************************************************************/
/* 条件编译处理                                              */
/* 且如果NO_DIRECT_DESTCODE为FALSE,NO_MIDCODE、NO_CONSOPTI、*/
/* NO_ECCOPTI、NO_LOOPOPTI、NO_DESTCODE均不能为FALSE         */
/*************************************************************/

/* 设置语法分析条件编译标志NO_PARSE为FALSE,         *
 * 如果为TRUE,则得到一个只有词法扫描功能的编译器    */
#define NO_PARSE      FALSE

/* 设置LL1语法分析条件编译标志NO_LL1为FALSE,		*
 * 如果为TRUE,则进行的递归下降法语法分析;否则,    *
 * 将进行LL1法的语法分析                            */
#define NO_LL1        FALSE

/* 设置语义分析条件编译标志NO_ANALYZE为FALSE,		*
 * 如果为TRUE,则得到一个只有语法分析功能的编译器	*/
#define NO_ANALYZE    FALSE

/* 设置中间代码生成标志NO_CODE为FALSE,	            *
 * 如果为TRUE,则不产生代码,得到一个只有语法分析     *
 * 功能的编译器	                                    */
#define  NO_CODE      FALSE

/* 设置中间代码生成标志NO_ANALYZE为FALSE,			*
 * 如果为TRUE,则不产生中间代码,直接生成目标代码     */
#define  NO_MIDCODE   FALSE

/* 设置常表达式优化标志NO_CONSTOPTI为FALSE,			*
 * 如果为TRUE,则不进行常表达式优化					*/
#define  NO_CONSOPTI  FALSE

/* 设置公共表达式优化标志NO_CONSTOPTI为FALSE,		*
 * 如果为TRUE,则不进行公共表达式优化				*/
#define  NO_ECCOPTI   FALSE

/* 设置循环不变式优化标志NO_LOOPOPTI为FALSE,		*
 * 如果为TRUE,则不进行公共表达式优化				*/
#define  NO_LOOPOPTI  FLASE

/* 设置目标代码生成标志NO_CONSTOPTI为FALSE,			*
 * 如果为TRUE,则不生成目标代码						*/
#define  NO_DESTCODE  FALSE

/* 设置目标代码的解释执行标志NO_EXECUTE为FALSE,	*
 * 如果为TRUE,则不解释执行目标代码					*/
#define  NO_EXECUTE  FALSE

#if !NO_PARSE
#endif

#if !NO_LL1
/* 条件编译,联入头文件parseLL1.h,该头文件定义了LL1语法解析器界面 */
#include "parseLL1.h"
#else
/* 条件编译,联入头文件parse.h,该头文件定义了递归下降法语法解析器界面 */
#include "parse.h"
#endif

#if !NO_ANALYZE
/* 条件编译,联入头文件zanalyze.h,该头文件定义了语义解析器界面 */
#include "analyze.h"
#endif

#if !NO_CODE
#endif

#if !NO_MIDCODE
/* 条件编译,联入头文件midcode.h,该头文件定义了中间代码生成文件的界面 */
#include "midcode.h"
#else
/* 条件编译,联入头文件cgen.h,code.h,这些头文件定义了由语法树直接生成最终代码的界面*/
#include "cgen.h"
#include "code.h"
#endif

#if !NO_CONSOPTI
/* 条件编译,联入头文件consOpti.h,该头文件定义了常表达式优化文件的界面 */
#include "consOpti.h"
#endif

#if !NO_ECCOPTI
/* 条件编译,联入头文件ECCsaving.h,该头文件定义了公共表达式优化文件的界面 */
#include "ECCsaving.h"
#endif

#if !NO_LOOPOPTI
/* 条件编译,联入头文件loopOpti.h,该头文件定义了循环不变式优化文件的界面 */
#include "loopOpti.h"
#endif

#if !NO_DESTCODE
/* 条件编译,联入头文件codegen.h,该头文件定义了目标代码生成的界面 */
#include "codegen.h"
#endif


#if !NO_EXECUTE
/* 条件编译,联入头文件tm.h,该头文件定义了解释执行程序的界面 */
#include "tm.h"
#endif




/*******************全局变量*******************/

FILE * source;		/* 源程序文本文件,为编译器输入文件 */

FILE * listing;		/* 中间列表文件,为编译器中间信息输出文件 */

/*指针fp,指向存放Token序列的文件"Tokenlist"*/
FILE  *fp;

/*Token序列中的token数目*/
int Tokennum=0;

/*清单的行号*/
int lineno=0;

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

/*指向各基本块的指针*/
CodeFile  *baseBlock[100];

/*保存主程序的display表的偏移*/
int StoreNoff ;

/*中间代码序列,以结构的形式给出*/
CodeFile  *midcode = NULL;

/*目标代码文件*/
FILE  *	code;

/********** 设置追踪标志初始值 **********/

/* 源代码文件追踪标志,初始为FALSE.如果为TRUE,       	*
 * 将源代码信息输出到中间文件listing			        *
 * 在zscanner.cpp文件的函数getNextChar()中,实现输出    */ 
int EchoSource = TRUE;		

/* 词法分析追踪标志,初始为FALSE.如果为TRUE,		*
 * 将词法分析信息输出到中间文件listing			*/
int TraceScan = FALSE;

/* 语法分析追踪标志,初始为FALSE.如果为TRUE,		*
 * 将语法分析信息输出到中间文件listing			*/
int TraceParse = TRUE;

/* 符号表输出标志,初始为FALSE.如果为TRUE,		*
 * 将语义分析时产生的符号表信息输出到中间文件   *
 * listing										*/
int  TraceTable = TRUE ;

/* 目标代码追踪标志,初始为FALSE.如果为TRUE,		*
 * 将目标代码的注释信息输出到中间文件listing	*/
int TraceCode = TRUE;

/*错误追踪标识,防止错误的进一步传递*/
int  Error = FALSE;


/********************************************************/
/* 函数名 main											*/
/* 功  能 函数将编译程序中各个功能部分有机结合在一起,	*/
/*		  完成用户需要的编译工作,输出相关信息和结果		*/
/* 说  明 函数参数argc指明参数个数,参数argv记录参字串	*/
/*		  用户应给定要编译的源程序文件目录名为调用参数	*/
/********************************************************/

main( )

{
  /*输入要编译的文件名*/
  char pgm[120];

  /*目标代码文件名*/
  char * codefile;

  printf("input program names:\n");   

  scanf("%s",pgm);                    
 
  /* 若未指定文件扩展名,给源文件加上扩展名.tny */
  if (strchr (pgm, '.') == NULL)
     strcat(pgm,".tny");

  /* 用只读方式打开源程序文件pgm,文件指针给source */
  source = fopen(pgm,"r");

  if (source==NULL)
  { 
	  fprintf(stderr,"File %s not found\n",pgm);
	  exit(1);
  }
      
  /* 将中间信息列表文件listing指向屏幕标准输出stdout */
   listing =  stdout;
   
   //testing = fopen("c://1//3.txt","w");

  /* 输出中间编译信息 */
  fprintf(listing,"\nTINY COMPILATION: %s\n",pgm);
  
  /* 调用词法分析函数,得到Token序列*/
  getTokenlist();

  if (EchoSource)
  { /*按键进入下一部分*/
    getchar();
    getchar();
    
  }

 /* 如果词法分析追踪标志为TRUE,则将生成的Token序列输出到屏幕 */
  if (TraceScan) 
  {
	fprintf(listing,"\nLexical analysizing:\n");
	//fprintf(testing,"\nLexical analysizing:\n");
	fprintf(listing,"\ntoken list:\n");
	printTokenlist();
    getchar();
  }



/*********************************/
/* 条件编译处理,选择语法分析部分 */
/*********************************/
/* 条件编译,如果!NO_PARSE为FALSE,  *
/* 得到一个只有词法扫描功能的编译器,*
/* 否则进行语法分析                 */
#if !NO_PARSE


/* 条件编译,只做LL1语法分析处理    *
/* 调用语法分析函数,生成语法分析树 */
#if !NO_LL1

  TreeNode * syntaxTree;

  fprintf(listing,"\nLL1 Syntax analysizing:\n");
  syntaxTree = parseLL1();
  
  /* 如果语法分析追踪标志为TRUE且没有语法错误,
     则将生成的语法树输出到屏幕 */
  if ((TraceParse)&&(!Error))
  { 
    fprintf(listing,"\nSyntax tree:\n\n");
    printTree(syntaxTree);
	getchar();
	getchar();
  }


/* 条件编译,只做递归下降语法解析处理*
 * 调用语法分析函数,生成语法分析树	*/
#else
  TreeNode * syntaxTree;

  fprintf(listing,"\nRecursion Syntax analysizing:\n");
  syntaxTree = parse();
  
  /* 如果语法分析追踪标志为TRUE且没有语法错误,
     则将生成的语法树输出到屏幕 */
  if ((TraceParse)&&(!Error))
  { 
    fprintf(listing,"\nSyntax tree:\n\n");
    printTree(syntaxTree);
	getchar();
  }
#endif//语法分析方法选择结束NO_LL1


/*********************************/
/* 条件编译处理,选择语义分析部分 */
/*********************************/
/*条件编译,当!NO_ANALYZE为真,且前面的分析没有错误,
  则进行下面的语义分析*/
#if !NO_ANALYZE
   { 
	   fprintf(listing ,"\nSematic analysizing:\n");
	   fprintf(listing ,"Checking  sematic  error......\n");
	   /*语义分析*/
	   analyze(syntaxTree);  
       if (!Error)
		  fprintf(listing ," \nNo  error !\n");

       /*输出符号表*/
	   if ((TraceTable)&&(!Error))
	   {
		   fprintf(listing ,"\nNow printing  symb table.....\n");
	 	   PrintSymbTable();
		   getchar();
		   getchar();
		}
        /*输出含符号表信息的语法树*/
	    if ((TraceParse)&&(!Error))
		{ 	
			fprintf(listing,"after  analysis ..");
			fprintf(listing,"\nSyntax tree:\n\n");
			printTree(syntaxTree);
			getchar( );
		}
	}



/*************************************/
/* 条件编译处理,选择中间代码生成部分 */
/*************************************/
/*条件编译,当!NO_CODE为FALSE,得到只有词法 *
  分析、语法分析、语义分析的编译器          */
#if !NO_CODE
   

/*条件编译,当!NO_MIDCODE为TURE,且前面没有 *
  错误,则进行下面的中间代码生成            */
#if !NO_MIDCODE
    if (!Error)
    {	
		midcode = GenMidCode(syntaxTree);
        fprintf(listing,"\n>>Generated  Midcode:\n"); 
		PrintMidCode(midcode);
		getchar();
	}

/*条件编译,当!NO_CONSOPTI为真,且前面没有错误,
  则进行下面的常表达式优化*/
#if !NO_CONSOPTI
	if (!Error)
    {	
		fprintf(listing,">> ConstDef   value  table :\n");
		midcode = ConstOptimize( );
		getchar();
		fprintf(listing,"\n>>Const Expression Optimize  Result:\n");
		PrintMidCode(midcode);
		getchar();
	}
#endif//结束NO_CONSOPTI条件编译

/*条件编译,当!NO_ECCOPTI为真,且前面没有错误,
  则进行下面的公共表达式优化*/
#if !NO_ECCOPTI
    if (!Error)
    {	
		midcode = ECCsave( );
		fprintf(listing,"\n>>ECC Optimize  Result:\n");
		PrintMidCode(midcode);
	}
#endif//结束NO_ECCOPTI条件编译

/*条件编译,当!NO_LOOPOPTI为真,且前面没有错误,
  则进行下面的循环不变式优化*/
#if !NO_LOOPOPTI
	if (!Error)
    {	
		midcode = LoopOpti();
		getchar();
		fprintf(listing,"\n>>LOOP Optimize  Result:\n");
		PrintMidCode(midcode);
	    getchar();
	}
#endif//结束NO_LOOPOPTI条件编译

/*条件编译,当!NO_DESTOPTI为真,且前面没有错误,
  则进行下面的目标代码生成*/
#if !NO_DESTCODE
	if(!Error)
	{
		//char * codefile;
		/*将源文件名,去掉扩展名,添加扩展名.tm*/
		//int fnlen = strcspn(pgm,".");
		//codefile = (char *) calloc(fnlen+4,sizeof(char));
		//strncpy(codefile,pgm,fnlen);
		//strcat(codefile,".tm");

		//注:由于可能在光盘上运行,故不能按照以前的方式放置目标文件。

		//指定目标文件名:
		 codefile = "c:\\destcode.tm";
		
		 /*输出目标代码所在的文件名*/
		fprintf(listing,"\n>>destcode file name:\n");
		fprintf(listing,codefile);
		code = fopen(codefile,"w");
	    if(code==NULL)
		{
			printf("Unable to open %s\n",codefile);
			exit(1);
		}
		codeGen(midcode,codefile);

		fclose(code);
	}
#endif//结束NO_DESTCODE的条件编译


/* 条件编译,跳过中间代码生成,直接由语法树生成,目标代码*/
#else
    if(!Error)
	{
		//char * codefile;
		//int fnlen = strcspn(pgm,".");
		//codefile = (char *) calloc(fnlen+4,sizeof(char));
		//strncpy(codefile,pgm,fnlen);
		//strcat(codefile,".tm");

		//注:由于可能在光盘上运行,故不能按照以前的方式放置目标文件。

		//指定目标文件名:
		 codefile = "c:\\destcode.tm";

		/*输出目标代码所在的文件名*/
		fprintf(listing,"\n>>destcode file name:\n");
		fprintf(listing,codefile);

		code = fopen(codefile,"w");
	    if(code==NULL)
		{
			printf("Unable to open %s\n",codefile);
			exit(1);
		}
		codeGen(syntaxTree,codefile);
		fclose(code);

	}

#endif//结束NO_MIDCODE的条件编译

	
/*解释执行目标代码*/
#if !NO_EXECUTE
	if(!Error)
		  tmain(codefile);
#endif//结束NO_EXECUTE的条件编译



#endif//结束NO_CODE的条件编译
#endif//结束NO_ANALYZE的条件编译
#endif//结束NO_PARSE的条件编译


 	getchar();
	fprintf(listing,"\nNow is free space ........\n");
	getchar();

	/*释放语法树空间*/
	if (syntaxTree!=NULL)
	{ freeTree(syntaxTree);
	     fprintf(listing,">>free  tree\n"); 
	}
	/*释放符号表空间*/
	freeTable();
	fprintf(listing, ">>free  symb table\n ");
		
	/*释放中间代码空间*/
    if (firstCode!=NULL)
	{  freeMidCode();
	   fprintf(listing, ">>free mid code\n");
	}

	/* 编译结束,关闭源程序文件source */
   fclose(source);

   /* 编译成功,程序正常返回 */
   return 0;
}
 






⌨️ 快捷键说明

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