TINY部分源码分析报告Word文档格式.docx

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

TINY部分源码分析报告Word文档格式.docx

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

TINY部分源码分析报告Word文档格式.docx

!

其结构如下所示:

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

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

当前位置:首页 > 人文社科 > 教育学心理学

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

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