CS 3723-001 Programming Languages
Fall 2004 -- Mid-term Exam
Answers

  1. Consider the formal Grammar

    1. Is this grammar ambiguous? (Yes or No) No
    2. Is this grammar suitable for a recursive descent parser? (Yes or No) No
    3. What is the associativity of the operator *? Left-to-right
      If we wanted to reverse its associativity, how would we change the grammar? T ---> F '*' T
    4. Construct the parse tree for the sentence: a * ( b + c )
      
                                         E
                                         |
                                         T
                                    +----+---------------------+
                                    |    |                     |
                                    |    |                     F
                                    |    |    +----------------+-----------+
                                    T    |    |                |           |
                                    |    |    |                E           |
                                    |    |    |                |           |
                                    |    |    |        +-------+------+    |
                                    |    |    |        |       |      |    |
                                    F    |    |        E       |      T    |
                                    |    |    |        |       |      |    |
                                    |    |    |        T       |      F    |
                                    |    |    |        |       |      |    |
                                    |    |    |        F       |      |    |
                                    |    |    |        |       |      |    |
                                    a    *    (        b       +      c    )
      


  2. This question has to do with finite state machines.

    1. Which of the following are legal floating point constants (in C or in Java)?
      1. 1e+1
      2. .1
      3. 0e0
      4. 1.e47
        
        public class Floats {
           public static void main (String[] args) {
              System.out.println("1e+1:  " + 1e+1);
              System.out.println(".1:    " + .1);
              System.out.println("0e0:   " + 0e0);
              System.out.println("1.e47: " + 1.e47);
           }
        }
        Output:
        1e+1:  10.0
        .1:    0.1
        0e0:   0.0
        1.e47: 1.0E47
        
    2. Give a finite state machine to recognize an identifier, assuming that an identifier just uses letters and digits. You can label arrows with letter or with digit.

  3. In a shift-reduce parser like the one we studied in class, describe what happens when the grammar rule    E ---> E + T    is used in a reduction? What is true about the stack before the reduction? What is true about the stack after the reduction? [The parser knows to reduce by looking up the symbol on the stack top (T in this case) and the current symbol (the next one) in the parse table, which in this case tells it to reduce.]
    There should be a match between the top of the stack and the right side of the grammar rule, that is, the symbols: "E", "+", "T" must be on the top of the stack, in order, with "T" at the very top. The reduction pops these off and pushes "E" back on. At the end all we know from this problem is that "E" is now on the top.


  4. Consider the grammar rule for a while statement in the Tiny® language, as it was presented for the class compiler project:    W ---> '{' E '?' { S } '}'

    1. There are two different kinds of curly brackets here.
      What do the curly brackets in quotes mean?
      These are terminal symbols, actual curly brackets that are part of the input source language.
      What do the curly brackets surrounding the S mean (those not in quotes)?
      These curly brackets are metasymbols meaning "zero or more repetitions of". In this case there are zero or more occurrences of the non-terminal S, the symbol for a statement.

    2. Give the function W used in your recursive descent parser to handle this rule. (Just the bare parser -- not anything else. Give it in as complete a detail as you can, using the language that you used for your programming.)

           // error handling not required
           private void W() {
              if (next == '{')  scan(); // possibly already checked for '{'
              else error();
              E();
              if (next == '?')  scan();
              else error();
              while (next != '}') {
                 S();
              }
              if (next == '}') scan();
              else error(7);
           }
        

    3. How does the parser know to call W, rather than some other function that is part of the recursive descent parser? (How does the parser decide to call W?) If the next token is a '{', then this is the start of a while statement and W needs to be called.

    4. The MIPS code generated inside the W function includes two labels and three instructions. Say what these five elements are and where they would be inserted along with the other MIPS code generated by parsing E and { S }.
        
        First a label --  WhileStart0: (with integer tacked onto the end, not necessarily 0)
        Then MIPS code generated by calling E
        Final part ends up with an address returned by E where the value of E
        will be held at run time, call this value returned "addr"
        Then the instruction --    lw   $t1,   addr*4($s1) # addr*4 is a constant
        Then the instruction --    beq  $t1,   $zero,   WhileEnd0 (same digit at end)
        Then code generated by the calls to S, however many there are
        Then the instruction --    j   WhileStart0  (same digit at end)
        Then the label --    WhileEnd0:  (same digit at end)
        Note:of course you don't have to use the names "WhileStart" etc.
        and many other variations from the above are possible.
        

    5. There is a crucial memory address that is needed to complete the code. Where does this address come from? Already answered in previous part.


  5. This is a question about run-time storage management, specifically, dynamic allocation from the heap. (This question is NOT concerned with returning a pointer to local storage or with the dangle example.)

    1. What is a memory leak in a language like C? This occurs when allocated storage is not properly freed, so that the storage is still allocated after all active pointers to the storage are overwritten or deallocated themselves.
    2. A memory leak is one of the two pitfalls mentioned related to the use of malloc in C. Give the other pitfall. The other pitfall occurs when storage is freed even though there is still an active pointer to the storage. Then if this pointer is chased, a program crash or system crash of some sort may occur.
    3. Can either of these pitfalls occur in C++? Yes (unless you use a garbage collector with the C++).
    4. Can either of these pitfalls occur in Java? No.


  6. Consider the attached Java program, which is a recursive descent parser:
    1. Briefly and informally describe the language that is being parsed.A sequence of matched parenthesis, each left paren with a matching right paren, and the first left paren only matches the final right paren.

    2. The "bare" parser (without error checking) is given in bold above. Reconstruct the grammar that is the basis for this parser and write it out carefully.
        
        P  ---->  Q  '#'
        Q  ---->  '('  R
        R  ---->  ')'  |  Q  R
        

    3. Add extra semantic code, so that the code will print each parenthesis along with the level of nesting of that parenthesis. The level should be printed after a left paren and followed by a blank. A right paren should be preceded by a blank, then the level number, and then the right paren. (Notice that your semantic code must also print the parens.) Here are several examples of runs with the correct output. (In each case the input is in boldface.) You must not write this code from scatch, but you must add to the parser above. For one possible answer see Java program


Points for each problem: 1-20, 2-20, 3-10, 4-20, 5-15, 6-15.