0 1 Micro MicroMicro Pascal begin Pascal var



例 一个微小编译器 0. 1 Micro语言描述 Micro语言(称Micro, Pascal语言的子集) begin Pascal var x 1: real; var z 1: real; x 1: =0. 5; z 1: =x 1+56; read(x 1); write(z 1+2. 3) end. 2020/12/5 Main(){ C float x 1; float z 1; x 1=0. 5; z 1=x 1+56; scanf(“%f”, &x 1); printf(“%f”, z 1+2. 3); } 北京化 大学信息科学与技术学院计算机系 3

● Pascal与C语言区别 begin Pascal C var x 1: real; Begin…end {…} var z 1: real; int x; //变量声明 var x 1: int; x 1: =0. 5; Float, double real z 1: =x 1+56; X=0. 5; //赋值 X: =0. 5; read(x 1); = <> //判等,判不等 == != write(z 1+2. 3) Read(…) Scanf(…) / getchar() end. Write(…) Printf(…) 语句以分号分隔,但end 语句以分号分隔 前的语句没有符号 程序结束. 无. Procedure Void function_name(…) Function Int/float function_name(…) If (…)…else… If (…) then…else… While(…) do … 2020/12/5 4 北京化 大学信息科学与技术学院计算机系 … …




程序的 字符串 序列 Token序列 例: begin var x 1: real; var z 1: real; x 1: =0. 5; z 1: =x 1+56; read(x 1); write(z 1+2. 3) end. $begin $line $real $semi $colon $real $assig ($rea. C, 0. 5) $assig ($id, x 1) $var $line $semi $plus ($id, x 1) $var $line ($int. C, 56) $colon ($id, z 1) ($id, x 1) ($id, z 1) $semi $line $read $Lparen ($id, x 1) $Rparen $semi $line $write $Lparen ($id, z 1) 2020/12/5 $plus $stop ($rea. C, 2. 3) $Rparen # 北京化 大学信息科学与技术学院计算机系 $line 8 $end

3. Micro语言的词法分析程序 例: begin var x 1: real; var z 1: real; x 1: =0. 5; z 1: =x 1+56; read(x 1); write(z 1+2. 3) end. Procedure scanner(); begin while ~Eof do { Noblank(ch); case ch of ‘A’. . ’Z’|’a’. . ’z’ {Identifier(name); case name of “begin” Gen. Token($begin); “end” Gen. Token($end); “var” Gen. Token($var); Noblank(ch): “int” Gen. Token($int); 跳过空格符串 “real” Gen. Token($real); 将第一个非空 格字符读到ch “read” Gen. Token($read); 中(删除空格 “write” Gen. Token($write); 符) other Gen. Token($id, name); end }; 2020/12/5 北京化 大学信息科学与技术学院计算机系 9

‘ 0’. . ’ 9’ ‘(’ ‘)’ ‘+’ ‘*’ ‘; ’ ‘: ’ {Constant(class, C); Gen. Token(Class, C)}; Gen. Token($Lparen); Read(ch); Gen. Token($Rparen); Read(ch); Gen. Token($plus); Read(ch); Gen. Token($mult); Read(ch); Gen. Token($semi); Read(ch); {Read(ch); if ch=‘=’ then {Gen. Token($assig); Read(ch)} else Gen. Token($colon)} ‘. ’ Gen. Token($stop); Read(ch); ‘enter’ Gen. Token($line); Read(ch); ‘other’ Lexical. Error(ch) end } end 2020/12/5 北京化 大学信息科学与技术学院计算机系 10





