编译原理第二版4.2答案

Exercises for Section 4.2

4.2.1

Consider the context-free grammar:

S -> S S + | S S * | a

and the string aa + a*.

  1. Give a leftmost derivation for the string.
  2. Give a rightmost derivation for the string.
  3. Give a parse tree for the string.
  4. ! Is the grammar ambiguous or unambiguous? Justify your answer.
  5. ! Describe the language generated by this grammar.
Answer
  1. S =lm=> SS* => SS+S* => aS+S* => aa+S* => aa+a*
  2. S =rm=> SS* => Sa* => SS+a* => Sa+a* => aa+a*
![4 2 1](https://f.cloud.github.com/assets/340282/469058/c08b4f9c-b6af-11e2-8236-f79c6a56215a.gif)
  1. Unambiguous
  2. The set of all postfix expressions consist of addition and multiplication

4.2.2

Repeat Exercise 4 . 2 . 1 for each of the following grammars and strings:

  1. S -> 0 S 1 | 0 1 with string 00011l.

  2. S -> + S S | * S S | a with string + * aaa.

  3. ! S -> S (S) S | ε with string (()())

  4. ! S -> S + S | S S | (S) | S * | a with string (a+a)*a

  5. ! S -> (L) | a 以及 L -> L, S | S with string ((a,a),a,(a))

  6. !! S -> a S b S | b S a S | ε with string aabbab

  7. The following grammar for boolean expressions:

    bexpr -> bexpr or bterm | bterm
    bterm -> bterm and bfactor | bfactor
    bfactor -> not bfactor | (bexpr) | true | false
    
Answer
  1. S =lm=> 0S1 => 00S11 => 000111
  2. S =rm=> 0S1 => 00S11 => 000111
  3. Omit
  4. Unambiguous
  5. The set of all strings of 0s and followed by an equal number of 1s

2、

  1. S =lm=> +SS => +*SSS => +*aSS => +*aaS => +*aaa
  2. S =rm=> +SS => +Sa => +*SSa => +*Saa => +*aaa
  3. Omit
  4. Unambiguous
  5. The set of all prefix expressions consist of addition and multiplication.

3、

  1. S =lm=> S(S)S => (S)S => (S(S)S)S => ((S)S)S => (()S)S => (()S(S)S)S => (()(S)S)S => (()()S)S => (()())S => (()())
  2. S =rm=> S(S)S => S(S) => S(S(S)S) => S(S(S)) => S(S()) => S(S(S)S()) => S(S(S)()) => S(S()()) => S(()()) => (()())
  3. Omit
  4. Ambiguous
  5. The set of all strings of symmetrical parentheses

4、

  1. S =lm=> SS => S*S => (S)*S => (S+S)*S => (a+S)*S => (a+a)*S => (a+a)*a
  2. S =rm=> SS => Sa => S*a => (S)*a => (S+S)*a => (S+a)*a => (a+a)*a
  3. Omit
  4. Ambiguous
  5. The set of all string of plus, mupplication, ‘a’ and symmetrical parentheses, and plus is not the beginning and end of the position, multiplication is not the beginning of the position

5、

  1. S =lm=> (L) => (L, S) => (L, S, S) => ((S), S, S) => ((L), S, S) => ((L, S), S, S) => ((S, S), S, S) => ((a, S), S, S) => ((a, a), S, S) => ((a, a), a, S) => ((a, a), a, (L)) => ((a, a), a, (S)) => ((a, a), a, (a))
  2. S =rm=> (L) => (L, S) => (L, (L)) => (L, (a)) => (L, S, (a)) => (L, a, (a)) => (S, a, (a)) => ((L), a, (a)) => ((L, S), a, (a)) => ((S, S), a, (a)) => ((S, a), a, (a)) => ((a, a), a, (a))
  3. Omit
  4. Unambiguous
  5. Something like tuple in Python

6、

  1. S =lm=> aSbS => aaSbSbS => aabSbS => aabbS => aabbaSbS => aabbabS => aabbab
  2. S =rm=> aSbS => aSbaSbS => aSbaSb => aSbab => aaSbSbab => aaSbbab => aabbab
  3. Omit
  4. Ambiguous
  5. The set of all strings of 'a’s and 'b’s of the equal number of 'a’s and 'b’s

7、 Unambiguous, boolean expression

4.2.3

Design grammars for the following languages:

  1. The set of all strings of 0s and 1s such that every 0 is immediately followed
    by at least one 1.
  2. ! The set of all strings of 0s and 1s that are palindromes; that is, the string
    reads the same backward as forward.
  3. ! The set of all strings of 0s and 1s with an equal number of 0s and 1s.
  4. !! The set of all strings of 0s and 1s with an unequal number of 0s and 1s.
  5. ! The set of all strings of 0s and as in which 011 does not appear as a
    substring.
  6. !! The set of all strings of 0s and 1s of the form xy, where x<>y and x and y are of the same length.
Answer

1、

S -> (0?1)*

2、

S -> 0S0 | 1S1 | 0 | 1 | ε

3、

S -> 0S1S | 1S0S | ε

5、

S -> 1*(0+1?)*

4.2.4

There is an extended grammar notation in common use.
In this notation, square and curly braces in production bodies are metasymbols
(like -> or |) with the following meanings:

  1. Square braces around a grammar symbol or symbols denotes that these
    constructs are optional. Thus, production A -> X[Y]Z has the same
    effect as the two productions A -> XYZ and A -> XZ.
  2. Curly braces around a grammar symbol or symbols says that these sym­bols
    may be repeated any number of times, including zero times. Thus,
    A -> X{YZ} has the same effect as the infinite sequence of productions
    A -> X, A -> XYZ, A -> XYZYZ, and so on.

Show that these two extensions do not add power to grammars; that is, any
language that can be generated by a grammar with these extensions can be
generated by a grammar without the extensions.

Proof
extended grammarnot extended grammar
A -> X[Y]ZA -> XZ | XYZ
A -> X{YZ}A -> XB
B -> YZB | ε

4.2.5

Use the braces described in Exercise 4.2.4 to simplify the
following grammar for statement blocks and conditional statements:

stmt -> if expr then stmt else stmt
      | if stmt them stmt
      | begin stmtList end
stmtList -> stmt; stmtList | stmt
Answer
stmt -> if expr then stmt [else stmt]
      | begin stmtList end
stmtList -> stmt [; stmtList]

4.2.6

Extend the idea of Exercise 4.2.4 to allow any regular expres­sion
of grammar symbols in the body of a production. Show that this extension
does not allow grammars to define any new languages.

Proof

Every regular grammar has a corresponding not extended grammar

4.2.7 !

A grammar symbol X (terminal or nonterminal) is useless if
there is no derivation of the form S =*=> wXy =*=> wxy. That is, X can never
appear in the derivation of any sentence.

  1. Give an algorithm to eliminate from a grammar all productions containing useless symbols.

  2. Apply your algorithm to the grammar:

    S -> 0 | A
    A -> AB
    B -> 1
    

4.2.8

The grammar in Fig. 4.7 generates declarations for a sin­gle
numerical identifier; these declarations involve four different, independent
properties of numbers.

stmt -> declare id optionList
optionList -> optionList option | ε
option -> mode | scale | precision | base
mode -> real | complex
scale -> fixed | floating
precision -> single | double
base -> binary | decimal
  1. Generalize the grammar of Fig. 4.7 by allowing n options Ai, for some
    fixed n and for i = 1,2… ,n, where Ai can be either ai or bi· Your
    grammar should use only 0(n) grammar symbols and have a total length
    of productions that is O(n).

  2. ! The grammar of Fig. 4.7 and its generalization in part (a) allow declarations
    that are contradictory and/or redundant, such as

    declare foo real fixed real floating

    We could insist that the syntax of the language forbid such declarations;
    that is, every declaration generated by the grammar has exactly one value
    for each of the n options. If we do, then for any fixed n there is only a finite
    number of legal declarations. The language of legal declarations thus has
    a grammar (and also a regular expression), as any finite language does.
    The obvious grammar, in which the start symbol has a production for
    every legal declaration has n! productions and a total production length
    of O(n x n!). You must do better: a total production length that is O(n2^n)

  3. !! Show that any grammar for part (b) must have a total production length of at least 2n.

  4. What does part © say about the feasibility of enforcing nonredundancy
    and noncontradiction among options in declarations via the syntax of the programming language?

Answer

1、

stmt -> declare id optionList
optionList -> optionList option | ε
option -> A_1 | A_2 | … | A_n
A_1 -> a_1 | b_1
A_2 -> a_2 | b_2
…
A_n -> a_n | b_n
  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值