山商编译原理复习版.docx
- 文档编号:30068758
- 上传时间:2023-08-04
- 格式:DOCX
- 页数:16
- 大小:246.20KB
山商编译原理复习版.docx
《山商编译原理复习版.docx》由会员分享,可在线阅读,更多相关《山商编译原理复习版.docx(16页珍藏版)》请在冰豆网上搜索。
山商编译原理复习版
编译原理复习指南
前四章占70分,后三章占30分。
【新复习范围如下】
第二章:
2.3,2.13,2.14
第三章:
3.2,3.3,3.10,3.16
第四章:
4.3,4.10,4.13
第五章:
5.4,5.6
第六章:
6.3,6.10,6.11
第七章:
7.1,7.2
第二章
2.3叙述由下列正规式描述的语言。
(1)0(0|1)*0
(2)((ε|0)1*)*
(3)(0|1)*0(0|1)(0|1)
(4)0*10*10*10*
(5)(00|11)*((01|10)(00|11)*(01|10)(00|11)*)*
解:
其中一种表述(这里说的01串包括ε)
(1)0(0|1)*0以0开头和结尾的长度至少是2的01串
(2)((ε|0)1*)*所有的01串
(3)(0|1)*0(0|1)(0|1)倒数第三位是0的01串
(4)0*10*10*10*含有3个1的01串
(5)(00|11)*((01|10)(00|11)*(01|10)(00|11)*)*含有偶数个0和偶数个1的01串
2.13构造表示0,1个数都是偶数的01字符串的DFA。
2.14构造DFA,识别{0,1}上能被5整除的二进制数。
解:
已读过尚未读已读部分的值
某时刻10101110005
读进0101011100052=10
读进11010111000102+1=21
读进21010111000212+1=43
读进31010111000432+1=87
5个状态即可,分别代表已读部分的值除以5的余数
第三章
3.2考虑文法S->aSbS|bSaS|ε
(a)为句子abab构造两个不同的最左推导,以说明此文法二义。
(b)为abab构造对应的最右推导。
(c)为abab构造对应的分析树。
(d)这个文法产生的语言是什么?
解:
(a)最左推导:
(1)S=>aSbS=>abS=>abaSbS=>ababS=>abab
(2)S=>aSbS=>abSaSbS=>abaSbS=>ababS=>abab
(b)最右推导:
(1)S=>aSbS=>aSbaSbS=>aSbaSb=>aSbab=>abab
(2)S=>aSbS=>aSb=>abSaSb=>abSab=>abab
(c)描述的语言是:
a,b数目相等的串
3.3下面的二义文法描述命题演算公式的语法,为它写一个等价的非二义文法。
SSandS|SorS|notS|p|q|(S)
解:
非二义文法的产生式如下:
EEorT|T
TTandF|F
FnotF|(E)|p|q
3.10构造下面文法的LL
(1)分析表
D->TL
T->int|real
L->idR
R->,idR|ε
解:
先计算FIRST和FOLLOW
FIRST(D)=FIRST(T)={int,real}
FIRST(L)={id}
FIRST(R)={,,ε}
FOLLOW(D)=FOLLOW(L)={$}
FOLLOW(T)={id}
FOLLOW(R)={$}
3.16给出接收文法S->(L)|a
L->L,S|S的LR(0)活前缀的DFA。
解:
拓展文法:
(1)S‘->S
(2)S->(L)
(3)S->a
(4)L->L,S
(5)L->S
(1)
(2)(3)(4)
(5)
第四章
4.3为文法S→(L)|a
L→L,S|S
(a)写一个语法制导定义,它输出括号的对数。
(b)写一个语法制导定义,它输出括号的最大深度。
解:
(a):
Sˊ→Snprint(S.val)
S→(L)S.val=L.val+1
S→aS.val=0
L→L1,SL.val=L1.val+S.val
L→SL.val=S.val
(b):
Sˊ→Snprint(S.val)
S→(L)S.val=L.val+1
S→aS.val=0
L→L1,SL.val=max(L1.val,S.val)
L→SL.val=S.val
4.10
文法如下:
S→(L)|a
L→L,S|S
(a)写一个翻译方案,它输出每个a的嵌套深度。
例如,对于句子(a,a(a,a)),输出的结果是222。
(b)写一个翻译方案,它打印出每个a在句子中是第几个字符。
例如,当句子是(a,(a,(a,a),(a)))时,打印的结果是2581014。
解:
(a):
S′→{S.depth=0}S
S→{L.depth=S.depth+1}(L)
S→a{print(S.depth)}
L→{L1.depth=L.depth}L1,
{S.depth=L.depth}S
L→{S.depth=L.depth}S
(b):
S′→{S.in=0}S
S→{L.in=S.in+1}(L){S.out=L.out+1}
S→a{S.out=S.in+1;print(S.out)}
L→{L1.in=L.in}L1,
{S.in=L1.out+1}S{L.out=S.out}
L→{S.in=L.in}S{L.out=S.out}
/*继承属性in表示句子中该文法符号推出的字符序列的前面已经有多少个字符。
综合属性out表示句子中该文法符号推出的字符序列的最后一个字符在句子中是第几个字符。
*/
4.13下面是构造语法树的一个S属性定义。
将这里的语义规则翻译成LR翻译器的栈操作代码段。
解:
语义规则翻译成LR翻译器的栈操作代码段如下:
E->E1+Tval[ntop]:
=mknode(‘+’,val[top-2],val[top])
E->E1-Tval[ntop]:
=mknode(‘-’,val[top-2],val[top])
E->T
T->(E)val[ntop]:
=val[top-1])
T->idval[ntop]:
=mklear(idval[top])
T->numval[ntop]:
=mklear(num,val[top])
其中,val是存放属性值的栈
top是栈顶指针
ntop=top-r+1(r的魔鬼待规约的产生式右部符号个数)
完成规约后,top:
=ntop
第五章
5.4为下列类型写类型表达式:
(a)指向实数的指针数组,数组的下标从0到99。
(b)两维数组(即数组的数组),它的行下标从0到9,列下标从0到19。
(c)函数,它的定义域是从整数到整数的指针的函数,它的值域是由一个整数和一个字符组成的纪录。
解:
(a)array(0..99,pointer(real))
(b)array(0..9,array(0..19,type))
(c)(integer→pointer(integer))→record((i:
integer)*(c:
char))
假定作为值域的记录类型的两个域分别叫i和c。
5.6下列文法定以字面常量表的表。
符号的解释和图5.2文法的那些相同,增加了类型list,它表示类型T的元素表。
P→D;E
D→D;D|id:
T
T→listofT|char|integer
E→(L)|literal|num|id
L→E,L|E
写一个类似5.3节中的翻译方案,以确定表达式(E)和表(L)的类型。
解:
P→D;E
D→D;D
D→id:
T{addtype(id.entry,T.type)}
T→char{T.type:
=char}
T→integer{T.type:
=integer}
T→listofT1{T.type:
=list(T1.type)}
E→literal{E.type:
=char}
E→num{E.type:
=integer}
E→id{E.type:
=lookup(id.entry)}
E→(L){E.type:
=list(L.type)}
L→E{L.type:
=E.type}
L→E,L1{L.type:
=ifL1.type=E.typethenE.typeelsetype_error}
第六章
6.3
考虑下面的C程序
main(){
char*cp1,*cp2;
cp1=“12345”;
cp2=“abcdefghij”;
strcpy(cp1,cp2);
printf(“cp1=%s\ncp2=%s\n”,cp1,cp2);
}
该程序经以前的某些C编译器编译后,运行结果为:
cp1=abcdefghij
cp2=ghij
试分析为什么cp2被修改。
解:
C语言中,字符串会添加‘\0’作为串的结束符,因此,串“12345”存储为“12345\0”,而串“12345\0abc\0”打印出来的只有12345。
常量区连续分配。
按照常量在程序中出现的先后次序来安排它们在数据区中的次序。
因而本题中”12345”和”abcdefghij”存储为
12345\0abcdefghij\0
cp1cp2
拷贝后结果为
abcdefghij\0fghij\0
cp1cp2
而cp1和cp2所指的地址没有变,因此cp2所指的字符串被修改了。
现代编译器把程序中的字符串常量单独分配在一个段中,把它们和其他的常数分开,并且该段的内容在程序运行时不能被修改,因此大都不会出现题目所讲的情况,而是运行时报告错误。
这样,该程序在执行串拷贝时,会报告段错误(segmentationfault)而异常终止。
即:
现代编译器编译通过,执行时会出错。
(GCC:
段错误/VC非法访问)
6.10一个C程序如下:
func(i1,i2,i3)
longi1,i2,i3;
{
longj1,j2,j3;
printf(“Addressofi1i2i3=%o,%o,%o\n”,&i1,&i2,&i3);
printf(“Addressofj1j2j3=%o,%o,%o\n”,&j1,&j2,&j3);
}
main(){
longi1,i2,i3;
func(i1,i2,i3);
}
该程序在X86/Linux上运行结果为:
Addressofi1,i2,i3=27777775460,27777775464,27777775470
Addressofj1,j2,j3=27777775444,27777775440,27777775434
从结果看func的3个形参地址逐渐升高,而3个局部变量地址逐渐降低。
试说明为什么?
解:
C语言中,实参从右向左进栈,所以func(i1,i2,i3)按i3,i2,i1的顺序进栈而j1,j2,j3按声明的顺序分配。
6.11下面的C程序中,printf的调用仅含格式控制串,运行时输出3个参数,分析之。
main(){
printf(“%d%d%d\n”);
}
解:
C语言不做实参和形参个数类型是否一致的检查。
printf函数根据第一个参数—格式控制列表,到栈中取参数。
本题中虽然只传了格式控制列表,但是printf函数分析格式控制列表,认为程序员还传了3个整型数,因此继续去栈中取3个参数,并输出之。
所以得到了三个不可预知值的整数。
第七章
7.1把算术表达式–(a+b)*(c+d)+(a+b-c)翻译成:
(a)语法树。
(b)有向无环图。
(c)后缀表示。
(d)三地址代码。
解:
(a)语法树(b)有向无环图
(c)后缀表示:
ab+cd+*-ab+c++
(d)三地址代码
t1:
=a+b
t2:
=c+d
t3:
=t1*t2
t4:
=-t3
t5:
=t1+c
t6:
=t4+t5
7.2把C程序
main(){
inti;
inta[10];
while(i<=10)
a[i]=0;
}
的可执行语句翻译成:
(a)语法树。
(b)后缀表示。
(c)三地址代码。
解:
(a)语法树
(b)后缀表示
i10<=aiarray0=while
(c)三地址代码
1:
ifi<=10goto3
2:
goto5
3:
a[i]:
=0;
4:
goto1
5:
return0
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 复习