?? 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
/* 設置常表達式優(yōu)化標志NO_CONSTOPTI為FALSE, *
* 如果為TRUE,則不進行常表達式優(yōu)化 */
#define NO_CONSOPTI FALSE
/* 設置公共表達式優(yōu)化標志NO_CONSTOPTI為FALSE, *
* 如果為TRUE,則不進行公共表達式優(yōu)化 */
#define NO_ECCOPTI FALSE
/* 設置循環(huán)不變式優(yōu)化標志NO_LOOPOPTI為FALSE, *
* 如果為TRUE,則不進行公共表達式優(yōu)化 */
#define NO_LOOPOPTI FLASE
/* 設置目標代碼生成標志NO_CONSTOPTI為FALSE, *
* 如果為TRUE,則不生成目標代碼 */
#define NO_DESTCODE FALSE
/* 設置目標代碼的解釋執(zhí)行標志NO_EXECUTE為FALSE, *
* 如果為TRUE,則不解釋執(zhí)行目標代碼 */
#define NO_EXECUTE FALSE
#if !NO_PARSE
#endif
#if !NO_LL1
/* 條件編譯,聯(lián)入頭文件parseLL1.h,該頭文件定義了LL1語法解析器界面 */
#include "parseLL1.h"
#else
/* 條件編譯,聯(lián)入頭文件parse.h,該頭文件定義了遞歸下降法語法解析器界面 */
#include "parse.h"
#endif
#if !NO_ANALYZE
/* 條件編譯,聯(lián)入頭文件zanalyze.h,該頭文件定義了語義解析器界面 */
#include "analyze.h"
#endif
#if !NO_CODE
#endif
#if !NO_MIDCODE
/* 條件編譯,聯(lián)入頭文件midcode.h,該頭文件定義了中間代碼生成文件的界面 */
#include "midcode.h"
#else
/* 條件編譯,聯(lián)入頭文件cgen.h,code.h,這些頭文件定義了由語法樹直接生成最終代碼的界面*/
#include "cgen.h"
#include "code.h"
#endif
#if !NO_CONSOPTI
/* 條件編譯,聯(lián)入頭文件consOpti.h,該頭文件定義了常表達式優(yōu)化文件的界面 */
#include "consOpti.h"
#endif
#if !NO_ECCOPTI
/* 條件編譯,聯(lián)入頭文件ECCsaving.h,該頭文件定義了公共表達式優(yōu)化文件的界面 */
#include "ECCsaving.h"
#endif
#if !NO_LOOPOPTI
/* 條件編譯,聯(lián)入頭文件loopOpti.h,該頭文件定義了循環(huán)不變式優(yōu)化文件的界面 */
#include "loopOpti.h"
#endif
#if !NO_DESTCODE
/* 條件編譯,聯(lián)入頭文件codegen.h,該頭文件定義了目標代碼生成的界面 */
#include "codegen.h"
#endif
#if !NO_EXECUTE
/* 條件編譯,聯(lián)入頭文件tm.h,該頭文件定義了解釋執(zhí)行程序的界面 */
#include "tm.h"
#endif
/*******************全局變量*******************/
FILE * source; /* 源程序文本文件,為編譯器輸入文件 */
FILE * listing; /* 中間列表文件,為編譯器中間信息輸出文件 */
/*指針fp,指向存放Token序列的文件"Tokenlist"*/
FILE * fp;
/*Token序列中的token數(shù)目*/
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文件的函數(shù)getNextChar()中,實現(xiàn)輸出 */
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;
/********************************************************/
/* 函數(shù)名 main */
/* 功 能 函數(shù)將編譯程序中各個功能部分有機結合在一起, */
/* 完成用戶需要的編譯工作,輸出相關信息和結果 */
/* 說 明 函數(shù)參數(shù)argc指明參數(shù)個數(shù),參數(shù)argv記錄參字串 */
/* 用戶應給定要編譯的源程序文件目錄名為調用參數(shù) */
/********************************************************/
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);
/* 調用詞法分析函數(shù),得到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語法分析處理 *
/* 調用語法分析函數(shù),生成語法分析樹 */
#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();
}
/* 條件編譯,只做遞歸下降語法解析處理*
* 調用語法分析函數(shù),生成語法分析樹 */
#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為真,且前面沒有錯誤,
則進行下面的常表達式優(yōu)化*/
#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為真,且前面沒有錯誤,
則進行下面的公共表達式優(yōu)化*/
#if !NO_ECCOPTI
if (!Error)
{
midcode = ECCsave( );
fprintf(listing,"\n>>ECC Optimize Result:\n");
PrintMidCode(midcode);
}
#endif//結束NO_ECCOPTI條件編譯
/*條件編譯,當!NO_LOOPOPTI為真,且前面沒有錯誤,
則進行下面的循環(huán)不變式優(yōu)化*/
#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的條件編譯
/*解釋執(zhí)行目標代碼*/
#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 + -