ch2-2PL0编译程序的实现(张素琴).ppt_第1页
ch2-2PL0编译程序的实现(张素琴).ppt_第2页
ch2-2PL0编译程序的实现(张素琴).ppt_第3页
ch2-2PL0编译程序的实现(张素琴).ppt_第4页
ch2-2PL0编译程序的实现(张素琴).ppt_第5页
已阅读5页,还剩107页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第2章 PL/0编译程序 本章目的:以PL/0编译程序为实例,学习编译 程序实现的基本步骤和相关技术 (1) PL/0编译程序的结构 (2) PL/0编译程序的词法,语法和语义实现 (3) PL/0编译程序的错误处理方法 (4) 目标代码生成和类pcode代码解释器 1. PL/0编译程序的结构 PL/0编译程序 PL/0 语言程序 类 pcode 代码 源语言(PL/0) 目标语言(类 p code) 实现语言(C) PL/0 类 pcode pascal/C PL/0编译程序 类 pcode解释程序 类 pcode代码 PL/0源程序 输入数据输出数据 PL/0编译系统的结构框架 PL/0语言 PL/0语言:PASCAL语言的子集 PL/0程序示例 PL/0的语法描述图 PL/0语言的EBNF表示 PL/0程序示例 CONST A=10; (* 常量说明部分 *) VAR B,C; (* 变量说明部分 *) PROCEDURE P; (* 过程说明部分 *) VAR D;(* P的局部变量说明部分 *) PROCEDURE Q; (* P的局部过程说明部分 *) VAR X; BEGIN READ(X); D:=X; WHILE X#0 DO CALL P; END; BEGIN WRITE(D); CALL Q; END; BEGIN CALL P; END. Q过程体 p过程体 主程序体 输入圆柱的半径和高,计算一些面积、体积等 z z var r, h, len, a1, a2, volumn; z begin zread(r); zread(h); z zlen := 2 * 3 * r; za1 := 3 * r * r; za2 := a1 + a1 + len * h; zvolumn := a1 * h; z zwrite(len); zwrite(a1); zwrite(a2); zwrite(volumn); z end. 计算最大公约数 l var m, n, r, q; l 计算m和n的最大公约数 l procedure gcd; l begin l while r#0 do l begin l q := m / n; l r := m - q * n; l m := n; l n := r; l end l end; l begin l read(m); l read(n); l 为了方便,规定m = n l if m 0 then l begin l fact := fact * m; l m := m - 1; l call factorial; l end; l end; l begin l 读入n l read(n); l sum := 0; l while n 0 do l begin l m := n; l fact := 1; l call factorial; l sum := sum + fact; l n := n - 1; l end; l 输出n ! l write(sum); l end. 程序 分程序 . 内的文字表示语法成分(短语) 或内的文字表示单词符号 程序 . 内的文字表示语法成分(短语) 语法图 const identnumber= , ; varident , ; ; procedure ident ; 分程序 语句 分程序 zP13-15 PL/0语言的EBNF表示 构成EBNF的元素(非终结符,终结符,开始符,规 则) EBNF 的元符号: 用左右尖括号括起来的内容为非终结符 = 读做定义为 =的左部由右部定义 读做定义为 的左部由右部定义 | 读做或 表示右部候选内容 表示花括号内的内容可重复任意次或限 定次数 表示方括号内的内容为任选项 ( ) 表示圆括号内的内容优先 zP15-16 例:用EBNF描述的定义 : =+|- =0|1|2|3|4|5|6|7|8|9 或 =+|-|0 =1|2|3|4|5|6|7|8|9 =0| PL/0语言是PASCAL语言的子集 同PASCAL 作用域规则(内层可引用包围它的外层定义的标识符), 上下文约束, 过程可嵌套定义,可递归调用 z 数据类型,只有整型 z 数据结构 ,只有简单变量和常数 z 数字最多为14位 z 标识符的有效长度是10 z 语句种类:if和while z 过程无参,最多可嵌套三层 目标代码类p-code 目标代码类p-code是一种栈式机的汇编语言。 栈式机系统结构:没有累加器和寄存器,只有存储栈指针 所有运算都在栈顶(零地址机) 指令格式: f l a f功能码 l层次差 (标识符引用层减去定义层) a根据不同的指令有所区别 指 令 功 能 表 const a=10; var b,c; procedure p; begin c:=b+a; end; begin read(b); while b#0 do begin call p; write(2*c); read(b); end end. ( 0) jmp 0 8 转向主程序入口 ( 1) jmp 0 2 转向过程p入口 ( 2) int 0 3 过程p入口,为过程p开辟空间 ( 3) lod 1 3 取变量b的值到栈顶 ( 4) lit 0 10 取常数10到栈顶 ( 5) opr 0 2 次栈顶与栈顶相加 ( 6) sto 1 4 栈顶值送变量c中 ( 7) opr 0 0 退栈并返回调用点(16) ( 8) int 0 5 主程序入口开辟5个栈空间 ( 9) opr 0 16 从命令行读入值置于栈顶 (10) sto 0 3 将栈顶值存入变量b中 (11) lod 0 3 将变量b的值取至栈顶 (12) lit 0 0 将常数值0进栈 (13) opr 0 9 次栈顶与栈顶是否不等 (14) jpc 0 24 等时转(24)(条件不满足转) (15) cal 0 2 调用过程p (16) lit 0 2 常数值2进栈 (17) lod 0 4 将变量c的值取至栈顶 (18) opr 0 4 次栈顶与栈顶相乘(2*c) (19) opr 0 14 栈顶值输出至屏幕 (20) opr 0 15 换行 (21) opr 0 16 从命令行读取值到栈顶 (22) sto 0 3 栈顶值送变量b中 (23) jmp 0 11 无条件转到循环入口(11) (24) opr 0 0 结束退栈 PL/0编译程序的结构 词法分析程序 语法语义分析程序 代码生成程序 表格管理程序 出错处理程序 PL/0源程序 目标程序 PL/0编译程序的总体设计 z以语法、语义分析程序为核心 词法分析程序和代码生成程序都作为一个过程, 当语法分析需要读单词时就调用词法分析程序, 而当语法、语义分析正确,需要生成相应的目标 代码时,则调用代码生成程序。 z表格管理程序实现变量,常量和过程标识符的信 息的登录与查找。 z出错处理程序,对词法和语法、语义分析遇到的 错误给出在源程序中出错的位置和与错误 性质有 关的编号,并进行错误恢复。 2 PL/0编译程序的分析工作 (词法,语法和语义) 2.1PL/0编译程序词法分析的实现 识别的单词: y保留字或关键字:如:BEGIN、 END、 IF、 THEN等 y运算符: 如:+、-、*、/、:=、#、=、 . VAR ; A BEGIN END READ ( ) A 为文法的 开始符号,以开 始符号作为根结 点构造一棵倒挂 着的语法树。 递归子程序法-语法分析程序由一组递归过 程组成 对应每个非终结符(语法单元),编一个独立的 处理过程(或函数,子程序)。 由(即开始符)开始,沿语法描述图 箭头所指出的方向进行分析(规则右部) 遇到非终结符(进入了又一个语法单元) ,则调用相应的处理过程 遇到终结符,则判断当前读入的单词是否 与该终结符相匹配,若匹配,再读取下一个单 词继续分析。 也称为递归下降分析器( recursive-descent parser ) 例:表达式的语法分析程序(递归子程序) 项 表达式 + - 项 + - 项 因子 因子 * / 语法图 因子的语法图 因子 ident number (表达式) z 表达式的EBNF 表达式=+|-项(+|-)项 项=因子(*|/)因子 因子=标识符|无符号整数|(表达式) 表达式=+|-项(+|-)项 pascal z 表达式的分析程序(递归子程序) procedure expr; begin if sym in plus, minus then begin getsym; term; end else term; while sym in plus, minus do begin getsym; term; end end; z 项=因子(*|/)因子 pascal z项的分析程序(递归子程序) procedure term; begin factor; while sym in times, slash do begin getsym; factor; end end; 因子=标识符|无符号整数|(表达式) z 因子的分析程序(递归子程序) procedure factor; begin if sym number then begin if sym = ( then begin getsym; expr; if sym = ) then getsym else error end else error end else getsym end else getsym end; 表达式=+|-项(+|-)项 in C z int expression(bool* fsys, int* ptx, int lev) z zif(sym=plus | sym=minus)/* 开头的正负号,当前表达式被 看作一个正的或负的项 */ z zgetsymdo; ztermdo(nxtlev, ptx, lev);/* 处理项 */ z zelse/* 此时表达式被看作项的加减 */ z ztermdo(nxtlev, ptx, lev);/* 处理项 */ z zwhile (sym=plus | sym=minus) z zgetsymdo; ztermdo(nxtlev, ptx, lev);/* 处理项 */ z zreturn 0; z 项=因子(*|/)因子 zint term(bool* fsys, int* ptx, int lev) z zfactordo(nxtlev, ptx, lev); /* 处理因 子 */ zwhile(sym=times | sym=slash) zgetsymdo; zfactordo(nxtlev, ptx, lev); z zreturn 0; z 因子=标识符|无符号整数|(表达式) int factor(bool* fsys, int* ptx, int lev) if(sym = ident)/* 因子为常量或变量 */ getsymdo; else if(sym = number)/* 因子为*/ getsymdo; else if (sym = lparen)/* 因子为表达式 */ expressiondo(nxtlev, ptx, lev); if (sym = rparen) getsymdo; else error(22);/* 缺少右括号 */ return 0; = begin(*main*) (*initialize*) (*r/w file set*) getsym; block( ); if sym period then error. end. 。 程序 pl0 分程序 block 语句 statement 条件 condition 表达式expression 项 term 因子 factor 语 法 调 用 关 系 图 编译系统总体流程图 2.3 PL/0编译程序语义分析的设计与实现 PL/0编译程序语法、语义分析的的核心程序是BLOCK过程 哪些语义分析工作? 如何实现?-语义分析环境(符号表) z 说明部分的分析与处理 z 表格管理 z 过程体(语句)的分析与处理 因子=标识符|无符号整数|(表达式) 语义分析 int factor(bool* fsys, int* ptx, int lev) z if(sym = ident)/* 因子为常量或变量 */ z zi = position(id, *ptx);/* 查找名字 */ zif (i = 0) zerror(11);/* 标识符未声明 */ z zelse zswitch (tablei.kind) zcase constant:/* 名字为常量 */ zbreak; zcase variable:/* 名字为变量 */ zbreak; zcase procedur: /* 名字为过程 */ zerror(21); /* 不能为过程名 */ z 登录符号表ch9 说明部分的分析与处理 对每个过程(含主程序)说明的对象(变量,常量和过程)造 符号表 登录标识符的属性。 标识符的属性:种类,所在层次,值和分配的相对位置。 登录信息由ENTER(见教材p440)过程完成。 符号表结构(见教材p455) Enum object constant, variable, procedur ; Struct tablestruct char nameal; enum object kind; int val; int level; int adr; int size; ; Struct tablestruct tabletxmax; 符号表结构 z 说明种类的定义: object= (constant, variable,procedur) (定义纯量/枚举类型) z 符号表的定义 table:array0txmax of record name:alfa; case kind:object of constant:(val:integer); variable:procedur:(level,adr,size: integer); 例程序说明部分为:CONST A=35,B=49; VAR C,D,E; PROCEDURE P; VAR G ; 符号表 名字 种类 层次/值 地址 存储空间 对应名字表 tx :table表的下标指针,是以值参数形式使用的 。 dx: 计算每个变量在运行栈中相对本过程基地址的 偏移量 ,放在table表中的adr域,生成目标代 码时再放在code中的a域 变量定义语句的处理(C) 语法:: := var , ; 程序: if (sym = varsym)/* 收到变量声明符号,开始处理变量声明 */ getsymdo; do vardeclarationdo( while (sym = comma) getsymdo; vardeclarationdo( if (sym = semicolon) getsymdo; else error(5); while (sym = ident); 注意:/填写名字表 getsymdo; else error(4); /* var后应是标识符 */ return 0; 变量定义语句的处理 语法:: := var , ; 程序: if sym=varsym then begin getsym; repeat vardeclaration;(*变量说明处理*) while sym=comma do begin getsym; vardeclaration end; if sym=semicolon then getsym else error(5) until sym amax) error(31);/* 数越界 */ num = 0; table(*ptx).val = num; break; 过程ENTER的实现(C) case variable:/* 变量名字 */ table(*ptx).level = lev; table(*ptx).adr = (*pdx); (*pdx)+; break; case procedur:/* 过程名字 */ table(*ptx).level = lev; break; 过程ENTER的实现 tx :table表的指针 procedure enter(k:object ); begin (* enter object into table *) tx:=tx+1; with tabletx do (* 开域语句 *) begin name:=id;(* 表示:=id;* ) kind:=k;(* 表示tabletx.kind:=k;* ) 过程ENTER的实现 case k of constant: begin if numamax then begin error(31); num:=0; end; val:=num;(* tabletx.val:=num;*) end; 过程ENTER的实现 variable: begin level:=lev; (*表示tabletx.level:=lev*) adr:=dx; (*表示tabletx.adr:=dx*) dx:=dx+1; end; procedur: level:=lev (* 表示tabletx.level:=lev;*) end(* case *); end end(*enter*); 过程体的处理 /* * 编译程序主体 * * lev: 当前分程序所在层 * tx: 名字表当前尾指针 * fsys: 当前模块后跟符号集合 */ int block(int lev, int tx, bool* fsys) 过程体的处理 /main()函数 if(-1 = block(0, 0, nxtlev) if (sym != period) error(9); interpret();/* 调用解释执行程序 */ 过程体的处理 while (sym = procsym) / block()函数 getsymdo; if (sym = ident) enter(procedur, . if (-1 = block(lev+1, tx, nxtlev) 过程体的处理变量引用的处理 y对语句进行语法分析 y语义分析 当遇到标识符的引用时就调用POSITION函数查 TABLE表,看是否有过正确定义,若已有,则从表中取相应 的有关信息,供代码的生成使用。若无定义则错。 y语义分析 TABLE表若已有过正确定义,检查引用与说明的属 性是否一致,若不一致则错。 y当语法语义正确时,就生成相应语句功能的目标代码 赋值语句的处理(C) if (sym = ident)/* 准备按照赋值语句处理 */ i = position(id, *ptx); if (i = 0) error(11);/* 变量未找到 */ else if(tablei.kind != variable) error(12);/* 赋值语句格式错误 */ i = 0; else gendo(sto, lev-tablei.level, tablei.adr); 赋值语句的处理 if sym = ident then begin i:= position(id); if i= 0 then error(11) else if tablei.kind 0 then with table i do gen(sto,lev-level,adr) end 第2章 PL/0编译程序 本章目的:以PL/0编译程序为实例,学习编译程序实现的基本 步骤和相关技术 1 PL/0编译程序的结构 2 PL/0编译程序的分析工作 (词法,语法和语义)实现 3 PL/0编译程序的错误处理方法 4 目标代码生成和类pcode代码解释器 编译程序的错误处理 错误处理的原则:尽可能准确指出出错位置, 错误性质,尽可能进行校正。 PL/0编译程序对语法错误的处理: (1) 对于易于校正的错误,如丢了逗号,分 号等,指出出错位置,加以校正,继续进行 分析。 (2) 对于难于校正的错误,给出错误的位置 与性质,跳过后面的一些单词,直到下一个 可以进行正常语法分析的语法单位。 z在进入某个语法单位时,调用TEST,检查当前符号 是否属于该语法单位的开始符号集合。若不属于 ,则滤去开始符号和后跟符号集合外的所有符号 。 z在语法单位分析结束时,调用TEST,检查当前符号 是否属于调用该语法单位时应有的后跟符号集合 。若不属于,则滤去后跟符号和开始符号集合外 的所有符号。 TEST TEST 开始符号集合与后跟符号集合 开始符号集合 symset=set of symbol; declbegsys, statbegsys, facbegsys:symset; 开始符号集合(*主程序*) declbegsys:=constsym,varsym,procsym; statbegsys:=beginsym,callsym,ifsym, whilesym,readsym,writesym; facbegsys:=ident,number,lparen; 后跟符号集合fsys作为参数: procedure test(s1,s2:symset; n:integer); procedure block(lev,tx:integer; fsys:symset); procedure statement(fsys:symset); procedure expression (fsys:symset); procedure term (fsys:symset); procedure factor (fsys:symset); READ语句的分析处理(C) if (sym = readsym)/处理read语句 getsymdo; if (sym != lparen) error(34);/格式错误,应是左括号 else do getsymdo; READ语句的语法语义分析处理 if sym=readsym then begin getsym; if symcomma; if symcxmax then(*指针越界*) begin write(program too long); close(fin);(*关闭文件*) writeln; exit end; PL/0编译程序的实现 with codecx do begin f:=x;(* 表示codecx.f:=x; *) l:=y;(* 表示codecx.l:=y; *) a:=z;(* 表示codecx.a:=z; *) end; cx:=cx+1 end (*gen*); PL/0编译程序的实现 对分程序的定义(见教材417,437页) procedure block(lev,tx:integer;fsys:symset); var dx:integer; (*data allocationindex*) tx0:integer; (*initial table index*) cx0:integer; (*initial code index*) ( tx0,cx0是tx,cx的初值) PL/0编译程序的实现 z 对分程序体人口的处理(见程序文本block 的过程体) begin (*block*) dx:=3; tx0:=tx; (保留当前table表指针值) tabletx.adr:=cx;(保留当前code指针值到过程名 的adr域 ) gen(jmp,0,0);(生成转向过程体入口的指令,该指令的地址 为cx 已保留在过程名的adr域,等生成 过程 体入口的指令时,再由tabletx.adr中取出 cx将过程体入口返填到cx中,即 ( jmp,0,0)的第3区域。 (注意dx, tx, cx的作用) CONST A=35,B=49; VAR C,D,E; PROCEDURE P; VAR G table表格管理 名字 类型 层次/值 地址 存储空间 (0) jmp 0 0 CX (1 ) jmp 0 0 . . 记录 过程在code的入 口到table中的adr域 PL/0编译程序的实现 过程体入口时的处理 codetabletx0.adr

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论