收藏 分享(赏)

success_C语言编译器的设计与实现.doc

上传人:dreamzhangning 文档编号:2332273 上传时间:2018-09-10 格式:DOC 页数:14 大小:247.50KB
下载 相关 举报
success_C语言编译器的设计与实现.doc_第1页
第1页 / 共14页
success_C语言编译器的设计与实现.doc_第2页
第2页 / 共14页
success_C语言编译器的设计与实现.doc_第3页
第3页 / 共14页
success_C语言编译器的设计与实现.doc_第4页
第4页 / 共14页
success_C语言编译器的设计与实现.doc_第5页
第5页 / 共14页
点击查看更多>>
资源描述

1、C 语言编译器的设计与实现01 计算机 4 班 18 号任春妍 2 号陈俊我们设计的编译程序涉及到编译五个阶段中的三个,即词法分析器、语法分析器和中间代码生成器。编译程序的输出结果包括词法分析后的二元式序列、变量名表、状态栈分析过程显示及四元式序列程序,整个编译程序分为三部分:(1) 词法分析部分(2) 语法分析处理及四元式生成部分 (3) 输出显示部分一词法分析器设计 由于我们规定的程序语句中涉及单词较少,故在词法分析阶段忽略了单词输入错误的检查,而将编译程序的重点放在中间代码生成阶段。词法分析器的功能是输入源程序,输出单词符号。我们规定输出的单词符号格式为如下的二元式: (单词种别,单词自

2、身的值)#define ACC -2#define syl_if 0#define syl_else 1#define syl_while 2#define syl_begin 3#define syl_end 4#define a 5#define semicolon 6#define e 7#define jinghao 8#define s 9#define L 10#define tempsy 11#define EA 12#define EO 13#define plus 14#define times 15#define becomes 16#define op_and 17#de

3、fine op_or 18#define op_not 19#define rop 20#define lparent 21#define rparent 22#define ident 23#define intconst 24函数说明 1 读取函数 readline( )、readch( )词法分析包含从源文件读取字符的操作,但频繁的读文件操作会影响程序执行效率,故实际上是从源程序文件” source.dat ”中读取一行到输入缓冲区,而词法分析过程中每次读取一个字符时则是通过执行 readch( )从输入缓冲区获得的;若缓冲区已被读空,则再执行 readline( )从 source.d

4、at 中读取下一行至输入缓冲区。2 扫描函数 scan( ) 扫描函数 scan( )的功能是滤除多余空格并对主要单词进行分析处理,将分析得到的二元式存入二元式结果缓冲区。3 变量处理 find( )变量处理中首先把以字母开头的字母数字串存到 spelling 数组中,然后进行识别。识别过程是先让它与保留关键字表中的所有关键字进行匹配,若获得成功则说明它为保留关键字,即将其内码值写入二元式结果缓冲区;否则说明其为变量,这时让它与变量名表中的变量进行匹配( 变量匹配函数 find( ) ) ,如果成功,则说明该变量已存在并在二元式结果缓冲区中标记为此变量( 值填为该变量在变量名表中的位置) ,否

5、则将该变量登记到变量名表中,再将这个新变量存入二元式缓存数组中。4 数字识别 number( ) 数字识别将识别出的数字填入二元式结果缓存数组。5 显示函数 显示函数的功能在屏幕上输出词法分析的结果( 即二元式序列程序) ,同时给出二元式个数及源程序行数统计。二语法分析器设计 语法分析器的核心是三张 SLR 分析表以及针对这三张 SLR 分析表进行语义加工的语义动作。编译程序中语法分析处理及四元式生成部分主要是以二元式作为输入,并通过 SLR 分析表对语法分析处理过程进行控制,使四元式翻译的工作有条不紊的进行,同时识别语法分析中的语法错误。在处理 if 和 while 语句时,需要进行真值或假

