版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、精品资料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-目标汇编代码文件。从该文件中可知程序运行的流程:检查参数正确否(tin
2、y.exefilename)->构造语法树(调用parse函数)->根据语法树生成代码(调用codeGen函数,该函数又调用cGen函数。2.GLOBALS.H:定义了关键字个数8个。定义了关键字,运算符等内容的枚举值。定义了语句类型的枚举值,这个决定树的结点。可编辑修改定义了变量类型(也就三种,void,integer,boolean)。定义了树的节点-这个最重要了!其结构如下所示:typedefstructtreeNodestructtreeNode*childMAXCHILDREN;structtreeNode*sibling;intlineno;NodeKindnodeki
3、nd;unionStmtKindstmt;ExpKindexp;kind;unionTokenTypeop;intval;char*name;attr;ExpTypetype;/*fortypecheckingofexps*/TreeNode;3.UTIL.C/UTIL.H主要函数TreeNode*newStmtNode(StmtKindkind)此函数创建一个有关语法树的声明节点TreeNode*newExpNode(ExpKindkind)此函数创建一个有关语法树的表述节点char*copyString(char*s)此函数分配和创建一个新的已存在树的复制voidprintTree(Tre
4、eNode*tree)输出一个语法树这两个文件主要是关于语法树的创建和输出4.SCAN.c/SCAN.H主要有这么几个函数:staticintgetNextChar(void);staticvoidungetNextChar(void);staticTokenTypereservedLookup(char*s);TokenTypegetToken(void);reservedLookup函数是查找关键字的,在符号表中找。这里还定义了一个保存关键字的结构:staticstructchar*str;TokenTypetok;reservedWordsMAXRESERVED"if"
5、;,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(!(linepo
6、s<bufsize)lineno+;if(fgets(lineBuf,BUFLEN-1,source)if(EchoSource)fprintf(listing,"%4d:%s",lineno,lineBuf);bufsize=strlen(lineBuf);linepos=0;returnlineBuflinepos+;elseEOF_flag=TRUE;returnEOF;elsereturnlineBuflinepos+;4.PARSE.C/PARSE.H有这么几个函数:TreeNode*parse(void)staticTreeNode*stmt_sequen
7、ce(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*fact
8、or(void);最重要的是parse这个函数,就是用来构造整个程序的语法树的。下面的一堆私有函数构造相应语法的语法树,然后parse最后把它们这些子树整合成一个大树。5.SYMTAB.C/SYMTAB.H这个是符号表操作的,也就是词法分析的时候查找表,看该token是不是关键字。如果不是,就当作表识符添加进去。在语法分析的时候也要用到,看变量有没有声明的时候用的。三、实验心得:通过这次实验,仔细地去查看和分析了TINY编译器的部分源码。了解到了编译器的运行:检查参数正确否(tiny.exefilename)->构造语法树(调用parse函数)->根据语法树生成代码(调用codeG
9、en函数),同时熟悉了编译器是如何使用prase函数进行语法树的构建以及语法树生成代码的转化,最主要的是进一步清晰了解到编译器的构造和运行原理,加深了对课本知识的运用和拓展,感觉收获很大!Main.c/*/*/*/*/*/*File:main.c/*MainprogramforTINYcompiler/*CompilerConstruction:PrinciplesandPractice/*KennethC.Louden/*/#include "globals.h/* set NO_PARSE to TRUE to get a scanner-only compiler创建一个只扫描
10、的编译器*/#define NO_PARSE FALSE/* set NO_ANALYZE to TRUE to get a parser-only compiler时创建一个只分析和扫描的编译器*/#define NO_ANALYZE FALSENO_PARSE 为 true 时NO_ANALYZE 为 true/*setNO_CODEtoTRUEtogetacompilerthatdoesnot*generatecodeNO_CODE为true时创建一个执行语义分析,但不生成代码的编译器*/#include "util.h"#if NO_PARSE #include &
11、quot;scan.h" #else#include "parse.h" #if !NO_ANALYZE #include "analyze.h #if !NO_CODE #include "cgen.h" #endif#defineNO_CODEFALSE/如果NO_PARSE为true,调用头文件scan.h/否则调用头文件prase.h/如果NO_ANALYZE为true,调用头文件analyze.h/如果NO_CODE为true,调用头文件cgen.h#endif#endif/结束预处理语句符号/*allocateglobal
12、variables分配全局变量*/intlineno=0;FILE*source;/指针指向源代码文件地址FILE*listing;/指针指向显示分析过程的文件的地址FILE*code;/指针指向目标汇编代码文件的地址/*allocateandsettracingflags分配和设置跟踪标志*/intEchoSource=FALSE;intTraceScan=FALSE;intTraceParse=FALSE;intTraceAnalyze=FALSE;intTraceCode=FALSE;intError=FALSE;/跟踪标志全部初始化为falsemain(intargc,char*arg
13、v)TreeNode*syntaxTree;charpgm120;/*sourcecodefilename*/if(argc!=2)fprintf(stderr,"usage:%s<filename>n",argv0);exit(1);/如果argv不为2,打印显示信息并退出strcpy(pgm,argv1);/复制argv1地址以null为退出字符的存储器区块到另一个存储器区块品pgm内if(strchr(pgm,'.')=NULL)strcat(pgm,".tny");/把.tyn文件所指字符串添加到pgm结尾处并添加
14、39;0'。source=fopen(pgm,"r");/以只读的方式打开pgm文件,并将指向pgm文件的指针返回给sourceif(source=NULL)fprintf(stderr,"File%snotfoundn",pgm);exit(1);/如果源代码文件为空,打印显示信息并退出listing=stdout;/*sendlistingtoscreen清单发送到屏幕*/fprintf(listing,"nTINYCOMPILATION:%sn",pgm);/答应显示语句#ifNO_PARSEwhile(getToken
15、()!=ENDFILE);/如果输入流没有结束就继续进行循环,直至结束#elsesyntaxTree=parse();/调用prase()函数构造语法树if(TraceParse)fprintf(listing,"nSyntaxtree:n");printTree(syntaxTree);/如果语法分析追踪标志为TRUE且没有语法错误,则将生成的语法树输出到屏幕#if!NO_ANALYZEif(!Error)if(TraceAnalyze)fprintf(listing,"nBuildingSymbolTable.n");buildSymtab(synt
16、axTree);/输出含符号表信息的语法树if(TraceAnalyze)fprintf(listing,"nCheckingTypes.n");typeCheck(syntaxTree);/输出含类型检查的语法树if(TraceAnalyze)fprintf(listing,"nTypeCheckingFinishedn");/打印结束信息#if!NO_CODEif(!Error)char*codefile;intfnlen=strcspn(pgm,".");codefile=(char*)calloc(fnlen+4,sizeof
17、(char);strncpy(codefile,pgm,fnlen);strcat(codefile,".tm");/将源文件名,去掉扩展名,添加扩展名.tmcode=fopen(codefile,"w");/以只写的方式打开目标汇编代码文件,并返回地址给codez指针if(code=NULL)printf("Unabletoopen%sn",codefile);exit(1);/如果code指针为空,打印显示信息并退出codeGen(syntaxTree,codefile);/目标代码生成fclose(code);#endif#en
18、dif#endif/结束之前对应的条件编译fclose(source);/关闭源代码文件return0;GLOBALS.H/*/*File:globals.h*/*GlobaltypesandvarsforTINYcompiler*/*mustcomebeforeotherincludefiles*/*CompilerConstruction:PrinciplesandPractice*/*KennethC.Louden*/*/#ifndef_GLOBALS_H_#define_GLOBALS_H_/宏定义#include<stdio.h>#include<stdlib.h&
19、gt;#include<ctype.h>#include<string.h>/头文件引用#ifndefFALSE#defineFALSE0/定义FALSE为0#endif#ifndefTRUE#defineTRUE1/定义TRUE为1#endif/*MAXRESERVED=thenumberofreservedwords*/#defineMAXRESERVED8/定义了关键字个数8个typedefenum/*book-keepingtokens*/ENDFILE,ERROR,/*reservedwords*/IF,THEN,ELSE,END,REPEAT,UNTIL,R
20、EAD,WRITE,/*multicharactertokens*/ID,NUM,/*specialsymbols*/ASSIGN,EQ,LT,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,SEMITokenType;/定义了关键字,运算符等内容的枚举值externFILE*source;/*sourcecodetextfileexternFILE*listing;/*listingoutputtextfile源代码地址*/显示分析过程的文件的地址*/目标汇编代码文件的地址 */externFILE*code;/*codetextfileforTMsimulatore
21、xternintlineno;/*sourcelinenumberforlisting*/*/*Syntaxtreeforparsing*/*/typedefenumStmtK,ExpKNodeKind;/定义了语句类型的枚举值,这个决定树的节点typedefenumIfK,RepeatK,AssignK,ReadK,WriteKStmtKind;typedefenumOpK,ConstK,IdKExpKind;/*ExpTypeisusedfortypechecking*/typedefenumVoid,Integer,BooleanExpType;/定义了变量类型#defineMAXCHI
22、LDREN3/定义了最大子节点typedefstructtreeNode/定义了树的节点structtreeNode*childMAXCHILDREN;structtreeNode*sibling;intlineno;NodeKindnodekind;unionStmtKindstmt;ExpKindexp;kind;unionTokenTypeop;intval;char*name;attr;ExpTypetype;/*fortypecheckingofexps*/TreeNode;/*Flags for tracing*/*/*/*EchoSource=TRUEcausesthesourc
23、eprogramto* beechoedtothelistingfilewithlinenumbers* duringparsing* /externintEchoSource;/*TraceScan=TRUEcausestokeninformationtobe* printedtothelistingfileaseachtokenis* recognizedbythescanner* /externintTraceScan;/*TraceParse=TRUEcausesthesyntaxtreetobe* printedtothelistingfileinlinearizedform* (u
24、singindentsforchildren)* /externintTraceParse;/*TraceAnalyze=TRUEcausessymboltableinserts* andlookupstobereportedtothelistingfile*/externintTraceAnalyze;/*TraceCode=TRUEcausescommentstobewritten* totheTMcodefileascodeisgenerated*/externintTraceCode;/*Error=TRUEpreventsfurtherpassesifanerroroccurs*/e
25、xternintError;#endifSCAN.C/*词法扫描程序*/#include"globals.h"#include"util.h"#include"scan.h"/*定义的状态*/typedefenumSTART,/*初始状态*/INASSIGN,/*进入到赋值状态*/INCOMMENT,/*进入到注释状态*/INNUM,/*进入到数字状态*/INID,/*进入到标志符状态*/DONE/*状态结束*/StateType;/*每当语法分析程序需要一个单词时,就调用该子程序,得到(类别码,单词的值)*/*语义标识符和保留字*/
26、chartokenStringMAXTOKENLEN+1;/*BUFLEN=源代码的输入缓冲长度*/#defineBUFLEN256staticcharlineBufBUFLEN;/*当前行*/staticintlinepos=0;/*在linebuf中的当前位置*/staticintbufsize=0;/*缓冲区的字符串当前大小*/staticintEOF_flag=FALSE;/*如果读入下一个字符出错,设置EOF_flag为假。*/*从linebuffer中读取下一个非空白字符,如果读完,则读入新行。*/staticintgetNextChar(void)if(!(linepos<
27、bufsize)lineno+;if(fgets(lineBuf,BUFLEN-1,source)if(EchoSource)fprintf(listing,"%4d:%s",lineno,lineBuf);bufsize=strlen(lineBuf);linepos=0;returnlineBuflinepos+;elseEOF_flag=TRUE;returnEOF;elsereturnlineBuflinepos+;/*如果读入下一个字符出错,在linebuf中回退一个字符。*/staticvoidungetNextChar(void)if(!EOF_flag)li
28、nepos-;/*保留字的查找表*/staticstructchar*str;TokenTypetok;reservedWordsMAXRESERVED="if",IF,"then",THEN,"else",ELSE,"end",END,"repeat",REPEAT,"until",UNTIL,"read",READ,"write",WRITE;/*标识符是否是保留字*/staticTokenTypereservedLookup(ch
29、ar*s)inti;for(i=0;i<MAXRESERVED;i+)if(!strcmp(s,reservedWordsi.str)returnreservedWordsi.tok;returnID;/*扫描仪的主要功能函数gettoken返回源文件中下一个标记*/TokenTypegetToken(void)/*存入tokenstring的位置*/inttokenStringIndex=0;/*保存当前要返回的token;*/TokenTypecurrentToken;当前状态StateTypestate=START;/*表示保存到tokenstring的flag*/intsave;
30、while(state!=DONE)intc=getNextChar();/*从输入buf中读入一个字符*/save=TRUE;switch(state)caseSTART:if(isdigit(c)state=INNUM;elseif(isalpha(c)/*判断字母*/state=INID;elseif(c=':')state=INASSIGN;elseif(c='')|(c='/t')|(c='/n')save=FALSE;elseif(c='')save=FALSE;state=INCOMMENT;else
31、state=DONE;switch(c)caseEOF:save=FALSE;currentToken=ENDFILE;break;case'=':currentToken=EQ;break;case'<':currentToken=LT;break;case'+':currentToken=PLUS;break;case'-':currentToken=MINUS;break;casecurrentToken=TIMES;break;case'/':currentToken=OVER;break;case&
32、#39;(':currentToken=LPAREN;break;case')':currentToken=RPAREN;break;case'':currentToken=SEMI;break;default:currentToken=ERROR;break;break;caseINCOMMENT:save=FALSE;if(c=EOF)state=DONE;currentToken=ENDFILE;elseif(c='')state=START;break;caseINASSIGN:state=DONE;if(c='='
33、;)currentToken=ASSIGN;else/*在输入中备份*/ungetNextChar();save=FALSE;currentToken=ERROR;break;caseINNUM:if(!isdigit(c)/*在输入中备份*/ungetNextChar();save=FALSE;state=DONE;currentToken=NUM;break;caseINID:if(!isalpha(c)/*在输入中备份*/ungetNextChar();save=FALSE;state=DONE;currentToken=ID;break;caseDONE:default:/*应该不会执
34、行*/fprintf(listing,"ScannerBug:state=%d/n",state);state=DONE;currentToken=ERROR;break;if(save)&&(tokenStringIndex<=MAXTOKENLEN)tokenStringtokenStringIndex+=(char)c;/*解析单词结束*/if(state=DONE)tokenStringtokenStringIndex='/0'if(currentToken=ID)currentToken=reservedLookup(toke
35、nString);if(TraceScan)fprintf(listing,"/t%d:",lineno);printToken(currentToken,tokenString);returncurrentToken;SCAN.H/*/*对于tiny编译器的扫描程序接口*/*/#ifndef_SCAN_H_#define_SCAN_H_/*maxtokenlen是token的最大大小*/#defineMAXTOKENLEN40/*tokenString数组保存每个token*/externchartokenStringMAXTOKENLEN+1;/*f函数getToken
36、返回源程序中的下一个token*/TokenTypegetToken(void);#endifUTIL.H/*/*/*File:util.h/*UtilityfunctionsfortheTINYcompiler*/*CompilerConstruction:PrinciplesandPractice*/*/*KennethC.Louden/*/#ifndef_UTIL_H_#define_UTIL_H_/*ProcedureprintTokenprintsatoken* anditslexemetothelistingfile* /voidprintToken(TokenType,const
37、char*);/*FunctionnewStmtNodecreatesanewstatement* nodeforsyntaxtreeconstruction* /TreeNode*newStmtNode(StmtKind);/*FunctionnewExpNodecreatesanewexpression* nodeforsyntaxtreeconstruction* /TreeNode*newExpNode(ExpKind);/*FunctioncopyStringallocatesandmakesanew* copyofanexistingstring* /char*copyString
38、(char*);/*procedureprintTreeprintsasyntaxtreetothe* listingfileusingindentationtoindicatesubtrees* /voidprintTree(TreeNode*);#endifUTIL.C/*/*/*File:util.c/*Utilityfunctionimplementation*/*fortheTINYcompiler*/*CompilerConstruction:PrinciplesandPractice*/*/*KennethC.Louden/*/#include"globals.h#in
39、clude"util.h"/*ProcedureprintTokenprintsatoken* anditslexemetothelistingfile此函数输出一个标号*/voidprintToken(TokenTypetoken,constchar*tokenString)/和一个词素switch(token)caseIF:caseTHEN:caseELSE:caseEND:caseREPEAT:caseUNTIL:caseREAD:caseWRITE:fprintf(listing,"reservedword:%sn",tokenString);b
40、reak;caseASSIGN:fprintf(listing,":=n");break;caseLT:fprintf(listing,"<n");break;caseEQ:fprintf(listing,"=n");break;caseLPAREN:fprintf(listing,"(n");break;caseRPAREN:fprintf(listing,")n");break;caseSEMI:fprintf(listing,"n");break;casePLUS
41、:fprintf(listing,"+n");break;caseMINUS:fprintf(listing,"-n");break;caseTIMES:fprintf(listing,"*n");break;caseOVER:fprintf(listing,"/n");break;caseENDFILE:fprintf(listing,"EOFn");break;caseNUM:fprintf(listing,"NUM,val=%sn",tokenString);break
42、;caseID:fprintf(listing,"ID,name=%sn",tokenString);break;caseERROR:fprintf(listing,"ERROR:%sn",tokenString);break;default:/*shouldneverhappen*/fprintf(listing,"Unknowntoken:%dn",token);/*FunctionnewStmtNodecreatesanewstatement* nodeforsyntaxtreeconstruction* /TreeNode*n
43、ewStmtNode(StmtKindkind)/此函数创建一个有关此法树的声明节点TreeNode*t=(TreeNode*)malloc(sizeof(TreeNode);inti;if(t=NULL)fprintf(listing,"Outofmemoryerroratline%dn",lineno);elsefor(i=0;i<MAXCHILDREN;i+)t->childi=NULL;t->sibling=NULL;t->nodekind=StmtK;t->kind.stmt=kind;t->lineno=lineno;retu
44、rnt;/*FunctionnewExpNodecreatesanewexpression*nodeforsyntaxtreeconstruction*/TreeNode*newExpNode(ExpKindkind)/此函数创建一个有关此法树的表述节点TreeNode*t=(TreeNode*)malloc(sizeof(TreeNode);inti;if(t=NULL)fprintf(listing,"Outofmemoryerroratline%dn",lineno);elsefor(i=0;i<MAXCHILDREN;i+)t->childi=NULL;
45、t->sibling=NULL;t->nodekind=ExpK;t->kind.exp=kind;t->lineno=lineno;t->type=Void;returnt;/*FunctioncopyStringallocatesandmakesanew*copyofanexistingstring*/char*copyString(char*s)/此函数分配和创建一个新的已存在树的复制intn;char*t;if(s=NULL)returnNULL;n=strlen(s)+1;t=malloc(n);if(t=NULL)fprintf(listing,"Outofmemoryerr
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年衢州市衢江区政务服务中心(窗口人员)招聘笔试参考试题及答案详解
- 2026江西九江市委机关幼儿园公开招聘合同制员工4人笔试备考试题及答案详解
- 沧州机箱机柜钣金加工质量管控方案
- 铁路青年职工当前思想状况调研报告(3篇)
- (新)劳动合同私了协议书(2026版)-1
- 2026年辽宁省阜新市政务服务中心(窗口人员)招聘笔试参考题库及答案详解
- 空运面试常见问题及对应答案
- 2026年银川市金凤区医疗系统事业编人员招聘笔试备考题库及答案详解
- 2026年广东省汕头市医疗系统事业编人员招聘笔试参考试题及答案详解
- 2026年舟山市定海区工会人员招聘笔试模拟试题及答案详解
- 2024版人教版初中语文九上名著《唐诗三百首》复习题
- T∕CAGIS 20-2026 T∕CSGPC 70-2026 测绘地理信息技术服务成本要素 通则
- 2026年文物保护工程从业资格考试(责任工程师近现代重要史迹及代表性建筑)经典试题及答案
- GB/T 17623-2026绝缘油中溶解气体组分含量的气相色谱测定法
- 2026年中国时尚耳夹数据监测研究报告
- 2026年4月自考02160流体力学试题及答案含评分参考
- 广西壮族自治区梧州市2026年高三第一次模拟考试物理试卷(含答案解析)
- 2026广州医药集团有限公司春季校园招聘笔试历年典型考点题库附带答案详解
- 上海市二级注册建造师继续教育(建筑工程)考试题库
- 电玩城安全生产责任制度
- pe管道顶管施工方案
评论
0/150
提交评论