《编译原理-龙书》练习第7章

7.1 存储组织

7.2 空间的栈式分配

7.2.4栈中的变长数据,在c语言中所有变长数据都在堆中。

7.2.1 1)这种情况下快排效果最差O(n*n)

2)栈中最多状态情况:

P(1, 9)

P(1, 8)

...

P(1,2)

P(1,1)

共9个

7.2.3  1)              f(5)

                 f(4)                       f(3)

       f(3)            f(2)          f(2) f(1)

   f(2) f(1)    f(1) f(0)    f(1) ff(0)

f(1) f(0)

2)

f(5)

f(4)

f(3)

f(2)

f(1)

参数

返回值

局部s、t

3)

f(5)

f(3)

f(1)

参数

返回值

局部s、t

7.2.4 上面g的活动记录,下面f的活动记录

g参数

g返回值

g中保存的机器状态

g中局部变量

f参数

f返回值                             这一行及以上g创建,g写入值

f控制链

f局部数据

7.2.5

a = a+1 = 4

a = a+2 = 6

a+a = 12

7.2.6 c=4 b=&c a=&b

x = 4 py = &c ppz=&b

c += 1 = 5

c += 2 = 7

x += 3 = 7

return 7+7+7=21

7.3 栈中非局部数据的访问


7.4 堆管理

7.4.1 80 30 60 50 70 20 40

1) 

80306050702040
44->28 12 **  

2)

80306050702040
   ******8

7.5 垃圾回收概述

7.5.1

1) B的引用计数-1

2) X以外其它变量计数-1

3) F引用计数-1

7.5.2 D引用计数-1

7.6 基于跟踪的回收的介绍

7.6.1 1) A->B被删除,标记为reached依次包括X A C F H I G E,B和D将被回收

2)A->C,X A B D E G H C F,没有可以回收

3)A->D,D G将被回收

4)B,C将被回收

7.6.2 只考虑第一个A->B被删除

 FreeUnreachedUnscannedScanned
 **Allnullnull
 **All-XXnull
 **All-X-AAX
 ............
 **B,DnullX-B,D
 **+B,D   

7.6.3 只考虑第一个A->B被删除

初始:X  A       B     ...    I

           0   100  200 ...   900

计算新位置之前,B,D没有被访问到,其它对象从左往右排

7.6.4

7.7 短停顿垃圾回收