6、值的拉链和返填工作,以便转移目标的正确填入。1. 控制语句的 SLR 分析表 1 设计过程如下:将扩展文法 G0) S S1)S if e S else S2)S while e S3)S L 4)S a;5)L S6)L SL用_CLOSURE 方法构造 LR(0)项目规范簇为:I0: S SS if e S else SS while e SS L S a ;I1: S SI2: S ife S else SI3: S while e SI4: S LL SL SLS if e S else SS while e SS L S a ;I5: S a;I6: S if e S else SS

7、 if e S else SS while e SS L S a ;I7: S while e SS if e S else SS while e SS L S a ;I8: S LI9: L SL SLL SLL SS if e S else SS while e SS L S a ;I10: S a ; I11: S if e S else SI12: S while e SI13: S L I14: S SL I15: S if e S else SS if e S else SS while e SS L S a ; I16: S if e S else S 构造文法 G中非终结符的

8、FOLLOW 集如下:1) FOLLOW(S) = # 2) S if e S else S 得 FOLLOW(S) = else S L 得 FOLLOW(L) = 3) S S 得 FOLLOW(S) = else , #L S 因为 FIRST(S) = ,所以 FOLLOW(S) = else , #, 在()项目规范簇中 ,只有 9 有“移进归约”冲突, L S L SL因为 FOLLOW(L) FIRST(L) = 所以可以用方法解决以上冲突,最后我们得到的分析表如下:ACTION GOTOif Else while a ; e # S L0 S2 S3 S4 S5 11 ACC2

9、 S63 S74 S2 S3 S4 S5 9 85 S106 S2 S3 S4 S5 117 S2 S3 S4 S5 128 S139 S2 S3 S4 R5 S5 9 1410 R4 R4 R411 1512 R2 R2 R213 R3 R3 R314 R615 S2 S3 S4 S5 1616 R1 R1 R1static int action2011=/* 0 */ 2, -1, 3, 4, -1, 5, -1, -1, -1, 1, -1,/* 1 */ -1, -1, -1, -1, -1, -1, -1, -1,ACC, -1, -1,/* 2 */ -1, -1, -1, -1,

10、 -1, -1, -1, 6, -1, -1, -1,/* 3 */ -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1,/* 4 */ 2, -1, 3, 4, -1, 5, -1, -1, -1, 9, 8,/* 5 */ -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1,/* 6 */ 2, -1, 3, 4, -1, 5, -1, -1, -1, 11, -1,/* 7 */ 2, -1, 3, 4, -1, 5, -1, -1, -1, 12, -1,/* 8 */ -1, -1, -1, -1, 13, -1, -

11、1, -1, -1, -1, -1,/* 9 */ 2, -1, 3, 4,105, 5, -1, -1, -1, 9, 14,/* 10*/ -1,104, -1, -1,104, -1, -1, -1,104, -1, -1,/* 11*/ -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,/* 12*/ -1,102, -1, -1,102, -1, -1, -1,102, -1, -1,/* 13*/ -1,103, -1, -1,103, -1, -1, -1,103, -1, -1,/* 14*/ -1, -1, -1, -1,106, -1,

12、-1, -1, -1, -1, -1,/* 15*/ 2, -1, 3, 4, -1, 5, -1, -1, -1, 16, -1,/* 16*/ -1,101, -1, -1,101, -1, -1, -1,101, -1, -1;其中,前 9 列为 action 值,后 2 列为 goto 值;016 表示 17 个移进状态( 即 Si) ;-1 表示出错;ACC 表示分析成功;而 100106 对应 7 个归约产生式:100 S S101 S if e S else S102 S while e S103 S L 104 S a;105 L S106 L SL2. 算术表达式的 LR 分

13、析表 2 设计如下:0) S E1) E E+E2) E E*E3) E (E)4) E i (过程略)ACTION GOTOI + * ( ) # E0 S3 S2 11 S4 S5 ACC2 S3 S2 63 R4 R4 R4 R44 S3 S2 75 S3 S2 86 S4 S5 S97 R1 R5 R1 R18 R2 R2 R2 R29 R3 R3 R3 R3static int action1107=/* 0 */ 3, -1, -1, 2, -1, -1, 1,/* 1 */ -1, 4, 5, -1, -1,ACC, -1,/* 2 */ 3, -1, -1, 2, -1, -1

