【编译原理】第四章部分课后题答案

news2024/9/17 7:40:13
第 四 章 课 后 习 题

T 4.1

根据表4.1的语法制导定义,为输入表达式 5 ∗ ( 4 ∗ 3 + 2 ) 5*(4*3+2) 5(43+2)构造注释分析树。

在这里插入图片描述
在这里插入图片描述


T 4.2

构造表达式 ( ( a ∗ b ) + ( c ) ) ((a*b)+(c)) ((ab)+(c))的分析树和语法树:

(a)根据表4.3的语法制导定义。

在这里插入图片描述

在这里插入图片描述

(b)根据图4.9的翻译方案。

在这里插入图片描述
在这里插入图片描述

有关“分析树”和“语法树”:

语法分析树和语法树不是一种东西。习惯上,我们把前者叫做“具体语法树”,其能够体现推导的过程;后者叫做“抽象语法树”,其不体现过程,只关心最后的结果。

语法分析树的定义:

对于 CFG G 的句型,分析树被定义为具有下述性质的一棵树:

  1. 根由开始符号所标记;
  2. 每个叶子由一个终结符、非终结符或 ε 标记;
  3. 每个内部节点都是非终结符;
  4. A A A 是某节点的内部标记,且 X 1 X_1 X1 X 2 X_2 X2、…、 X n X_n Xn 是该节点从左到右的所有孩子的标记。则: A → X 1 X 2 . . . X n A\rightarrow X_1X_2...X_n AX1X2...Xn 是一个产生式。若 A→ε,则标记为 A A A 的节点可以仅有一个标记为 ε ε ε 的孩子。若 A → ε A\rightarrow ε Aε ,则标记为 A A A 的节点可以仅有一个标记为 ε ε ε 的孩子。

简而言之,利用产生式推导出句型G的过程以树的形式表现。

语法树的定义:

对于 CFG G 的句型,语法树被定义为具有下述性质的一棵树:

  1. 根与内部节点由表达式中的操作符标记;
  2. 叶子由表达式中的操作数标记;
  3. 用于改变运算优先级和结合性的括号,被隐含在语法树的结构中。

简而言之,叶子全是操作数,内部全是操作符,树里没有非终结符也不能有括号。


T 4.3

为文法
S → ( L )   ∣   a L → L , S   ∣   S S\rightarrow(L)\space |\space a \\ L\rightarrow L,S\space|\space S S(L)  aLL,S  S
(a)写一个语法制导定义,它输出括号的对数。
S ′ → S n p r i n t ( S . v a l ) S → ( L ) S . v a l = L . v a l + 1 S → a S . v a l = 0 S → L ,   S 1 L . v a l = L . v a l + S 1 . v a l L → S L . v a l = S . v a l \left. \begin{array}{l} % 左对齐 S'\rightarrow S\textbf{n} && print(S.val) \\ S\rightarrow (L) && S.val = L.val + 1 \\ S\rightarrow a && S.val = 0 \\ S\rightarrow L,\space S_1 && \textcolor{red}{L.val = L.val + S_1.val} \\ L\rightarrow S && L.val = S.val \\ \end{array} \right. SSnS(L)SaSL, S1LSprint(S.val)S.val=L.val+1S.val=0L.val=L.val+S1.valL.val=S.val
(b)写一个语法制导定义,它输出括号嵌套的最大深度。
S ′ → S n p r i n t ( S . v a l ) S → ( L ) S . v a l = L . v a l + 1 S → a S . v a l = 0 S → L ,   S 1 L . v a l = m a x ( L . v a l , S 1 . v a l ) L → S L . v a l = S . v a l \left. \begin{array}{l} % 左对齐 S'\rightarrow S\textbf{n} && print(S.val) \\ S\rightarrow (L) && S.val = L.val + 1 \\ S\rightarrow a && S.val = 0 \\ S\rightarrow L,\space S_1 && \textcolor{red}{L.val = max(L.val,S_1.val)} \\ L\rightarrow S && L.val = S.val \\ \end{array} \right. SSnS(L)SaSL, S1LSprint(S.val)S.val=L.val+1S.val=0L.val=max(L.val,S1.val)L.val=S.val
红色部分为二者的不同之处。


T 4.4

下面的文法定义语言 L = { a n b n c m ∣ m , n ≥ 1 } L= \{a^n b^n c^m| m,n ≥1\} L={anbncmm,n1}。写一个语法制导定义,其语义规则的作用是:对不属于语言 L L L的子集 L 1 = { a n b n c n ∣ n ≥ 1 } L_1= \{a^n b^n c^n| n ≥1\} L1={anbncnn1}的句子,打印出错信息。
S → D C D → a D b   ∣   a b C → C c   ∣   c S\rightarrow DC\\ D\rightarrow aDb\space | \space ab \\ C\rightarrow Cc\space |\space c \\ SDCDaDb  abCCc  c
语法制导定义如下:
S → D C i f   D . l e n g t h ≠ C . l e n g t h   t h e n   p r i n t ( ‘ ‘ e r r o r ” ) D → a b D . l e n g t h = 1 D → a D 1 b D . l e n g t h = D 1 . l e n g t h + 1 C → c D . l e n g t h = 1 C → C 1 c C . l e n g t h = C 1 . l e n g t h + 1 \left. \begin{array}{l} % 左对齐 S\rightarrow DC && if \space D.length ≠ C.length \space then \space print(``error”)\\ D\rightarrow ab && D.length = 1\\ D\rightarrow aD_1b && D.length = D_1.length + 1\\ C\rightarrow c && D.length = 1\\ C\rightarrow C_1c && C.length = C_1.length + 1\\ \end{array} \right. SDCDabDaD1bCcCC1cif D.length=C.length then print(‘‘error)D.length=1D.length=D1.length+1D.length=1C.length=C1.length+1


T 4.5

