Exercises

Chapter 1 - Introduction

  1. Explain the terms
    • Translator
    • Source language – object language
    • Compiler
    • Interpreter
    • Assembler
    • Preprocessor/precompiler
  2. Why are translators necessary?
  3. Describe, using an explanatory diagram, the most important parts of a compiler. The description should be based on function and input/output.
  4. What is a pass (for translators)? Why are passes divided up in some cases and which factors affect this separation?
  5. What is a “compiler-compiler” (functionality and input/output) ?

Chapter 2 - A Simple Syntax-Directed Translator

Questions on this chapter can be found together with those of the next chapter.

Chapter 3 - Lexical Analysis

  1. What is the function of a “scanner”? What type of input/output is there?
  2. Why separate lexical analysis from syntax analysis?
  3. Define “alphabet”, “string”, “string length”, “empty string”, “concatenation of two strings” and “string exponent”.
  4. Define “language”, “concatenation” (“product”) of two languages, “closure” and “positive closure” of a language?
  5. Let A = \lbrace a, b \rbrace and B = \lbrace 0, 1 \rbrace. What are AB, A^* och A^+ ?
  6. How do you define a regular expression of a language? Provide some examples.
  7. Define the concepts of
    • deterministic finite state automaton
    • transition graph – transition table
  8. What is the difference between a deterministic finite-state automaton and a non-deterministic one?
  9. Explain the connection between scanner, regular expressions, finite state automata and transition graph/transition table.
  10. How a lexical analyser is designed and implemented has been covered in the lab assignment on lexical analysis. You must know all the stages of designing a scanner.

Chapter 4 - Syntax Analysis

  1. What is a grammar and why has it been introduced? Explain in this context

    • BNF-grammar
    • rule (production)
    • terminal and non-terminal symbols
    • vocabulary
    • languages which are generated by a grammar
  2. Explain the concepts of

    • derivation
    • direct derivation
    • leftmost and rightmost derivation
    • sentential form
    • sentence
    • parse tree
  3. What is an ambiguous grammar? Why should you not use one of these when describing syntax?

  4. Construct an ambiguous grammar for logical expressions:

    Logical expressions consist of operators, parentheses and variables. The logical operators are, in order of priority, (highest first) NOT, AND, OR, EQU (equivalence) and IMP (implication).

    Assume that the above priority rules and left associativity apply. Write the corresponding unambiguous context-free grammar. What does the grammar look like if right associativity applies? Also derive the two expressions below using the left associative grammar.

  5. Derive and draw the corresponding parse tree for the unambiguous grammar in question 4 for the strings

    a OR b AND NOT c
    (x IMP y) EQU z AND NOT u
  6. The first (optional) lab assignment on grammars and formal languages contains several assignments relevant to this chapter.

  7. What is a parser (syntax analyser) ?

  8. Define

    • canonical derivation
    • left- and right-sentential form
    • handle
    • canonical reduction sequence
  9. Explain the difference between top-down and bottom-up parsing with respect to the construction of the parse tree and the derivation sequence.

  10. Given the following context-free grammar with the start symbol S:

    1
    2
    3
    4
    S → a A S
      | b
    A → c A s
      | ε
    

    A top-down parser finds the rules in the order 1 3 4 2 1 4 2.

    What was the input sequence? In what order would a bottom-up parser have found (reduced) the rules for the corresponding input?

  11. How does a “shift-reduce” parser work?

  12. A “shift-reduce” parser often uses a stack for parsing. Show how a parse, of the same input and using the same grammar as in question  10 above, works. Show how the stack, input and the action taken change during the analysis.

  13. Explain how a “top-down parser with backup” works by showing how the syntax tree is successively built up and how branches are pruned on failures. Exemplify using the grammar G(<{onestring}>) and the sentence aeeb\$.

  14. Why is left recursion a problem for top-down analysis? Give two different ways to rewrite a grammar so as to eliminate left recursion.

  15. Why should a top-down syntax analyser in a compiler never back up during analysis (4 reasons)?

  16. Explain briefly how a recursive descent parser works.

  17. Write a recursive descent parser for the grammar in question 10 above.

  18. What is an LR parser? How does it work? State some advantages and disadvantages of the method.

  19. What is a “configuration” (in connection with the LR technique)? Show how it changes depending on the parsing action (4 cases).

  20. There are two parse tables in the LR technique. Which are they and what do they contain? What does the parse routine look like?

  21. Show which steps an LR parser goes through for the sentence (id + id)*id$. Use the table on page 252 in the course book (page 219 in the first edition).

  22. Explain and put into the correct context

    • viable prefix
    • LR(0) item
    • canonical LR(0) collection
    • augmented grammar
    • shift-reduce conflict / reduce-reduce conflict
  23. Given a canonical LR(0) collection, how are the trees for an SLR(1) parser generally constructed?

  24. Write the SLR(1) tables for the grammar

    1
    2
    3
    S → 1 S 1
      | 0 S 0
      | 2
    
  25. What is the difference between the different classes of LR parsers:

    LR(0) – SLR(1) – LALR(1) – LR(1) – … – LR(k) ?

  26. Show another way of representing the parse tables than in matrix form.

Chapter 5 - Syntax-Directed Translation

  1. Explain these concepts
    • syntax-directed translation schema
    • semantic routine — semantic rule
    • semantic stack
  2. How do you call semantic rules in top-down and bottom-up syntax analysis?
  3. Write a syntax-directed translation schema which evaluates arithmetic expressions directly. This sort of schema is usually known as an “attributed translation grammar”. Show how such a translation can be implemented in an LR parser environment, with a semantic stack.
  4. Write a syntax-directed translation schema which generates quadruples from while-statements and if-statements. Which attributes are needed?

