语法制导翻译
- 格式:doc
- 大小:29.00 KB
- 文档页数:8
编译原理分知识点习题-语法制导和翻译1.⼀般情况下,为什么语义分析部分仅产⽣中间代码解答:⼀般情况下,语义分析部分仅产⽣中间代码,其原因是:可使难点分解,分别解决。
可对语义分析产⽣的中间代码进⾏优化,以产⽣⾼效率的⽬标代码。
语义分析通常与机器⽆关,⽬标代码往往与机器有关。
把语义分析与⽬标代码⽣成分开,可让⼀个语义分析程序适⽤于多个⽬标代码⽣成程序。
2.(湖北省⾼等教育⾃学考试)什么是语法制导翻译为什么把这种⽅法叫语法制导翻译解答:所谓语法制导翻译,是指在语法规则的制导下,通过计算语义规则,完成对输⼊符号串的翻译。
由于使⽤属性⽂法时把语法规则和语义规则分开,但在使⽤语法规则进⾏推导或规约的同时⼜使⽤这些语义规则来知道翻译与最终产⽣⽬标代码,所以称为语法制导翻译。
3.给出将附值语句翻译成四元式的语法制导定义,允许右部表达式含有加法、乘法、取负、括号运算。
⽣成赋值语句X:=B*(C+D)+A 的四元式。
解答:赋值语句的⾃下⽽上的语法制导翻译过程描述为:规则语义动作(1)A::=i:=E {GEN (:=,,__,ENTRY(i) ) }(2)E::=E1+E2 {:=NEWTEMP;GEN(+,, ,}(3)E::= E1*E2 { :=NEWTEMP;GEN(*,, ,}(4)E::=-E1 { :=NEWTEMP;GEN(@,,__,}(5)E::=(E1) {:= }(6)E::=i {:= ENTRY(i) }⽣成的赋值语句X:=B*(C+D)+A的四元式为:(+,C,D,T1)(*,B,T1,T2)(+,T2,A,T3)(:=,T3,_,X)4.给出将布尔表达式翻译成四元式的语法制导定义。
解答:布尔表达式的语义⼦程序为:规则语义动作(1) E::=I {:=null;:=NXQ;GEN (Jez , ENTRY(i), __,0) }(2) E::= i1 rop i2 { :=null;:=NXQ;GEN (Jnrop,ENTRY(i1), ENTRY(i2),0)}(3) E::= (E1) {:=, :=; }(4) E::= ? E1 { :=NXQ;GEN ( J, __, __, 0); BP , NXQ);}(5) E A::=E1∧ { if =nullthen begin::=NXQ;GEN ( J, __, __, 0)End;BP ( , NXQ );:=null; := }(6) E ::= E A E2 {if ≠nullthen beginBP , NXQ);:=nullEnd:=; }(7) E0::=E1∨ { if :=nullthen begin:=NXQ;GEN ( J, __, __, 0)End;:=;BP ,NXG);}(8) E::=E0E2 { if ≠nullthen:=MERG,Else beginBP ,NXQ);:=End;:=}其中:NXQ指⽰器指向下⼀个将要形成但尚未形成的四元式的地址(编号),初值为1,每当执⾏GEN⼀次,NXQ⾃动加1。
1.一般情况下,为什么语义分析部分仅产生中间代码解答:一般情况下,语义分析部分仅产生中间代码,其原因是:可使难点分解,分别解决。
可对语义分析产生的中间代码进行优化,以产生高效率的目标代码。
语义分析通常与机器无关,目标代码往往与机器有关。
把语义分析与目标代码生成分开,可让一个语义分析程序适用于多个目标代码生成程序。
2.(湖北省高等教育自学考试)什么是语法制导翻译为什么把这种方法叫语法制导翻译解答:所谓语法制导翻译,是指在语法规则的制导下,通过计算语义规则,完成对输入符号串的翻译。
由于使用属性文法时把语法规则和语义规则分开,但在使用语法规则进行推导或规约的同时又使用这些语义规则来知道翻译与最终产生目标代码,所以称为语法制导翻译。
3.'4.5.给出将附值语句翻译成四元式的语法制导定义,允许右部表达式含有加法、乘法、取负、括号运算。
生成赋值语句X:=B*(C+D)+A的四元式。
解答:赋值语句的自下而上的语法制导翻译过程描述为:规则语义动作(1)A::=i:=E {GEN (:=,,__,ENTRY(i) ) }(2)E::=E1+E2{:=NEWTEMP;GEN(+,, ,}(3)E::= E1*E2{ :=NEWTEMP;'GEN(*,, ,}(4)E::=-E1{ :=NEWTEMP;GEN(@,,__,}(5)E::=(E1) {:= }(6)E::=i {:= ENTRY(i) }生成的赋值语句X:=B*(C+D)+A的四元式为:(+,C,D,T1)((*,B,T1,T2)(+,T2,A,T3)(:=,T3,_,X)6.给出将布尔表达式翻译成四元式的语法制导定义。
解答:布尔表达式的语义子程序为:规则语义动作(1) E::=I {:=null;:=NXQ;【GEN (Jez , ENTRY(i), __,0) }(2) E::= i1 rop i2 { :=null;:=NXQ;GEN (Jnrop,ENTRY(i1), ENTRY(i2),0)}(3) E::= (E1) {:=, :=; }(4) E::= ¬ E1 { :=NXQ;GEN ( J, __, __, 0); BP , NXQ);}(5) E A::=E1∧{ if =null】then begin::=NXQ;GEN ( J, __, __, 0)End;BP ( , NXQ );:=null; := }(6) E ::= E A E2 {if ≠null,then beginBP , NXQ);:=nullEnd:=; }(7) E0::=E1∨{ if :=nullthen begin>:=NXQ;GEN ( J, __, __, 0)End;:=;BP ,NXG);}(8) E::=E0E2 { if ≠nullthen::=MERG,Else beginBP ,NXQ);:=End;:=}其中:~NXQ指示器指向下一个将要形成但尚未形成的四元式的地址(编号),初值为1,每当执行GEN一次,NXQ自动加1。
语法制导翻译
语法制导翻译是一种将源语言(通常为自然语言)的语法结构与目标语言的语法结构相对应的翻译方法。
它通过语法分析器和语法制导翻译器来实现。
在语法制导翻译中,源语言和目标语言的语法规则被定义成一个或多个上下文无关文法。
语法制导翻译的主要思想是在语法分析树中嵌入翻译动作,并通过语法制导翻译器将源语言转换为目标语言。
语法制导翻译器的主要任务是对每个语法分析树节点进行翻译动作的定义,并将这些翻译动作与语法分析器的分析过程相结合,最终生成目标语言的语法结构。
语法制导翻译是机器翻译领域的一种重要研究方向,它可以有效地解决自然语言翻译中的语言差异和歧义问题。
同时,它也是编译原理、计算机语言学等领域中的基础性问题。
for循环语句翻译递归下降法输出三地址码/////////////#define MAX 100#include<iostream.h>#include<stdio.h>#include<string.h>char str[MAX];char ch;int turn;char strToken[MAX];int kind;int n=0;//存放strtoken[]元素的个数struct Word//结构体存放单词{int sort;char word[MAX];//存放strtoken[]的内容};//record[x]=new Word;Word *record[12];//放所有识别出来的单词,分别存放他们的编号以及字符串,x是其下标////////////////////词法分析///////////////////////int buffer()//载入{int i=0;cout<<"输入程序,以“#”作为结束标志。
"<<endl;for(int n=0;n<=MAX;n++){for(;i<=MAX;i++){scanf("%c",&str[i]);/////////////cin>>str[i]不可用,用C语言读入字符。
if(str[i]=='#')break;///////如果尾数为识别码#,则表示程序读完,跳出循环.}break;}return(i);bool IsLetter(char ch)///////////判断是否是字母{if(ch>=65&&ch<=90||ch>=97&&ch<=122)return(true);elsereturn(false);}bool IsDigit(char ch)//////////判断是否是数字{if(ch>=48&&ch<=57)return(true);elsereturn(false);}char GetChar(int i)///////读取字符{char ch;ch=str[i];return(ch);}char GetBC(char ch)////判断是不是空格或者换行,如果是,直接读取下一个字符直道不再空白为止{if(ch==32||ch==10){turn++;ch=GetChar(turn);ch=GetBC(ch);/////////递归实现return(ch);}elsereturn(ch);}void Concat()/////////////连接,即为strtoken[]赋值{strToken[n]=ch;n++;int Reserve()/////以单词为单位查找保留字,是则返回编码,不是则返回0,用来区分标志符和保留字{if(strcmp(strToken," DIM\0")==0)///////调用strcmp函数实现,return(1);else if(strcmp(strToken,"for\0")==0)return(2);else if(strcmp(strToken,"step\0")==0)return(3);else if(strcmp(strToken,"until\0")==0)return(4);else if(strcmp(strToken,"do\0")==0)return(5);elsereturn(6);}void clear(){n=0;}/////////////*语法递归分析*/////////////////int A(int * c,int & q){if(c[q++]==3){if(c[q]==7){ q++;return 1;}else {cout<<"step右部出错"<<endl;return 0;}}else {cout<<"error 'step'"<<endl;return 0;}}int B(int * b,int & o)if(b[o++]==4){if(b[o]==7){ o++;return 1;}else {cout<<"until右部出错"<<endl;return 0;}}else {cout<<"error 'until'"<<endl;return 0;}}int S2(int * d,int & h){if(d[h++]==6){if(d[h++]==8){if((d[h]==6||d[h]==7)) {h++; return 1;}else {cout<<"赋值语句右部出错"<<endl;return 0;}}else {cout<<"赋值语句缺少赋值运算符"<<endl;return 0;} }else {cout<<"赋值语句左部出错"<<endl;return 0;}}int S1(int * m,int & n){if(S2(m,n)){if(A(m,n)){if(B(m,n)) return 1;else return 0;}else return 0;}else return 0;}int S(int *a,int & z){if (a[z++]==2){if (S1(a,z)){if(a[z++]==5){{cout<<"succeed!"<<endl;return 1;}else return 0;}else {cout<<"error 'do'"<<endl; return 0;}}else return 0;}else {cout<<"error 'for'"<<endl; return 0;}}void main(){cout<<"*************产生式***************"<<endl;// for step until do i j =cout<<" S ->for S1 do S2"<<endl; // 编号2 3 4 5 6 7 8cout<<" S1 ->S2AB"<<endl;cout<<" S2 ->i=j"<<endl;cout<<" A ->stepj"<<endl;cout<<" B ->untilj"<<endl;int num;turn=0;num=buffer()-1;int x=0;//计识别的单词的个数for(;turn<=num;turn++)//总循环,ch存放刚读入的字符,strtoken[]存放已识别的标志付或保留字,turn是数组str[]的下标{ch=GetChar(turn);ch=GetBC(ch);if(IsLetter(ch)){while(IsLetter(ch)&&turn<=num||IsDigit(ch)&&turn<=num){Concat();ch=GetChar(++turn);}strToken[n]='\0';ch=NULL;//此ch不是标志符中的符号kind=Reserve();record[x]=new Word; record[x]->sort=kind;//12345或6 //cout<<kind; //测试cout<<"(";for(int i=0;i<n;i++){record[x]->word[i]=strToken[i];cout<<record[x]->word[i];//输出识别的标志符或保留字}cout<<","<<kind<<")"<<endl;record[x]->word[i]='\0';clear();x++;}else if(IsDigit(ch)){while(IsDigit(ch)&&turn<=num){Concat();ch=GetChar(++turn);}ch=NULL;turn=turn-1;kind=7;//////////////record[x]=new Word;record[x]->sort=kind;////////////////cout<<"(";for(int i=0;i<n;i++){record[x]->word[i]=strToken[i];cout<<record[x]->word[i];}cout<<","<<kind<<")"<<endl;record[x]->word[i]='\0';clear();x++;}else if(ch=='='){kind=8;///////record[x]=new Word;record[x]->word[0]='=';record[x++]->sort=kind;cout<<"(=,"<<kind<<")"<<endl;}elsecout<<"error input!"<<endl;}//////////////////////*语法分析*//////////////////int y;/*for(y=0;y<x;y++){cout<<record[y]->sort<<" ";//打印单词的编号。