TINY部分源碼分析報(bào)告_第1頁(yè)
TINY部分源碼分析報(bào)告_第2頁(yè)
TINY部分源碼分析報(bào)告_第3頁(yè)
TINY部分源碼分析報(bào)告_第4頁(yè)
TINY部分源碼分析報(bào)告_第5頁(yè)
已閱讀5頁(yè),還剩16頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、精選優(yōu)質(zhì)文檔-傾情為你奉上TINY源碼分析一、文件概述MAIN.C: 主函數(shù)GLOBALS.H:全局定義的文件SCAN.C/SCAN.H: 詞法分析PARSE.C/PARSE.H:語(yǔ)法分析UTIL.C/UTIL.H:構(gòu)造樹SYMTAB.C/SYMTAB.H:符號(hào)表CGEN.C/CGEN.H:生成"匯編代碼"CODE.C/CODE.H:這個(gè)只是用來(lái)把分析過(guò)程輸出到屏幕的.二、各個(gè)文件的分析1.MAIN.C:主要有三個(gè)FILE*句柄:source-源代碼文件。listing-顯示分析過(guò)程的文件,這里重定向到stdout。code-目標(biāo)匯編代碼文件。從該文件中可知程序運(yùn)行的流程:

2、檢查參數(shù)正確否(tiny.exe filename)->構(gòu)造語(yǔ)法樹(調(diào)用parse函數(shù))->根據(jù)語(yǔ)法樹生成代碼(調(diào)用codeGen函數(shù),該函數(shù)又調(diào)用cGen函數(shù)。2.GLOBALS.H:定義了關(guān)鍵字個(gè)數(shù)8個(gè)。定義了關(guān)鍵字,運(yùn)算符等內(nèi)容的枚舉值。定義了語(yǔ)句類型的枚舉值,這個(gè)決定樹的結(jié)點(diǎn)。定義了變量類型(也就三種,void, integer, boolean)。定義了樹的節(jié)點(diǎn)-這個(gè)最重要了!其結(jié)構(gòu)如下所示:typedef struct treeNodestruct treeNode * childMAXCHILDREN;struct treeNode * sibling;int lin

3、eno;NodeKind nodekind;union StmtKind stmt; ExpKind exp; kind;union TokenType op;int val;char * name; attr;ExpType type; /* for type checking of exps */ TreeNode;3. UTIL.C/UTIL.H 主要函數(shù)TreeNode * newStmtNode(StmtKind kind) 此函數(shù)創(chuàng)建一個(gè)有關(guān)語(yǔ)法樹的聲明節(jié)點(diǎn)TreeNode * newExpNode(ExpKind kind) 此函數(shù)創(chuàng)建一個(gè)有關(guān)語(yǔ)法樹的表述節(jié)點(diǎn)char * cop

4、yString(char * s) 此函數(shù)分配和創(chuàng)建一個(gè)新的已存在樹的復(fù)制 void printTree( TreeNode * tree ) 輸出一個(gè)語(yǔ)法樹 這兩個(gè)文件主要是關(guān)于語(yǔ)法樹的創(chuàng)建和輸出4.SCAN.c/SCAN.H主要有這么幾個(gè)函數(shù):static int getNextChar(void);static void ungetNextChar(void);static TokenType reservedLookup (char * s);TokenType getToken(void);reservedLookup函數(shù)是查找關(guān)鍵字的,在符號(hào)表中找。這里還定義了一個(gè)保存關(guān)鍵字的結(jié)構(gòu)

5、:static struct char* str;TokenType tok; reservedWordsMAXRESERVED="if",IF,"then",THEN,"else",ELSE,"end",END,"repeat",REPEAT,"until",UNTIL,"read",READ,"write",WRITE;最重要的是getToken(void)函數(shù)。這個(gè)相當(dāng)于lex的功能,進(jìn)行詞法分析。也就是一個(gè)DFA,switch后

6、面跟了一堆的case。其中g(shù)etNextChar(void)函數(shù)的思路,以下列出:static int getNextChar(void)if (!(linepos < bufsize)lineno+;if (fgets(lineBuf,BUFLEN-1,source)if (EchoSource) fprintf(listing,"%4d: %s",lineno,lineBuf);bufsize = strlen(lineBuf);linepos = 0;return lineBuflinepos+;elseEOF_flag = TRUE;return EOF;el

7、se return lineBuflinepos+;4.PARSE.C/PARSE.H有這么幾個(gè)函數(shù):TreeNode * parse(void)static TreeNode * stmt_sequence(void);static TreeNode * statement(void);static TreeNode * if_stmt(void);static TreeNode * repeat_stmt(void);static TreeNode * assign_stmt(void);static TreeNode * read_stmt(void);static TreeNode *

8、 write_stmt(void);static TreeNode * exp(void);static TreeNode * simple_exp(void);static TreeNode * term(void);static TreeNode * factor(void);最重要的是parse這個(gè)函數(shù),就是用來(lái)構(gòu)造整個(gè)程序的語(yǔ)法樹的。下面的一堆私有函數(shù)構(gòu)造相應(yīng)語(yǔ)法的語(yǔ)法樹,然后parse最后把它們這些子樹整合成一個(gè)大樹。5.SYMTAB.C/SYMTAB.H這個(gè)是符號(hào)表操作的,也就是詞法分析的時(shí)候查找表,看該token是不是關(guān)鍵字。如果不是,就當(dāng)作表識(shí)符添加進(jìn)去。在語(yǔ)法分析的時(shí)候也要用

9、到,看變量有沒(méi)有聲明的時(shí)候用的。三、實(shí)驗(yàn)心得:通過(guò)這次實(shí)驗(yàn),仔細(xì)地去查看和分析了TINY編譯器的部分源碼。了解到了編譯器的運(yùn)行:檢查參數(shù)正確否(tiny.exe filename)->構(gòu)造語(yǔ)法樹(調(diào)用parse函數(shù))->根據(jù)語(yǔ)法樹生成代碼(調(diào)用codeGen函數(shù)),同時(shí)熟悉了編譯器是如何使用prase函數(shù)進(jìn)行語(yǔ)法樹的構(gòu)建以及語(yǔ)法樹生成代碼的轉(zhuǎn)化,最主要的是進(jìn)一步清晰了解到編譯器的構(gòu)造和運(yùn)行原理,加深了對(duì)課本知識(shí)的運(yùn)用和拓展,感覺(jué)收獲很大!Main.c/*/* File: main.c */* Main program for TINY compiler */* Compiler C

10、onstruction: Principles and Practice */* Kenneth C. Louden */*/#include "globals.h"/* set NO_PARSE to TRUE to get a scanner-only compiler ,NO_PARSE為true時(shí)創(chuàng)建一個(gè)只掃描的編譯器 */#define NO_PARSE FALSE /* set NO_ANALYZE to TRUE to get a parser-only compiler ,NO_ANALYZE為true時(shí)創(chuàng)建一個(gè)只分析和掃描的編譯器*/#define NO_

11、ANALYZE FALSE/* set NO_CODE to TRUE to get a compiler that does not * generate code NO_CODE為true時(shí)創(chuàng)建一個(gè)執(zhí)行語(yǔ)義分析,但不生成代碼的編譯器 */#define NO_CODE FALSE#include "util.h"#if NO_PARSE#include "scan.h" /如果NO_PARSE為true,調(diào)用頭文件scan.h#else#include "parse.h" /否則調(diào)用頭文件prase.h#if !NO_ANALYZ

12、E#include "analyze.h" /如果NO_ANALYZE為true,調(diào)用頭文件analyze.h#if !NO_CODE#include "cgen.h" /如果NO_CODE為true,調(diào)用頭文件cgen.h#endif #endif#endif /結(jié)束預(yù)處理語(yǔ)句符號(hào)/* allocate global variables 分配全局變量*/int lineno = 0;FILE * source; /指針指向源代碼文件地址FILE * listing; /指針指向顯示分析過(guò)程的文件的地址FILE * code; /指針指向目標(biāo)匯編代碼文件

13、的地址/* allocate and set tracing flags 分配和設(shè)置跟蹤標(biāo)志*/int EchoSource = FALSE;int TraceScan = FALSE;int TraceParse = FALSE;int TraceAnalyze = FALSE;int TraceCode = FALSE;int Error = FALSE; /跟蹤標(biāo)志全部初始化為falsemain( int argc, char * argv ) TreeNode * syntaxTree; char pgm120; /* source code file name */ if (argc

14、 != 2) fprintf(stderr,"usage: %s <filename>n",argv0); exit(1); /如果argv不為2,打印顯示信息并退出 strcpy(pgm,argv1) ; /復(fù)制argv1地址以null為退出字符的存儲(chǔ)器區(qū)塊到另一個(gè)存儲(chǔ)器區(qū)塊品pgm內(nèi) if (strchr (pgm, '.') = NULL) strcat(pgm,".tny"); /把.tyn文件所指字符串添加到pgm結(jié)尾處并添加'0'。 source = fopen(pgm,"r")

15、; /以只讀的方式打開(kāi)pgm文件,并將指向pgm文件的指針?lè)祷亟osource if (source=NULL) fprintf(stderr,"File %s not foundn",pgm); exit(1); /如果源代碼文件為空,打印顯示信息并退出 listing = stdout; /* send listing to screen 清單發(fā)送到屏幕*/ fprintf(listing,"nTINY COMPILATION: %sn",pgm); /答應(yīng)顯示語(yǔ)句#if NO_PARSE while (getToken()!=ENDFILE); /如

16、果輸入流沒(méi)有結(jié)束就繼續(xù)進(jìn)行循環(huán),直至結(jié)束#else syntaxTree = parse();/調(diào)用prase()函數(shù)構(gòu)造語(yǔ)法樹 if (TraceParse) fprintf(listing,"nSyntax tree:n"); printTree(syntaxTree); / 如果語(yǔ)法分析追蹤標(biāo)志為TRUE且沒(méi)有語(yǔ)法錯(cuò)誤,則將生成的語(yǔ)法樹輸出到屏幕 #if !NO_ANALYZE if (! Error) if (TraceAnalyze) fprintf(listing,"nBuilding Symbol Table.n"); buildSymta

17、b(syntaxTree); /輸出含符號(hào)表信息的語(yǔ)法樹 if (TraceAnalyze) fprintf(listing,"nChecking Types.n"); typeCheck(syntaxTree);/輸出含類型檢查的語(yǔ)法樹 if (TraceAnalyze) fprintf(listing,"nType Checking Finishedn");/打印結(jié)束信息 #if !NO_CODE if (! Error) char * codefile; int fnlen = strcspn(pgm,"."); codefil

18、e = (char *) calloc(fnlen+4, sizeof(char); strncpy(codefile,pgm,fnlen); strcat(codefile,".tm"); /將源文件名,去掉擴(kuò)展名,添加擴(kuò)展名.tm code = fopen(codefile,"w");/以只寫的方式打開(kāi)目標(biāo)匯編代碼文件,并返回地址給codez指針 if (code = NULL) printf("Unable to open %sn",codefile); exit(1); /如果code指針為空,打印顯示信息并退出 codeGe

19、n(syntaxTree,codefile);/目標(biāo)代碼生成 fclose(code); #endif#endif#endif/結(jié)束之前對(duì)應(yīng)的條件編譯 fclose(source); /關(guān)閉源代碼文件 return 0;GLOBALS.H/*/* File: globals.h */* Global types and vars for TINY compiler */* must come before other include files */* Compiler Construction: Principles and Practice */* Kenneth C. Louden */

20、*/#ifndef _GLOBALS_H_ #define _GLOBALS_H_ /宏定義#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <string.h> /頭文件引用#ifndef FALSE#define FALSE 0 /定義FALSE為0#endif #ifndef TRUE#define TRUE 1 /定義TRUE為1#endif/* MAXRESERVED = the number of reserved words */#define MAXRE

21、SERVED 8 /定義了關(guān)鍵字個(gè)數(shù)8個(gè)typedef enum /* book-keeping tokens */ ENDFILE,ERROR, /* reserved words */ IF,THEN,ELSE,END,REPEAT,UNTIL,READ,WRITE, /* multicharacter tokens */ ID,NUM, /* special symbols */ ASSIGN,EQ,LT,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,SEMI TokenType; / 定義了關(guān)鍵字,運(yùn)算符等內(nèi)容的枚舉值 extern FILE* source;

22、 /* source code text file源代碼地址 */ extern FILE* listing; /* listing output text file 顯示分析過(guò)程的文件的地址*/extern FILE* code; /* code text file for TM simulator 目標(biāo)匯編代碼文件的地址*/extern int lineno; /* source line number for listing */*/* Syntax tree for parsing */*/typedef enum StmtK,ExpK NodeKind;/定義了語(yǔ)句類型的枚舉值,這個(gè)

23、決定樹的節(jié)點(diǎn)typedef enum IfK,RepeatK,AssignK,ReadK,WriteK StmtKind;typedef enum OpK,ConstK,IdK ExpKind;/* ExpType is used for type checking */typedef enum Void,Integer,Boolean ExpType;/定義了變量類型#define MAXCHILDREN 3 /定義了最大子節(jié)點(diǎn)typedef struct treeNode/定義了樹的節(jié)點(diǎn) struct treeNode * childMAXCHILDREN; struct treeNode

24、 * sibling; int lineno; NodeKind nodekind; union StmtKind stmt; ExpKind exp; kind; union TokenType op; int val; char * name; attr; ExpType type; /* for type checking of exps */ TreeNode;/*/* Flags for tracing */*/* EchoSource = TRUE causes the source program to * be echoed to the listing file with l

25、ine numbers * during parsing */extern int EchoSource;/* TraceScan = TRUE causes token information to be * printed to the listing file as each token is * recognized by the scanner */extern int TraceScan;/* TraceParse = TRUE causes the syntax tree to be * printed to the listing file in linearized form

26、 * (using indents for children) */extern int TraceParse;/* TraceAnalyze = TRUE causes symbol table inserts * and lookups to be reported to the listing file */extern int TraceAnalyze;/* TraceCode = TRUE causes comments to be written * to the TM code file as code is generated */extern int TraceCode;/*

27、 Error = TRUE prevents further passes if an error occurs */extern int Error; #endifSCAN.C/* 詞法掃描程序 */#include "globals.h"#include "util.h"#include "scan.h"/*定義的狀態(tài)*/typedef enum START, /*初始狀態(tài)*/ INASSIGN, /*進(jìn)入到賦值狀態(tài)*/ INCOMMENT, /*進(jìn)入到注釋狀態(tài)*/ INNUM, /*進(jìn)入到數(shù)字狀態(tài)*/ INID, /*進(jìn)入到標(biāo)志

28、符狀態(tài)*/ DONE /*狀態(tài)結(jié)束*/StateType;/*每當(dāng)語(yǔ)法分析程序需要一個(gè)單詞時(shí),就調(diào)用該子程序,得到 (類別碼,單詞的值)*/* 語(yǔ)義標(biāo)識(shí)符和保留字*/char tokenStringMAXTOKENLEN+1;/* BUFLEN = 源代碼的輸入緩沖長(zhǎng)度 */#define BUFLEN 256static char lineBufBUFLEN; /* 當(dāng)前行 */static int linepos = 0; /* 在linebuf中的當(dāng)前位置*/static int bufsize = 0; /* 緩沖區(qū)的字符串當(dāng)前大小*/static int EOF_flag = FAL

29、SE; /* 如果讀入下一個(gè)字符出錯(cuò),設(shè)置EOF_flag為假。*/* 從linebuffer中讀取下一個(gè)非空白字符,如果讀完,則讀入新行。 */static int getNextChar(void) if (!(linepos < bufsize) lineno+; if (fgets(lineBuf,BUFLEN-1,source) if (EchoSource) fprintf(listing,"%4d: %s",lineno,lineBuf); bufsize = strlen(lineBuf); linepos = 0; return lineBuflin

30、epos+; else EOF_flag = TRUE; return EOF; else return lineBuflinepos+;/* 如果讀入下一個(gè)字符出錯(cuò),在linebuf中回退一個(gè)字符 。*/static void ungetNextChar(void) if (!EOF_flag) linepos- ;/* 保留字的查找表 */static struct char* str; TokenType tok; reservedWordsMAXRESERVED = "if",IF,"then",THEN,"else",ELS

31、E,"end",END, "repeat",REPEAT,"until",UNTIL,"read",READ, "write",WRITE; /* 標(biāo)識(shí)符是否是保留字*/static TokenType reservedLookup (char * s) int i; for (i=0;i<MAXRESERVED;i+) if (!strcmp(s,reservedWordsi.str) return reservedWordsi.tok; return ID;/* 掃描儀的主要功能函數(shù)g

32、ettoken返回源文件中下一個(gè)標(biāo)記 */TokenType getToken(void) /* 存入tokenstring的位置 */int tokenStringIndex = 0;/* 保存當(dāng)前要返回的token; */ TokenType currentToken;當(dāng)前狀態(tài) StateType state = START;/* 表示保存到tokenstring的flag */ int save; while (state != DONE) int c = getNextChar(); /*從輸入buf中讀入一個(gè)字符*/ save = TRUE; switch (state) case

33、START: if (isdigit(c) state = INNUM; else if (isalpha(c) /*判斷字母*/ state = INID; else if (c = ':') state = INASSIGN; else if (c = ' ') | (c = '/t') | (c = '/n') save = FALSE; else if (c = '') save = FALSE; state = INCOMMENT; else state = DONE; switch (c) case E

34、OF: save = FALSE; currentToken = ENDFILE; break; case '=': currentToken = EQ; break; case '<': currentToken = LT; break; case '+': currentToken = PLUS; break; case '-': currentToken = MINUS; break; case '*': currentToken = TIMES; break; case '/': cu

35、rrentToken = OVER; break; case '(': currentToken = LPAREN; break; case ')': currentToken = RPAREN; break; case '': currentToken = SEMI; break; default: currentToken = ERROR; break; break; case INCOMMENT: save = FALSE; if (c = EOF) state = DONE; currentToken = ENDFILE; else if

36、 (c = '') state = START; break; case INASSIGN: state = DONE; if (c = '=') currentToken = ASSIGN; else /* 在輸入中備份 */ ungetNextChar(); save = FALSE; currentToken = ERROR; break; case INNUM: if (!isdigit(c) /* 在輸入中備份 */ ungetNextChar(); save = FALSE; state = DONE; currentToken = NUM; bre

37、ak; case INID: if (!isalpha(c) /* 在輸入中備份*/ ungetNextChar(); save = FALSE; state = DONE; currentToken = ID; break; case DONE: default: /* 應(yīng)該不會(huì)執(zhí)行 */ fprintf(listing,"Scanner Bug: state= %d/n",state); state = DONE; currentToken = ERROR; break; if (save) && (tokenStringIndex <= MAXT

38、OKENLEN) tokenStringtokenStringIndex+ = (char) c; /*解析單詞結(jié)束*/ if (state = DONE) tokenStringtokenStringIndex = '/0' if (currentToken = ID) currentToken = reservedLookup(tokenString); if (TraceScan) fprintf(listing,"/t%d: ",lineno); printToken(currentToken,tokenString); return current

39、Token;SCAN.H/*/ /* 對(duì)于tiny編譯器的掃描程序接口 */*/#ifndef _SCAN_H_#define _SCAN_H_/* maxtokenlen是token的最大大小*/#define MAXTOKENLEN 40/* tokenString數(shù)組保存每個(gè)token */extern char tokenStringMAXTOKENLEN+1;/* f函數(shù)getToken返回源程序中的下一個(gè)token*/TokenType getToken(void);#endifUTIL.H/*/* File: util.h */* Utility functions for th

40、e TINY compiler */* Compiler Construction: Principles and Practice */* Kenneth C. Louden */*/#ifndef _UTIL_H_#define _UTIL_H_/* Procedure printToken prints a token * and its lexeme to the listing file */void printToken( TokenType, const char* );/* Function newStmtNode creates a new statement * node

41、for syntax tree construction */TreeNode * newStmtNode(StmtKind);/* Function newExpNode creates a new expression * node for syntax tree construction */TreeNode * newExpNode(ExpKind);/* Function copyString allocates and makes a new * copy of an existing string */char * copyString( char * );/* procedur

42、e printTree prints a syntax tree to the * listing file using indentation to indicate subtrees */void printTree( TreeNode * );#endifUTIL.C/*/* File: util.c */* Utility function implementation */* for the TINY compiler */* Compiler Construction: Principles and Practice */* Kenneth C. Louden */*/#inclu

43、de "globals.h"#include "util.h"/* Procedure printToken prints a token * and its lexeme to the listing file */void printToken( TokenType token, const char* tokenString )/此函數(shù)輸出一個(gè)標(biāo)號(hào)和一個(gè)詞素 switch (token) case IF: case THEN: case ELSE: case END: case REPEAT: case UNTIL: case READ: case

44、 WRITE: fprintf(listing, "reserved word: %sn",tokenString); break; case ASSIGN: fprintf(listing,":=n"); break; case LT: fprintf(listing,"<n"); break; case EQ: fprintf(listing,"=n"); break; case LPAREN: fprintf(listing,"(n"); break; case RPAREN: fp

45、rintf(listing,")n"); break; case SEMI: fprintf(listing,"n"); break; case PLUS: fprintf(listing,"+n"); break; case MINUS: fprintf(listing,"-n"); break; case TIMES: fprintf(listing,"*n"); break; case OVER: fprintf(listing,"/n"); break; case E

46、NDFILE: fprintf(listing,"EOFn"); break; case NUM: fprintf(listing, "NUM, val= %sn",tokenString); break; case ID: fprintf(listing, "ID, name= %sn",tokenString); break; case ERROR: fprintf(listing, "ERROR: %sn",tokenString); break; default: /* should never happen */ fprintf(listing,"Unknown token: %dn",token); /* Function newStmtNo

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論