Chapter 6 - Intermediate-Code Generation

  1. Why is the source code translated to an internal form instead of directly generating machine code?

  2. What does the general form for the following representations look like?

    • infix
    • postfix (reverse Polish notation)
    • abstract syntax trees
    • quadruples
    • triples
  3. Compare and provide some advantages and disadvantages of triples and quadruples.

  4. Given an abstract syntax tree, how is it transformed to reverse Polish notation in a simple way?

  5. Show how expressions in reverse Polish notation can be evaluated (interpreted and values calculated) by using a stack. What is it that you put on the stack?

  6. Translate the following statements to postfix, abstract syntax tree, quadruples and triples:

    z := (x+20) * 15 - (y+2)/a
    
    if a < 10 then
       if b < 5 then x := a else x := a + b
    else x := a - b
    
    while x < 10 do
    begin f := f + 10 * x; x := x -1; end
    

Chapter 7 - Run-Time Environments

  1. Why is there usually a symbol table in a compiler?

  2. Give examples of data which should be found in a symbol table for a language like Pascal or Algol 60.

  3. State two different ways of storing names in the symbol table.

  4. What is the difference in the way “arrays” with a fixed and variable number of dimensions, for example, are stored in the symbol table?

  5. Lists, trees and hash coded tables are three common storage forms for symbol tables. Discuss the advantages and disadvantages of these forms of storage. Is there any one answer as to which method should be used? Why?

  6. Describe a tree-structured symbol table. Show how it is constructed when storing the symbols D G A B E F C in this order in it. You could for instance use a binary tree and sort on the position of the letters in the alphabet.

  7. Describe a hash coded symbol table. Show it graphically by putting some names in the table. Provide examples of how the hash function can be calculated.

  8. Assume we have a hash coded symbol table. Given the program sequence below

        BEGIN
            ADAM, BERTIL : INTEGER;
            BEGIN
                ADAM, CAESAR : REAL;
            END;
            BEGIN
                BERTIL, DAVID : BOOLEAN
    L1:             BEGIN
                        CAESAR, ERIK : INTEGER
    L2:             END
            END
    L3: END
    

    Show what the hash table, symbol table och and the block table will look like at L1, L2 and L3.

  9. Show some different ways of how arrays can be stored during execution (consider both fixed and variable arrays). What is a “dope vector”?

  10. The following excerpt of a program is written in some Algol-like language:

    begin
       procedure odd(m, n);
       begin
       int i := 0;
         n := m + 1;
         i := m;
       end ;
       (* ... *)
       i := 2;
       odd(i+1, i);
    end
    

    (All variables are integer types).

    Describe what happens when odd is called and what value i has after the call in these cases

    • call by reference
    • call by value
    • call by value/result
    • call by name
  11. What is a “thunk”? What is it used for?

  12. What is meant by static memory allocation? What are the advantages? Give examples of languages where such memory allocation is applied.

  13. When do you need dynamic memory allocation?

  14. What is meant by stack allocation? When must this type of allocation be used?

    Explain in this context the concepts of

    • activation record
    • display

    Give examples of languages which use stack allocation.

  15. What is meant by heap allocation? When is it needed? Explain these concepts

    • fragmentation
    • garbage collection
  16. How is memory allocation performed in FORTRAN? What does an activation record contain? How are procedure calls and returns performed?

  17. Describe what is normally contained in an activation record for Algol.

  18. One of the problems with memory assignment in Algol is its pure block structure. Show what happens to an activation record (and the rest of the stack) when entering and leaving a block, especially when there are variable array structures.

  19. Given a procedure ole and in it a declared procedure dole which is called by ole, i.e.

            PROCEDURE ole ...
    L1:     BEGIN
                PROCEDURE dole
    L2:         END of dole
                ...
                dole
                ...
            END of dole
    

    Describe the appearance of the stack at L1 and L2. How is the new display set up?

  20. Explain how, from the dole procedure in the previous example, you can address declared variables outside ole, in ole and in dole. What function have the displays in the addressing?

Chapter 8 - Code Generation

  1. Compilers normally generate one of three types of object code. Which are they? What are the advantages and disadvantages of generating the various types?
  2. What three main problems are their with code generation?
  3. Code generation from tree structures. Describe an algorithm which marks nodes in a tree with their register needs during code generation. Describe an algorithm which generates code from a tree whose nodes are marked with such register needs.
  4. What is meant by “peephole optimization”? Give some examples of code improvements which can be done using this technique.

Chapter 9 - Machine-Independent Optimizations

  1. What is meant by
    • algorithm optimization
    • local optimization
    • loop optimization
    • global optimization
  2. What is a “basic block”?
  3. Describe briefly and give examples of the following optimization within a “basic block”
    • constant folding
    • elimination of common sub-expressions
    • reduction in strength
  4. Describe briefly the loop optimizations below
    • moving loop invariants
    • eliminating induction variables
  5. What should you take into consideration before putting optimization routines into a compiler?

Chapter X - Bootstrapping

  1. What is a compiler-compiler (functionality and input/output)?

  2. What is meant by cross-compilation?

  3. What is meant by “bootstrapping”?

    State a neat and “easy” (it is never easy) way to implement a new language, say Pascal, on a machine A. The compiler should be written in the language itself, here Pascal. Assume that machine A has some high-level language, say FORTRAN, that you should start from.

    Show what you should do, with the least possible work, to implement the language above (here Pascal) on another machine B.

    Draw figures in connection with the exercises above.