关闭

关闭

关闭

封号提示

内容

首页 编译原理实验报告.doc

编译原理实验报告.doc

编译原理实验报告.doc

上传者: tan超chao 2018-01-16 评分 0 0 0 0 0 0 暂无简介 简介 举报

简介:本文档为《编译原理实验报告doc》,可适用于IT/计算机领域,主题内容包含编译原理实验报告实验报告课程名称编译原理题目名称对PL的修改与扩充学生学院计算机学院专业班级计算机科学与技术四班学号学生姓名指导教师张巍年月日编译原符等。

编译原理实验报告实验报告课程名称编译原理题目名称对PL的修改与扩充学生学院计算机学院专业班级计算机科学与技术四班学号学生姓名指导教师张巍年月日编译原理实验报告一、实验内容对PL作以下修改扩充:()增加单词:保留字ELSEREPEATUNTILRETURN运算符==()修改单词:不等号#改为<>()增加条件语句的ELSE子句二、概述程序运行环境:、实现工具:BorlandCBuilding、运行平台:WindowsX,NT,,XP源程序:PL源程序是基于C语言写的PL编译程序它包含了词法分析程序、语法语义分析程序、代码生成程序和目标程序。其中语法语义分析程序包括表格管理程序和出错处理程序。PL编译程序以语法语义分析程序为核心词法分析程序和大妈生成程序都作为一个独立的过程当语法分析需要读入单词时就调用词法分析程序而当语法分析正确需生成相应的目标代码时则调用代码生成程序。此外用表格管理程序建立变量、常量和过程标识符的说明与引用之间的信息联系。用出错处理程序对词法和语法分析遇到的错误给出在源程序中出错的位置和错误性质。当源程序编译正确时PL编译程序自动调用解释执行程序对目标代码进行解释执行并按用户程序的要求输入数据和输出运行结果。目标程序:目标程序是在目标代码生成的基础上调用解析执行程序来实现的。三、结构设计说明:(各功能模块描述PL:主程序。Error(intn):出错处理打印出错位置和错误编码。GetCh():滤掉空格读取一个单词GetSym():词法分析读取一个单词GEN(FCTX,intY,intZ):生成目标代码并送入目标程序区TEST(SYMSETS,SYMSETS,intN):测试当前单词符号是否合法ENTER(OBJECTSK,intLEV,intTX,intDX):登陆名字表POSITION(ALFAID,intTX):查找标识符在名字表中的位置ENTER(OBJECTSK,intLEV,intTX,intDX):登陆名字表ConstDeclaration(intLEV,intTX,intDX):常量定义处理ListCode(intCX):列出目标代码清单FACTOR(SYMSETFSYS,intLEV,intTX)因子处理TERM(SYMSETFSYS,intLEV,intTX):项处理EXPRESSION(SYMSETFSYS,intLEV,intTX):表达试处理CONDITION(SYMSETFSYS,intLEV,intTX):条件处理STATEMENT(SYMSETFSYS,intLEV,intTX):语句部分处理Block(intLEV,intTX,SYMSETFSYS):分程序分析处理过程BASE(intL,intB,intS):通过静态链求出数据区的基地址Interpret():对目标代码的解释执行程序主要成分描述:()符号表在编译过程中符号表用来存放语言程序中出现的有关标识符的属性信息这些信息集中反映了标识符的语义特性属性。符号表的功能主要有收集符号属性、上下文语义的合法性检查的依据和作为目标代码生成阶段地址分配的依据。从编译系统的造表过程来区分符号表可分为静态表如:保留字、标准函数名表等和动态表如:标识符表、符号表等)。符号表有若干个表项组成每个表项有单词的名字域和属性域两部分。符号表的属性主要包括:符号名、符号的类型、符号的存储类型、符号的作用于及可视性、符号变量的存储分配信息及符号的其他特性。()运行时存储组织和管理从逻辑上看在代码生成前编译程序必须进行目标程序欲行环境的设计和数据空间的分配。因此在程序运行过程中存储区常常被划分成:目标区、静态数据区、栈区和堆区。数据空间的使用和管理方法分成三种:静态存储分配、栈式动态存储分配和堆式动态存储分配。在栈式存储分配的实现中常常使用两个指针来实现最顶端数据区的管理一个是SP另一个是TOP。SP总是指向现行过程活动记录的起点TOP始终指向已占用的栈顶单元。嵌套过程语言的栈式实现只是增加了非局部变量的存取其方法有在过程活动记录中增设存取链和在每进入一个过程后在建立它的活动记录的同时建立一张嵌套层次显示表display。在分程序结构的存储管理中要注意分清楚各过程体的活动记录和SP及TOP指针的始末位置。在过程调用过程中有可能有参数的传递其路径有:传值传地址传名及宏扩展等。()语法分析方法语法分析的任务是识别单词符号序列是否符号给定的语法规则它是编译程序的核心部分。PL编译程序的语法分析采用了自顶向下的递归子程序法。就是说对应每个非终结符语法单元编一个独立的处理程序。语法分析从读入第一个单词开始有开始符程序出发沿语法描述图箭头所指的方向进行分析。当遇到非终结符时则条用相应的处理过程从语法描述图看也就进入了一个语法单元再沿当前所进入的语法描述图的箭头方向进行分析但遇到事终结符时则判断当前读入的单词是否与图中的终结符相匹配若匹配则执行相应的语义程序。再读取下一个单词继续分析。遇到分支点时将当前的单词与分支点上的多个终结符逐个比较若都不匹配时可能是进入下一非终极符语法单位或是出错。()中间代码表示中间代码常见的形式有逆波兰记号(后缀式)、三元式、四元式和树形表示。逆波兰记号式最简单的一种中间代码表示形式这种表示法将运算对象写在前面把运算符号写在后面其最大的优点是易于计算机处理表达式。利用一个栈自左至右扫描算术表达式(后缀表示)。每碰到运算对象就把它推进栈碰到运算符若该运算符是二目的则对栈顶部的两个运算对象实施该运算并将运算结构代替这两个运算对象而进栈。若是一目运算符则对栈顶元素执行该运算并以运算结果代替该元素进栈。最后的结果留在栈顶。每个三元式个组成部分式:算符op第运算对象ARG和第运算对象ARG。对于一目算符op只需算用一个算符对象多目算符可用若干个相继的三元式表示。树形表示是三元式表示的翻版。四元式的四个组成成分式:算符op第一和第二运算对象ARG和ARG及运算结果RESULT。运算对象和运算结果有时指用户自己定义的变量有时指编译程序引进的临时变量。四元式之间的联系式铜鼓临时变量实现的。四、源程序(只列出修改部分而且头文件没有列出)constNORW=*#OFRESERVEDWORDS*增加保留字的数目typedefenum{NUL,IDENT,NUMBER,PLUS,MINUS,TIMES,SLASH,ODDSYM,EQL,NEQ,LSS,LEQ,GTR,GEQ,LPAREN,RPAREN,COMMA,SEMICOLON,PERIOD,BECOMES,BEGINSYM,ENDSYM,IFSYM,THENSYM,ELSESYM,WHILESYM,WRITESYM,READSYM,DOSYM,CALLSYM,CONSTSYM,VARSYM,PROCSYM,PROGSYM,REPEATSYM,UNTILSYM,RETURNSYM,DPLUS,DMINUS,PLUSBECOMES,MINUSBECOMES,}SYMBOL字体加粗的为添加的保留字char*SYMOUT={"NUL","IDENT","NUMBER","PLUS","MINUS","TIMES","SLASH","ODDSYM","EQL","NEQ","LSS","LEQ","GTR","GEQ","LPAREN","RPAREN","COMMA","SEMICOLON","PERIOD","BECOMES","BEGINSYM","ENDSYM","IFSYM","THENSYM","ELSESYM","WHILESYM","WRITESYM","READSYM","DOSYM","CALLSYM","CONSTSYM","VARSYM","PROCSYM","PROGSYM","REPEATSYM","UNTILSYM","RETURNSYM","DPLUS","DMINUS","PLUSBECOMES""PLUSBECOMES"}字体加粗的为添加的保留字voidGetCh(){if(CC==LL){if(feof(FIN)){Form>printfs("PROGRAMINCOMPLETE")fprintf(FOUT,"PROGRAMINCOMPLETEn")fclose(FOUT)exit()}LL=CC=CH=''while(!feof(FIN)CH!=){CH=fgetc(FIN)LINELL=CH}LINELL=''LINELL=Strings=IntToStr(CX)while(sLength()<)s=""ss=s""LINEForm>printfs(scstr())fprintf(FOUT,"sn",s)}CH=LINECC}*GetCh()*voidGetSym(){inti,J,KALFAAwhile(CH<='')GetCh()if(CH>='A'CH<='Z'){*IDORRESERVEDWORD*K=do{if(K<AL)AK=CHGetCh()}while((CH>='A'CH<='Z')||(CH>=''CH<=''))AK=''strcpy(ID,A)i=J=NORWdo{K=(iJ)if(strcmp(ID,KWORDK)<=)J=Kif(strcmp(ID,KWORDK)>=)i=K}while(i<=J)if(i>J)SYM=WSYMKelseSYM=IDENT}elseif(CH>=''CH<=''){*NUMBER*K=NUM=SYM=NUMBERdo{NUM=*NUM(CH'')KGetCh()}while(CH>=''CH<='')if(K>NMAX)Error()}elseif(CH==':'){GetCh()if(CH=='='){SYM=BECOMESGetCh()}elseSYM=NUL}else*THEFOLLOWINGTWOCHECKWEREADDEDBECAUSEASCIIDOESNOTHAVEASINGLECHARACTERFOR<=OR>=*if(CH=='<'){GetCh()if(CH=='='){SYM=LEQGetCh()}elseif(CH=='>'){SYM=NEQGetCh()}修改不等号“#”为“<>”elseSYM=LSS}elseif(CH=='>'){GetCh()if(CH=='='){SYM=GEQGetCh()}elseSYM=GTR}elseif(CH==''){如果读到''GetCh()继续读取字符添加运算符用DPLUS表示if(CH=='')如果读到下一个字符为''{SYM=DPLUSGetCh()即执行自加运算继续读取字符}添加运算符=用PLUSBECOMES表示elseif(CH=='=')如果读到下一个字符为'='{SYM=PLUSBECOMES,GetCh()识别为'='的符号}elseSYM=PLUS否则如果没读到则执行加法运算}elseif(CH==''){如果读到''GetCh()继续读取字符添加运算符用DMINUS表示if(CH=='')如果读到''{SYM=DMINUSGetCh()}执行自减一运算继续读取字符添加运算符=用MINUSBECOMES表示elseif(CH=='=')如果下一个字符是'='{SYM=MINUSBECOMES,GetCh()识别为'='的符号}elseSYM=MINUS否则执行减法运算}else{SYM=SSYMCHGetCh()}}*GetSym()*voidSTATEMENT(SYMSETFSYS,intLEV,intTX){*STATEMENT*caseIFSYM:GetSym()CONDITION(SymSetUnion(SymSetNew(THENSYM,DOSYM,ELSESYM),FSYS),LEV,TX)if(SYM==THENSYM)GetSym()elseError()CX=CXGEN(JPC,,)保存jpc条件跳转指令的地址等待else首地址或指令结束地址的回填STATEMENT(SymSetUnion(SymSetNew(SEMICOLON,ELSESYM,IDENT),FSYS),LEV,TX)if(SYM==SEMICOLON)GetSym()if(SYM==ELSESYM)添加保留字else的语句{GetSym()继续读取单词CX=CXGEN(JMP,,)保存无条件跳转指令的地址等待结束指令地址的回填CODECXA=CX把else首地址回填给jpc条件转移指令跳转的地址STATEMENT(FSYS,LEV,TX)执行语句CODECXA=CX结束指令的地址回填到无条件跳转的地址}else{CODECXA=CX如果不是else直接将当前地址回填到jpc有条件跳转指令的地址STATEMENT(SymSetUnion(SymSetNew(SEMICOLON,ENDSYM),FSYS),LEV,TX)}break}*STATEMENT*voidfastcallTForm::ButtonRunClick(TObject*Sender){for(CH=''CH<='^'CH)SSYMCH=NULstrcpy(KWORD,"BEGIN")strcpy(KWORD,"CALL")strcpy(KWORD,"CONST")strcpy(KWORD,"DO")strcpy(KWORD,"ELSE")strcpy(KWORD,"END")strcpy(KWORD,"IF")strcpy(KWORD,"ODD")strcpy(KWORD,"PROCEDURE")strcpy(KWORD,"PROGRAM")strcpy(KWORD,"READ")strcpy(KWORD,"REPEAT")strcpy(KWORD,"RETURNSYM")strcpy(KWORD,"THEN")strcpy(KWORD,"UNTIL")strcpy(KWORD,"VAR")strcpy(KWORD,"WHILE")strcpy(KWORD,"WRITE")WSYM=BEGINSYMWSYM=CALLSYMWSYM=CONSTSYMWSYM=DOSYMWSYM=ELSESYMWSYM=ENDSYMWSYM=IFSYMWSYM=ODDSYMWSYM=PROCSYMWSYM=PROGSYMWSYM=READSYMWSYM=REPEATSYMWSYM=RETURNSYMWSYM=THENSYMWSYM=UNTILSYMWSYM=VARSYMWSYM=WHILESYMWSYM=WRITESYMSSYM''=PLUSSSYM''=MINUSSSYM'*'=TIMESSSYM''=SLASHSSYM'('=LPARENSSYM')'=RPARENSSYM'='=EQLSSYM','=COMMASSYM''=PERIODSSYM''=SEMICOLONstrcpy(MNEMONICLIT,"LIT")strcpy(MNEMONICOPR,"OPR")strcpy(MNEMONICLOD,"LOD")strcpy(MNEMONICSTO,"STO")strcpy(MNEMONICCAL,"CAL")strcpy(MNEMONICINI,"INI")strcpy(MNEMONICJMP,"JMP")strcpy(MNEMONICJPC,"JPC")DECLBEGSYS=(int*)malloc(sizeof(int)*)STATBEGSYS=(int*)malloc(sizeof(int)*)FACBEGSYS=(int*)malloc(sizeof(int)*)for(intj=j<j){DECLBEGSYSj=STATBEGSYSj=FACBEGSYSj=}DECLBEGSYSCONSTSYM=DECLBEGSYSVARSYM=DECLBEGSYSPROCSYM=STATBEGSYSBEGINSYM=STATBEGSYSCALLSYM=STATBEGSYSIFSYM=STATBEGSYSREPEATSYM=STATBEGSYSRETURNSYM=STATBEGSYSWHILESYM=STATBEGSYSWRITESYM=FACBEGSYSIDENT=FACBEGSYSNUMBER=FACBEGSYSLPAREN=FACBEGSYSDPLUS=FACBEGSYSDMINUS=五、测试用例测试else语句的程序:*****PLCompilerDemo*****===COMPILEPL===PROGRAMEXVARA,B,CBEGINA:=C:=READ(B)IFA=BTHENWRITE(C)ELSEWRITE(A)ENDJMPINILITSTOLITSTOOPRSTOLODLODOPRJPCLODOPROPRJMPLODOPROPROPR~~~RUNPL~~~~~~ENDPL~~~六、开发过程和完成情况怎么说好呢,可以用一句俗话概括这次课程设计的感受:过程是曲折的前途的光明的。我觉得到目前为止这次的编译原理的课程设计是我碰到过的算是比较难做设计仿佛以前做的哪些东西根本不值一提。不过也正因为如此我在课堂上学到的东西可以用上了。可以说获益非浅。在开发的过程中我通过反复的看程序查资料和动脑筋慢慢地掌握这些知识。从完全不懂那些程序函数的定义到基本弄懂。特别是对函数或过程的嵌套开始时我对于他们之间的关系一无所知后来通过找资料终于搞清楚了他们之间的结构层次。例如对于BLOCK这个语法语义分析程序它是整个编译程序的核心。在它体内定义的过程也就特别多但这些过程或函数之间的调用关系却是清晰明了的。比如现在执行语法语义的分析就它首先要调用enter()函数来登录名字表再在position()函数查找其位置然后是常量或变量的声明列出代码再执行statement()语句分析函数在执行statement()过程中还要执行表达式函数expresssion()和条件判断函数condition()就好像流水处理一样。当然由于自己本身的知识和能力有限对于很多问题处理得并不是很好就好像在程序的运行过程中出现的错误提示如果是一个经验丰富的设计人员会很快看出问题的所在而自己就得找资料一个一个错误地排除甚至有时候给出的提示虽然看起来是某个原因造成的但其实是另一个错误和程序的不完善所导致的这就更让人头疼了。不过这些错误也也我积累了不少的经验。纵观这次的课程设计所要求的基本内容我都基本能完成选做的内容也有一部分能够做好但由于时间的关系比较难做的都放弃了。

用户评论(0)

0/200

精彩专题

上传我的资料

每篇奖励 +2积分

资料评价:

/15
0下载券 下载 加入VIP, 送下载券

意见
反馈

立即扫码关注

爱问共享资料微信公众号

返回
顶部