为下面文法写一个语法制导的定义,它完成一个句子的 w h i l e − d o while-do whiledo最大嵌套层次的计算并输出这个计算结果。
S → E E → while   E   do   E   ∣   id : = E   ∣   E + E   ∣   id   ∣   ( E ) S\rightarrow E \\ E\rightarrow \textbf{while}\space E \space \textbf{do} \space E \space |\space \textbf{id}:=E\space|\space E + E\space|\space \textbf{id} \space|\space(E) SEEwhile E do E  id:=E  E+E  id  (E)
语法制导定义如下:
S → E p r i n t ( S . l o o p ) E → while E 1 do E 2 E . l o o p = m a x ( E 1 . l o o p , E 2 . l o o p ) + 1 E → id : = E E . l o o p = E 1 . l o o p E → E 1 + E 2 E . l o o p = m a x ( E 1 . l o o p , E 2 . l o o p ) E → id E . l o o p = 0 E → ( E 1 ) E . l o o p : = E 1 . l o o p \left. \begin{array}{l} % 左对齐 S→E && print(S.loop) \\ E→ \textbf{while} E_1 \textbf{do} E_2 && E.loop = max(E_1.loop, E_2.loop)+1 \\ E→ \textbf{id}:=E && E.loop = E_1.loop \\ E→E_1+ E2 && E.loop = max(E_1.loop, E_2.loop) \\ E→ \textbf{id} && E.loop = 0\\ E→(E_1) && E.loop := E_1.loop \\ \end{array} % 左对齐 \right. SEEwhileE1doE2Eid:=EEE1+E2EidE(E1)print(S.loop)E.loop=max(E1.loop,E2.loop)+1E.loop=E1.loopE.loop=max(E1.loop,E2.loop)E.loop=0E.loop:=E1.loop


T 4.6

下列文法产生由 + + +作用于整常数或实常数的表达式。两个整数相加时,结果是整型,否则是实型。
E → E + T   ∣   T T → num . num   ∣   num E\rightarrow E+T\space | \space T \\ T\rightarrow\textbf{num}.\textbf{num}\space|\space\textbf{num} EE+T  TTnum.num  num
( a)给出决定每个子表达式类型的语法制导定义。
E → E 1 + T i f   ( E 1 . t y p e = = i n t e g e r )   a n d   ( T . t y p e = = i n t e g e r )   t h e n      E . t y p e = i n t e g e r e l s e      E . t y p e = r e a l E → T E . t y p e = T . t y p e T → num . num T . t y p e = r e a l T → num T . t y p e = i n t e g e r \left. \begin{array}{l} % 左对齐 E\rightarrow E_1+T && if \space (E_1.type==integer)\space and\space(T.type==integer)\space then\\ && \space\space\space\space E.type=integer \\ &&else\\&& \space\space\space\space E.type = real \\ E\rightarrow T && E.type = T.type \\ T\rightarrow \textbf{num} . \textbf{num} && T.type = real \\ T\rightarrow \textbf{num} && T.type = integer \\ \end{array} \right. EE1+TETTnum.numTnumif (E1.type==integer) and (T.type==integer) then    E.type=integerelse    E.type=realE.type=T.typeT.type=realT.type=integer
( b)扩充(a)的语法制导定义,既决定类型,又把表达式翻译成后缀表示。使用一元算符 i n t t o r e a l inttoreal inttoreal把整数变成等价的实数,使得后缀式中 + + +的两个对象有同样的类型。
E → E 1 + T i f   ( E 1 . t y p e = = i n t e g e r )   a n d   ( T . t y p e = = i n t e g e r )   t h e n      E . t y p e = i n t e g e r      p r i n t ( ′ + ′ , E 1 . v a l , T . v a l ) e l s e      E . t y p e = r e a l      i f   E 1 . t y p e = i n t e g e r   t h e n          E 1 . t y p e = r e a l          E 1 . v a l = i n t t o r e a l ( E 1 . v a l )      i f   T . t y p e = i n t e g e r   t h e n          T . t y p e = r e a l          T . v a l = i n t t o r e a l ( T . v a l )      p r i n t ( ′ + ′ , E 1 . v a l , T . v a l ) E → T E . t y p e = T . t y p e E . v a l = T . v a l T → num . num T . t y p e = r e a l T . v a l = num . num . l e x v a l T → num T . t y p e = i n t e g e r T . v a l = num . l e x v a l \left. \begin{array}{l} % 左对齐 E\rightarrow E_1+T && if \space (E_1.type==integer)\space and \space (T.type==integer)\space then \\ && \space\space\space\space E.type = integer \\ && \space\space\space\space print('+', E_1.val, T.val) \\ && else \\ && \space\space\space\space E.type=real \\ && \space\space\space\space if \space E_1.type = integer \space then \\ && \space\space\space\space\space\space\space\space E_1.type = real \\ && \space\space\space\space\space\space\space\space E_1.val = inttoreal(E_1.val) \\ && \space\space\space\space if \space T.type = integer \space then \\ && \space\space\space\space\space\space\space\space T.type = real \\ && \space\space\space\space\space\space\space\space T.val = inttoreal(T.val) \\ && \space\space\space\space print('+',E_1.val, T.val) \\ E\rightarrow T && E.type = T.type \\ && E.val = T.val \\ T\rightarrow \textbf{num}.\textbf{num} && T.type=real \\ && T.val = \textbf{num}.\textbf{num}.lexval \\ T\rightarrow \textbf{num} && T.type = integer \\ && T.val = \textbf{num}.lexval \\ \end{array} \right. EE1+TETTnum.numTnumif (E1.type==integer) and (T.type==integer) then    E.type=integer    print(+,E1.val,T.val)else    E.type=real    if E1.type=integer then        E1.type=real        E1.val=inttoreal(E1.val)    if T.type=integer then        T.type=real        T.val=inttoreal(T.val)    print(+,E1.val,T.val)E.type=T.typeE.val=T.valT.type=realT.val=num.num.lexvalT.type=integerT.val=num.lexval


T 4.7

给出对表达式求导数的语法制导定义,表达式由 + + + ∗ * 作用于变量x和常数组成,如 x ∗ ( 3 ∗ x + x ∗ x ) x * (3 * x+ x *x) x(3x+xx),并假定没有任何化简,例如将 3 ∗ x 3*x 3x翻译成 3 ∗ 1 + 0 ∗ x 3*1+0*x 31+0x

