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

  1. Consider the formal Grammar

    1. Is this grammar ambiguous? (Yes or No)
    2. Is this grammar suitable for a recursive descent parser? (Yes or No)
    3. What is the associativity of the operator *? If we wanted to reverse its associativity, how would we change the grammar?
    4. Construct the parse tree for the sentence: 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

    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?


  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?
      What do the curly brackets surrounding the S mean (those not in quotes)?

    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.)

    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?)

    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 }.

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


  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?
    2. A memory leak is one of the two pitfalls mentioned related to the use of malloc in C. Give the other pitfall.
    3. Can either of these pitfalls occur in C++?
    4. Can either of these pitfalls occur in Java?


  6. Consider the attached Java program, which is a recursive descent parser:

    1. Briefly and informally describe the language that is being parsed.

    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.

    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.

        (()())#
        (0 (1  1)(1  1) 0)
        ( () (( )) (() () ) () ) #
        (0 (1  1)(1 (2  2) 1)(1 (2  2)(2  2) 1)(1  1) 0)
        ((((((((((()))))))))))#
        (0 (1 (2 (3 (4 (5 (6 (7 (8 (9 (10  10) 9) 8) 7) 6) 5) 4) 3) 2) 1) 0)
        ( () (( )) (()) () (((() (()) ) () ) )  )#
        (0 (1  1)(1 (2  2) 1)(1 (2  2) 1)(1  1)(1 (2 (3 (4  4)(4 (5  5) 4) 3)(3  3) 2) 1) 0)
        


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