4. Micro语言的语法分析程序 例: begin var x 1: real; var z 1: real; x 1: =0. 5; z 1: =x 1+56; read(x 1); write(z 1+2. 3) end. Procedure Parser(); begin Match($begin, 1); Match($var, 2); LD: Match($id, 3); Match(kind, n):读当前Token, Match($colon, 4); 并检查Token. LH=kind?若不 Match($int. C/$rea. C, 5); 等,则打出错误编号n。 声明 Token. LH:Token的左半部。 Match($semi, 6); Token. RH:Token的右半部。 Read. Token(token); if token=$line then Read. Token(token); if token=$var then goto LD; Read. Token(token): 把当前Token读到token中 2020/12/5 北京化 大学信息科学与技术学院计算机系 15

语句 LS: case token of $write {Match($Lparen, 7); Expr(); Match($Rparen, 8)}; 单词 $read {Match($Lparen, 9); Match($id, 10); Match($Rparen, 11)}; 例: $id {Match($assig, 12); Expr()}; begin var x 1: real; other {error(13)} var z 1: real; end; Read. Token(token); //读语句的后继符 x 1: =0. 5; z 1: =x 1+56; read(x 1); 后继符 write(z 1+2. 3) end. 2020/12/5 北京化 大学信息科学与技术学院计算机系 16

case token of $semi {Read. Token(token); if token=$line then Read. Token(token); goto LS}; $line Match($end); $end {Read. Token(token); if token=$stop then STOP else Error(14)} other {Error(15)} end 2020/12/5 北京化 大学信息科学与技术学院计算机系 例: begin var x 1: real; var z 1: real; x 1: =0. 5; z 1: =x 1+56; read(x 1); write(z 1+2. 3) end. 17

● Micro语言的语法分析子程序—表达式的语法检查 Procedure Expr(); 例: begin z 1: =x 1+56; LF: Read. Token(token); var x 1: real; read(x 1); case token of var z 1: real; write(z 1+2. 3) ($id, . . ) skip; x 1: =0. 5; end. ($int. C, . . ) skip; ($rea. C, . . ) skip; $Lparen begin Expr(); Match($Rparen, 16) end; other error(17) case token of (接左) end; $plus goto LF; Read. Token(token); (接右) $mult goto LF; 2020/12/5 Other Back. Token End Token指针 end 18 回溯一步 北京化 大学信息科学与技术学院计算机系



2. Micro语言的语义分析程序 Procedure Semantic(); Enter(name, Entry, s): 将 begin Creat; //建空符号表 name填入符号表,并在 Read. Token(); //读$begin entry中给出其表项地址。 若已有同名项,则s取true LD: Read. Token(token); 值,否则取false。 case token. LH of $var {Read. Token(token); Enter(token. RH, Entry, s); if s=true then Error(1); // 重复声明错 Set. Attribute(ent ry, Addr, Type): Read. Token(); Read. Token(token); //: $int/$real 将标识符的地址 case token. LH of 和类型填入符号 $int Set. Attribute(entry, new. Addr, int. Type); 表的entry项内 $real Set. Attribute(entry, new. Addr, real. Type) end; Read. Token(); goto LD}; //; 2020/12/5 北京化 大学信息科学与技术学院计算机系 21