14、, 6,/* 3 */ -1,104,104, -1,104,104, -1,/* 4 */ 3, -1, -1, 2, -1, -1, 7,/* 5 */ 3, -1, -1, 2, -1, -1, 8,/* 6 */ -1, 4, 5, -1, 9, -1, -1,/* 7 */ -1,101, 5, -1,101,101, -1,/* 8 */ -1,102,102, -1,102,102, -1,/* 9 */ -1,103,103, -1,103,103, -1;3.布尔表达式的 SLR 分析表 3 设计如下:(过程略)1) S B2) B i3) B i rop i4) B ( B

15、 )5) B ! B6) A B LR 分析表控制语义加工的实现:当扫描 LR 分析表的当前状态为归约状态时,则在调用与该状态对应的产生式进行归约的同时,调用相应的语义子程序进行有关的翻译工作。现在对 LR 分析器的分析栈加以扩充,使得每个文法符号之后都跟着它的语义值。为了清晰起见,我们把这个栈的每一项看成由三部分组成:状态 state ,文法符号 syl 和语义值 val。编译程序实现算术表达式、布尔表达式及程序语句的语义加工时,都是按这种状态栈加工方式进行的。例如:( 5 + 3 ) * 6 的分析过程序号 STATE Val syl input1 0 - # ( 5 + 3 ) * 6

16、#2 02 - #( 5 + 3 ) * 6 #3 023 - #(5 + 3 ) * 6 #4 026 -5 #(E + 3 ) * 6 #5 0264 -5- #(E+ 3 ) * 6 #6 02643 -5- #(E+3 ) * 6 #7 02647 -5-3 #(E+E ) * 6 #8 026 -8 #(E ) * 6 #9 0269 -8- #(E) * 6 #10 01 -8 #E * 6 #11 015 -8- #E* * 6 #12 0153 -8- #E*6 #13 0158 -8-6 #E*E #14 01 -48 #E #15 ACC在分析过程中,第(3)步操作后的状态

17、栈为 023,根据栈顶状态“ 3”和现行输入符号“ +”( input 栏字符串的第一个字符)查分析表 ACTION3,+=R4 ,即按第(4)个产生式 En 来进行归约;由于产生式右部仅含一项,故去掉状态栈栈顶“3” ;此时 2 变为新的栈顶状态,再查( 2,E )的下一状态 s:GOTO2,E=6,即将状态 6 和文法符号 E 压栈,最后得到第( 4)步的状态。第( 7)步操作后也是如此,当前状态栈为 02647,根据栈顶状态 7 和现行输入符号“ ) ”查分析表 ACTION7, )=R1,即按第(1)个产生式 EE1+E2 进行归约;由于产生式右部有三项,故去掉状态栈栈顶的 647 三

