TINY部分源码分析报告.docx

上传人:b****5 文档编号:3868523 上传时间:2022-11-26 格式:DOCX 页数:24 大小:22.89KB
下载 相关 举报
TINY部分源码分析报告.docx_第1页
第1页 / 共24页
TINY部分源码分析报告.docx_第2页
第2页 / 共24页
TINY部分源码分析报告.docx_第3页
第3页 / 共24页
TINY部分源码分析报告.docx_第4页
第4页 / 共24页
TINY部分源码分析报告.docx_第5页
第5页 / 共24页
点击查看更多>>
下载资源
资源描述

TINY部分源码分析报告.docx

《TINY部分源码分析报告.docx》由会员分享,可在线阅读,更多相关《TINY部分源码分析报告.docx(24页珍藏版)》请在冰豆网上搜索。

TINY部分源码分析报告.docx

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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 数学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1