CS 3723/3731 Programming Languages
Final Exam, Spring 2003

  1. Formal Grammars and Languages:

    1. Consider the following grammar for very simple arithmetic expressions. Here "P" is the start symbol, and "digit" is any one of the ten digits.
        
             P  --->  E  '#'
             E  --->  E  '+'  T   |   T 
             T  --->  T  '*'  F   |   F 
             F  --->  '('  E  ')'  |  digit
            

      Give the parse tree for the sentence:

        7 * ( 3 + 2 ) #

    2. Is the grammar above ambiguous? (Yes or No.)

    3. What is the associativity and precedence of the operators + and *?

    4. Which of the two parsing methods that we studied in recitations can utilize this grammar? (Perhaps both, perhaps one, perhaps none. If one or more, you must identify it/them by name.)

     

  2. Semantic Actions:

      Consider the following grammar:
      
           P  --->  E '#'
           E  --->  T { '+'  T }
           T  --->  F { '*'  F }
           F  --->  '('  E  ')'  |  digit
      
    1. Does this grammar have the same language as the previous grammar? (Yes or No.) Does this grammar have the same parse trees as the previous grammar? (Yes or No.)

      Below is a parser for this grammar, written in C. The main function plays the role of P. (The parser in Java could look almost the same.)

       

       

      
      #include 
      #include 
      #include 
      char next;
      void E(void);
      void T(void);
      void S(void);
      void F(void);
      void error(int);
      void scan(void);
      
      void main(void)
      {
         scan();
         E();
         if (next != '#') error(1);
         else printf("Success\n");
      }
      
      void E(void)
      {
         T();
         while (next == '+') {
            scan();
            T();
         }
      }
      
      void T(void)
      {
         F();
         while (next == '*') {
            scan();
            F();
         }
      }
      
            
      
      void F(void)
      {
         if (isdigit(next)) {
            scan();
         }
         else if (next == '(') {
            scan();
            E();
            if (next == ')') scan();
            else error(2);
         }
         else {
            error(3);
         }
      }
      void scan(void)
      {
         while (isspace(next = getchar()))
            ;
      }
      void error(int n)
      {
         printf("\n*** ERROR: %i\n", n);
         exit(1);
      }
      
      

    2. Modify and add to the code above so that it will work as an evaluator of integer expressions. (In a recitation, we studied an evaluator using doubles, but this evaluator is to use ints. You can write on the exam, or copy material onto a separate sheet. This code is C, but the parts needing changes are essentially the same as Java, so just don't worry about it.) If the executable is named evala then the following shows what results of runs should be:

        pandora% evala
        (4 + 5)#
        Value: 9
        pandora% evala
        1+3+5+7+9#
        Value: 25
        pandora% evala
        2*2 + 3*3 + 5*5 + 7*7 + (2+9)*(3+8) + 
           (6+7)*(5+8) + (5+6+6)*(4+5+8)#
        Value: 666
        

     

  3. The Lisp Language:

    1. In each case say what the Lisp interpreter would produce when it evaluates the given input (there are no errors):
      1. 17
      2. (+ (* 2 3) (* 8 4))
      3. (car '((a b c) d (e)))
      4. (cdr '((a b c) d (e)))
      5. (car (cdr '(a b c)))
      6. (cons '(a) '(b c))
      7. (append '(a) '(b c))
      8. (list '(a) '(b c))
      9. (cond ((= 4 (* 2 2)) 47)
               (t 54))
      10. ()

    2. Explain why each of the following inputs is in error when evaluated by Lisp. Explain in each case exactly what the error is (not what the error message, if any, is).

        (car (cdr '(a b c))

        (car (car '(a b c)))

        (car (cdr (a b c)))

    3. Write a recursive Lisp function dropatoms that will take a list as input and will delete all the atoms at the top level, keeping all lists at the top level. For example,
        > (dropatoms '((a) b c))
        ((A))
        > (dropatoms '(a b c))
        NIL
        > (dropatoms '(a (b) c))
        ((B))
        > (dropatoms '(a b (c)))
        ((C))
        > (dropatoms '(4 a c (a b) d e (g h)))
        ((A B) (G H))
        > (dropatoms '(6 (a (b) c) (((b))) a b))
        ((A (B) C) (((B))))
                 

      [Hint: Use the predicate atom to check if an S-expression is an atom. Think recursively -- handle the car and then recursively handle the cdr.]

     

     

     

     

  4. The Postscript Language:

    Consider the following Postscript programs:

    1. The two Postscript programs above produce the same output. Use a sketch to show exactly what will be printed.

    2. Insert statements at the % above to change the coordinate system so that the output will be at the approximate middle of the page, and will appear vertically (bottom of letters at the right and top of the letters at the left). [Hint: In Postscript, a positive angle goes counter-clockwise.]

    3. Change the utsa function so that the parameters to moveto are passed on the stack. Use this to print the UTSA horizontally (not rotated as in 2), so that the bottom of the UTSA is 350 points from the bottom of the page, and so that the UTSA is exactly centered horizontally on the page. [Hint: Use the Postscript function stringwidth which pushes on the stack the width and height moved while printing the string. You will want to just pop the height, which is zero here anyway.]

    4. Write Postscript code that will fill the page with a 0.5 graylevel by tracing a path around the border of the page and then filling it.

    5. Add to the part 4 code and use the method in part 3 to place a white UTSA with a black outlined border centered exactly horizontally on the page (keeping the gray background). [Hint: (UTSA) false charpath creates a path outlining the characters. Also 0 is the code for black.]

     

     

  5. Topics from C, C++, and Java:

    Generic constructs in C, C++, and Java:

    1. Consider C++ templates. What are its advantage(s) compared with other generic methods (in C and Java)? What are disadvantage(s) of template?

    2. From an object-oriented point of view, what is wrong with using an arbitrary Object in Java and using instanceof to decide what type of object it is?

  6. The Prolog Language:

      Consider Prolog facts and rules in the attached sheet: an example from class about CS courses. [Recall that any name starting with a capital letter is a variable.]

    1. What happens when the following is entered (after loading in the example facts and rules), followed by typing ";" over and over?
        ?- spring_2003_courses(X, Y, wagner).
        

      Suppose the following additional rule is included in the source:

          course_and_office(Course, Fac, Office) :- 
               spring_2003_courses(Course, _ , Fac),
               faculty(Fac, _, Office).
        
    2. Give the meaning of the symbol :- in this rule. Give the meaning of the main comma between the two parts (not the commas inside parentheses).

    3. What happens when the following is entered, followed by typing ";" over and over.
        ?- course_and_office(X, Y, Z).
        
      What new facts does the additional rule provide? What is the term from relational database theory for this type of operation?

    4. Consider the first set of facts about courses, starting with
        
        spring_2003_courses(cs3233, 1230-tr,  tian).
        
      Give at least three reasons why one would not want to include the office number of the faculty member as part of this fact, producing facts that would look like:
        
        spring_2003_courses(cs3233, 1230-tr,  tian, 'SB 3.02.00').
        
    5. Write a rule for facts named tr_at_1230 that would provide the faculty name, and office for faculty teaching a course at 12:30 pm on TR.