编译原理 lec8
- 格式:ppt
- 大小:303.50 KB
- 文档页数:52
第八章 语法制导翻译和中间代码生成1.给出下面表达式的逆波兰表示(后缀式): (1) a*(-b+c)(4) (A ∧B) ∨(⌝C ∨ D)(7) if(x+y)*z=0 then s ∶=(a+b)*c else s ∶=a*b*c解(1) ab-c+*(4) AB ∧C ⌝D ∨∨(7) xy+z*0=sab+c*:=sab*c*:=¥(注:¥表示if-then-else 运算)2. 请将表达式-(a+b)*(c+d)-(a+b+c)分别表示成三元式、间接三元式和四元式序列。
答案:三元式(1) (+ a, b) (2) (+ c, d)(3) (* (1), (2)) (4) (- (3), /) (5) (+ a, b)(6) (+,(5),c) (7) (- (4), (6)) 间接三元式间接三元式序列 间接码表 (1) (+ a, b) (1) (2) (+ c, d) (2) (3) (* (1), (2)) (3) (4) (- (3), /) (4)¥= :=*:=+ xyzs +cxa bs* c*a b(5) (- (4), (1)) (1)(6) (- (4), (5)) (5)(6)四元式(1) (+, a, b, t1) (2) (+, c, d, t2) (3) (*, t1, t2, t3) (4) (-, t3, /, t4)(5) (+, a, b, t5) (6) (+, t5, c, t6) (6) (-, t4, t6, t7)3. 采用语法制导翻译思想,表达式E 的"值"的描述如下: 产生式 语义动作(0) S ′→E {print E.VAL}(1) E →E1+E2 {E.VAL ∶=E1.VAL+E2.VAL} (2) E →E1*E2 {E.VAL ∶=E1.VAL*E2.VAL} (3) E →(E1) {E.VAL ∶=E1.VAL} (4) E →n {E.VAL ∶=n.LEXVAL}如果采用LR 分析法,给出表达式(5 * 4 + 8) * 2的语法树并在各结点注明语义值VAL 。
LL(1)文法(源代码)#includ e "stdio.h"#includ e "stdlib.h"#define MaxRul eNum8#define MaxVnN um 5#define MaxVtN um 5#define MaxSta ckDep th 20#define MaxPLe ngth20#define MaxStL ength 50struct pRNode /*产生式右部结构*/{int rCurso r;struct pRNode *next;};struct pNode{int lCurso r;int rLengt h; /*右部长度*/struct pRNode *rHead; /*右部结点头指针*/};char Vn[MaxVnN um + 1]; /*非终结符集*/int vnNum;char Vt[MaxVtN um + 1]; /*终结符集*/int vtNum;struct pNodeP[MaxRul eNum];int PNum;char buffer[MaxPLe ngth+ 1];char ch;char st[MaxStL ength]; /*要分析的符号串*/struct collec tNode{int nVt;struct collec tNode *next;};struct collectNode* first[MaxVnN um + 1]; /*first集*/ struct collectNode* follow[MaxVnN um + 1]; /*follow集*/int analys eTabl e[MaxVnN um + 1][MaxVtN um + 1 + 1];int analyseStack[MaxSta ckDep th + 1]; /*分析栈*/int topAnal yse; /*分析栈顶*/void Init();/*初始化*/int IndexC h(char ch);void InputV t(); /*输入终结符*/void InputV n();/*输入非终结符*/void ShowChA rray(char* collect, int num);/*输出Vn或V t的内容*/ void InputP();/*产生式输入*/bool CheckP(char * st);/*判断产生式正确性*/void First(int U);void AddFirst(int U, int nCh); /*加入first集*/bool HaveEm pty(int nVn);void Follow(int V);/*计算foll ow集*/void AddFol low(int V, int nCh, int kind);void ShowCol lect(struct collectNode **collect);/*输出firs t或fol low集*/ void FirstF ollow();/*计算first和fol low*/void CreateA T();/*构造预测分析表*/void ShowAT();/*输出分析表*/void Identi fy(char *st);void InitSt ack();void ShowSt ack();void Pop();void Push(int r);void main(void){char todo,ch;Init();InputV n();InputV t();InputP();getcha r();FirstF ollow();printf("所得firs t集为:");ShowCo llect(first);printf("所得foll o w集为:");ShowCo llect(follow);Create A T();ShowAT();todo = 'y';while('y' == todo){printf("\n是否继续进行句型分析?(y / n):"); todo = getcha r();while('y' != todo && 'n' != todo){printf("\n(y / n)? ");todo = getcha r();}if('y' == todo){int i;InitSt ack();printf("请输入符号串(以#结束) : ");ch = getcha r();i = 0;while('#' != ch && i < MaxStL ength){if(' ' != ch && '\n' != ch){st[i++] = ch;}ch = getcha r();}if('#' == ch && i < MaxStL ength){st[i] = ch;Identi fy(st);}elseprintf("输入出错!\n");}}getcha r();}void Init(){int i,j;vnNum= 0;vtNum= 0;PNum = 0;for(i = 0; i <= MaxVnN um; i++)Vn[i] = '\0';for(i = 0; i <= MaxVtN um; i++)Vt[i] = '\0';for(i = 0; i < MaxRul eNum; i++) {P[i].lCurso r = NULL;P[i].rHead= NULL;P[i].rLengt h = 0;}PNum = 0;for(i = 0; i <= MaxPLe ngth; i++)buffer[i] = '\0';for(i = 0; i < MaxVnN um; i++){first[i] = NULL;follow[i] = NULL;}for(i = 0; i <= MaxVnN um; i++) {for(j = 0; j <= MaxVnN um + 1; j++) analys eTabl e[i][j] = -1;}}int IndexC h(char ch){int n;n = 0; /*is Vn?*/while(ch != Vn[n] && '\0' != Vn[n]) n++;if('\0' != Vn[n])return 100 + n;n = 0; /*is Vt?*/while(ch != Vt[n] && '\0' != Vt[n]) n++;if('\0' != Vt[n])return n;return -1;}/*输出Vn或V t的内容*/void ShowCh Array(char* collec t){int k = 0;while('\0' != collec t[k]){printf(" %c ", collec t[k++]);}printf("\n");}/*输入非终结符*/void InputV n(){int inErr= 1;int n,k;char ch;while(inErr){printf("\n请输入所有的非终结符,注意:");printf("请将开始符放在第一位,并以#号结束:\n");ch = ' ';n = 0;/*初始化数组*/while(n < MaxVnN um){Vn[n++] = '\0';}n = 0;while(('#' != ch) && (n < MaxVnN um)){if(' ' != ch && '\n' != ch && -1 == IndexC h(ch)){Vn[n++] = ch;vnNum++;}ch = getcha r();}Vn[n] = '#'; /*以“#”标志结束用于判断长度是否合法*/ k = n;if('#' != ch){if( '#' != (ch = getcha r())){while('#' != (ch = getcha r()));printf("\n符号数目超过限制!\n");inErr= 1;contin ue;}}/*正确性确认,正确则,执行下下面,否则重新输入*/ Vn[k] = '\0';ShowCh Array(Vn);ch = ' ';while('y' != ch && 'n' != ch){if('\n' != ch){printf("输入正确确认?(y/n):");}scanf("%c", &ch);}if('n' == ch){printf("录入错误重新输入!\n");inErr= 1;}else{inErr= 0;}}}/*输入终结符*/void InputV t(){int inErr= 1;int n,k;char ch;while(inErr){printf("\n请输入所有的终结符,注意:");printf("以#号结束:\n");ch = ' ';n = 0;/*初始化数组*/while(n < MaxVtN um){Vt[n++] = '\0';}n = 0;while(('#' != ch) && (n < MaxVtN um)){if(' ' != ch && '\n' != ch && -1 == IndexC h(ch)) {Vt[n++] = ch;vtNum++;}ch = getcha r();}Vt[n] = '#';k = n;if('#' != ch){if( '#' != (ch = getcha r())){while('#' != (ch = getcha r()));printf("\n符号数目超过限制!\n");inErr= 1;contin ue;}}Vt[k] = '\0';ShowCh Array(Vt);ch = ' ';while('y' != ch && 'n' != ch){if('\n' != ch){printf("输入正确确认?(y/n):");}scanf("%c", &ch);}if('n' == ch){printf("录入错误重新输入!\n");inErr= 1;}else{inErr= 0;}}}/*产生式输入*/void InputP(){char ch;int i = 0, n,num;printf("请输入文法产生式的个数:");scanf("%d", &num);PNum = num;getcha r(); /*消除回车符*/printf("\n请输入文法的%d个产生式,并以回车分隔每个产生式:", num); printf("\n");while(i < num){printf("第%d个:", i);/*初始化*/for(n =0; n < MaxPLe ngth; n++)buffer[n] = '\0';/*输入产生式串*/ch = ' ';n = 0;while('\n' != (ch = getcha r()) && n < MaxPLe ngth){if(' ' != ch)buffer[n++] = ch;}buffer[n] = '\0';if(CheckP(buffer)){pRNode *pt, *qt;P[i].lCurso r = IndexC h(buffer[0]);pt = (pRNode*)malloc(sizeof(pRNode));pt->rCurso r = IndexC h(buffer[3]);pt->next = NULL;P[i].rHead= pt;n = 4;while('\0' != buffer[n]){qt = (pRNode*)malloc(sizeof(pRNode));qt->rCurso r = IndexC h(buffer[n]);qt->next = NULL;pt->next = qt;pt = qt;n++;}P[i].rLengt h = n - 3;i++;}elseprintf("输入符号含非法在成分,请重新输入!\n"); }}/*判断产生式正确性*/bool CheckP(char * st){int n;if(100 > IndexC h(st[0]))return false;if('-' != st[1])return false;if('>' != st[2])return false;for(n = 3; '\0' != st[n]; n ++){if(-1 == IndexC h(st[n]))return false;}return true;}void First(int U){int i,j;for(i = 0; i < PNum; i++){if(P[i].lCurso r == U){struct pRNode* pt;pt = P[i].rHead;j = 0;while(j < P[i].rLengt h){if(100 > pt->rCurso r){AddFir st(U, pt->rCurso r);break;}else{if(NULL == first[pt->rCurso r - 100]){First(pt->rCurso r);}AddFir st(U, pt->rCurso r);if(!HaveEm pty(pt->rCurso r)){break;}else{pt = pt->next;}}j++;}if(j >= P[i].rLengt h) /*当产生式右部都能推出空时*/ AddFir st(U, -1);}}}/*加入first集*/void AddFir st(int U, int nCh){struct collec tNode *pt, *qt;int ch; /*用于处理Vn*/pt = NULL;qt = NULL;if(nCh < 100){pt = first[U - 100];while(NULL != pt){if(pt->nVt == nCh)break;else{qt = pt;pt = pt->next;}}if(NULL == pt){pt = (struct collec tNode *)malloc(sizeof(struct collec tNode));pt->nVt = nCh;pt->next = NULL;if(NULL == first[U - 100]){first[U - 100] = pt;}else{qt->next = pt; /*qt指向fi rst集的最后一个元素*/}pt = pt->next;}}else{pt = first[nCh - 100];while(NULL != pt){ch = pt->nVt;if(-1 != ch){AddFir st(U, ch);}pt = pt->next;}}}bool HaveEm pty(int nVn){if(nVn < 100)return false;struct collec tNode *pt;pt = first[nVn - 100];while(NULL != pt){if(-1 == pt->nVt)return true;pt = pt->next;}return false;}void Follow(int V){int i;struct pRNode *pt ;if(100 == V) /*当为初始符时*/AddFol low(V, -1, 0 );for(i = 0; i < PNum; i++){pt = P[i].rHead;while(NULL != pt && pt->rCurso r != V)pt = pt->next;if(NULL != pt){pt = pt->next;if(NULL == pt){if(NULL == follow[P[i].lCurso r - 100] && P[i].lCurso r != V) {Follow(P[i].lCurso r);}AddFol low(V, P[i].lCurso r, 0);}else{while(NULL != pt && HaveEm pty(pt->rCurso r)){AddFol low(V, pt->rCurso r, 1);pt = pt->next;}if(NULL == pt){if(NULL == follow[P[i].lCurso r - 100] && P[i].lCurso r != V) {Follow(P[i].lCurso r);}AddFol low(V, P[i].lCurso r, 0);}else{AddFol low(V, pt->rCurso r, 1);}}}}}void AddFol low(int V, int nCh, int kind){struct collec tNode *pt, *qt;int ch;pt = NULL;qt = NULL;if(nCh < 100) /*为终结符时*/{pt = follow[V - 100];while(NULL != pt){if(pt->nVt == nCh)break;else{qt = pt;pt = pt->next;}}if(NULL == pt){pt = (struct collec tNode *)malloc(sizeof(struct collec tNode));pt->nVt = nCh;pt->next = NULL;if(NULL == follow[V - 100]){follow[V - 100] = pt;}else{qt->next = pt; /*qt指向fo llow集的最后一个元素*/}pt = pt->next;}}else{if(0 == kind){pt = follow[nCh - 100];while(NULL != pt){ch = pt->nVt;AddFol low(V, ch, 0);pt = pt->next;}}else{pt = first[nCh - 100];while(NULL != pt){ch = pt->nVt;if(-1 != ch){AddFol low(V, ch, 1);}pt = pt->next;}}}}/*输出first或fol low集*/void ShowCo llect(struct collec tNode **collec t) {int i;struct collec tNode *pt;i = 0;while(NULL != collec t[i]){pt = collec t[i];printf("\n%c:\t", Vn[i]);while(NULL != pt){if(-1 != pt->nVt){printf(" %c", Vt[pt->nVt]);}elseprintf(" #");pt = pt->next;}i++;}printf("\n");}/*计算first和fol low*/void FirstF ollow(){int i;i = 0;while('\0' != Vn[i]){if(NULL == first[i])First(100 + i);i++;}i = 0;while('\0' != Vn[i]){if(NULL == follow[i])Follow(100 + i);i++;}}/*构造预测分析表*/void Create A T(){int i;struct pRNode *pt;struct collec tNode *ct;for(i = 0; i < PNum; i++){pt = P[i].rHead;while(NULL != pt && HaveEm pty(pt->rCurso r)) {ct = first[pt->rCurso r - 100];while(NULL != ct){if(-1 != ct->nVt)analys eTabl e[P[i].lCurso r - 100][ct->nVt] = i;ct = ct->next;}pt = pt->next;}if(NULL == pt){ct = follow[P[i].lCurso r - 100];while(NULL != ct){if(-1 != ct->nVt)analys eTabl e[P[i].lCurso r - 100][ct->nVt] = i;elseanalys eTabl e[P[i].lCurso r - 100][vtNum] = i;ct = ct->next;}}else{if(100 <= pt->rCurso r) /*不含空的非终结符*/ {ct = first[pt->rCurso r - 100];while(NULL != ct){analys eTabl e[P[i].lCurso r - 100][ct->nVt] = i;ct = ct->next;}}else /*终结符或者空*/{if(-1 == pt->rCurso r){ct = follow[P[i].lCurso r - 100];while(NULL != ct){if(-1 != ct->nVt)analys eTabl e[P[i].lCurso r - 100][ct->nVt] = i;else /*当含有#号时*/analys eTabl e[P[i].lCurso r - 100][vtNum] = i;ct = ct->next;}}else /*为终结符*/{analys eTabl e[P[i].lCurso r - 100][pt->rCurso r] = i;}}}}}/*输出分析表*/void ShowAT(){int i,j;printf("构造预测分析表如下:\n");printf("\t|\t");for(i = 0; i < vtNum; i++){printf("%c\t", Vt[i]);}printf("#\t\n");printf("- - -\t|- - -\t");for(i = 0; i <= vtNum; i++)printf("- - -\t");printf("\n");for(i = 0; i < vnNum; i++){printf("%c\t|\t", Vn[i]);for(j = 0; j <= vtNum; j++){if(-1 != analys eTabl e[i][j])printf("R(%d)\t", analys eTabl e[i][j]);elseprintf("error\t");}printf("\n");}}void Identi fy(char *st){int curren t,step,r; /*r表使用的产生式的序号*/ printf("\n%s的分析过程:\n", st);printf("步骤\t分析符号栈\t当前指示字符\t使用产生式序号\n");step = 0;curren t = 0;printf("%d\t",step);ShowSt ack();printf("\t\t%c\t\t- -\n", st[curren t]);while('#' != st[curren t]){if(100 > analys eStac k[topAna lyse]){if(analys eStac k[topAna lyse] == IndexC h(st[curren t])){Pop();curren t++;step++;printf("%d\t", step);ShowSt ack();printf("\t\t%c\t\t出栈、后移\n", st[curren t]);}else{printf("%c-%c不匹配!", analyseStack[topAnal yse], st[curren t]);printf("此串不是此文法的句子!\n");return;}}else /*当为非终结符时*/{r = analys eTabl e[analys eStac k[topAna lyse] - 100][IndexC h(st[curren t])];if(-1 != r){Push(r);step++;printf("%d\t", step);ShowSt ack();printf("\t\t%c\t\t%d\n", st[curren t], r);}else{printf("此串不是此文法的句子!\n");return;}}if('#' == st[curren t]){if(0 == topAna lyse&& '#' == st[curren t]){step++;printf("%d\t", step);ShowSt ack();printf("\t\t%c\t\t分析成功!\n", st[curren t]);printf("%s是给定文法的句子!\n", st);}else{while(topAna lyse> 0){if(100 > analys eStac k[topAna lyse]){printf("此串不是此文法的句子!\n");return;}else{r = analys eTabl e[analys eStac k[topAna lyse] - 100][vtNum];if(-1 != r){Push(r); /*产生式右部代替左部,指示器不移动*/step++;printf("%d\t", step);ShowSt ack();if(0 == topAna lyse&& '#' == st[curren t]){printf("\t\t%c\t\t分析成功!\n", st[curren t]);printf("%s是给定文法的句子!\n", st);}elseprintf("\t\t%c\t\t%d\n", st[curren t], r);}else{printf("此串不是此文法的句子!\n");return;}}}}}/*初始化栈及符号串*/void InitSt ack(){int i;/*分析栈的初始化*/for(i = 0; i < MaxStL ength; i++)st[i] = '\0';analyseStack[0] = -1; /*#(-1)入栈*/ analyseStack[1] = 100; /*初始符入栈*/ topAna lyse= 1;}/*显示符号栈中内容*/void ShowSt ack(){int i;for(i = 0; i <= topAna lyse; i++){if(100 <= analys eStac k[i])printf("%c", Vn[analys eStac k[i] - 100]); else{if(-1 != analys eStac k[i])printf("%c", Vt[analys eStac k[i]]);elseprintf("#");}}}/*栈顶出栈*/void Pop(){topAna lyse--;}void Push(int r){int i;struct pRNode *pt;Pop();pt = P[r].rHead;if(-1 == pt->rCurso r)return;topAna lyse+= P[r].rLengt h;for(i = 0; i < P[r].rLengt h; i++){analyseStack[topAnal yse - i] = pt->rCurso r;/*逆序入栈*/ pt = pt->next;}}。
第1 章引论第1 题解释下列术语:(1)编译程序(2)源程序(3)目标程序(4)编译程序的前端(5)后端(6)遍答案:(1)编译程序:如果源语言为高级语言,目标语言为某台计算机上的汇编语言或机器语言,则此翻译程序称为编译程序。
(2)源程序:源语言编写的程序称为源程序。
(3)目标程序:目标语言书写的程序称为目标程序。
(4)编译程序的前端:它由这样一些阶段组成:这些阶段的工作主要依赖于源语言而与目标机无关。
通常前端包括词法分析、语法分析、语义分析和中间代码生成这些阶段,某些优化工作也可在前端做,也包括与前端每个阶段相关的出错处理工作和符号表管理等工作。
(5)后端:指那些依赖于目标机而一般不依赖源语言,只与中间代码有关的那些阶段,即目标代码生成,以及相关出错处理和符号表操作。
(6)遍:是对源程序或其等价的中间语言程序从头到尾扫视并完成规定任务的过程。
第2 题一个典型的编译程序通常由哪些部分组成?各部分的主要功能是什么?并画出编译程序的总体结构图。
答案:一个典型的编译程序通常包含8 个组成部分,它们是词法分析程序、语法分析程序、语义分析程序、中间代码生成程序、中间代码优化程序、目标代码生成程序、表格管理程序和错误处理程序。
其各部分的主要功能简述如下。
词法分析程序:输人源程序,拼单词、检查单词和分析单词,输出单词的机内表达形式。
语法分析程序:检查源程序中存在的形式语法错误,输出错误处理信息。
语义分析程序:进行语义检查和分析语义信息,并把分析的结果保存到各类语义信息表中。
中间代码生成程序:按照语义规则,将语法分析程序分析出的语法单位转换成一定形式的中间语言代码,如三元式或四元式。
中间代码优化程序:为了产生高质量的目标代码,对中间代码进行等价变换处理。
目标代码生成程序:将优化后的中间代码程序转换成目标代码程序。
表格管理程序:负责建立、填写和查找等一系列表格工作。
表格的作用是记录源程序的各类信息和编译各阶段的进展情况,编译的每个阶段所需信息多数都从表格中读取,产生的中间结果都记录在相应的表格中。
编译原理8参考答案编译原理8参考答案编译原理是计算机科学中的一门重要课程,它研究的是将高级语言转化为机器语言的过程。
在编译原理的学习过程中,学生们经常会遇到各种难题,而参考答案则是帮助他们解决这些问题的有力工具。
下面是一些编译原理8的参考答案,希望能对学习者有所帮助。
1. 什么是编译器?编译器是一种将高级语言转化为机器语言的程序。
它负责将源代码进行词法分析、语法分析、语义分析等一系列处理,最终生成可执行的目标代码。
2. 请简述编译器的工作原理。
编译器的工作原理主要包括以下几个步骤:- 词法分析:将源代码分解为一个个的词法单元。
- 语法分析:根据语法规则将词法单元组织成语法树。
- 语义分析:对语法树进行类型检查、语义检查等操作。
- 中间代码生成:将语法树转化为中间代码,比如三地址码、四元式等。
- 代码优化:对中间代码进行优化,提高程序的执行效率。
- 目标代码生成:将优化后的中间代码转化为目标机器代码。
- 目标代码优化:对目标机器代码进行优化,进一步提高执行效率。
3. 什么是词法分析?词法分析是编译器的第一步,它将源代码分解为一个个的词法单元。
词法单元包括关键字、标识符、运算符、常量等。
词法分析器通常使用正则表达式、有限自动机等方法进行实现。
4. 什么是语法分析?语法分析是编译器的第二步,它根据语法规则将词法单元组织成语法树。
语法分析器通常使用上下文无关文法和语法分析算法(如LL(1)、LR(1)等)进行实现。
5. 什么是语义分析?语义分析是编译器的第三步,它对语法树进行类型检查、语义检查等操作。
语义分析器通常使用符号表、类型检查规则等进行实现。
6. 什么是中间代码生成?中间代码生成是编译器的第四步,它将语法树转化为中间代码。
中间代码是一种介于源代码和目标代码之间的抽象表示形式,可以是三地址码、四元式、虚拟机指令等。
7. 什么是代码优化?代码优化是编译器的第五步,它对中间代码进行优化,提高程序的执行效率。