经分析可知对每个文法符号需要有两个属性

  • . e x p .exp .exp 用来记录原表达式
  • . s .s .s 用来记录该表达式求导的结果
  • ∣ ∣ || ∣∣ 用来表示串拼接

E ′ → E n p r i n t ( E . s ) E → E 1 + T E . e x p = E 1 . e x p   ∣ ∣   ′ + ′   ∣ ∣   T . e x p E . s = E 1 . s   ∣ ∣   ′ + ′   T . s E → T E . e x p = T . e x p E . s = T . s T → T 1 ∗ F T . e x p = T 1 . e x p   ∣ ∣   ′ ∗ ′   F . e x p T . s = ′ ( ′   ∣ ∣   T 1 . s   ∣ ∣   ′ ) ′   ∣ ∣   ′ ∗ ′   ∣ ∣   F . e x p   ∣ ∣   ′ + ′   ∣ ∣   T . e x p   ∣ ∣   ′ ∗ ′   ∣ ∣   F . s T → F T . e x p = F . e x p T . s = F . s F → ( E ) F . e x p = ′ ( ′   ∣ ∣   E . e x p   ∣ ∣   ′ ) ′ F . s = ′ ( ′   ∣ ∣   E . s   ∣ ∣   ′ ) ′ F → num F . e x p = num . l e x m e F . s = ′ 0 ′ F → x F . e x p = ′ x ′ F . s = ′ 1 ′ \left. \begin{array}{l} % 左对齐 E'\rightarrow E\textbf{n} && print(E.s) \\ E\rightarrow E_1+T && E.exp = E_1.exp\space||\space '+' \space || \space T.exp \\ && E.s = E_1.s\space ||\space '+'\space T.s \\ E\rightarrow T && E.exp = T.exp \\ && E.s = T.s \\ T\rightarrow T_1*F && T.exp = T_1.exp\space || \space '*' \space F.exp \\ && T.s = '('\space||\space T_1.s\space || \space ')'\space || \space '*' \space || \space F.exp\space ||\space '+' \space || \space T.exp \space ||\space '*' \space || \space F.s \\ T\rightarrow F && T.exp = F.exp \\ && T.s = F.s \\ F\rightarrow (E) && F.exp='('\space ||\space E.exp\space || \space ')' \\ && F.s = '('\space ||\space E.s\space|| \space ')' \\ F\rightarrow \textbf{num} && F.exp = \textbf{num}.lexme \\ && F.s = '0' \\ F\rightarrow\textbf{x}&& F.exp = '\textbf{x}' \\ && F.s = '\textbf{1}'\\ \end{array} \right. EEnEE1+TETTT1FTFF(E)FnumFxprint(E.s)E.exp=E1.exp ∣∣ + ∣∣ T.expE.s=E1.s ∣∣ + T.sE.exp=T.expE.s=T.sT.exp=T1.exp ∣∣  F.expT.s=( ∣∣ T1.s ∣∣ ) ∣∣  ∣∣ F.exp ∣∣ + ∣∣ T.exp ∣∣  ∣∣ F.sT.exp=F.expT.s=F.sF.exp=( ∣∣ E.exp ∣∣ )F.s=( ∣∣ E.s ∣∣ )F.exp=num.lexmeF.s=0F.exp=xF.s=1


T 4.8

给出把中缀表达式翻译成没有冗余括号的中缀表达式的语法制导定义。例如,因为 + + + ∗ * 是左结合, ( ( a ∗ ( b + c ) ) ∗ ( d ) ) ((a * (b+c))*(d)) ((a(b+c))(d))可以重写成 a ∗ ( b + c ) ∗ d a* (b+c) * d a(b+c)d

两种方法:

  1. 先把表达式的括号都去掉,然后在必要的地方再加括号
  2. 去掉表达式中的冗余括号,保留必要的括号

第一种方法:

  • . e x p .exp .exp 用来记录表达式
  • ∣ ∣ || ∣∣ 用来表示串拼接