$other while token!=$stop do { if token. LH=$id then Find(token. RH, entry, s) ; if s=false then Error(2); //无声明错 Change. Token(entry) } end; Find(name, entry, s): 用name查找符号表,并在addr和 type中给出其name的地址和类型。若已有同名项,则s 取true值,否则取false。 Change. Token(entry): 将被读token(标识符)的右半部改 为entry地址 2020/12/5 北京化 大学信息科学与技术学院计算机系 22



2. Micro语言的目标代码生成程序 Search(RH(tk), v. Addr, v. Type): Procedure Gen. Code. S(); 用符号表的某项地址entry求 begin LS: Read. New. Token(tk); 变量的地址和类型。 case LH(tk) of $id {Search(RH(tk), v. Addr, v. Type); 赋值的左边 Read. New. Token(); //: = Seman. Stack(t Gen. Code. E(); 赋值的右边 op): 表示 Seman. Stac e. Addr: =Seman. Stack(top). addr; e. Type: =Seman. Stack(top). Type; k的顶元素 Sendcode(cod if ~Equ(v. Type, e. Type) then Error(1); Sendcode(STO, e. Addr, v. Addr); e): 把代码 code送入代 POP}; 类型不相容错 码区 2020/12/5 北京化 大学信息科学与技术学院计算机系 25

$write {Read. New. Token(); //读 ( Gen. Code. E(); e. Addr: =Seman. Stack(top). addr; Sendcode(OUT, e. Addr); POP; Read. New. Token()};//读 ) $read {Read. New. Token(tk); Search(RH(tk), v. Addr, v. Type); //求变量地址 Sendcode(INP, v. Addr)}; end; Read. New. Token(tk); if tk=$semi then goto LS else Send. Code(STOP) end 2020/12/5 北京化 大学信息科学与技术学院计算机系 26

● 无括号表达式的目标代码生成程序 Procedure Gen. Code. E(); Produce. Code :用语义栈 begin Seman. Stack的内容生成代码 L 0: Read. New. Token(tk); L 1: case tk of ($id, entry) {Search(entry, v. Addr, v. Type) ; //求变量地址 push(v. Addr, v. Type); goto L 0 }; ($int. C, val) {push(val, int); goto L 0 }; 判断优先级 ($rea. C, val) {push(val, real); goto L 0 }; $plus|$mult if top>1 && Seman. Stack(top-1)<<tok then push(tok); goto L 0 Else Produce. Code; goto L 1 Other if top>1 then { Produce. Code; goto L 1} end 2020/12/5 北京化 大学信息科学与技术学院计算机系 27

Procedure Produce. Code; begin if ~Equa(typ 1, typ 2) then Error() else { temp: =New. Addr; Send. Code(OP, Addr 1, temp); Pop(3); push(temp, typ 1) } end Produce. Code :用语义栈Seman. Stack的内容生成代码 2020/12/5 北京化 大学信息科学与技术学院计算机系 28

● 带括号表达式的目标代码生成程序 Procedure Gen. Code. E(); Operand. Stack:分量栈 begin Operator. Stack:运算符栈 push. Operator(); � ); L 0: Read. New. Token(tk); L 1: case tk of ($id, entry) {Search(entry, v. Addr, v. Type); push. Operand(v. Addr, v. Type); goto L 0 }; ($int. C, val) {push. Operand(val, int); goto L 0 }; ($rea. C, val) {push. Operand(val, real); goto L 0 }; $Lparen {push. Operator(); � ); goto L 0 }; 2020/12/5 北京化 大学信息科学与技术学院计算机系 29

● 带括号表达式的目标代码生成程序(接上) $plus, $mult case Operator. Stack(top) of � {push. Operator(tok); goto L 0}; $plus|$mult if Operator. Stack(top)<<tok then {push. Operator(tok); goto L 0}; else {Produce. Code; goto L 1} end $Rparen case Operator. Stack(top) of � {pop. Operator. Stack; goto L 0}; $plus|$mult {Produce. Code; goto L 1} end 2020/12/5 北京化 大学信息科学与技术学院计算机系 30

● 带括号表达式的目标代码生成程序(接上) Other case Operator. Stack(top) of � {pop. Operator. Stack; return}; $plus|$mult {Produce. Code; goto L 1} end 请验证表达式 5*(a+b*(c+d)) 2020/12/5 北京化 大学信息科学与技术学院计算机系 31

● 目标代码生成子程序Produce. Code If ~Equa(typ 1, typ 2) then Error() Else { temp: =New. Addr; Send. Code(OP, ADDR 1, ADDR 2, temp); Pop(3); Push(temp, typ 1) } 2020/12/5 北京化 大学信息科学与技术学院计算机系 32


Thank you. Beijing University of Chemical Technology Beijing, P R China 2020/12/5 北京化 大学信息科学与技术学院计算机系 34
- Slides: 34