logo资料库

广工2015编译原理实验报告.docx

第1页 / 共11页
第2页 / 共11页
第3页 / 共11页
第4页 / 共11页
第5页 / 共11页
第6页 / 共11页
第7页 / 共11页
第8页 / 共11页
资料共11页,剩余部分请下载后查看
一.实验要求
1.基本内容
2.选做内容
3.本人在实验中已完成的功能
二.概述
三.结构设计说明
1)PL/0编译程序的结构图
2)PL/0编译程序的过程或函数的功能表
3)PL/0编译程序的总体流程图
四.主要成分描述
1)符号表
2)运行时存储组织和管理
3)语法分析方法
4)中间代码表示
五.测试用例
六.开发过程和完成情况
1)增加单词:
2)修改单词:不等号# 改为 <>
3)增加条件语句的ELSE子句
4)扩充赋值运算:*= 和 /=
七.心得体会
实验报告 课程名称____ 编译原理__________ 题目名称_ PL/0 编译程序的修改扩充_ 学生学院 计算机学院 专业班级 学 号 学生姓名 指导教师 2015 年 12 月 6 日
一.实验要求 1. 基本内容 对 PL/0 作以下修改扩充: (1)增加单词:保留字 ELSE,FOR,STEP,UNTIL, RETURN 运算符 *=,/=,&,||,! (2)修改单词:不等号# 改为 <> (3)增加条件语句的 ELSE 子句,要求:写出相关文法,语法图,语义 规则。 2. 选做内容 扩充赋值运算:*= 和 /= 3. 本人在实验中已完成的功能 (1)增加单词:保留字 ELSE,FOR,STEP,UNTIL, RETURN 运算符 *=,/=,&,||,! (2)修改单词:不等号# 改为 <> (3)增加条件语句的 ELSE 子句,要求:写出相关文法,语法图,语义规 则。 (4)扩充赋值运算:*= 和 /= 二.概述 (1)源语言:PL/0 语言 (2)目标语言: 类 PCODE 指令代码 (3)实现平台:Borland C++ Builder 6 (4)运行平台:Windows7 三.结构设计说明 1) PL/0 编译程序的结构图
2) PL/0 编译程序的过程或函数的功能表 过程或函数名 简要功能说明 pl0 error getsym getch gen test block enter position(函数) constdeclaration vardeclaration listode statement expression term factor condition interpret base(函数) 3) PL/0 编译程序的总体流程图 主程序 出错处理,打印出错位置和错误编码 词法分析,读取一个单词 漏掉空格,读取一个字符 生成目标代码,并送入目标程序区 测试当前单词符号是否合法 分程序分析处理过程 登录名字表 查找标识符在名字表中的位置 常量定义处理 变量说明处理 列出目标代码清单 语句处理 表达式处理 项处理 因子处理 条件处理 对目标代码的解释执行程序 通过静态链求出数据区的基地址
四.主要成分描述 1) 符号表 为了组成一条指令,编译程序必须知道其操作码及其参数(数或地址)。这些值是 由编译程序本身联系到相应标识符上去的。这种联系是在处理常数、变量和过程说明完 成的。为此,标识符表应包含每一标识符所联系的属性;如果标识符被说明为常数,其 属性值为常数值;如果标识符被说明成变量,其属性就是由层次和修正量(偏移量)组 成的地址;如果标识符被说明为过程,其属性就是过程的入口地址及层次。常数的值由 程序正文提供,编译的任务就是确定存放该值的地址。我们选择顺序分配变量和代码的 方法;每遇到一个变量说明,就将数据单元的下标加一(PL/0 机中,每个变量占一个 存贮单元)。开始编译一个过程时,要对数据单元的下标 dx 赋初值,表示新开辟一个数 据区。dx 的初值为 3,因为每个数据区包含三个内部变量 RA,DL 和 SL。 2) 运行时存储组织和管理 对于源程序的每一个过程(包括主程序),在被调用时,首先在数据段中开辟三个 空间,存放静态链 SL、动态链 DL 和返回地址 RA。静态链记录了定义该过程的直接外过 程(或主程序)运行时最新数据段的基地址。动态链记录调用该过程前正在运行的过程 的数据段基址。返回地址记录了调用该过程时程序运行的断点位置。对于主程序来说, SL、DL 和 RA 的值均置为 0。静态链的功能是在一个子过程要引用它的直接或间接父过 程(这里的父过程是按定义过程时的嵌套情况来定的,而不是按执行时的调用顺序定的) 的变量时,可以通过静态链,跳过个数为层差的数据段,找到包含要引用的变量所在的 数据段基址,然后通过偏移地址访问它。 在过程返回时,解释程序通过返回地址恢复指令指针的值到调用前的地址,通过当 前段基址恢复数据段分配指针,通过动态链恢复局部段基址指针。实现子过程的返回。 对于主程序来说,解释程序会遇到返回地址为 0 的情况,这时就认为程序运行结束。 解释程序过程中的 base 函数的功能,就是用于沿着静态链,向前查找相差指定层 数的局部数据段基址。这在使用 sto、lod、stoArr、lodArr 等访问局部变量的指令中 会经常用到。 类 PCODE 代码解释执行的部分通过循环和简单的 case 判断不同的指令,做出相应 的动作。当遇到主程序中的返回指令时,指令指针会指到 0 位置,把这样一个条件作为 终至循环的条件,保证程序运行可以正常的结束。 3) 语法分析方法 语法分析子程序采用了自顶向下的递归子程序法,语法分析同时也根据程序的语义 生成相应三元代码,并提供了出错处理的机制。语法分析主要由分程序分析过程(BLOCK)、 参数变量分析过程(ParaDeclaration)、参数变量处理过程(ParaGetSub)、数组处理 过程(ParaGetSub)、常量定义分析过程(ConstDeclaration)、变量定义分析过程 (Vardeclaration)、语句分析过程(Statement)、表达式处理过程(Expression)、项 处理过程(Term)、因子处理过程(Factor)和条件处理过程(Condition)构成。这些 过程在结构上构成一个嵌套的层次结构。除此之外,还有出错报告过程(Error)、代码 生成过程(Gen)、测试单词合法性及出错恢复过程(Test)、登录名字表过程(Enter)、
查询名字表函数(Position)以及列出类 PCODE 代码过程(Listcode)作过语法分析的 辅助过程。 4) 中间代码表示 目标代码类 pcode 是一种假想栈式计算机的汇编语言。 五.测试用例 测试代码: PROGRAM E01; VAR A,B,C; BEGIN READ(A); READ(B); IF A<>B THEN IF B>10 THEN BEGIN B*=1+1; WRITE(B); END ELSE BEGIN B/=1+1; WRITE(B); END ELSE IF B>10 THEN BEGIN
B*=1+2; WRITE(B); END ELSE BEGIN B/=4-1; WRITE(B); END; &; ||; !; FOR; STEP; UNTIL; RETURN; END. 运行结果: 六.开发过程和完成情况 1) 增加单词: 保留字 ELSE,FOR,STEP,UNTIL, RETURN 运算符 *=,/=,&,||,! 增加 5 个保留字和 5 个运算符,合计 10 个单词。 其中保留字 ELSE,FOR,TO,DOWNTO,RETURN 分别对应 ELSESYM, FORSYM, STEPSYM, UNTILSYM, RETURNSYM, 运算符 *= ,/= ,& ,|| , !对应 TIMESSBK, SLASHSBK, AND, OR, NOT。 增加保留字 typedef enum { NUL, IDENT, NUMBER, PLUS, MINUS, TIMES, SLASH, ODDSYM, EQL, NEQ, LSS, LEQ, GTR, GEQ, LPAREN, RPAREN, COMMA, SEMICOLON, PERIOD, BECOMES, BEGINSYM, ENDSYM, IFSYM, THENSYM, WHILESYM, WRITESYM, READSYM, DOSYM, CALLSYM, CONSTSYM, VARSYM, PROCSYM, PROGSYM, ELSESYM, FORSYM, STEPSYM, UNTILSYM, RETURNSYM, TIMESSBK, SLASHSBK, AND, OR, NOT } 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", "WHILESYM", "WRITESYM", "READSYM", "DOSYM", "CALLSYM",
"CONSTSYM", "VARSYM", "PROCSYM", "PROGSYM", "ELSESYM", "FORSYM", "STEPSYM", "UNTILSYM", "RETURNSYM", "TIMESSBK", "SLASHSBK", "AND", "OR", "NOT" }; for (CH=' '; CH<='^'; CH++) SSYM[CH]=NUL; strcpy(KWORD[ 2],"CALL"); strcpy(KWORD[ 4],"DO"); strcpy(KWORD[ 6],"END"); strcpy(KWORD[ 8],"IF"); strcpy(KWORD[10],"PROCEDURE"); strcpy(KWORD[ 1],"BEGIN"); strcpy(KWORD[ 3],"CONST"); strcpy(KWORD[ 5],"ELSE"); strcpy(KWORD[ 7],"FOR"); strcpy(KWORD[ 9],"ODD"); strcpy(KWORD[11],"PROGRAM"); strcpy(KWORD[12],"READ"); strcpy(KWORD[13],"RETURN");strcpy(KWORD[14],"STEP"); strcpy(KWORD[16],"UNTIL"); strcpy(KWORD[15],"THEN"); strcpy(KWORD[17],"VAR"); strcpy(KWORD[18],"WHILE"); strcpy(KWORD[19],"WRITE"); WSYM[ 1]=BEGINSYM; WSYM[ 2]=CALLSYM; WSYM[ 3]=CONSTSYM; WSYM[ 4]=DOSYM; WSYM[ 5]=ELSESYM; WSYM[ 6]=ENDSYM; WSYM[ 7]=FORSYM; WSYM[ 8]=IFSYM; WSYM[10]=PROCSYM; WSYM[ 9]=ODDSYM; WSYM[11]=PROGSYM; WSYM[12]=READSYM; WSYM[13]=RETURNSYM; WSYM[14]=STEPSYM; WSYM[16]=UNTILSYM; WSYM[15]=THENSYM; WSYM[17]=VARSYM; WSYM[18]=WHILESYM; WSYM[19]=WRITESYM; SSYM['+']=PLUS; SSYM['*']=TIMES; SSYM['(']=LPAREN; SSYM['=']=EQL; SSYM['.']=PERIOD; SSYM[';']=SEMICOLON; SSYM['&']=AND; SSYM['!']=NOT; SSYM['-']=MINUS; SSYM['/']=SLASH; SSYM[')']=RPAREN; SSYM[',']=COMMA; //SSYM['#']=NEQ; 不需要 然后在 STATEMENT(SYMSET FSYS,int LEV,int &TX)函数中增加: case FORSYM: GetSym(); Form1->printfs("~~~~ FOR ~~~~"); break; case STEPSYM: GetSym(); Form1->printfs("~~~~ STEP ~~~~"); break; case UNTILSYM: GetSym();
分享到:
收藏