TINY部分源码分析报告.docx
- 文档编号:3868523
- 上传时间:2022-11-26
- 格式:DOCX
- 页数:24
- 大小:22.89KB
TINY部分源码分析报告.docx
《TINY部分源码分析报告.docx》由会员分享,可在线阅读,更多相关《TINY部分源码分析报告.docx(24页珍藏版)》请在冰豆网上搜索。
TINY部分源码分析报告
TINY源码分析
一、文件概述
MAIN.C:
主函数
GLOBALS.H:
全局定义的文件
SCAN.C/SCAN.H:
词法分析
PARSE.C/PARSE.H:
语法分析
UTIL.C/UTIL.H:
构造树
SYMTAB.C/SYMTAB.H:
符号表
CGEN.C/CGEN.H:
生成"汇编代码"
CODE.C/CODE.H:
这个只是用来把分析过程输出到屏幕的.
二、各个文件的分析
1.MAIN.C:
主要有三个FILE*句柄:
source--源代码文件。
listing--显示分析过程的文件,这里重定向到stdout。
code--目标汇编代码文件。
从该文件中可知程序运行的流程:
检查参数正确否(tiny.exe)->构造语法树(调用parse函数)->根据语法树生成代码(调用codeGen函数,该函数又调用cGen函数。
2.GLOBALS.H:
定义了关键字个数8个。
定义了关键字,运算符等内容的枚举值。
定义了语句类型的枚举值,这个决定树的结点。
定义了变量类型(也就三种,void,integer,boolean)。
定义了树的节点--这个最重要了!
!
其结构如下所示:
typedefstructtreeNode
{
structtreeNode*child[MAXCHILDREN];
structtreeNode*sibling;
intlineno;
NodeKindnodekind;
union{StmtKindstmt;ExpKindexp;}kind;
union{TokenTypeop;
intval;
char*name;}attr;
ExpTypetype;/*fortypecheckingofexps*/
}TreeNode;
3.UTIL.C/UTIL.H
主要函数
TreeNode*newStmtNode(StmtKindkind)
此函数创建一个有关语法树的声明节点
TreeNode*newExpNode(ExpKindkind)
此函数创建一个有关语法树的表述节点
char*copyString(char*s)
此函数分配和创建一个新的已存在树的复制
voidprintTree(TreeNode*tree)
输出一个语法树
这两个文件主要是关于语法树的创建和输出
4.SCAN.c/SCAN.H
主要有这么几个函数:
staticintgetNextChar(void);
staticvoidungetNextChar(void);
staticTokenTypereservedLookup(char*s);
TokenTypegetToken(void);
reservedLookup函数是查找关键字的,在符号表中找。
这里还定义了一个保存关键字的结构:
staticstruct
{char*str;
TokenTypetok;
}reservedWords[MAXRESERVED]
=
{{"if",IF},{"then",THEN},{"else",ELSE},{"end",END},
{"repeat",REPEAT},{"until",UNTIL},{"read",READ},
{"write",WRITE}};
最重要的是getToken(void)函数。
这个相当于lex的功能,进行词法分析。
也就是一个DFA,switch后面跟了一堆的case。
其中getNextChar(void)函数的思路,以下列出:
staticintgetNextChar(void)
{
if(!
(linepos { lineno++; if(fgets(lineBuf,BUFLEN-1,source)) { if(EchoSource)fprintf(listing,"%4d: %s",lineno,lineBuf); bufsize=strlen(lineBuf); linepos=0; returnlineBuf[linepos++]; } else { EOF_flag=TRUE; returnEOF; } } elsereturnlineBuf[linepos++]; } 4.PARSE.C/PARSE.H 有这么几个函数: TreeNode*parse(void) staticTreeNode*stmt_sequence(void); staticTreeNode*statement(void); staticTreeNode*if_stmt(void); staticTreeNode*repeat_stmt(void); staticTreeNode*assign_stmt(void); staticTreeNode*read_stmt(void); staticTreeNode*write_stmt(void); staticTreeNode*exp(void); staticTreeNode*simple_exp(void); staticTreeNode*term(void); staticTreeNode*factor(void); 最重要的是parse这个函数,就是用来构造整个程序的语法树的。 下面的一堆私有函数构造相应语法的语法树,然后parse最后把它们这些子树整合成一个大树。 5.SYMTAB.C/SYMTAB.H 这个是符号表操作的,也就是词法分析的时候查找表,看该token是不是关键字。 如果不是,就当作表识符添加进去。 在语法分析的时候也要用到,看变量有没有声明的时候用的。 三、实验心得: 通过这次实验,仔细地去查看和分析了TINY编译器的部分源码。 了解到了编译器的运行: 检查参数正确否(tiny.exe)->构造语法树(调用parse函数)->根据语法树生成代码(调用codeGen函数),同时熟悉了编译器是如何使用prase函数进行语法树的构建以及语法树生成代码的转化,最主要的是进一步清晰了解到编译器的构造和运行原理,加深了对课本知识的运用和拓展,感觉收获很大! Main.c /****************************************************/ /*File: main.c*/ /*MainprogramforTINYcompiler*/ /*CompilerConstruction: PrinciplesandPractice*/ /*KennethC.Louden*/ /****************************************************/ #include"globals.h" /*setNO_PARSEtoTRUEtogetascanner-onlycompiler,NO_PARSE为true时创建一个只扫描的编译器*/ #defineNO_PARSEFALSE /*setNO_ANALYZEtoTRUEtogetaparser-onlycompiler,NO_ANALYZE为true时创建一个只分析和扫描的编译器*/ #defineNO_ANALYZEFALSE /*setNO_CODEtoTRUEtogetacompilerthatdoesnot *generatecodeNO_CODE为true时创建一个执行语义分析,但不生成代码的编译器 */ #defineNO_CODEFALSE #include"util.h" #ifNO_PARSE #include"scan.h"//如果NO_PARSE为true,调用头文件scan.h #else #include"parse.h"//否则调用头文件prase.h #if! NO_ANALYZE #include"analyze.h"//如果NO_ANALYZE为true,调用头文件analyze.h #if! NO_CODE #include"cgen.h"//如果NO_CODE为true,调用头文件cgen.h #endif #endif #endif//结束预处理语句符号 /*allocateglobalvariables分配全局变量*/ intlineno=0; FILE*source;//指针指向源代码文件地址 FILE*listing;//指针指向显示分析过程的文件的地址 FILE*code;//指针指向目标汇编代码文件的地址 /*allocateandsettracingflags分配和设置跟踪标志*/ intEchoSource=FALSE; intTraceScan=FALSE; intTraceParse=FALSE; intTraceAnalyze=FALSE; intTraceCode=FALSE; intError=FALSE;//跟踪标志全部初始化为false main(intargc,char*argv[]) {TreeNode*syntaxTree; charpgm[120];/*sourcecode*/ if(argc! =2) {fprintf(stderr,"usage: %s<>\n",argv[0]); exit (1);//如果argv不为2,打印显示信息并退出 } strcpy(pgm,argv[1]);//复制argv[1]地址以null为退出字符的存储器区块到另一个存储器区块品pgm内 if(strchr(pgm,'.')==NULL) strcat(pgm,".tny");//把.tyn文件所指字符串添加到pgm结尾处并添加'\0'。 source=fopen(pgm,"r");//以只读的方式打开pgm文件,并将指向pgm文件的指针返回给source if(source==NULL) {fprintf(stderr,"notfound\n",pgm); exit (1);//如果源代码文件为空,打印显示信息并退出 } listing=stdout;/*sendlistingtoscreen清单发送到屏幕*/ fprintf(listing,"\nTINYCOMPILATION: %s\n",pgm);//答应显示语句 #ifNO_PARSE while(getToken()! =ENDFILE);//如果输入流没有结束就继续进行循环,直至结束 #else syntaxTree=parse();//调用prase()函数构造语法树 if(TraceParse){ fprintf(listing,"\nSyntaxtree: \n"); printTree(syntaxTree);//如果语法分析追踪标志为TRUE且没有语法错误,则将生成的语法树输出到屏幕 } #if! NO_ANALYZE if(! Error) {if(TraceAnalyze)fprintf(listing,"\nBuildingSymbolTable...\n"); buildSymtab(syntaxTree);//输出含符号表信息的语法树 if(TraceAnalyze)fprintf(listing,"\nCheckingTypes...\n"); typeCheck(syntaxTree);//输出含类型检查的语法树 if(TraceAnalyze)fprintf(listing,"\nTypeCheckingFinished\n");//打印结束信息 } #if! NO_CODE if(! Error) {char*codefile; intfnlen=strcspn(pgm,"."); codefile=(char*)calloc(fnlen+4,sizeof(char)); strncpy(code); strcat(codefile,".tm");//将源文件名,去掉扩展名,添加扩展名.tm code=fopen(codefile,"w");//以只写的方式打开目标汇编代码文件,并返回地址给codez指针 if(code==NULL) {printf("Unabletoopen%s\n",codefile); exit (1);//如果code指针为空,打印显示信息并退出 } codeGen(syntaxTree,code目标代码生成 fclose(code); } #endif #endif #endif//结束之前对应的条件编译 fclose(source);//关闭源代码文件 return0; } GLOBALS.H /****************************************************/ /*File: globals.h*/ /*GlobaltypesandvarsforTINYcompiler*/ /*mustcomebeforeotherincludefiles*/ /*CompilerConstruction: PrinciplesandPractice*/ /*KennethC.Louden*/ /****************************************************/ #ifndef_GLOBALS_H_ #define_GLOBALS_H_//宏定义 #include #include #include #include #ifndefFALSE #defineFALSE0//定义FALSE为0 #endif #ifndefTRUE #defineTRUE1//定义TRUE为1 #endif /*MAXRESERVED=thenumberofreservedwords*/ #defineMAXRESERVED8//定义了关键字个数8个 typedefenum /*book-keepingtokens*/ {END, /*reservedwords*/ IF,THEN,ELSE,END,REPEAT,UNTIL,READ,WRITE, /*multicharactertokens*/ ID,NUM, /*specialsymbols*/ ASSIGN,EQ,LT,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,SEMI }TokenType;//定义了关键字,运算符等内容的枚举值 externFILE*source;/*sourcecodetextfile源代码地址*/ externFILE*listing;/*listingoutputtextfile显示分析过程的文件的地址*/ externFILE*code;/*codetextTMsimulator目标汇编代码文件的地址*/ externintlineno;/*sourcelinenumberforlisting*/ /**************************************************/ /***********Syntaxtreeforparsing************/ /**************************************************/ typedefenum{StmtK,ExpK}NodeKind;//定义了语句类型的枚举值,这个决定树的节点 typedefenum{IfK,RepeatK,AssignK,ReadK,WriteK}StmtKind; typedefenum{OpK,ConstK,IdK}ExpKind; /*ExpTypeisusedfortypechecking*/ typedefenum{Void,Integer,Boolean}ExpType;//定义了变量类型 #defineMAXCHILDREN3//定义了最大子节点 typedefstructtreeNode//定义了树的节点 {structtreeNode*child[MAXCHILDREN]; structtreeNode*sibling; intlineno; NodeKindnodekind; union{StmtKindstmt;ExpKindexp;}kind; union{TokenTypeop; intval; char*name;}attr; ExpTypetype;/*fortypecheckingofexps*/ }TreeNode; /**************************************************/ /***********Flagsfortracing************/ /**************************************************/ /*EchoSource=TRUEcausesthesourceprogramto *beechoedtothelistinglinenumbers *duringparsing */ externintEchoSource; /*TraceScan=TRUEcausestokeninformationtobe *printedtothelistingeachtokenis *recognizedbythescanner */ externintTraceScan; /*TraceParse=TRUEcausesthesyntaxtreetobe *printedtothelistinglinearizedform *(usingindentsforchildren) */ externintTraceParse; /*TraceAnalyze=TRUEcausessymboltableinserts *andlookupstobereportedtothelistingfile */ externintTraceAnalyze; /*TraceCode=TRUEcausescommentstobewritten *totheTMcodecodeisgenerated */ externintTraceCode; /*Error=TRUEpreventsfurtherpassesifanerroroccurs*/ externintError; #endif SCAN.C /*词法扫描程序*/ #include"globals.h" #include"util.h" #include"scan.h" /*定义的状态*/ typedefenum { START,/*初始状态*/ INASSIGN,/*进入到赋值状态*/ INCOMMENT,/*进入到注释状态*/ INNUM,/*进入到数字状态*/ INID,/*进入到标志符状态*/ DONE/*状态结束*/ }StateType; /*每当语法分析程序需要一个单词时,就调用该子程序,得到(类别码,单词的值)*/ /*语义标识符和保留字*/ chartokenString[MAXTOKENLEN+1]; /*BUFLEN=源代码的输入缓冲长度*/ #defineBUFLEN256 staticcharlineBuf[BUFLEN];/*当前行*/ staticintlinepos=0;/*在linebuf中的当前位置*/ staticintbufsize=0;/*缓冲区的字符串当前大小*/ staticintEOF_flag=FALSE;/*如果读入下一个字符出错,设置EOF_flag为假。 */ /*从linebuffer中读取下一个非空白字符,如果读完,则读入新行。 */ staticintgetNextChar(void) {if(! (linepos {lineno++; if(fgets(lineBuf,BUFLEN-1,source)) {if(EchoSource)fprintf(listing,"%4d: %s",lineno,lineBuf); bufsize=strlen(lineBuf); linepos=0; returnlineBuf[linepos++]; } else {EOF_flag=TRUE; returnEOF; } } elsereturnlineBuf[linepos++]; } /*如果读入下一个字符出错,在linebuf中回退一个字符。 */ staticvoidungetNextChar(void) {if(! EOF_flag)linepos--;} /*保留字的查找表*/ staticstruct {char*str; TokenTypetok; }reservedWords[MAXRESERVED] ={{"if",IF},{"then",THEN},{"else",ELSE},{"end",END}, {"repeat",REPEAT},{"until",UNTIL},{"read",READ}, {"write",WRITE}}; /*标识符是否是保留字*/ staticTokenTypereservedLookup(char*s) {inti; for(i=0;i if(! s
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- TINY 部分 源码 分析 报告