Homework
COP-3402, Spring 2024
1. HW1
Please respond with "yes" (in webcourses) once you've completed your VirtualBox and vagrant setup.
2. HW2
Using command-line unix tools only, what set of commands could you use to find which files have the name "message" in a directory or its subdirectories? For example, your file system looks like this:
mydir/ file1.txt subdir/ message.txt
What command(s) could you use to print the contents of the file having the name "message.txt"?
3. HW3
In our toy compiler, how are numbers represented in the input language?
How are numbers represented in the output language?
What about operators, such as addition, how are they represented in the input and output language and how do they differ?
4. HW4
What does a parser generator, such as bison, do?
What is the input of the parser generator?
What is its output?
5. HW5
- What distinguishes parse trees (aka concrete syntax trees) and abstract syntax trees?
- In the first SimpleC project, what will we use semantic actions in the parser for?
6. HW6
- Convert regular expression (ab|ba)*c to a nondeterministic finite automaton (NFA). Recall that concatenation has higher precendence than alternation.
- Convert the NFA created above into a deterministic finite automaton (DFA).
6.1. Notes
Automata may be drawn either as state diagrams or transition tables.
Use only the three regular expression operators for this homework. plus any parentheses used to make order of operations explicit.
- alternation, e.g.,
a|(bc)
- concatenation, e.g.,
ab
- Kleene closure, e.g.,
(ab)*
The order of operations, from highest to lowest, is Kleene closure, concatenation, and alternation.
7. HW7
- Write a derivation of the string "aacdbb" using the following grammar. Recall that the first production's nonterminal is the starting symbol, in this case \(A\).
- \(T \to a T b\)
- \(T \to V\)
- \(V \to c V\)
- \(V \to d\)
Use the following parse table for the above grammar to show each step of the LR parsing algorithm for the string "aacdbb$" where $ is the end of input sentinel. Start on state 0. The numbers after "reduce" are the production numbers from the grammar above. Show the sequence of actions and gotos and optionally show the state stack and/or the derivation or syntax tree.
State a b c d $ T V 0 shift 2 shift 3 shift 6 goto 1 goto 4 1 accept 2 shift 2 shift 3 shift 6 goto 7 goto 4 3 shift 3 shift 6 goto 5 4 reduce 2 reduce 2 reduce 2 reduce 2 reduce 2 5 reduce 3 reduce 3 reduce 3 reduce 3 reduce 3 6 reduce 4 reduce 4 reduce 4 reduce 4 reduce 4 7 shift 8 8 reduce 1 reduce 1 reduce 1 reduce 1 reduce 1 State a b c d $ T V The beginning of this would be
state lookahead action stack 0 (a)acdbb$ (0,a) = shift 2 0 a 2 2 a(a)cdbb$ (2,a) = shift 2 0 a 2 a 2 2 aa(c)dbb$ (2,c) = shift 3 0 a 2 a 2 c 3 3 aac(d)bb$ (3,d) = shift 6 0 a 2 a 2 c 3 d 6 6 aacd(b)b$ (6,b) = reduce 4 \(V \to d\) 0 a 2 a 2 c 3 V 3 (3,V) = goto 5 0 a 2 a 2 c 3 V 5
7.1. Notes
Context-free grammars are notated with the following conventions in this homework:
- Terminals are a lowercase letter or an \(\epsilon\) for empty string
- Nonterminals are an uppercase letter
- Productions use an arrow, e.g., \(A \to b\)
- Starting symbol, by convention the nonterminal of the first production
An LR parsing table lists one state per row. The columns are the terminals in the language (the action table) and the nonterminals of the language (the goto table). Each entry in the action table is shifts a terminal, reduces a nonterminal, accepts the input. or results in an error (empty cell). The goto table takes a nonterminal a transition to a state or is empty, meaning an error.
8. HW8
Draw the AST for the following program. Then record the symbol tables in the symbol tables for each scope and annotate the tree with the types of each expression and operator.
int x; main { int x; int y; y = 2; x = y; return 0; }
9. HW9
Show what the call stack would look like when calling factorial(2). In particular show the stacks frames for both factorial(2) and factorial(1), including parameters, local variables, return address (can just use the name of the function), and the pointer to the caller's stack frame. It's sufficient to show the call stack after the second call to factorial, i.e., containing the stack frames work factorial(2) and factorial(1).
factorial(x) { if (x <= 1) { return 1; } else { int new_x = x - 1; return x * factorial(new_x); } }
10. HW10
How do assigning to a variable and assigning to a pointer differ in assembly in the implementaiton of our SimpleC compiler?
For instance, local variables are stored in an offset from the stack frame, so their values are loaded into memory. What happens with an assignment to a pointer dereference? Show an assembly code example of a pointer dereference.
11. HW11
- Assuming that
y
has an offset of -8 from%rbp
, what would the AT&T-syntax assembly operation look like fory = 3
? - if
y
has an offset of -8 from%rbp
andx
has an offset of -16, what sequence of AT&T-syntax assembly instructions could be used to implementx = *y
?
12. HW12
How can we implement a less-than operator in assembly? For instance, if we want to generate code to evaluate x < y
, and we know that x is in register %rax
, y is in %rbx
, and we want the result to also be stored in %rax
, what sequence of assembly instructions could we use?