当前位置:文档之家› FOR循环语句的翻译程序设计(LL(1)法、输出三地址)

FOR循环语句的翻译程序设计(LL(1)法、输出三地址)

课程设计任务书学生姓名:专业班级:指导教师:工作单位:题目: FOR循环语句的翻译程序设计(LL(1)法、输出三地址表示)初始条件:理论:学完编译课程,掌握一种计算机高级语言的使用。

实践:计算机实验室提供计算机及软件环境。

如果自己有计算机可以在其上进行设计。

要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)(1)写出符合给定的语法分析方法的文法及属性文法。

(2)完成题目要求的中间代码三地址表示的描述。

(3)写出给定的语法分析方法的思想,完成语法分析和语义分析程序设计。

(4)编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。

(5)设计报告格式按附件要求书写。

课程设计报告书正文的内容应包括:1 系统描述(问题域描述);2 文法及属性文法的描述;3 语法分析方法描述及语法分析表设计;4 按给定的题目给出中间代码形式的描述及中间代码序列的结构设计;5 编译系统的概要设计;6 详细的算法描述(流程图或伪代码);7 软件的测试方法和测试结果;8 研制报告(研制过程,本设计的评价、特点、不足、收获与体会等);9 参考文献(按公开发表的规范书写)。

时间安排:设计安排一周:周1、周2:完成系统分析及设计。

周3、周4:完成程序调试及测试。

周5:撰写课程设计报告。

设计验收安排:设计周的星期五第1节课开始到实验室进行上机验收。

设计报告书收取时间:设计周的次周星期一上午10点。

指导教师签名:年月日系主任(或责任教师)签名:年月日FOR循环语句的翻译程序设计——LL(1)法、输出三地址1.系统描述1.1问题描述用LL(1)法设计、编制、调试一个FOR(表达式1;表达式2;表达式3)〈赋值语句〉的语法及语义分析程序,输出三地址代码。

1.2功能描述(1)能对for循环语句做词法分析,并将其中的某些语句做预处理,如i++转换为i=i+1等。

(2)能依据给定的LL(1)文法判断输入串是否符合LL(1)文法(3)给出输入串的LL(1)分析过程(4)完成对语句中控制变量赋值语句,控制条件语句以及控制变量变换语句的翻译(5)完成对赋值语句包括复杂语句的翻译(6)能够对三个表达式缺少一个或多个的情况下进行翻译(7)用翻译后的语句以三地址代码的中间代码形式正确的表达for循环的执行流程。

2.文法及属性文法的描述2.1文法的语言描述(0)A->for(C;C;C){Y} (“}Y{)C;C;C(for”)(1)Y->i=E; (“;E=i”)(2)C->iD (“Di”)(3)C-> (“”)(4)D->=E (“E=”)(5)D-><E (“E<”)(6)D->>E (“E>”)(7)E->LM (“ML”)(8)M->+LM (“ML+”)(9)M->-LM (“ML-“)(10)M->ε(“”)(11)L->NP (“PN”)(12)P->*NP (“PN*”)(13)P->/NP (“PN/”)(14)P->ε(“”)(15)N->i (“i”) (i表示标识符或常数) (16)N->(E) (“)E(“)(17)D-><=E (“E=<”)(18)D->>=E (“E=>”)2.2属性文法的描述2.2.1FOR语句for(C1 C2 C3)n C1n+1 goto n+3n+2 C3n+3 if C2==true goto Y.startn+4 goto Y.end+2Y.start ...................//赋值语句的开始...... ...................Y.end ...................//赋值语句结束Y.end+1 goto n+2Y.end+2 //跳出循环体后第一条语句2.2.2表达式和赋值语句Y->i=E;(C->i=E;) { i.value=E.V alue }E->E1 op E2 (op: +,-,*,/,>,>=,<或<=){E.place = newtemp; //生成新的变量E.value =E1.value op E2.value}N->(E) { N.value=E.value }N->i { N.value=i.value }3 语法分析方法描述及语法分析表设计3.1LL(1)文法及预测分析法的描述LL(1):第1个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将用最左推导,1表明只需向右看一个符号便可决定如何推导即选择哪个产生式(规则)进行推导。

从文法的开始符号出发企图推导出与输入的单词串完全相匹配的句子,若输入串是文法给定的句子,则必能推出,反之必然出错。