S → E p r i n t ( E . e x p ) E → E 1 + T i f   T . o p = = ′ + ′   t h e n      E . e x p = E 1 . e x p   ∣ ∣   ′ + ′   ∣ ∣   ′ ( ′   ∣ ∣   T . e x p   ∣ ∣   ′ ) ′ e l s e      E . e x p = E 1 . e x p   ∣ ∣   ′ + ′   ∣ ∣   T . e x p E . o p = T . o p E → T E . e x p = T . e x p E . o p = T . o p T → T 1 ∗ F i f   ( F . o p = = ′ + ′ )   o r   ( F . o p = = ′ ∗ ′ )   t h e n      i f   T 1 . o p = = ′ + ′   t h e n          T . e x p = ′ ( ′   ∣ ∣   T 1 . c o d e   ∣ ∣   ′ ) ′   ∣ ∣   ′ ∗ ′   ∣ ∣   ′ ( ′   ∣ ∣   F . e x p   ∣ ∣   ′ ) ′      e l s e          T . e x p = T 1 . e x p   ∣ ∣   ′ ∗ ′   ∣ ∣   ′ ( ′   ∣ ∣   F . e x p   ∣ ∣   ′ ) ′ e l s e   i f   T 1 . o p = = ′ + ′   t h e n      T . e x p = ′ ( ′   ∣ ∣   T 1 . e x p   ∣ ∣   ′ ) ′   ∣ ∣   ′ ∗ ′   ∣ ∣   F . e x p e l s e      T . e x p = T 1 . e x p   ∣ ∣   ′ ∗ ′   ∣ ∣   F . e x p T . o p = ′ ∗ ′ T → F T . e x p = F . e x p T . o p = F . o p F → id F . e x p = id . l e x m e F . o p = id F → ( E ) F . e x p = E . e x p F . o p = E . o p \left. \begin{array}{l} % 左对齐 S\rightarrow E && print(E.exp) \\ E\rightarrow E_1+T && if \space T.op == '+' \space then \\ && \space\space\space\space E.exp = E_1.exp \space || \space '+'\space ||\space '(' \space || \space T.exp \space || \space ')' \\ && else \\ && \space\space\space\space E.exp = E_1.exp \space || \space '+'\space || \space T.exp \\ && E.op = T.op \\ E\rightarrow T && E.exp = T.exp \\ && E.op = T.op \\ T\rightarrow T_1*F && if \space (F.op == '+')\space or\space (F.op == '*')\space then \\ && \space\space\space\space if \space T_1.op == '+' \space then \\ && \space\space\space\space\space\space\space\space T.exp = '(' \space || \space T_1.code \space || \space ')'\space || \space '*' \space || \space '(' \space || \space F.exp \space || \space ')' \\ && \space\space\space\space else \\ && \space\space\space\space\space\space\space\space T.exp = T_1.exp \space || \space '*'\space || \space '(' \space || \space F.exp \space ||\space ')' \\ && else\space if\space T_1.op == '+' \space then \\ && \space\space\space\space T.exp = '(' \space || \space T_1.exp \space ||\space ')'\space || \space'*'\space || \space F.exp \\ && else \\ && \space\space\space\space T.exp = T_1.exp \space ||\space '*'\space || \space F.exp \\ && T.op = '*' \\ T\rightarrow F && T.exp = F.exp \\ && T.op = F.op \\ F\rightarrow \textbf{id} && F.exp = \textbf{id}.lexme \\ && F.op = \textbf{id} \\ F\rightarrow (E) && F.exp = E.exp \\ && F.op = E.op \\ \end{array} % 左对齐 \right. SEEE1+TETTT1FTFFidF(E)print(E.exp)if T.op==+ then    E.exp=E1.exp ∣∣ + ∣∣ ( ∣∣ T.exp ∣∣ )else    E.exp=E1.exp ∣∣ + ∣∣ T.expE.op=T.opE.exp=T.expE.op=T.opif (F.op==+) or (F.op==) then    if T1.op==+ then        T.exp=( ∣∣ T1.code ∣∣ ) ∣∣  ∣∣ ( ∣∣ F.exp ∣∣ )    else        T.exp=T1.exp ∣∣  ∣∣ ( ∣∣ F.exp ∣∣ )else if T1.op==+ then    T.exp=( ∣∣ T1.exp ∣∣ ) ∣∣  ∣∣ F.expelse    T.exp=T1.exp ∣∣  ∣∣ F.expT.op=T.exp=F.expT.op=F.opF.exp=id.lexmeF.op=idF.exp=E.expF.op=E.op

第二种方法:

  • E E E T T T F F F两个继承属性 l e f t o p left_op leftop r i g h t o p right_op rightop分别表示左右两侧算符的优先级
  • 给它们一个综合属性 s e l f o p self_op selfop表示自身主算符的优先级
  • 再给一个综合属性 c o d e code code表示没有冗余括号的表达式
  • 分别用1和2表示加和乘的优先级,用3表示 i d id id ( E ) (E) (E)的优先级,用0表示左侧或右侧没有运算对象的情况