7.8 垃圾回收中的高级论题





  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理龙书答案 完整性高 第二 2.2 Exercises for Section 2.2 2.2.1 Consider the context-free grammar: S -> S S + | S S * | a Show how the string aa+a* can be generated by this grammar. Construct a parse tree for this string. What language does this grammar generate? Justify your answer. answer S -> S S * -> S S + S * -> a S + S * -> a a + S * -> a a + a * L = {Postfix expression consisting of digits, plus and multiple signs} 2.2.2 What language is generated by the following grammars? In each case justify your answer. S -> 0 S 1 | 0 1 S -> + S S | - S S | a S -> S ( S ) S | ε S -> a S b S | b S a S | ε ⧗ S -> a | S + S | S S | S * | ( S ) answer L = {0n1n | n>=1} L = {Prefix expression consisting of plus and minus signs} L = {Matched brackets of arbitrary arrangement and nesting, includes ε} L = {String has the same amount of a and b, includes ε} ? 2.2.3 Which of the grammars in Exercise 2.2.2 are ambiguous answer No No Yes Yes Yes 2.2.4 Construct unambiguous context-free grammars for each of the following languages. In each case show that your grammar is correct. Arithmetic expressions in postfix notation. Left-associative lists of identifiers separated by commas. Right-associative lists of identifiers separated by commas. Arithmetic expressions of integers and identifiers with the four binary operators +, - , *, /. answer 1. E -> E E op | num 2. list -> list , id | id 3. list -> id , list | id 4. expr -> expr + term | expr - term | term term -> term * factor | term / factor | factor factor -> id | num | (expr) 5. expr -> expr + term | expr - term | term term -> term * unary | term / unary | unary unary -> + factor | - factor factor - > id | num | (expr) 2.2.5 Show that all binary strings generated by the following grammar have values divisible by 3. Hint. Use induction on the number of nodes in a parse tree. num -> 11 | 1001 | num 0 | num num Does the grammar generate all binary strings with values divisible by 3? answer prove any string derived from the grammar can be considered to be a sequence consisting of 11, 1001 and 0, and not prefixed with 0. the sum of this string is: sum = Σn (21 + 20) * 2 n + Σm (23 + 20) * 2m = Σn 3 * 2 n + Σm 9 * 2m It is obviously can divisible by 3. No. Consider string "10101", it is divisible by 3, but cannot derived from the grammar. Question: any general prove? 2.2.6 Construct a context-free grammar for roman numerals. Note: we just consider a subset of roman numerals which is less than 4k. answer wikipedia: Roman_numerals via wikipedia, we can categorize the single noman numerals into 4 groups: I, II, III | I V | V, V I, V II, V III | I X then get the production: digit -> smallDigit | I V | V smallDigit | I X smallDigit -> I | II | III | ε and we can find a simple way to map roman to arabic numerals. For example: XII => X, II => 10 + 2 => 12 CXCIX => C, XC, IX => 100 + 90 + 9 => 199 MDCCCLXXX => M, DCCC, LXXX => 1000 + 800 + 80 => 1880 via the upper two rules, we can derive the production: romanNum -> thousand hundred ten digit thousand -> M | MM | MMM | ε hundred -> smallHundred | C D | D smallHundred | C M smallHundred -> C | CC | CCC | ε ten -> smallTen | X L | L smallTen | X C smallTen -> X | XX | XXX | ε digit -> smallDigit | I V | V smallDigit | I X smallDigit -> I | II | III | ε 2.3 Exercises for Section 2.3 2.3.1 Construct a syntax-directed translation scheme that trans­ lates arithmetic expressions from infix notation into prefix notation in which an operator appears before its operands; e.g. , -xy is the prefix notation for x - y . Give annotated parse trees for the inputs 9-5+2 and 9-5*2.。 answer productions: expr -> expr + term | expr - term | term term -> term * factor | term / factor | factor factor -> digit | (expr) translation schemes: expr -> {print("+")} expr + term | {print("-")} expr - term | term term -> {print("*")} term * factor | {print("/")} term / factor | factor factor -> digit {print(digit)} | (expr) 2.3.2 Construct a syntax-directed translation scheme that trans­ lates arithmetic expressions from postfix notation into infix notation. Give annotated parse trees for the inputs 95-2* and 952*-. answer productions: expr -> expr expr + | expr expr - | expr expr * | expr expr / | digit translation schemes: expr -> expr {print("+")} expr + | expr {print("-")} expr - | {print("(")} expr {print(")*(")} expr {print(")")} * | {print("(")} expr {print(")/(")} expr {print(")")} / | digit {print(digit)} Another reference answer E -> {print("(")} E {print(op)} E {print(")"}} op | digit {print(digit)} 2.3.3 Construct a syntax-directed translation scheme that trans­ lates integers into roman numerals answer assistant function: repeat(sign, times) // repeat('a',2) = 'aa' translation schemes: num -> thousand hundred ten digit { num.roman = thousand.roman || hundred.roman || ten.roman || digit.roman; print(num.roman)} thousand -> low {thousand.roman = repeat('M', low.v)} hundred -> low {hundred.roman = repeat('C', low.v)} | 4 {hundred.roman = 'CD'} | high {hundred.roman = 'D' || repeat('X', high.v - 5)} | 9 {hundred.roman = 'CM'} ten -> low {ten.roman = repeat('X', low.v)} | 4 {ten.roman = 'XL'} | high {ten.roman = 'L' || repeat('X', high.v - 5)} | 9 {ten.roman = 'XC'} digit -> low {digit.roman = repeat('I', low.v)} | 4 {digit.roman = 'IV'} | high {digit.roman = 'V' || repeat('I', high.v - 5)} | 9 {digit.roman = 'IX'} low -> 0 {low.v = 0} | 1 {low.v = 1} | 2 {low.v = 2} | 3 {low.v = 3} high -> 5 {high.v = 5} | 6 {high.v = 6} | 7 {high.v = 7} | 8 {high.v = 8} 2.3.4 Construct a syntax-directed translation scheme that trans­ lates roman numerals into integers. answer productions: romanNum -> thousand hundred ten digit thousand -> M | MM | MMM | ε hundred -> smallHundred | C D | D smallHundred | C M smallHundred -> C | CC | CCC | ε ten -> smallTen | X L | L smallTen | X C smallTen -> X | XX | XXX | ε digit -> smallDigit | I V | V smallDigit | I X smallDigit -> I | II | III | ε translation schemes: romanNum -> thousand hundred ten digit {romanNum.v = thousand.v || hundred.v || ten.v || digit.v; print(romanNun.v)} thousand -> M {thousand.v = 1} | MM {thousand.v = 2} | MMM {thousand.v = 3} | ε {thousand.v = 0} hundred -> smallHundred {hundred.v = smallHundred.v} | C D {hundred.v = smallHundred.v} | D smallHundred {hundred.v = 5 + smallHundred.v} | C M {hundred.v = 9} smallHundred -> C {smallHundred.v = 1} | CC {smallHundred.v = 2} | CCC {smallHundred.v = 3} | ε {hundred.v = 0} ten -> smallTen {ten.v = smallTen.v} | X L {ten.v = 4} | L smallTen {ten.v = 5 + smallTen.v} | X C {ten.v = 9} smallTen -> X {smallTen.v = 1} | XX {smallTen.v = 2} | XXX {smallTen.v = 3} | ε {smallTen.v = 0} digit -> smallDigit {digit.v = smallDigit.v} | I V {digit.v = 4} | V smallDigit {digit.v = 5 + smallDigit.v} | I X {digit.v = 9} smallDigit -> I {smallDigit.v = 1} | II {smallDigit.v = 2} | III {smallDigit.v = 3} | ε {smallDigit.v = 0} 2.3.5 Construct a syntax-directed translation scheme that trans­ lates postfix arithmetic expressions into equivalent prefix arithmetic expressions. answer production: expr -> expr expr op | digit translation scheme: expr -> {print(op)} expr expr op | digit {print(digit)} Exercises for Section 2.4 2.4.1 Construct recursive-descent parsers, starting with the follow­ ing grammars: S -> + S S | - S S | a S -> S ( S ) S | ε S -> 0 S 1 | 0 1 Answer 1) S -> + S S | - S S | a void S(){ switch(lookahead){ case "+": match("+"); S(); S(); break; case "-": match("-"); S(); S(); break; case "a": match("a"); break; default: throw new SyntaxException(); } } void match(Terminal t){ if(lookahead = t){ lookahead = nextTerminal(); }else{ throw new SyntaxException() } } 2) S -> S ( S ) S | ε void S(){ if(lookahead == "("){ S(); match("("); S(); match(")"); S(); } } 3) S -> 0 S 1 | 0 1 void S(){ switch(lookahead){ case "0": match("0"); S(); match("1"); break; case "1": // match(epsilon); break; default: throw new SyntaxException(); } } Exercises for Section 2.6 2.6.1 Extend the lexical analyzer in Section 2.6.5 to remove com­ ments, defined as follows: A comment begins with // and includes all characters until the end of that line. A comment begins with /* and includes all characters through the next occurrence of the character sequence */. 2.6.2 Extend the lexical analyzer in Section 2.6.5 to recognize the relational operators <, =, >. 2.6.3 Extend the lexical analyzer in Section 2.6.5 to recognize float­ ing point numbers such as 2., 3.14, and . 5. Answer Source code: commit 8dd1a9a Code snippet(src/lexer/Lexer.java): public Token scan() throws IOException, SyntaxException{ for(;;peek = (char)stream.read()){ if(peek == ' ' || peek == '\t'){ continue; }else if(peek == '\n'){ line = line + 1; }else{ break; } } // handle comment if(peek == '/'){ peek = (char) stream.read(); if(peek == '/'){ // single line comment for(;;peek = (char)stream.read()){ if(peek == '\n'){ break; } } }else if(peek == '*'){ // block comment char prevPeek = ' '; for(;;prevPeek = peek, peek = (char)stream.read()){ if(prevPeek == '*' && peek == '/'){ break; } } }else{ throw new SyntaxException(); } } // handle relation sign if("".indexOf(peek) > -1){ StringBuffer b = new StringBuffer(); b.append(peek); peek = (char)stream.read(); if(peek == '='){ b.append(peek); } return new Rel(b.toString()); } // handle number, no type sensitive if(Character.isDigit(peek) || peek == '.'){ Boolean isDotExist = false; StringBuffer b = new StringBuffer(); do{ if(peek == '.'){ isDotExist = true; } b.append(peek); peek = (char)stream.read(); }while(isDotExist == true ? Character.isDigit(peek) : Character.isDigit(peek) || peek == '.'); return new Num(new Float(b.toString())); } // handle word if(Character.isLetter(peek)){ StringBuffer b = new StringBuffer(); do{ b.append(peek); peek = (char)stream.read(); }while(Character.isLetterOrDigit(peek)); String s = b.toString(); Word w = words.get(s); if(w == null){ w = new Word(Tag.ID, s); words.put(s, w); } return w; } Token t = new Token(peek); peek = ' '; return t; } Exercises for Section 2.8 2.8.1 For-statements in C and Java have the form: for ( exprl ; expr2 ; expr3 ) stmt The first expression is executed before the loop; it is typically used for initializ­ ing the loop index. The second expression is a test made before each iteration of the loop; the loop is exited if the expression becomes O. The loop itself can be thought of as the statement {stmt expr3 ; }. The third expression is executed at the end of each iteration; it is typically used to increment the loop index. The meaning of the for-statement is similar to expr1 ; while ( expr2 ) {stmt expr3 ; } Define a class For for for-statements, similar to class If in Fig. 2.43. Answer class For extends Stmt{ Expr E1; Expr E2; Expr E3; Stmt S; public For(Expr expr1, Expr expr2, Expr expr3, Stmt stmt){ E1 = expr1; E2 = expr2; E3 = expr3; S = stmt; } public void gen(){ E1.gen(); Label start = new Lable(); Lalel end = new Lable(); emit("ifFalse " + E2.rvalue().toString() + " goto " + end); S.gen(); E3.gen(); emit("goto " + start); emit(end + ":") } } 2.8.2 The programming language C does not have a boolean type. Show how a C compiler might translate an if-statement into three-address code. Answer Replace emit("isFalse " + E.rvalue().toString() + " goto " + after); with emit("ifNotEqual " + E.rvalue().toString() + " 0 goto " + after); or emit("isNotEqualZero " + E.rvalue().toString() + " goto " + after);

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值