[UMN logo]

CSCI 5106: Programming Languages
Spring 2006, University of Minnesota
Assignment 2
Comments on Grading


General Remarks

This assignment was graded out of 20 + 4 points, the additional points being for the extra credit portion. Problem 1 carried 4 points divided as 3 and 1 between the two parts, Problems 2 and 3 carried 2.5 points each, Problem 4 carried 2+3+2 points and Problem 5 carried 2+2 points. In the extra credit problem, the points were divided evenly between the two parts.

The average for this assignment was 15.84, the median was 17.00, the standard deviation was 4.12 and the highest score was 19.50.


Problem 1

This problem required you to show that you had understood the discussion we had in class concerning the construction of the expression grammar in Figure 2.6 of the book. The first part had you simply using this intuition in a slightly different context.

For the second part of this problem, some of you introduced a new category for expressions involving unary minus, which allows this operator to appear freely in expressions. However, the problem statement indicates that expressions like 2 + - 3 are to be treated as illegal. The extrapolation of this description to other situations was also discussed in some detail on the HyperNews page for this homework. Bearing all this in mind, suppose that the language in question had only the binary + and -, to be interpreted as left associative operators. Then the grammar would have been

   <E> ::= <E> '+' <F> | <E> '-' <F> | <F>
   <F> ::= num | name | '(' <E> ')'
Now if the language were to be extended to include the unary minus in the way described, the following grammar might be used to describe it:
   <E> ::= <E'> | '-' <F>
   <E'> ::= <E'> '+' <F> | <E'> '-' <F> | <F>
   <F> ::= num | name | '(' <E> ')'
In the grammars presented here, <E> is assumed to be the start symbol, in keeping with the convention described in the book.


Problems 2 and 3

These problems mainly required you to show that you understood what parse trees are and what abstract syntax is and what the difference between these two notions is. We have discussed this matter at some length in class, so we won't rehash this here. If you still have questions, make sure to ask the instructor or the TA or post something to HyperNews.


Problem 4

The point brought out by this problem is actually something that a lot of people find confusing about the syntax of C initially. That many of you were able to pinpoint the ambiguity accurately indicates that you understand the issue well. Anyway, the issue is essentially one of deciding between the scopes of * (that identifies pointer types) on the one hand and '[' number ']' and '(' Type ')' on the other. In particular, consider the expression int * name'[' number ']'. This has two different parses depending on how you resolve the scoping issue.

The solution to the problem, once you have decided that * has lower precedence follows a pattern that we have discussed in detail in class, that you should have encountered in Problem 3 and that you should know how to implement by now. If this is still not clear to you, talk to one of your classmates, post a query on HyperNews or ask the instructor or TA for help.

If * is made a postfix operator, then every operator becomes a postfix one and the scope of each operator unambiguous: it extends leftward from the operator all the way to the end of the Declarator. Actually, postfix notation is unambiguous even when binary and other arity operators are present, as you should know from reading the book.

Almost everyone figured out that it is necessary to introduce a new terminal symbol, so that there is one category for pointer-type declarators, and one for the other types. However, many people provided productions which allowed these two different declarators to interact freely, yielding a grammar with the same kind of ambiguities as the original. The point of introducing the new non-terminal is to force a hierarchy on the different kinds of type declarations so as to enforce precedence restrictions as in the expression grammar we saw in class. Thus, your grammar should have a production of the form

Declarator ::= * Declarator | OtherTypes
where OtherTypes covers all the type expressions other than the ones that have * as the top level type constructor, unless it is enclosed within parentheses.


Problem 5

The first part of this problem required you to describe the abstract syntax for Pascal statements. We had done something like this in the very first lecture on syntax descriptions and so the problem was in a sense checking if you had understood this. For most statement forms, the abstract syntax should have been obvious. For example consider the if-then-else. This has three meaningful subcomponents: the condition, the then part and the else part. Assuming that these have the abstract syntax representations C, T and E, and choosing the name cond to represent the relationship between these that is implied in the if-then-else statement, we could use the abstract syntax
                     cond
                   /  |  \ 
                  /   |   \
                 C    T    E
for such a statement. We can also write this in linear form as cond(C,T,E) as we have observed in class.

Some people had difficulty deciding what to do with the last kind of statement described by the grammar. This statement is essentially combining a sequence of statements into one single statement. We can use the name seq to denote the operation of combining two statements into one that is intended when we write one statement after another in a programming language. Using this combining operation repeatedly, we get the abstract syntax for any arbitrary sequence. For example, suppose we have the following concrete syntax:

       begin S1 ; S2 ; S3 end
Let the abstract syntax for S1 be A1, for S2 be A2 and for S3 be A3. Then the abstract syntax for the shown concrete syntax might be
seq(A1, seq(A2, A3)).

The second part of the problem required you to describe a way to represent the abstract syntax internally in a programming language. If you chose Scheme to do this problem, you could use the usual list representation where something indicating the operator is the first element of the list and the representations of the subcomponents are the remaining elements. Thus, assuming that C1, T1 and E1 are such representations of C, T and E respectively, the representation of cond(C,T,E) might be the list

      '("cond"  C1  T1  E1)
or even simply
      '(cond  C1  T1  E1)

If you chose Java to do this problem, then you would have one abstract class called Stmt and other (concrete) classes corresponding to the various statement forms that inherit from Stmt For example, corresponding to conditional forms, we would have the following class definition.

    public class Cond extends Stmt {
        public Expr  test;
        public Stmt  then;
        Public Stmt  else;
    }


Problem 6

The class definition that we wrote down for Problem 5 was very minimal. We would likely want constructors to create objects of such classes from given values for the subcomponents. The first part of this problem required you to provide such constructors. If you did this in Scheme, the task was simpler. You just had to write down a one line function that returned the right kind of list.

The second part of the problem required you to first understand attribute grammars that build on context free grammars and then to see how these could be used to translate from parses or parse trees to abstract syntax. The relevant attribute for each category in your grammar in this case was, obviously, the abstract syntax of the expression recognized. This attribute would have to be constructed from the attributes for relevant parts of the righthand side of each rule using the constructors you defined in the first part of this question. Incidentally, it is precisely this kind of structure that gets used in the presentation to Yacc or Bison of the grammar of some language that you want to build a parser for. These programs then automatically generate a parser that returns the abstract syntax for expressions it parses. You will see more of this kind of stuff if you take a compilers course after this one.


Last updated on Feb 20, 2006 by gopalan@cs.umn.edu and xqi@cs.umn.edu