S → E E . l e f t _ o p = 0 E . r i g h t _ o p = 0 p r i n t ( E . e x p ) E → E 1 + T E 1 . l e f t _ o p = E . l e f t _ o p E 1 . r i g h t _ o p = 1 T . l e f t _ o p = 1 T . r i g h t _ o p = E . r i g h t _ o p E . e x p = E 1 . e x p   ∣ ∣   ′ + ′   ∣ ∣   T . e x p E . s e l f _ o p = 1 E → T T . l e f t _ o p = E . l e f t _ o p T . r i g h t _ o p = E . r i g h t _ o p E . e x p = T . e x p E . s e l f _ o p = T . s e l f _ o p T → T 1 ∗ F i f   ( F . o p = = ′ + ′ )   o r   ( F . o p = = ′ ∗ ′ )   t h e n      i f   T 1 . o p = = ′ + ′   t h e n          T . e x p = ′ ( ′   ∣ ∣   T 1 . c o d e   ∣ ∣   ′ ) ′   ∣ ∣   ′ ∗ ′   ∣ ∣   ′ ( ′   ∣ ∣   F . e x p   ∣ ∣   ′ ) ′      e l s e          T . e x p = T 1 . e x p   ∣ ∣   ′ ∗ ′   ∣ ∣   ′ ( ′   ∣ ∣   F . e x p   ∣ ∣   ′ ) ′ e l s e   i f   T 1 . o p = = ′ + ′   t h e n      T . e x p = ′ ( ′   ∣ ∣   T 1 . e x p   ∣ ∣   ′ ) ′   ∣ ∣   ′ ∗ ′   ∣ ∣   F . e x p e l s e      T . e x p = T 1 . e x p   ∣ ∣   ′ ∗ ′   ∣ ∣   F . e x p T . o p = ′ ∗ ′ T → F T . e x p = F . e x p T . o p = F . o p F → id F . e x p = id . l e x m e F . s e l f _ o p = 3 F → ( E ) E . l e f t _ o p = 0 E . r i g h t _ o p = 0 F . s e l f _ o p =      i f   ( F . l e f t _ o p < E . s e l f _ o p )   a n d   ( E . s e l f _ o p > = F . r i g h t _ o p )   t h e n          E . s e l f _ o p      e l s e          3 F . e x p =      i f   ( F . l e f t _ o p < E . s e l f _ o p )   a n d   ( E . s e l f _ o p > = F . r i g h t _ o p )   t h e n          E . e x p      e l s e           ′ ( ′   ∣ ∣   E . e x p   ∣ ∣   ′ ) ′ \left. \begin{array}{l} % 左对齐 S\rightarrow E && E.left\_op = 0 \\ && E.right\_op = 0 \\ && print(E.exp) \\ E\rightarrow E_1+T && E_1.left\_op=E.left\_op \\ && E_1.right\_op=1 \\ && T.left\_op = 1 \\ && T.right\_op = E.right\_op \\ && E.exp = E_1.exp \space || \space '+'\space || \space T.exp \\ && E.self\_op = 1 \\ E\rightarrow T && T.left\_op = E.left\_op \\ && T.right\_op = E.right\_op \\ && E.exp = T.exp \\ && E.self\_op = T.self\_op \\ T\rightarrow T_1*F && if \space (F.op == '+')\space or\space (F.op == '*')\space then \\ && \space\space\space\space if \space T_1.op == '+' \space then \\ && \space\space\space\space\space\space\space\space T.exp = '(' \space || \space T_1.code \space || \space ')'\space || \space '*' \space || \space '(' \space || \space F.exp \space || \space ')' \\ && \space\space\space\space else \\ && \space\space\space\space\space\space\space\space T.exp = T_1.exp \space || \space '*'\space || \space '(' \space || \space F.exp \space ||\space ')' \\ && else\space if\space T_1.op == '+' \space then \\ && \space\space\space\space T.exp = '(' \space || \space T_1.exp \space ||\space ')'\space || \space'*'\space || \space F.exp \\ && else \\ && \space\space\space\space T.exp = T_1.exp \space ||\space '*'\space || \space F.exp \\ && T.op = '*' \\ T\rightarrow F && T.exp = F.exp \\ && T.op = F.op \\ F\rightarrow \textbf{id} && F.exp = \textbf{id}.lexme \\ && F.self\_op=3 \\ F\rightarrow (E) && E.left\_op =0 \\ && E.right\_op = 0 \\ && F.self\_op = \\ && \space\space\space\space if \space (F.left\_op < E.self\_op) \space and \space (E.self\_op >= F.right\_op) \space then \\ && \space\space\space\space\space\space\space\space E.self\_op \\ && \space\space\space\space else \\ && \space\space\space\space\space\space\space\space 3 \\ && F.exp = \\ && \space\space\space\space if \space (F.left\_op < E.self\_op) \space and \space (E.self\_op >= F.right\_op) \space then \\ && \space\space\space\space\space\space\space\space E.exp \\ && \space\space\space\space else \\ && \space\space\space\space\space\space\space\space '('\space || \space E.exp \space || \space ')' \\ \end{array} % 左对齐 \right. SEEE1+TETTT1FTFFidF(E)E.left_op=0E.right_op=0print(E.exp)E1.left_op=E.left_opE1.right_op=1T.left_op=1T.right_op=E.right_opE.exp=E1.exp ∣∣ + ∣∣ T.expE.self_op=1T.left_op=E.left_opT.right_op=E.right_opE.exp=T.expE.self_op=T.self_opif (F.op==+) or (F.op==) then    if T1.op==+ then        T.exp=( ∣∣ T1.code ∣∣ ) ∣∣  ∣∣ ( ∣∣ F.exp ∣∣ )    else        T.exp=T1.exp ∣∣  ∣∣ ( ∣∣ F.exp ∣∣ )else if T1.op==+ then    T.exp=( ∣∣ T1.exp ∣∣ ) ∣∣  ∣∣ F.expelse    T.exp=T1.exp ∣∣  ∣∣ F.expT.op=T.exp=F.expT.op=F.opF.exp=id.lexmeF.self_op=3E.left_op=0E.right_op=0F.self_op=    if (F.left_op<E.self_op) and (E.self_op>=F.right_op) then        E.self_op    else        3F.exp=    if (F.left_op<E.self_op) and (E.self_op>=F.right_op) then        E.exp    else        ( ∣∣ E.exp ∣∣ )


T 4.9

S S S的综合属性 v a l val val给出下面文法中 S S S产生的二进制数的值。例如,输入 101.101 101.101 101.101时, S . v a l = 5.625 S. val=5.625 S.val=5.625
S → L . L   ∣   L L → L B   ∣   B B → 0   ∣   1 S\rightarrow L.L\space | \space L \\ L\rightarrow LB\space | \space B \\ B \rightarrow 0 \space | \space 1 \\ SL.L  LLLB  BB0  1
(a)仅用综合属性决定 S . v a l S. val S.val
S → L 1 . L 2 S . v a l = L 1 . v a l + L 2 . v a l / p o w e r ( 2 , L 2 . l e n g t h ) S → L S . v a l = L . v a l L → L 1 B L . v a l = L 1. v a l ∗ 2 + B . v a l L . l e n g t h = L 1 . l e n g t h + 1 L → B L . v a l = B . v a l L . l e n g t h = 1 B → 0 B . v a l = 0 B → 1 B . v a l = 1 \left. \begin{array}{l} % 左对齐 S\rightarrow L_1.L_2 && S.val = L_1.val + L_2.val / power(2, L_2.length) \\ S\rightarrow L && S.val = L.val \\ L\rightarrow L_1B && L.val = L1.val * 2 + B.val \\ && L.length = L_1.length + 1 \\ L\rightarrow B && L.val = B.val \\ && L.length = 1 \\ B\rightarrow 0 && B.val = 0 \\ B\rightarrow 1 && B.val = 1 \\ \end{array} \right. SL1.L2SLLL1BLBB0B1S.val=L1.val+L2.val/power(2,L2.length)S.val=L.valL.val=L1.val2+B.valL.length=L1.length+1L.val=B.valL.length=1B.val=0B.val=1

(b)用 L L L属性定义决定 S . v a l S.val S.val。在该定义中, B B B的唯一综合属性是 c c c(还需要继承属性),它给出由 B B B产生的位对最终值的贡献。例如, 101.101 101.101 101.101的最前一位和最后一位对值 5.625 5.625 5.625的贡献分别是 4 4 4 0.125 0.125 0.125