18、项;此时 2 变为新的栈顶状态,再查( 2,E)的下一状态 s:GOTO2 , E=6,即将状态 6 和文法符号 E 压栈,最后得到第(8)步的状态。三中间代码生成器设计:布尔表达式 布尔表达式在程序语言中有两个基本作用:一是用作控制语句( 如 if -else 或 while 语句)的条件式;二是用于逻辑演算,计算逻辑值。布尔表达式是由布尔算符( L SL | S此时为程序语句构造相应的 SLR 分析表就简单多了。前面的程序语句文法中所添加的非终结符是为了能及时回填有关四元式转移目标而引入的,在取消了这些非终结符后又如何解决及时回填转移目标的问题呢?我们采取的解决方法是增加两个数组 labe

19、lmark 和 labeltemp 来分别记录语句嵌套中每一层布尔表达式( 如果有的话)e 的首地址以及每一层 else( 如果有的话)之前的四元式地址( 即无条件转出此层 if 语句的四元式) 。也即,对程序语句的翻译来说: 在处理完布尔表达式 e 后,回填 if 或 while 语句的真值链; 在归约完每一个语句 S 之后检查符号栈,看在 S 之前的文法符号是否 if 或 while,若是则回填假值链( 假值入口为语句 S 所对应的四元式序列之后;对 if 语句,此时已在该序列之后加入了一条无条件转移的四元式) ; 在 if 语句中,else 前面要加入一个无条件转移的四元式转向 if 语

20、句末尾;在 while 语句尾要有一个无条件转移四元式转向 while 语句开头。四数据结构说明 编译程序中涉及到的数据结构说明如下:char ch=0; /*从字符缓冲区中读取当前字符 */int count=0; /*词法分析结果缓冲区计数器*/static char spelling10=“ “; /*存放识别的字*/static char line81=“ “; /*一行字符缓冲区( 最多 80 个字符)*/char *pline; /*字符缓冲区指针*/static char ntab110010; /*变量名表:共 100 项,每项长度为 10*/struct ntab int t

21、c; /*真值*/int fc; /*假值*/ntab2200; /*在布尔表达式 ) 中保存有关布尔变量的真、假值 */int label=0; /*指向 ntab2 的指针*/struct rewords char sp10;int sy; /*匹配表的结构,用来与输入缓冲区中的单词进行匹配*/struct rewords rewords8=“if“,syl_if,“else“,syl_else,“while“,syl_while,“,syl_begin,“,syl_end,“ /*匹配表初始化,大小为 8*/struct aaint syl; /*存放名字*/int pos; /*存放名

22、字所对应的值*/buf100, /*词法分析结果缓冲区 */n, /*读取二元式的当前字符 */n1, /*当前表达式中的字符 */E, /*非终结符*/sstack100, /*算术或布尔表达式加工处理使用的符号栈 */ibuf100, /*算术或布尔表达式使用的缓冲区*/stack1000; /*语法分析加工处理使用的符号栈 */struct aa oth; /*四元式中空白位置*/struct fourexp char op10;struct aa arg1;struct aa arg2;int result;fexp200; /*四元式的结构定义*/int ssp=0; /*指向 ss

23、tack 栈指针*/struct aa *pbuf=buf; /*指向词法分析缓冲区的指针 */int nlength=0; /*词法分析中记录单词的长度 */int tt1=0; /*变量名表指针 */FILE *cfile; /*源程序文件,为结束符*/int lnum=0; /*源程序行数记数 */int sign=0; /*sign=0 为赋值语句;sign=1 为 while 语句;sign=3 为 if 语句*/int newt=0; /*临时变量计数器*/int nxq=100; /* nxq 总是指向下一个将要形成的四元式地址,每次执行 gen()时,地址自动增 1*/int

24、lr; /*扫描 LR 分析表 1 过程中保存的当前状态值*/int lr1; /*扫描 LR 分析表 2 或表 3 所保存的当前状态值*/int sp=0; /*查找 LR 分析表时状态栈的栈顶指针*/int stack1100; /*状态栈 1 定义*/int sp1=0; /*状态栈 1 的栈顶指针*/int num=0; /*算术或布尔表达式缓冲区指针*/struct ll int nxq1; /*记录下一条四元式的地址*/int tc1; /*真值链*/int fc1; /*假值链*/labelmark10; /*记录语句嵌套层次的数组,即记录嵌套中每层的布尔表达式 e 的首地址*/int labeltemp10; /*记录语句嵌套层次的数组,即记录每一层 else 之前的四元式地址*/int pointmark=-1; /*labelmark 数组指针*/int pointtemp=-1; /*labeltemp 数组指针*/五编译程序运行测试测试 source.dat 得源程序如下: while (ab) if (m=n) a=a+1;elsewhile (k=h) x=x+2;#经编译程序运行后得到的输出结果如下:1)词法分析得出的相应的名字的号码和他的值2)列举程序中所有的变量3)状态栈的移进-归约过程 4)最后产生的四元式中间代码

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报