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

!
其结构如下所示:
typedefstructtreeNode
{
structtreeNode*child[MAXCHILDREN];
structtreeNode*sibling;
intlineno;
NodeKindnodekind;
union{StmtKindstmt;
ExpKindexp;
}kind;
union{TokenTypeop;
intval;
char*name;
}attr;
ExpTypetype;
/*fortypecheckingofexps*/
}TreeNode;
3.UTIL。
H
主要函数
TreeNode*newStmtNode(StmtKindkind)
此函数创建一个有关语法树的声明节点
TreeNode*newExpNode(ExpKindkind)
此函数创建一个有关语法树的表述节点
char*copyString(char*s)
此函数分配和创建一个新的已存在树的复制
voidprintTree(TreeNode*tree)
输出一个语法树
这两个文件主要是关于语法树的创建和输出
4.SCAN。
c/SCAN。
主要有这么几个函数:
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〈bufsize))
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。
有这么几个函数:
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。
C/SYMTAB.H
这个是符号表操作的,也就是词法分析的时候查找表,看该token是不是关键字。
如果不是,就当作表识符添加进去。
在语法分析的时候也要用到,看变量有没有声明的时候用的。
三、实验心得:
通过这次实验,仔细地去查看和分析了TINY编译器的部分源码。
了解到了编译器的运行:
exefilename)—〉构造语法树(调用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。
#if!
NO_CODE
cgen。
//如果NO_CODE为true,调用头文件cgen。
#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];
/*sourcecodefilename*/
if(argc!
=2)
{fprintf(stderr,"
usage:
%s<
filename〉\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,”File%snotfound\n"
pgm);
exit
(1);
//如果源代码文件为空,打印显示信息并退出
}
listing=stdout;
/*sendlistingtoscreen清单发送到屏幕*/
fprintf(listing,"
\nTINYCOMPILATION:
%s\n”,pgm);
//答应显示语句
#ifNO_PARSE
while(getToken()!
=ENDFILE);
//如果输入流没有结束就继续进行循环,直至结束
syntaxTree=parse();
//调用prase()函数构造语法树
if(TraceParse){
\nSyntaxtree:
\n”);
printTree(syntaxTree);
//如果语法分析追踪标志为TRUE且没有语法错误,则将生成的语法树输出到屏幕
#if!
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!
if(!
{char*codefile;
intfnlen=strcspn(pgm,"
.”);
codefile=(char*)calloc(fnlen+4,sizeof(char));
strncpy(codefile,pgm,fnlen);
strcat(codefile,”.tm”);
//将源文件名,去掉扩展名,添加扩展名.tm
code=fopen(codefile,”w"
//以只写的方式打开目标汇编代码文件,并返回地址给codez指针
if(code==NULL)
{printf(”Unabletoopen%s\n”,codefile);
//如果code指针为空,打印显示信息并退出
codeGen(syntaxTree,codefile);
//目标代码生成
fclose(code);
#endif//结束之前对应的条件编译
fclose(source);
//关闭源代码文件
return0;
/****************************************************/
/*File:
globals.h*/
/*GlobaltypesandvarsforTINYcompiler*/
/*mustcomebeforeotherincludefiles*/
/*KennethC.Louden*/
/****************************************************/
#ifndef_GLOBALS_H_
#define_GLOBALS_H_//宏定义
#include〈stdio。
h〉
#include〈stdlib.h〉
#include<
ctype。
#include<
string.h〉//头文件引用
#ifndefFALSE
#defineFALSE0//定义FALSE为0
#endif
#ifndefTRUE
#defineTRUE1//定义TRUE为1
/*MAXRESERVED=thenumberofreservedwords*/
#defineMAXRESERVED8//定义了关键字个数8个
typedefenum
/*book-keepingtokens*/
{ENDFILE,ERROR,
/*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;
/*codetextfileforTMsimulator目标汇编代码文件的地址*/
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;
union{TokenTypeop;
intval;
char*name;
}attr;
ExpTypetype;
/*fortypecheckingofexps*/
}TreeNode;
/**************************************************/
/***********Flagsfortracing************/
/**************************************************/
/*EchoSource=TRUEcausesthesourceprogramto
*beechoedtothelistingfilewithlinenumbers
*duringparsing
externintEchoSource;
/*TraceScan=TRUEcausestokeninformationtobe
*printedtothelistingfileaseachtokenis
*recognizedbythescanner
externintTraceScan;
/*TraceParse=TRUEcausesthesyntaxtreetobe
*printedtothelistingfileinlinearizedform
*(usingindentsforchildren)
*/
externintTraceParse;
/*TraceAnalyze=TRUEcausessymboltableinserts
*andlookupstobereportedtothelistingfile
externintTraceAnalyze;
/*TraceCode=TRUEcausescommentstobewritten
*totheTMcodefileascodeisgenerated
externintTraceCode;
/*Error=TRUEpreventsfurtherpassesifanerroroccurs*/
externintError;
#endif
C
/*词法扫描程序*/
#include”globals。
h”
util.h”
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中读取下一个非空白字符,如果读完,则读入新行.*/
{if(!
(linepos<
bufsize))
{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--;
/*保留字的查找表*/
{char*str;
TokenTypetok;
}reservedWords[MAXRESERVED]
={{”if”,IF},{”then”,THEN},{”else”,ELSE},{"
end"
END},
{"
repeat”,REPEAT},{"
until"
UNTIL},{"
read”,READ},
{”write"
WR