LL(1)优点:实现方法简单、直观,便于手工构造或自动生成语法分析器。

文法很容易写出。

LL(1)缺点:对文法有一定得限制,要求推导过程中紧跟在飞终结符右边可能出现的终结符集不相交,要求文法产生式中不能含有左公共因子和左递归。

但并不是所有文法的左公共因子都能在有限的步骤内替换成无左公共因子的文法。

另外在做语法制导翻译时中间代码的输出方案相对于LR法比较复杂。

LR分析法的句柄即体现了算符的优先级,出现句柄即做相应的归约动作,中间代码很容易写出,实现很简单。

LL(1)是做自顶向下推导,因此设计LL(1)的语法制导翻译输出中间代码很需要技巧,涉及到了判断符号的优先级。

3.2预测分析表的构造先求出每个产生式的select集,以产生式左侧非终结符为纵轴,以终结符(包括#)为横轴作预测分析表,在非终结符与其select集中元素对应的单元格中填上相应产生式的右部或其序号,没有则填-1。

单元格中数字表示选用第几个产生式,-1表示出错,num代表常数,i代表标识符。

4. 中间代码形式的描述及中间代码序列的结构设计4.1三地址代码描述把表达式及各种语句表示成一组三元式。

每个三元式3个组成部分是:酸腐op,第一运算对象ARG1,和第二运算对象ARG2.例如a:=b*c+b*d的表示为:(1)(* b, c)(2)(* b, d)(3)(+ (1), (2))(4)(:= (3), a)与后缀式不同,三地址码含有对中间计算结果的显式引用,比如三元式(1)表示的是b*c的结果。

三元式(3)中的(1)和(2)分别表示第1个三元式和第2个三元式的结果。

对于一目算符op,只需选用一个运算对象,不妨规定只用ARG1.至于多目算符,可用若干个相继的三元式表示。

三地址代码一般形式:x:=y op z表示为<1>y op z<2>x:=<1>4.2中间代码序列的结构设计以for(i=0;i<10;i++){i=i+2;}为例,三地址中间代码生成序列如下:<1>i=0<2>goto <4><3>i=i+1<4>i<10<5>if <4> goto <7><6>goto <10><7>i+2<8>i=<7><9>goto <3><10>三地址代码结构:<1>控制变量赋值<2>跳转到判断语句<3>控制变量更改<4>判断语句<5>若成立跳转到赋值语句循环体<6>不成立则跳转到循环结束<7>赋值语句<i><i+1>跳转至控制变量更改语句<i+2>循环结束语句由于临时变量的个数是未知的,所以在语义分析的过程中需要保存临时变量的个数,以便保证下一条语句序号及循环出口的正确。

5.编译系统的概要设计5.1LL(1)文法的设计(1)文法的设计需要合理,使之符合LL(1)文法的要求,尽量避免产生式右部首部有交集,而某些文法的左公共因子无法完全消除(2)文法应该考虑到循环条件的三个产生式中有一个或多个为空的情况下的循环流程(部分语言如C语言甚至允许三个条件都为空,第一个条件空,则需要循环体之前的语句中对讯黄控制变量进行赋值;第二个条件为空,则循环会无限执行下去,即进入死循环;第三个条件为空,则在循环体中对控制变量进行改变)。

(3)对于循环体中的赋值语句,不仅仅有形如i=a+b的简单语句,还应考虑更复杂的复合赋值语句,这时就要进行操作符的优先级分析。

5.2语法及语义分析有LL(1)文法写出预测分析表,由此可以用预测分析法对输入串进行分析。

当分析栈栈顶为非终结符时,通过查表,将非终结符出栈,并将表中产生式右部逆序进栈,若对应单元为空或为错误标记,则出错;当栈顶为终结符时,若与当前输入符号相同,则栈顶出栈,输入串指针后移,若不同则出错。

一直分析下去,知道最后栈中只剩下#并且输入串也只有一个#,则该输入串可以被指定的LL(1)文法所识别,反之则否。

对赋值语句的翻译。

主要是对操作符的优先级的比较,使用算符优先分析法。

死机一个操作符栈和一个操作数栈,当前操作符的优先级小于或者等于当前输入符号时,输入符号进操作符栈,若大于,则操作符栈顶出栈,操作数栈两次出栈(二目运算符)进行运算,并将结果(中间变量)进操作数栈,依此分析。

6.详细的算法描述(伪代码描述)main() //主函数{lexicalAnalyze(); //词法分析(预处理parseAnalyze((); //语法预测分析semanticsOutput(); //语义输出}部分方法的实现:lexicalAnalyze(){ //输入串的词法分析string input[];string tmp=getText(); //读取文件到临时字符串if(tmp.end!=’#’) tmp.end=’#’; //在字符串末尾添加’#’do{curString=getWord(tmp); //从字符串中获取有效单词if(curString==”“) tmpPointer++;continue; //去除无效空格,并移动扫描指针curString->input[]; //将单词存入字符串数组if((input[n-1]=="<"||input[n-1]==">")&&input[n]=="=") //组合<=和>=input[n-1].append(input[n]);if((input[n-1]=="+"||input[n-1]=="-")&&input[n]==input[n-1]) //转换++和--i=i±1->input[];if((input[n-2]=="+"||input[n-2]=="-")&&input[n-1]=="=") //转换+=和-=i=i±n->input[];}parseAnalyze(){ //语法分析statck ana();ana.push(“#”); //”#”和”A”进分析栈ana.push(“A”);if(input[]==”for”){if(ana.getTop==input[]){input_pointr++; //输入串扫描指针右移ana.pop(); //栈顶出栈}if(ana.getTop==”A”){ana.pop;ana.reversePush(“for(C;C;C){Y}”); //产生式右部逆序入栈}}if(input[]==”i”){if(ana.getTop==input[]){...}if(ana.getTop==”C”){...}if(ana.getTop==”Y”){...}......}......if(input[]==”#”) //匹配成功{if(ana.getTop==input[]) cout<<”Match successful!”;}else cout<<”Match fail!”; //匹配失败}constProcess() //常数处理,字符串共有i个字符{for(dotCount=0;dotCount<i;dotCount++) //对小数点定位,无则返回-1if(curString[dotCount]==’.’) return dotCount;else return -1 ;for(eCount=0;eCount<i;eCount++) //对e定位,无则返回-1if(curString[eCount]==’e’) return eCount;else return -1;if(dotCount==-1&&eCount==-1) //纯整数的情况{for(count=0;count<i;count++)parseInt+=(curString[count]-30H)*pow(10.0,i-1-count); //ASCII转为整数}else if(dotCount!=-1&&eCount==-1) //纯小数的情况{for(leftCount=0;leftCount<dotCount;leftCount++) //小数的整数部分parseInt+=(curString[leftCout]=30H)*pow(10.0,dotCount-1-leftCount);for(rightCount=dotCount+1;rightCount<i;rightCount++) //小数的小数部分parseDecimal+=(curString[leftCout]=30H)*pow(10.0,dotCount-reghtCount);parseBase=parseInt+parseDecimal;}else //含有e的情况{if(k!=-1) //e前面是小数{for(leftCount=0;leftCount<dotCount;leftCount++) //小数的整数部分parseInt+=(curString[leftCout]=30H)*pow(10.0,dotCount-1-leftCount);for(rightCount=dotCount+1;rightCount<eCount;rightCount++) //小数的小数部分parseDecimal+=(curString[leftCout]=30H)*pow(10.0,dotCount-reghtCount);parseBase=paseInt+parseDecimal;}else //e前面是整数{for(count=0;count<eCount;count++)pareseBase+=(curString[count]-30H)*pow(10.0,eCount-1-count);}for(count=eCount+1;count<i;count++) //指数的幂paresePower+=(curString[count]-30H)*pow(i-1-count);parseTotal=parseBase*pow(10.0,parsePower);}}semanticsOutput //执行语义动作{/*对于赋值语句和布尔表达式,调用词法分析程序分析并同步记录临时变量的个数*/ }7.软件的测试方法和测试结果在文本文件中输入for(i=0;i<=10;i++){i+=2;}词法分析结果(转换过双目运算符):语法分析过程:三地址代码输出结果:将循环条件的第三个产生式删除后的输出结果:8.研制报告8.1研制过程本实验在文法的构造方面遇到了困难,LL(1)对文法有一定的限制:不能含有左公共因子和左递归,表现在产生的select集不相交,而又要能表示比较宽泛的for循环的格式,需要用到一些空产生式,这又增加了select集相交的可能性,所有构造LL(1)遇到了一些困难,不过最终还是构造出了符合LL(1)文法要求的文法。

相关主题