Some sample exam 2 questions:
1. BRIEFLY define the following terms and give an example of how each term is used: (4 each, no more than six on the midterm)
• Shift in LR Parser
• Reduce in LR Parser
• Shift-Reduce Conflict
• Reduce-Reduce Conflict
• Precedence Declaration
• LR(k) Parsing
• SLR Parsing
• Canonical LR(1) Table
• LR(0) Items
• LALR Parsing
• Closure of a Set of LR(0) Items
• Syntax-directed translation
• Abstract syntax tree
• Static scoping
• Dynamic scoping
• Declaration of a name
• Use of a name
• Undeclared name
• Multiply declared name
• Symbol table
• Parameter passing
• Call by value
• Call by reference
• Call by value-result
• Base/immutable type
• Type constructor
• Type coercion
• Type polymorphism
• Name equivalence for types
• Structural equivalence for types
2. Describe the relationship between a production and an item in an LR(0) grammar. How does this relate to the notion of the stack in an LR(0) grammar? Give an algorithm for constructing the closure of a set of items LR(0) with respect to a particular grammar. (10)
3. For the following grammar, construct the set of LR(0) states to recognize viable prefixes of this language. Then fill out an SLR parse table for this grammar and indicate whether the grammar is ambiguous. (15)
S -> A \$
A -> -- A B | ++ A B | id B
B -> -- B | ++ B | .
4. What is the difference between SLR and LR(1) parsing? What changes when constructing an LR table versus an SLR table? How does an LALR parser differ from SLR and LR(1) parsers? (10)
5. In bison, how do you (1) resolve conflicts related to operator precedence, (2) resolve conflicts due to operator associativity, and (3) attach a syntax-directed translation action to a production? (10)
6. Below is a grammar for understanding simple arithmetic expressions:
E -> E * E
-> E + E
-> ( E )
-> int Assuming that precedence and associativity have been handled, what translation actions would you add to the grammar to get it to print out the input expression in a postfix notation (e.g., (3 + 5) * 4 would print out as 3 5 + 4 *). Now add actions to print out the expression in a prefix notation (* + 3 5 4). (15)
7. Discuss how the semantic stack works for an LL parser and how an AST can emerge from that stack. Show the actions you would attach to the grammar in the previous question to build up an AST. Once you have added the actions, show any further adjustments you would need to make to the grammar to make it LL (1). (Assume * has higher precedence than + and both are left associative.) (15)
8. Describe static and dynamic scoping and how they differ. Give an example of a program that has different output assuming static versus dynamic scoping. (10)
9. Most programming languages have scoping rules with respect to variables. Why? Give an example of a situation that requires scoping rules to resolve (and where scoping is useful). Would it be possible to avoid having scoping rules (and if so, what are the advantages and disadvantages of your approach)? (15)
10. Define parameter passing and the parameter passing methods call by value and call by reference. Give an example of a program that works differently under the two different mechanisms. (15)
11. What are the two main jobs of a symbol table? What types of errors does it catch in performing these jobs? (10)
12. What are the main operations for a symbol table? Discuss the data structures associated with a symbol table maintained as a list of hashtables and how the operations of a symbol table are implemented in that case. Give an example of what your symbol table would look like for a sample program. (15)
13. Answer the previous question but where the symbol table is maintained as a hash table of lists. (15)
14. What is a type system? Who defines it and how is it used in creating a compiler? (10)
15. Give three examples of tasks that are typically performed in a type checker. What types of errors are recognized in a type checker? (10)
16. What are three of the constructors available for constructing types? What operations are typically associated with these constructors and how are they used in type checking? (10)
17. What is the difference between static and dynamic type checking? What is the difference between name and structural equivalence? What is a cyclic type? Give examples to demonstrate your answers. (15)
18. Show an outline of how a piece of code might work to type check a divide operator that can apply to two operands of type int or float but does not apply to values of type bool. How would your code change if coercion from bools to ints and ints to floats is allowed (but not bools to floats)? (15)
19. How would you type check a for statement from C++? What symbol table issues are introduced by a for statement? (15)