📄 main.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 + -