先将文法改写为:
S → L . R   ∣   L L → B L   ∣   B R → R B   ∣   B B → 0   ∣   1 S\rightarrow L.R\space | \space L \\ L\rightarrow BL \space | \space B \\ R\rightarrow RB \space | \space B \\ B \rightarrow 0 \space | \space 1 \\ SL.R  LLBL  BRRB  BB0  1
所求语法制导定义如下,其中 i i i B B B的继承属性, v a l val val c c c是综合属性。
S → L . R S . v a l = L . v a l + R . v a l S → L S . v a l = L . v a l L → B L 1 B . i = L 1 . c ∗ 2 L . c = L 1 . c ∗ 2 L . v a l = L 1 . v a l + B . c L → B B . i = 1 L . c = 1 L . v a l = B . c R → R 1 B B . i = R 1 . c / 2 R . c = R 1 . c / 2 R . v a l = R 1 . v a l + B . c R → B B . i = 0.5 R . c = 0.5 R . v a l = B . c B → 0 B . c = 0 B → 1 B . c = B . i \left. \begin{array}{l} % 左对齐 S\rightarrow L.R && S.val=L.val + R.val \\ S\rightarrow L && S.val=L.val \\ L\rightarrow BL_1 && B.i = L_1.c*2 \\ && L.c = L_1.c*2 \\ && L.val = L_1.val+B.c \\ L\rightarrow B && B.i = 1 \\ && L.c = 1 \\ && L.val = B.c \\ R\rightarrow R_1B && B.i = R_1.c/2 \\ && R.c = R_1.c/2 \\ && R.val = R_1.val + B.c \\ R\rightarrow B B.i = 0.5 \\ && R.c = 0.5 \\ && R.val = B.c \\ B\rightarrow 0 && B.c = 0 \\ B\rightarrow 1 && B.c = B.i \\ \end{array} \right. SL.RSLLBL1LBRR1BRBB.i=0.5B0B1S.val=L.val+R.valS.val=L.valB.i=L1.c2L.c=L1.c2L.val=L1.val+B.cB.i=1L.c=1L.val=B.cB.i=R1.c/2R.c=R1.c/2R.val=R1.val+B.cR.c=0.5R.val=B.cB.c=0B.c=B.i
分析:首先,从 B B B推出的串是不可能知道这个 B B B在串中的具体位置的,因此也不可能计算它的贡献。这样 B B B必须有继承属性,它被用来计算 B B B的贡献。对于一个二进制数,如 101.101 101.101 101.101,对于小数点前的 1 1 1,我们需要知道它处在从右向左数的第几位上;而对于小数点后的 1 1 1,我们需要知道它处在从左向右数的第几位上。考察原来的文法,从下面左图的分析树可以看出,不管是小数点前还是后,它都是一种自左向右的归约,适合于自左向右地计数。这样,小数点左边就需要用继承属性来计数,这就增加了难度。而且,由于小数点左右都是用非终结符 L L L,那么, L L L就即要有综合属性来用于从自左向右地计数,又要有继承属性来用于自右向左地计数,显然语法制导定义的难度会大大增加。所以我们采用改写文法的办法,让分析树是右图的形式。这样,小数点两边的归约方式不一样,适合于不同方向的计数,使我们的语法制导定义能简洁得多。

在这里插入图片描述


T 4.10

重写例4.3语法制导定义的基础文法,然后重新设计语法制导定义,使得仅用综合属性就能把类型信息填入符号表。

在这里插入图片描述

改写后文法和语法制导定义为:
L → T id L . t y p e = T . t y p e a d d t y p e   ( id . e n t r y , L . t y p e ) L → L 1 , id L . t y p e = L 1. t y p e a d d t y p e   ( id . e n t r y , L . t y p e ) T → int T . t y p e = i n t e g e r T → real T . t y p e = real \left. \begin{array}{l} % 左对齐 L→T \textbf{id} && L.type = T.type \\ && addtype\space(\textbf{id}.entry, L.type) \\ L→L_1,\textbf{id} && L.type = L1.type\\ && addtype\space(\textbf{id}.entry, L.type) \\ T→\textbf{int} && T.type = integer \\ T→\textbf{real} && T.type = \textbf{real} \\ \end{array} \right. LTidLL1,idTintTrealL.type=T.typeaddtype (id.entry,L.type)L.type=L1.typeaddtype (id.entry,L.type)T.type=integerT.type=real


T 4.12

文法如下:
S → ( L )   ∣   a L → L , S   ∣   S S\rightarrow (L)\space | \space a \\ L\rightarrow L, S\space | \space S \\ S(L)  aLL,S  S
(a)写一个翻译方案,它输出每个 a a a的嵌套深度。例如,对于句子 ( a , ( a , a ) ) (a, (a,a)) (a,(a,a)),输出的结果是 1   2   2 1\space2\space2 1 2 2
S ′ → { S . d e p t h = 0 } S S → { L . d e p t h = S . d e p t h + 1 } ( L ) S → a { p r i n t ( S . d e p t h ) } L → { L 1 . d e p t h = L . d e p t h } L 1 , { S . d e p t h = L . d e p t h } S L → { S . d e p t h = L . d e p t h } S \left. \begin{array}{l} % 左对齐 S'\rightarrow &&& \{S.depth=0\} \\ & S \\ S\rightarrow &&& \{L.depth = S.depth + 1\} \\ & (L) \\ S\rightarrow a &&& \{print(S.depth)\} \\ L\rightarrow &&& \{L_1.depth=L.depth\} \\ & L_1, && \{S.depth = L.depth\} \\ & S \\ L\rightarrow &&& \{S.depth = L.depth\} \\ & S \\ \end{array} \right. SSSaLLS(L)L1,SS{S.depth=0}{L.depth=S.depth+1}{print(S.depth)}{L1.depth=L.depth}{S.depth=L.depth}{S.depth=L.depth}

