第七章语法制导翻译和中间代码生成 ·7.1语义处理概述 ·7.2属性文法和语法制导翻译 7.3中间代码生成(一些语句的翻译) ·74符号表
第七章语法制导翻译和中间代码生成 • 7.1语义处理概述 • 7.2属性文法和语法制导翻译 • 7.3 中间代码生成(一些语句的翻译) • 7.4符号表
7.1语义处理(语义分析和中间代码生成) 在编译中的逻辑阶段 源语言程序 词法分析 前端处理 语法分析 语义分析 语义处理 中间代码生成 中间代码 后端处理 代码生成 汇编代码
源语言程序 中间代码 汇编代码 词法分析 语义分析 语法分析 中间代码生成 代码生成 在编译中的逻辑阶段 前 端 处 理 后 端 处 理 语 义 处 理 7.1 语义处理(语义分析和中间代码生成)
语义处理 源语言程序 词法分析 前端处理 语法分析 语义分析 语义处理 后端处理 代码生成 汇编代码
源语言程序 汇编代码 词法分析 语义分析 语法分析 代码生成 前 端 处 理 后 端 处 理 语 义 处 理 语义处理
语义处理 语义处理的任务 ·静态语义检查 静态语义:语法规则的良形式条件 静态语义检查:审查静态语义 动态语义处理 ·动态语义:程序单元执行的操作 ·动态语义处理:生成(中间目标)代码
语义处理 语义处理的任务: • 静态语义检查 • 静态语义:语法规则的良形式条件 • 静态语义检查:审查静态语义 • 动态语义处理 • 动态语义:程序单元执行的操作 • 动态语义处理:生成(中间/目标)代码
语义处理 语义处理的实现 ·属性文法:描述语义规则。 语法制导鄱译:在语法分析的同时,执行 语义规则描述的动作 检查静态语义 生成中间代码眉标代码
语义处理 语义处理的实现: • 属性文法:描述语义规则。 • 语法制导翻译:在语法分析的同时,执行 语义规则描述的动作: • 检查静态语义 • 生成中间代码/目标代码
语义处理 语义处理的环境:符号表 为语义分析提供类型、作用域等信息。 为代码生成提供类型、作用域、存储类别、 存储(相对)位置等信息
语义处理 语义处理的环境:符号表 • 为语义分析提供类型、作用域等信息。 • 为代码生成提供类型、作用域、存储类别、 存储(相对)位置等信息
语义处理 PL/编译程序的语义处理(一)cal语句的处理 if sym callsym then begin getsym; if sym < ident then error(14) else begin i: position(id) if i=0 then error(11) else with table[] do if kind procedur then gen(cal, lev-level, adr) else error (15); getsym end nd
语义处理 if sym = callsym then begin getsym; if sym <> identthen error(14) else begin i := position(id); if i = 0 then error(11) else with table[i] do if kind = procedur then gen(cal, lev-level, adr) else error(15); getsym end end PL/0编译程序的语义处理(一)call语句的处理
语义处理 PL/0编译程序的语义处理(二)语义错误列表 error11:标识符未说明; error12:赋值语句中,赋值号左部的标识符属性应为 变量; error15:ca!后标识符的属性应为过程; error21:表达式内标识符属性不能为过程; eror32:read语句括号中的标识符不是变量
语义处理 error 11:标识符未说明; error 12:赋值语句中,赋值号左部的标识符属性应为 变量; error 15:call后标识符的属性应为过程; error 21:表达式内标识符属性不能为过程; error 32:read语句括号中的标识符不是变量。 … PL/0编译程序的语义处理(二)语义错误列表
pL/0编译器的符号表 const a=10 var procedure p b egin read(b) while b#o do begin call write(2*c) read (b end ent 编译程序分析到第8行时符号表的内容 name kind ⅴa11eve1 address size a constant 10 b variable variable 000 4 procedure
PL/0编译器的符号表 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. name kind val level address size a constant 10 b variable 0 3 c variable 0 4 p procedure 0 3 编译程序分析到第8行时符号表的内容
0)jmp08转向主程序入口 1)jmp02转向过程p入 const a=10 2)int03过程p入口,为过程p开辟空间 (3)10d13取变量b的值到栈顶 var b,C, 4)1010取常数10到栈顶 procedure p (5)0pr02次栈顶与栈顶相加 begin 6)sto14栈顶值送变量c中 opr00退栈并返回调用点(16) C∴=b+a =(8)int05主程序入口开辟5个栈空间 end 9)opr016从命令行读入值置于栈顶 (10)sto03将栈顶值存入变量b中 begin (11)1od03将变量b的值取至栈顶 read (b) (12)1it00将常数值0进栈 (13)opr09次栈顶与栈顶是否不等 while beto do (14)jpc024等时转(24)(条件不满足转) egin (15)ca102调用过 (16)1it02常数值2进栈 call p (17)1od04将变量c的值取至栈顶 write(2*c);‖(18)r04次栈顶与栈顶相乘(2*c) read (b) (19)opr014栈顶值输出至屏幕 end (20)opr015换行 (21)opr016从命令行读取值到栈顶 end (22)sto03栈顶值送变量b中 (23)jmp011无条件转到循环入口(11) 424)opr00结束退栈
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 结束退栈