(b)写一个翻译方案,它打印出每个 a a a在句子中是第几个字符。例如,当句子是 ( a , ( a , ( a , a ) , ( a ) ) ) (a,(a,(a,a),(a))) (a,(a,(a,a),(a)))时,打印的结果是 2   5   8   10   14 2\space5\space8\space10\space14 2 5 8 10 14
S ′ → { S . i n = 0 } S S → { L . i n = S . i n + 1 } ( L ) { S . o u t = L . o u t + 1 } S → a { S . o u t = S . i n + 1 ; p r i n t ( S . o u t ) } L → { L 1 . i n = L . i n } L 1 , { S . i n = L 1 . o u t + 1 } S { L . o u t = S . o u t } L → { S . i n = L . i n } S { L . o u t = S . o u t } \left. \begin{array}{l} % 左对齐 S'\rightarrow &&&\{S.in=0\} \\ & S \\ S\rightarrow &&& \{L.in=S.in+1\} \\ & (L) && \{S.out = L.out + 1\} \\ S\rightarrow & a && \{S.out = S.in+1;print(S.out)\} \\ L\rightarrow &&& \{L_1.in=L.in\} \\ & L_1, && \{S.in = L_1.out+1\} \\ & S && \{L.out= S.out\} \\ L\rightarrow &&& \{S.in = L.in\} \\ & S && \{L.out = S.out\} \\ \end{array} \right. SSSLLS(L)aL1,SS{S.in=0}{L.in=S.in+1}{S.out=L.out+1}{S.out=S.in+1;print(S.out)}{L1.in=L.in}{S.in=L1.out+1}{L.out=S.out}{S.in=L.in}{L.out=S.out}


T 4.13

语句的文法如下:
S → id : = E   ∣   if   E   then   S   ∣   while   E   do   S   ∣   begin   S ; S   end   ∣   break S →\textbf{id}:=E\space |\space \textbf{if}\space E \space \textbf{then}\space S \space |\space \textbf{while} \space E\space \textbf{do}\space S \space |\space \textbf{begin}\space S;S\space \textbf{end} \space |\space \textbf{break} Sid:=E  if E then S  while E do S  begin S;S end  break
写一个翻译方案,其语义动作的作用是:若发现break不是出现在循环语句中,及时报告错误。
S ′ → { S . l o o p = f a l s e } S S → id : = E S → if   E   then { S 1 . l o o p = S . l o o p } S 1 S → while   E   do { S 1 . l o o p = t r u e } S 1 S → begin { S 1 . l o o p = S . l o o p } S 1 ; { S 2 . l o o p = S . l o o p } S 2   end S → break { i f   n o t   S . l o o p   t h e n   p r i n t ( ′ e r r o r ′ ) } \left. \begin{array}{l} % 左对齐 S'\rightarrow &&& \{S.loop=false\} \\ &S \\ S\rightarrow & \textbf{id}:=E \\ S\rightarrow & \textbf{if}\space E \space \textbf{then} && \{S_1.loop = S.loop\} \\ & S_1 \\ S\rightarrow &\textbf{while} \space E\space \textbf{do} && \{S_1.loop=true\} \\ & S_1 \\ S\rightarrow & \textbf{begin} && \{S_1.loop = S.loop\}\\ & S_1; && \{S_2.loop=S.loop\}\\ & S_2\space \textbf{end} \\ S\rightarrow &\textbf{break} && \{if \space not \space S.loop \space then \space print('error')\} \end{array} \right. SSSSSSSid:=Eif E thenS1while E doS1beginS1;S2 endbreak{S.loop=false}{S1.loop=S.loop}{S1.loop=true}{S1.loop=S.loop}{S2.loop=S.loop}{if not S.loop then print(error)}


T 4.14

程序的文法如下:
P → D D → D ; D   ∣   id : T   ∣   proc   id ; D ; S P→D \\ D→D;D \space | \space \textbf{id}:T \space | \space \textbf{proc} \space \textbf{id};D;S PDDD;D  id:T  proc id;D;S
(a)写一个语法制导定义,打印该程序一共声明了多少个 id \textbf{id} id

s s s D D D的综合属性,用于 D D D id \textbf{id} id 的个数。
P → D p r i n t ( D . s ) D → D 1 ; D 2 p r i n t ( D . s = D 1 . s + D 2 . s ) D → id : T D . s = 1 D → proc   id ; D 1 ; S D . s = D 1 . s + 1 \left. \begin{array}{l} % 左对齐 P\rightarrow D && print(D.s) \\ D\rightarrow D_1;D_2 && print(D.s = D_1.s+D_2.s) \\ D\rightarrow \textbf{id} : T && D.s = 1 \\ D\rightarrow \textbf{proc} \space \textbf{id};D_1;S && D.s = D_1.s + 1 \\ \end{array} \right. PDDD1;D2Did:TDproc id;D1;Sprint(D.s)print(D.s=D1.s+D2.s)D.s=1D.s=D1.s+1
(b)写一个翻译方案,打印该程序每个变量 id \textbf{id} id的嵌套深度。

i i i D D D的继承属性,用于计算 D D D所在的程序嵌套深度。
P → { D . i = 1 } D D → { D 1 . i = D . i } D 1 ; { D 2 . i = D . i } D 2 D → id : T { p r i n t ( D . i ) } D → proc   id ; { D 1 . i = D . i + 1 } D 1 ; S \left. \begin{array}{l} % 左对齐 P\rightarrow &&& \{D.i = 1\} \\ & D \\ D\rightarrow &&& \{D_1.i = D.i\} \\ & D_1; && \{D_2.i = D.i\} \\ & D_2 \\ D\rightarrow & \textbf{id} : T && \{print(D.i)\} \\ D\rightarrow & \textbf{proc} \space \textbf{id}; && \{D_1.i = D.i + 1\} \\ & D_1;S\\ \end{array} \right. PDDDDD1;D2id:Tproc id;D1;S{D.i=1}{D1.i=D.i}{D2.i=D.i}{print(D.i)}{D1.i=D.i+1}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/99949.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++中你不知道的namespace和using的用法

目录 引言 一: 冒号作用域 二、名字控制 1 命令空间 2 命令空间的使用 三、 using的指令 1 using的声明 2 using的编译指令 引言 你是不是只认为namespace 和 using 在C中是基本的语法框架&#xff0c;但是却不知道它们的真正用法&#xff0c;看完文章你会对using和name…

计算机毕设Python+Vue校园志愿者服务系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

软件测试零基础如何快速入门 ?这里有全网最详细的学习资料

目录 前言 一、首先&#xff0c;我们要了解清楚用人部门对初级测试人员的定位&#xff1a; 二、清楚了初级测试人员需要具备的能力 三、找到正确的方向 四、最后需要做的就是储备自己的能力。 一.找本软件测试基础的书 二.写文档 三.执行测试 四.多关注技术博文 五、…

城市管理网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; “模块划分&#xff1a;公告类型&#xff0c;公告信息&#xff0c;城管信息&#xff0c;居民信息&#xff0c;设诉类型&…

工程师为微型晶体管开发新的集成路线

新南威尔士大学悉尼团队展示了高 κ 钙钛矿膜如何充当二维晶体管的绝缘体 新南威尔士大学悉尼分校的研究人员开发了一种微小、透明且灵活的材料&#xff0c;可用作晶体管中的新型电介质&#xff08;绝缘体&#xff09;组件。 最近发表在《自然》杂志上的研究“高 κ 钙钛矿膜…

面试题61. 扑克牌中的顺子

晚上做了道题&#xff0c;写完看了大佬的题解发现自己很蠢&#xff0c;思维不够光想着模拟了&#xff0c;来回考虑细节磕磕绊绊写完这么一道题。虽然也是写出来了&#xff0c;复杂度都是ok的&#xff0c;不过代码长&#xff0c;处理细节麻烦。 记录一下这道题 从若干副扑克牌中…

对DataFrame的列标签增加后缀的DataFrame.add_suffix()方法

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 为DataFrame的列标签增加后缀 DataFrame.add_suffix() [太阳]选择题 关于以下python代码说法错误的一项是? import pandas as pd df pd.DataFrame({"A": [1,2],"B":[1…

基于Unity整合BEPUphysicsint物理引擎实战

上一节我们详细的讲解BEPUphysicsint 的物理事件。此物理引擎会产生了碰撞事件与非碰撞事件&#xff0c;碰撞事件大家好理解&#xff0c;非碰撞事件例如: 物理Entity的update事件,Entity的activation/deactivation事件等。本节课来实战如何编译BEPUphysicsint源码到自己的项目,…

Linux 服务器数据同步利器

一、简介 1 认识 Rsync&#xff08;remote synchronize&#xff09;是一个远程数据同步工具&#xff0c;可通过LAN/WAN快速同步多台主机间的文件。Rsync使用所谓的“Rsync算法”来使本地和远 程两个主机之间的文件达到同步&#xff0c;这个算法只传送两个文件的不同部分&#x…

【毕业设计_课程设计】基于机器视觉的害虫种类及数量检测(源码+论文)

文章目录0 项目说明1 研究目的2 研究内容及结论3 文件介绍4 论文目录5 项目源码0 项目说明 基于机器视觉的害虫种类及数量检测 提示&#xff1a;适合用于课程设计或毕业设计&#xff0c;工作量达标&#xff0c;源码开放 1 研究目的 研究的目的在于建立一套远程病虫害自动识别…

UNION 和 UNION ALL

合并查询结果 利用UNION关键字&#xff0c;可以给出多条SELECT语句&#xff0c;并将它们的结果组合成单个结果集。合并时&#xff0c;两个表对应的列数和数据类型必须相同&#xff0c;并且相互对应。 各个SELECT语句之间使用UNION或UNION ALL关键字分隔。 语法格式 SELECT c…

(附源码)node.js外卖平台 毕业设计 151448

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于外卖平台当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了外卖平台&#xff0c;它彻底改变了过去传统的管理方式…

神州数码交换机CS6200命令(二)

神州数码交换机CS6200命令&#xff08;二&#xff09; 1.基于流的重定向 QOS(Quality of Servcie)-服务品质保障&#xff0c;不产生新的带宽而是根据需求控制带宽 简易配置顺序&#xff1a; 1.配置分类表(class map) 对数据建立一个分类规则 2.配置策略表(policy map) 对…

左(9)--题目讲解

前言 仅记录学习笔记&#xff0c;如有错误欢迎指正。 题目&#xff1a; leetcode的洗衣机问题 思路&#xff1a; 首先看能不能数量相等 总和%机器数量 0 然后分情况讨论&#xff1a;对于任何一个位置都有至少需要搬动n次&#xff0c;最大值就是答案&#xff01; 题目2&am…

APT最佳学习案例:写个简易版 ButterKnife

前言 目的&#xff1a;写个简易版 ButterKnife&#xff0c;借手写 ButterKnife 去了解如何实现注解、annotationProcessor 的等使用。 先看下butterknife的结构&#xff1a; 源码地址 https://github.com/LucasXu01/MyButterKnife ButterKnife的使用 在build.gradle添加依…

Java : 详解八种基本数据类型的包装类

Java &#xff1a; 详解八种基本数据类型的包装类 每博一文案 人生路漫漫越长大&#xff0c;越明白每个人的路都是漫长而艰辛的。无论我们有多累&#xff0c;我们都无路可退。 就像马丁说的那样&#xff1a;每一个强大的人都曾咬着牙度过一段&#xff0c;没人帮忙&#xff0c;…

Rabbitmq与交换机

目录 一、交换机简介 1、Exchange(交换机)的作用 2、Exchange(交换机)的类型 3、交换机的属性 二、交换机的使用 1、创建项目 2、给子模块添加依赖( rabbitmq-provider、 rabbitmq-consumer) 3、直连交换机(Direct Exchange)使用 4、主题交换机(Topic Exchange)的使用 5、…

【图像分割】和声搜索算法图像多级阈值分割【含Matlab源码 2044期】

⛄一、和声搜索算法的图像阈值寻优算法简介 苹果图像识别是指将苹果果实从枝叶、土壤、天空等背景中分离出来, 即图像分割。最大类间方差法 (OTSU算法)是由日本学者大津展之 (OTSU) 提出的全局阈值选取方法。该方法存在缺乏自适应性、易造成噪声干扰和过分割现象、运算需要大量…

[附源码]计算机毕业设计Python的项目管理系统(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

Kafka 安装 快速入门

Kafka 安装 快速入门 Apache Kafka是流行的用于大规模收集、处理、存储和分析数据的开源流处理系统。它以其卓越的性能、低延迟、容错和高吞吐量而闻名&#xff0c;能够每秒处理数千条消息。常用来构建数据管道、利用实时数据流、实现系统监控、数据集成。 如上图&#xff0c;…