CSC376 · Exam intelligence
Compiler Design and Construction important questions
From 6 past TU papers: which questions keep coming back, how much they carry, and what is most likely to show up next. Every question links to a model answer.
Most likely in the next examStatistical
Ranked by how often a topic is asked, its marks weight, and whether it is due after skipping the 2081.1 paper. No guarantees; study the whole syllabus.
1asked 10xavg 7 marks · LR parsingAnswerHideCreate the LR(1) parsing table for following grammar.S→AAS \rightarrow AAS→AAA→0AA \rightarrow 0AA→0AA→εA \rightarrow \varepsilonA→ε_[10]_
Create the LR(1) parsing table for following grammar.S→AAS \rightarrow AAS→AAA→0AA \rightarrow 0AA→0AA→εA \rightarrow \varepsilonA→ε_[10]_
LR(1) Parsing Table for the Grammar
Step 1: EXTRACT - Given Data
Grammar: $$S \to AA$$ $$A \to 0A$$ $$A \to \varepsilon$$
- Terminals: $${0, $}$$
- Non-terminals: ${S, A}$
- Marks: 10
Step 2: SOLVE
Augmented Grammar
$$ \begin{aligned} (0)\ & S' \to S\ (1)\ & S \to AA\ (2)\ & A \to 0A\ (3)\ & A \to \varepsilon \end{aligned} $$
Canonical LR(1) Item Sets
Closure rule: For $[B \to \alpha \bullet C\beta, a]$, add $[C \to \bullet \gamma, b]$ for each $b \in \text{FIRST}(\beta a)$.
$$I_0 = \text{Closure}([S' \to \bullet S, $])$$
- $$[S' \to \bullet S, $]$$
- $$[S \to \bullet AA, $]$$ (dot before $S$, FIRST($$$ $$) = $$$ $$)
- Dot before first $A$; lookahead $=$ FIRST$$(A$) = {0, $}$$ (since $A \Rightarrow \varepsilon$):
- $$[A \to \bullet 0A, 0/$]$$
- $$[A \to \bullet, 0/$]$$
Transitions: $S \to I_1$, $A \to I_2$, $0 \to I_3$
$I_1 = \text{goto}(I_0, S)$
- $$[S' \to S \bullet, $]$$ (Accept)
$I_2 = \text{goto}(I_0, A)$
- $$[S \to A \bullet A, $]$$
- Dot before second $A$; lookahead $=$ FIRST($$$ $$) $$= {$}$$:
- $$[A \to \bullet 0A, $]$$
- $$[A \to \bullet, $]$$
Transitions: $A \to I_4$, $0 \to I_5$
$I_3 = \text{goto}(I_0, 0)$
- $$[A \to 0 \bullet A, 0/$]$$
- Dot before $A$; lookahead $$= {0, $}$$:
- $$[A \to \bullet 0A, 0/$]$$
- $$[A \to \bullet, 0/$]$$
Transitions: $A \to I_6$, $0 \to I_3$ (self-loop, same item set)
$I_4 = \text{goto}(I_2, A)$
- $$[S \to AA \bullet, $]$$ (reduce by rule 1)
$I_5 = \text{goto}(I_2, 0)$
- $$[A \to 0 \bullet A, $]$$
- $$[A \to \bullet 0A, $]$$
- $$[A \to \bullet, $]$$
Transitions: $A \to I_7$, $0 \to I_5$ (self-loop)
$I_6 = \text{goto}(I_3, A)$
- $$[A \to 0A \bullet, 0/$]$$ (reduce by rule 2)
$I_7 = \text{goto}(I_5, A)$
- $$[A \to 0A \bullet, $]$$ (reduce by rule 2)
Reduce actions
- $I_0$: $$[A \to \bullet, 0/$]$$ → reduce by rule 3 on $0$ and $$$ $$
- $I_2$: $$[A \to \bullet, $]$$ → reduce by rule 3 on $$$ $$
- $I_3$: $$[A \to \bullet, 0/$]$$ → reduce by rule 3 on $0$ and $$$ $$
- $I_4$: reduce by rule 1 on $$$ $$
- $I_5$: $$[A \to \bullet, $]$$ → reduce by rule 3 on $$$ $$
- $I_6$: reduce by rule 2 on $0$ and $$$ $$
- $I_7$: reduce by rule 2 on $$$ $$
Notation: $sn$ = shift and go to state $n$; $rn$ = reduce by production $n$; $acc$ = accept; blank = error.
LR(1) Parsing Table
| State | Action 0 | Action $ | Goto S | Goto A |
|---|---|---|---|---|
| 0 | s3 / r3 | r3 | 1 | 2 |
| 1 | acc | |||
| 2 | s5 | r3 | 4 | |
| 3 | s3 / r3 | r3 | 6 | |
| 4 | r1 | |||
| 5 | s5 | r3 | 7 | |
| 6 | r2 | r2 | ||
| 7 | r2 |
Note on conflicts (States 0 and 3)
In states $I_0$ and $I_3$ the item $[A \to \bullet, 0]$ calls for reduce by rule 3 on input $0$, while the items $[A \to \bullet 0A, \dots]$ call for shift on $0$. This is a shift/reduce conflict on 0.
Resolving in favor of shift (standard convention, and required for this grammar to accept strings like $00$), the entries $s3$ / $s5$ are used on input $0$. With this resolution the parser works correctly. Strictly, the grammar is not LR(1) because of this genuine shift/reduce conflict in states 0 and 3, so I have shown both actions in those cells.
Final Result
The canonical collection has 8 states ($I_0$ through $I_7$), and the completed LR(1) table is as shown above, with shift/reduce conflicts on input 0 in states 0 and 3 (resolved by shift).
2asked 6xavg 6 marks · Top-down parsingAnswerHideCompute the FIRST and FOLLOW of all the non-terminals in following grammar. S→ABS \rightarrow ABS→ABA→0A′∣1A′∣εA \rightarrow 0A' \mid 1A' \mid \varepsilonA→0A′∣1A′∣εA′→SSA′∣εA' \rightarrow SSA' \mid \varepsilonA′→SSA′∣εB→AS∣1B \rightarrow AS \mid 1B→AS∣1_[5]_
Compute the FIRST and FOLLOW of all the non-terminals in following grammar. S→ABS \rightarrow ABS→ABA→0A′∣1A′∣εA \rightarrow 0A' \mid 1A' \mid \varepsilonA→0A′∣1A′∣εA′→SSA′∣εA' \rightarrow SSA' \mid \varepsilonA′→SSA′∣εB→AS∣1B \rightarrow AS \mid 1B→AS∣1_[5]_
FIRST and FOLLOW Computation
Given data (Grammar)
$$S \rightarrow AB$$ $$A \rightarrow 0A' \mid 1A' \mid \varepsilon$$ $$A' \rightarrow SSA' \mid \varepsilon$$ $$B \rightarrow AS \mid 1$$
Non-terminals: $S, A, A', B$
Terminals: $0, 1$
Start symbol: $S$
Step 1: FIRST Sets
FIRST(A)
From $A \rightarrow 0A' \mid 1A' \mid \varepsilon$: $$FIRST(A) = {0, 1, \varepsilon}$$
FIRST(B)
From $B \rightarrow AS \mid 1$:
- $B \rightarrow 1$ gives $1$
- $B \rightarrow AS$: add $FIRST(A)\setminus{\varepsilon} = {0,1}$; since $\varepsilon \in FIRST(A)$, also add $FIRST(S)$.
Since $S$ cannot derive $\varepsilon$ (needs both $A$ and $B$ to vanish, but $B$ cannot), $FIRST(S)$ adds only ${0,1}$: $$FIRST(B) = {0, 1}$$
FIRST(S)
From $S \rightarrow AB$:
- Add $FIRST(A)\setminus{\varepsilon} = {0,1}$
- Since $\varepsilon \in FIRST(A)$, add $FIRST(B) = {0,1}$
- $\varepsilon$ not added (B cannot derive $\varepsilon$) $$FIRST(S) = {0, 1}$$
FIRST(A')
From $A' \rightarrow SSA' \mid \varepsilon$:
- $A' \rightarrow \varepsilon$ gives $\varepsilon$
- $A' \rightarrow SSA'$: add $FIRST(S) = {0,1}$ $$FIRST(A') = {0, 1, \varepsilon}$$
Summary
| Non-terminal | FIRST |
|---|---|
| $S$ | ${0, 1}$ |
| $A$ | ${0, 1, \varepsilon}$ |
| $A'$ | ${0, 1, \varepsilon}$ |
| $B$ | ${0, 1}$ |
Step 2: FOLLOW Sets
Rules: Start gets $$$ $$; for $X\to \alpha Y\beta$ add $FIRST(\beta)\setminus{\varepsilon}$ to $FOLLOW(Y)$; if $\varepsilon\in FIRST(\beta)$ or $\beta$ empty, add $FOLLOW(X)$ to $FOLLOW(Y)$.
FOLLOW(S)
- Start symbol: add $$$ $$
- $A' \rightarrow SSA'$:
- First $S$ followed by $SA'$: add $FIRST(S)\setminus{\varepsilon}={0,1}$
- Second $S$ followed by $A'$: add $FIRST(A')\setminus{\varepsilon}={0,1}$; since $\varepsilon\in FIRST(A')$, add $FOLLOW(A')$
- $B \rightarrow AS$: $S$ at end, add $FOLLOW(B)$
$$FOLLOW(S) = {$, 0, 1} \cup FOLLOW(A') \cup FOLLOW(B)$$
FOLLOW(A)
- $S \rightarrow AB$: $A$ followed by $B$, add $FIRST(B)\setminus{\varepsilon}={0,1}$; $\varepsilon\notin FIRST(B)$, no more.
- $B \rightarrow AS$: $A$ followed by $S$, add $FIRST(S)\setminus{\varepsilon}={0,1}$; $\varepsilon\notin FIRST(S)$, no more. $$FOLLOW(A) = {0, 1}$$
FOLLOW(A')
- $A \rightarrow 0A' \mid 1A'$: $A'$ at end, add $FOLLOW(A)={0,1}$
- $A' \rightarrow SSA'$: $A'$ at end, add $FOLLOW(A')$ (itself, no new info) $$FOLLOW(A') = {0, 1}$$
FOLLOW(B)
- $S \rightarrow AB$: $B$ at end, add $FOLLOW(S)$ $$FOLLOW(B) = FOLLOW(S)$$
Resolve FOLLOW(S) and FOLLOW(B)
$$FOLLOW(S) = {$, 0, 1} \cup FOLLOW(A') \cup FOLLOW(B)$$ $$= {$, 0, 1} \cup {0,1} \cup FOLLOW(B)$$
Since $FOLLOW(B) = FOLLOW(S)$, this is self-referential and adds nothing new: $$FOLLOW(S) = {$, 0, 1}$$ $$FOLLOW(B) = {$, 0, 1}$$
Final Answer
| Non-terminal | FIRST | FOLLOW |
|---|---|---|
| $S$ | ${0, 1}$ | $${$, 0, 1}$$ |
| $A$ | ${0, 1, \varepsilon}$ | ${0, 1}$ |
| $A'$ | ${0, 1, \varepsilon}$ | ${0, 1}$ |
| $B$ | ${0, 1}$ | $${$, 0, 1}$$ |
3asked 4xavg 6 marks · due (skipped 2081.1) · Code OptimizationAnswerHideWhy code optimization is needed? Describe any two techniques for loop optimization. [5]
Why code optimization is needed? Describe any two techniques for loop optimization. [5]
Code optimization is the process of transforming a program to make it more efficient without changing its output or meaning. It is needed because: - Reduces space and increases speed: Optimization reduces the memory consumed by the progr...
4asked 4xavg 5 marks · due (skipped 2081.1) · Run-time storage managementAnswerHideHow do you represent recursion in an activation tree? Generate the three-address code for the following instruction: [5]
How do you represent recursion in an activation tree? Generate the three-address code for the following instruction: [5]
STEP 1 - EXTRACT: Given Data
Part 1: Conceptual question about representing recursion in an activation tree. No numeric data.
Part 2: "Generate the three-address code for the following instruction."
Critical issue: The actual instruction/expression to be translated into three-address code is NOT provided in the question text. The statement ends with "the following instruction:" but no instruction, expression, or code fragment follows.
Therefore, the specific expression required for Part 2 is missing or unreadable, and three-address code cannot be generated for an expression that was not given. An expression such as a = b * c + b * d can only be treated as an illustration, not as the question's data.
I will fully answer Part 1 (conceptual, no data needed) and, for Part 2, explain the method and demonstrate it on a clearly-labelled illustrative example (marked as assumed, since the actual instruction is missing).
STEP 2 - SOLVE
Part 1: Representing Recursion in an Activation Tree
An activation tree shows the flow of control among procedure activations during a program's execution.
Properties:
- Each node = one activation (one call) of a procedure.
- The root = the activation of
main. - Node for
Pis the parent of node forQif control flows fromPintoQ(i.e.,PcallsQ). - Left-to-right ordering reflects the temporal order in which activations begin.
Recursion representation: When a procedure calls itself, the activation tree contains several distinct nodes bearing the same procedure name, arranged as a chain (or subtree) descending from the calling node. Each recursive call is a separate activation with its own activation record (own parameters, locals, return address) pushed onto the control stack.
Example: fact(n) computing $n!$
$$ \text{fact}(4) \rightarrow \text{fact}(3) \rightarrow \text{fact}(2) \rightarrow \text{fact}(1) $$
fact(4)
|
fact(3)
|
fact(2)
|
fact(1)
- Each node is a distinct activation even though the procedure name repeats.
- At any moment, the runtime stack holds exactly the activation records lying on the path from the root to the currently active node.
- On return,
fact(1)'s record is popped, control resumes infact(2), and so on.
Thus recursion = repeated nodes of the same procedure along a root-to-leaf path, each with its own activation record on the stack.
Part 2: Three-Address Code Generation
Missing data: The question says "Generate the three-address code for the following instruction:" but no instruction/expression was supplied in the given text. I cannot produce the intended answer without it. Below I state the method and demonstrate it on an assumed illustrative expression (clearly marked as not from the question).
Method (syntax-directed translation):
- $E \rightarrow id$:
E.place = id - $E \rightarrow E_1 * E_2$: emit
t = E1.place * E2.place - $E \rightarrow E_1 + E_2$: emit
t = E1.place + E2.place - $S \rightarrow id = E$: emit
id = E.place
Assumed example (illustrative only): $a = b * c + b * d$
$$ \begin{aligned} t_1 &= b * c \ t_2 &= b * d \ t_3 &= t_1 + t_2 \ a &= t_3 \end{aligned} $$
Quadruple form $(op, arg_1, arg_2, result)$:
| Op | Arg1 | Arg2 | Result |
|---|---|---|---|
* | b | c | t1 |
* | b | d | t2 |
+ | t1 | t2 | t3 |
= | t3 | - | a |
Caveat: If the actual exam instruction differs (e.g., x = (a + b) * (c + d) or a control statement), the code must be regenerated from that expression. The above b*c+b*d result is not verifiable because the source instruction was absent from the given question.
5asked 3xavg 6 marks · due (skipped 2081.1) · Annotated Parse TreeAnswerHideWhat is annotated parse tree? Define S-attributed grammar with an example. [5]
What is annotated parse tree? Define S-attributed grammar with an example. [5]
--- An annotated parse tree is a parse tree in which each node is labeled with its grammar symbol along with the values of its associated attributes. In Syntax-Directed Translation (SDT), semantic rules are used to compute attribute valu...
Most repeated questions
Topics asked at least twice, most-asked first.
asked 10xavg 7 marks · 2081.1, 2081, 2080, 2078, 2076...AnswerHideCreate the LR(1) parsing table for following grammar.S→AAS \rightarrow AAS→AAA→0AA \rightarrow 0AA→0AA→εA \rightarrow \varepsilonA→ε_[10]_
Create the LR(1) parsing table for following grammar.S→AAS \rightarrow AAS→AAA→0AA \rightarrow 0AA→0AA→εA \rightarrow \varepsilonA→ε_[10]_
LR(1) Parsing Table for the Grammar
Step 1: EXTRACT - Given Data
Grammar: $$S \to AA$$ $$A \to 0A$$ $$A \to \varepsilon$$
- Terminals: $${0, $}$$
- Non-terminals: ${S, A}$
- Marks: 10
Step 2: SOLVE
Augmented Grammar
$$ \begin{aligned} (0)\ & S' \to S\ (1)\ & S \to AA\ (2)\ & A \to 0A\ (3)\ & A \to \varepsilon \end{aligned} $$
Canonical LR(1) Item Sets
Closure rule: For $[B \to \alpha \bullet C\beta, a]$, add $[C \to \bullet \gamma, b]$ for each $b \in \text{FIRST}(\beta a)$.
$$I_0 = \text{Closure}([S' \to \bullet S, $])$$
- $$[S' \to \bullet S, $]$$
- $$[S \to \bullet AA, $]$$ (dot before $S$, FIRST($$$ $$) = $$$ $$)
- Dot before first $A$; lookahead $=$ FIRST$$(A$) = {0, $}$$ (since $A \Rightarrow \varepsilon$):
- $$[A \to \bullet 0A, 0/$]$$
- $$[A \to \bullet, 0/$]$$
Transitions: $S \to I_1$, $A \to I_2$, $0 \to I_3$
$I_1 = \text{goto}(I_0, S)$
- $$[S' \to S \bullet, $]$$ (Accept)
$I_2 = \text{goto}(I_0, A)$
- $$[S \to A \bullet A, $]$$
- Dot before second $A$; lookahead $=$ FIRST($$$ $$) $$= {$}$$:
- $$[A \to \bullet 0A, $]$$
- $$[A \to \bullet, $]$$
Transitions: $A \to I_4$, $0 \to I_5$
$I_3 = \text{goto}(I_0, 0)$
- $$[A \to 0 \bullet A, 0/$]$$
- Dot before $A$; lookahead $$= {0, $}$$:
- $$[A \to \bullet 0A, 0/$]$$
- $$[A \to \bullet, 0/$]$$
Transitions: $A \to I_6$, $0 \to I_3$ (self-loop, same item set)
$I_4 = \text{goto}(I_2, A)$
- $$[S \to AA \bullet, $]$$ (reduce by rule 1)
$I_5 = \text{goto}(I_2, 0)$
- $$[A \to 0 \bullet A, $]$$
- $$[A \to \bullet 0A, $]$$
- $$[A \to \bullet, $]$$
Transitions: $A \to I_7$, $0 \to I_5$ (self-loop)
$I_6 = \text{goto}(I_3, A)$
- $$[A \to 0A \bullet, 0/$]$$ (reduce by rule 2)
$I_7 = \text{goto}(I_5, A)$
- $$[A \to 0A \bullet, $]$$ (reduce by rule 2)
Reduce actions
- $I_0$: $$[A \to \bullet, 0/$]$$ → reduce by rule 3 on $0$ and $$$ $$
- $I_2$: $$[A \to \bullet, $]$$ → reduce by rule 3 on $$$ $$
- $I_3$: $$[A \to \bullet, 0/$]$$ → reduce by rule 3 on $0$ and $$$ $$
- $I_4$: reduce by rule 1 on $$$ $$
- $I_5$: $$[A \to \bullet, $]$$ → reduce by rule 3 on $$$ $$
- $I_6$: reduce by rule 2 on $0$ and $$$ $$
- $I_7$: reduce by rule 2 on $$$ $$
Notation: $sn$ = shift and go to state $n$; $rn$ = reduce by production $n$; $acc$ = accept; blank = error.
LR(1) Parsing Table
| State | Action 0 | Action $ | Goto S | Goto A |
|---|---|---|---|---|
| 0 | s3 / r3 | r3 | 1 | 2 |
| 1 | acc | |||
| 2 | s5 | r3 | 4 | |
| 3 | s3 / r3 | r3 | 6 | |
| 4 | r1 | |||
| 5 | s5 | r3 | 7 | |
| 6 | r2 | r2 | ||
| 7 | r2 |
Note on conflicts (States 0 and 3)
In states $I_0$ and $I_3$ the item $[A \to \bullet, 0]$ calls for reduce by rule 3 on input $0$, while the items $[A \to \bullet 0A, \dots]$ call for shift on $0$. This is a shift/reduce conflict on 0.
Resolving in favor of shift (standard convention, and required for this grammar to accept strings like $00$), the entries $s3$ / $s5$ are used on input $0$. With this resolution the parser works correctly. Strictly, the grammar is not LR(1) because of this genuine shift/reduce conflict in states 0 and 3, so I have shown both actions in those cells.
Final Result
The canonical collection has 8 states ($I_0$ through $I_7$), and the completed LR(1) table is as shown above, with shift/reduce conflicts on input 0 in states 0 and 3 (resolved by shift).
asked 6xavg 6 marks · 2081.1, 2081, 2080, 2075AnswerHideCompute the FIRST and FOLLOW of all the non-terminals in following grammar. S→ABS \rightarrow ABS→ABA→0A′∣1A′∣εA \rightarrow 0A' \mid 1A' \mid \varepsilonA→0A′∣1A′∣εA′→SSA′∣εA' \rightarrow SSA' \mid \varepsilonA′→SSA′∣εB→AS∣1B \rightarrow AS \mid 1B→AS∣1_[5]_
Compute the FIRST and FOLLOW of all the non-terminals in following grammar. S→ABS \rightarrow ABS→ABA→0A′∣1A′∣εA \rightarrow 0A' \mid 1A' \mid \varepsilonA→0A′∣1A′∣εA′→SSA′∣εA' \rightarrow SSA' \mid \varepsilonA′→SSA′∣εB→AS∣1B \rightarrow AS \mid 1B→AS∣1_[5]_
FIRST and FOLLOW Computation
Given data (Grammar)
$$S \rightarrow AB$$ $$A \rightarrow 0A' \mid 1A' \mid \varepsilon$$ $$A' \rightarrow SSA' \mid \varepsilon$$ $$B \rightarrow AS \mid 1$$
Non-terminals: $S, A, A', B$
Terminals: $0, 1$
Start symbol: $S$
Step 1: FIRST Sets
FIRST(A)
From $A \rightarrow 0A' \mid 1A' \mid \varepsilon$: $$FIRST(A) = {0, 1, \varepsilon}$$
FIRST(B)
From $B \rightarrow AS \mid 1$:
- $B \rightarrow 1$ gives $1$
- $B \rightarrow AS$: add $FIRST(A)\setminus{\varepsilon} = {0,1}$; since $\varepsilon \in FIRST(A)$, also add $FIRST(S)$.
Since $S$ cannot derive $\varepsilon$ (needs both $A$ and $B$ to vanish, but $B$ cannot), $FIRST(S)$ adds only ${0,1}$: $$FIRST(B) = {0, 1}$$
FIRST(S)
From $S \rightarrow AB$:
- Add $FIRST(A)\setminus{\varepsilon} = {0,1}$
- Since $\varepsilon \in FIRST(A)$, add $FIRST(B) = {0,1}$
- $\varepsilon$ not added (B cannot derive $\varepsilon$) $$FIRST(S) = {0, 1}$$
FIRST(A')
From $A' \rightarrow SSA' \mid \varepsilon$:
- $A' \rightarrow \varepsilon$ gives $\varepsilon$
- $A' \rightarrow SSA'$: add $FIRST(S) = {0,1}$ $$FIRST(A') = {0, 1, \varepsilon}$$
Summary
| Non-terminal | FIRST |
|---|---|
| $S$ | ${0, 1}$ |
| $A$ | ${0, 1, \varepsilon}$ |
| $A'$ | ${0, 1, \varepsilon}$ |
| $B$ | ${0, 1}$ |
Step 2: FOLLOW Sets
Rules: Start gets $$$ $$; for $X\to \alpha Y\beta$ add $FIRST(\beta)\setminus{\varepsilon}$ to $FOLLOW(Y)$; if $\varepsilon\in FIRST(\beta)$ or $\beta$ empty, add $FOLLOW(X)$ to $FOLLOW(Y)$.
FOLLOW(S)
- Start symbol: add $$$ $$
- $A' \rightarrow SSA'$:
- First $S$ followed by $SA'$: add $FIRST(S)\setminus{\varepsilon}={0,1}$
- Second $S$ followed by $A'$: add $FIRST(A')\setminus{\varepsilon}={0,1}$; since $\varepsilon\in FIRST(A')$, add $FOLLOW(A')$
- $B \rightarrow AS$: $S$ at end, add $FOLLOW(B)$
$$FOLLOW(S) = {$, 0, 1} \cup FOLLOW(A') \cup FOLLOW(B)$$
FOLLOW(A)
- $S \rightarrow AB$: $A$ followed by $B$, add $FIRST(B)\setminus{\varepsilon}={0,1}$; $\varepsilon\notin FIRST(B)$, no more.
- $B \rightarrow AS$: $A$ followed by $S$, add $FIRST(S)\setminus{\varepsilon}={0,1}$; $\varepsilon\notin FIRST(S)$, no more. $$FOLLOW(A) = {0, 1}$$
FOLLOW(A')
- $A \rightarrow 0A' \mid 1A'$: $A'$ at end, add $FOLLOW(A)={0,1}$
- $A' \rightarrow SSA'$: $A'$ at end, add $FOLLOW(A')$ (itself, no new info) $$FOLLOW(A') = {0, 1}$$
FOLLOW(B)
- $S \rightarrow AB$: $B$ at end, add $FOLLOW(S)$ $$FOLLOW(B) = FOLLOW(S)$$
Resolve FOLLOW(S) and FOLLOW(B)
$$FOLLOW(S) = {$, 0, 1} \cup FOLLOW(A') \cup FOLLOW(B)$$ $$= {$, 0, 1} \cup {0,1} \cup FOLLOW(B)$$
Since $FOLLOW(B) = FOLLOW(S)$, this is self-referential and adds nothing new: $$FOLLOW(S) = {$, 0, 1}$$ $$FOLLOW(B) = {$, 0, 1}$$
Final Answer
| Non-terminal | FIRST | FOLLOW |
|---|---|---|
| $S$ | ${0, 1}$ | $${$, 0, 1}$$ |
| $A$ | ${0, 1, \varepsilon}$ | ${0, 1}$ |
| $A'$ | ${0, 1, \varepsilon}$ | ${0, 1}$ |
| $B$ | ${0, 1}$ | $${$, 0, 1}$$ |
asked 4xavg 6 marks · 2080, 2078, 2076, 2075AnswerHideWhy code optimization is needed? Describe any two techniques for loop optimization. [5]
Why code optimization is needed? Describe any two techniques for loop optimization. [5]
Code optimization is the process of transforming a program to make it more efficient without changing its output or meaning. It is needed because: - Reduces space and increases speed: Optimization reduces the memory consumed by the progr...
asked 4xavg 5 marks · 2081, 2080, 2078, 2075AnswerHideHow do you represent recursion in an activation tree? Generate the three-address code for the following instruction: [5]
How do you represent recursion in an activation tree? Generate the three-address code for the following instruction: [5]
STEP 1 - EXTRACT: Given Data
Part 1: Conceptual question about representing recursion in an activation tree. No numeric data.
Part 2: "Generate the three-address code for the following instruction."
Critical issue: The actual instruction/expression to be translated into three-address code is NOT provided in the question text. The statement ends with "the following instruction:" but no instruction, expression, or code fragment follows.
Therefore, the specific expression required for Part 2 is missing or unreadable, and three-address code cannot be generated for an expression that was not given. An expression such as a = b * c + b * d can only be treated as an illustration, not as the question's data.
I will fully answer Part 1 (conceptual, no data needed) and, for Part 2, explain the method and demonstrate it on a clearly-labelled illustrative example (marked as assumed, since the actual instruction is missing).
STEP 2 - SOLVE
Part 1: Representing Recursion in an Activation Tree
An activation tree shows the flow of control among procedure activations during a program's execution.
Properties:
- Each node = one activation (one call) of a procedure.
- The root = the activation of
main. - Node for
Pis the parent of node forQif control flows fromPintoQ(i.e.,PcallsQ). - Left-to-right ordering reflects the temporal order in which activations begin.
Recursion representation: When a procedure calls itself, the activation tree contains several distinct nodes bearing the same procedure name, arranged as a chain (or subtree) descending from the calling node. Each recursive call is a separate activation with its own activation record (own parameters, locals, return address) pushed onto the control stack.
Example: fact(n) computing $n!$
$$ \text{fact}(4) \rightarrow \text{fact}(3) \rightarrow \text{fact}(2) \rightarrow \text{fact}(1) $$
fact(4)
|
fact(3)
|
fact(2)
|
fact(1)
- Each node is a distinct activation even though the procedure name repeats.
- At any moment, the runtime stack holds exactly the activation records lying on the path from the root to the currently active node.
- On return,
fact(1)'s record is popped, control resumes infact(2), and so on.
Thus recursion = repeated nodes of the same procedure along a root-to-leaf path, each with its own activation record on the stack.
Part 2: Three-Address Code Generation
Missing data: The question says "Generate the three-address code for the following instruction:" but no instruction/expression was supplied in the given text. I cannot produce the intended answer without it. Below I state the method and demonstrate it on an assumed illustrative expression (clearly marked as not from the question).
Method (syntax-directed translation):
- $E \rightarrow id$:
E.place = id - $E \rightarrow E_1 * E_2$: emit
t = E1.place * E2.place - $E \rightarrow E_1 + E_2$: emit
t = E1.place + E2.place - $S \rightarrow id = E$: emit
id = E.place
Assumed example (illustrative only): $a = b * c + b * d$
$$ \begin{aligned} t_1 &= b * c \ t_2 &= b * d \ t_3 &= t_1 + t_2 \ a &= t_3 \end{aligned} $$
Quadruple form $(op, arg_1, arg_2, result)$:
| Op | Arg1 | Arg2 | Result |
|---|---|---|---|
* | b | c | t1 |
* | b | d | t2 |
+ | t1 | t2 | t3 |
= | t3 | - | a |
Caveat: If the actual exam instruction differs (e.g., x = (a + b) * (c + d) or a control statement), the code must be regenerated from that expression. The above b*c+b*d result is not verifiable because the source instruction was absent from the given question.
asked 4xavg 7 marks · 2081.1, 2078, 2076, 2075AnswerHideDefine explicit and implicit type conversion. Why do we need to check type of the system? Justify with an example. [5]
Define explicit and implicit type conversion. Why do we need to check type of the system? Justify with an example. [5]
Type Conversion and Type Checking
Explicit Type Conversion
Explicit type conversion (also called type casting) is a conversion that is manually performed by the programmer by writing a specific instruction in the source code. The programmer explicitly specifies the target type to which a value should be converted.
Example:
int a = 10;
float b = (float) a; // programmer explicitly casts int to float
Implicit Type Conversion
Implicit type conversion (also called type coercion) is a conversion that is automatically performed by the compiler without any explicit instruction from the programmer. The compiler applies conversion rules defined by the type system when operands of different types are used together.
Example:
int a = 5;
float b = 3.2;
float c = a + b; // compiler automatically converts 'a' to float
Here, the integer a is automatically promoted to float before the addition is performed.
Why Do We Need to Check the Type of a System?
The collection of different data types and their associated rules to assign types to programming language constructs is known as type systems. A type checker implements a type system.
Type checking is necessary for the following reasons:
1. Ensures Type Correctness
Type checking verifies that operations are applied to compatible types. Without it, meaningless operations (such as adding a string to an integer) could go undetected.
2. Prevents Runtime Errors
Catching type mismatches at compile time avoids unexpected crashes or incorrect results at runtime.
3. Enforces Language Rules
Type systems define informal rules such as:
"If both operands of addition are of type integer, then the result is of type integer."
The type checker enforces these rules consistently across the program.
4. Supports Semantic Correctness
Even if a program is syntactically correct, it may be semantically wrong due to type mismatches. Type checking adds a layer of semantic validation.
Justification with an Example
Consider the following expression:
int x = 5;
char ch = 'A';
int result = x + ch;
Without type checking:
The compiler would not know whether adding an int and a char is valid, and the result type would be undefined or erroneous.
With type checking: The type checker applies the rule:
| Operand 1 | Operand 2 | Operation | Result Type |
|---|---|---|---|
int | char | + | int (char is coerced to its ASCII integer value) |
The type checker detects that char can be implicitly converted to int (ASCII value of 'A' = 65), so:
result = 5 + 65 = 70
This is a valid, well-typed expression. If instead we wrote:
int x = 5;
char *str = "hello";
int result = x + str; // TYPE ERROR
The type checker would flag this as a type error because adding an integer and a string pointer violates the type rules, preventing a potential runtime crash.
Summary
| Feature | Explicit Conversion | Implicit Conversion |
|---|---|---|
| Initiated by | Programmer | Compiler |
| Also known as | Type casting | Type coercion |
| Risk | Possible data loss if misused | May cause unintended behavior |
Type checking is essential to ensure that every operation in a program is applied to operands of appropriate and compatible types, making programs safe, correct, and predictable.
asked 4xavg 6 marks · 2081.1, 2078, 2076, 2075AnswerHideWhat are the roles of macros and preprocessor? Discuss about one pass and multi pass compiler. [5]
What are the roles of macros and preprocessor? Discuss about one pass and multi pass compiler. [5]
Roles of Macros and Preprocessor; One Pass vs Multi-Pass Compiler
1. Roles of Macros and Preprocessor
A preprocessor is a tool that processes the source code before it is passed to the compiler. It is generally considered a part of the compiler system and produces input for the compiler proper.
Key Functions of a Preprocessor:
i) Macro Processing: A preprocessor allows a user to define macros, which are shorthands for longer constructs. When the preprocessor encounters a macro call, it replaces it with the corresponding expanded code before compilation begins.
- Example:
#define MAX 100replaces every occurrence ofMAXwith100.
ii) File Inclusion: The preprocessor handles header file inclusion by inserting the content of specified files into the program text.
- Example:
#include <stdio.h>inserts the standard I/O header file.
iii) Rational Preprocessor: These preprocessors augment older languages with more modern flow-of-control and data structuring facilities, making legacy code more manageable.
iv) Language Extensions: These preprocessors attempt to add capabilities to the language by building in macro-like constructs, effectively extending what the base language can express.
2. One Pass vs Multi-Pass Compiler
One Pass Compiler:
A compiler in which all phases are combined and executed in a single pass over the source program.
Multi-Pass Compiler:
A compiler in which different phases are grouped into multiple passes, each pass reading the output of the previous one.
Comparison Table:
| Feature | One Pass Compiler | Multi-Pass Compiler |
|---|---|---|
| Structure | All phases combined into one single pass | Different phases grouped into multiple passes |
| Intermediate Representation | Not created | Created between passes |
| Speed | Faster | Slightly slower |
| Also Called | Narrow compiler | Wide compiler |
| Memory Usage | Requires less memory | Requires more memory |
| Example | Pascal compiler | C++ compiler |
Summary:
- A one pass compiler is simpler and faster but less flexible, as it cannot easily handle forward references.
- A multi-pass compiler is more powerful and can perform better optimization since it has a complete view of the program through intermediate representations.
asked 3xavg 6 marks · 2080, 2076, 2075AnswerHideWhat is annotated parse tree? Define S-attributed grammar with an example. [5]
What is annotated parse tree? Define S-attributed grammar with an example. [5]
--- An annotated parse tree is a parse tree in which each node is labeled with its grammar symbol along with the values of its associated attributes. In Syntax-Directed Translation (SDT), semantic rules are used to compute attribute valu...
asked 3xavg 5 marks · 2081, 2080, 2078AnswerHideWhat types of information are stored in a symbol table? Discuss the activation record. [5]
What types of information are stored in a symbol table? Discuss the activation record. [5]
A symbol table is a data structure used by compilers to hold information about source-program constructs. The information is collected incrementally by the analysis phases and used by the synthesis phases to generate target code. The fol...
asked 3xavg 7 marks · 2078, 2076, 2075AnswerHideList out the tasks performed by Lexical Analyser. Define DFA. Convert the Regular Expression (a+b)∗a(a+b)(a+b)^*a(a+b)(a+b)∗a(a+b) to DFA directly.[10]
List out the tasks performed by Lexical Analyser. Define DFA. Convert the Regular Expression (a+b)∗a(a+b)(a+b)^*a(a+b)(a+b)∗a(a+b) to DFA directly.[10]
- RE to convert (canonical/deduplicated form): $r = (a+b)^,a,(a+b)$ - Alphabet: $\Sigma = {a, b}$ - Marks: 10 Note: The question string repeats the pattern; the intended standard example is $(a+b)^a(a+b)$. --- 1. Scanning the source ...
asked 3xavg 6 marks · 2078, 2076, 2075AnswerHideExplain about the factors affecting target code generation. [5]
Explain about the factors affecting target code generation. [5]
Target code generation is the final phase of compilation that translates optimized intermediate code into machine-level instructions for a specific target machine. Several factors influence how efficient and correct the generated target ...
asked 3xavg 5 marks · 2081.1, 2081, 2078AnswerHideDifferentiate between synthesized and inherited attributes with example. [5]
Differentiate between synthesized and inherited attributes with example. [5]
Attributes of a node that are derived from its children nodes are called synthesized attributes. - Information flows bottom-up in the parse tree (from children to parent). - A node's attribute value is computed from the attribute values ...
asked 2xavg 8 marks · 2081, 2076AnswerHideWhat are the significances of intermediate code? Differentiate between DAG and Syntax tree. Represent the instruction A = B + C - D * E + G using quadruple and triple.[10]
What are the significances of intermediate code? Differentiate between DAG and Syntax tree. Represent the instruction A = B + C - D * E + G using quadruple and triple.[10]
Intermediate Code, DAG vs Syntax Tree, and Quadruple/Triple Representation
Given Data (Extracted)
- Task 1: Significances of intermediate code (conceptual)
- Task 2: Differentiate DAG vs Syntax tree (conceptual)
- Task 3: Expression to represent using quadruple and triple: $$A = B + C - D * E + G$$
Operator precedence assumption: * binds tighter than +/-; + and - are left-associative and equal precedence, evaluated left to right. So the expression parses as:
$$A = ((B + C) - (D * E)) + G$$
1. Significances of Intermediate Code (3 marks)
Intermediate code (IC) is a machine-independent representation produced between the analysis (front end) and synthesis (back end) phases of a compiler.
| Significance | Explanation |
|---|---|
| Machine Independence | IC is not tied to any target CPU, keeping the front end portable. |
| Retargetability | One front end can serve many target machines by swapping only the back-end code generator. |
| Enables Optimization | Machine-independent optimizations (common subexpression elimination, constant folding, dead-code removal) are applied conveniently on IC. |
| Front-end Reuse for Many Languages | Several source-language front ends can share a single back end if they emit the same IC. |
| Modularity / Simpler Compiler Design | Clean separation of phases eases development, debugging, and maintenance. |
| Aids Error/Type Checking | Type mismatches and semantic issues can be handled while generating IC. |
2. Difference Between DAG and Syntax Tree (3 marks)
| Feature | Syntax Tree | DAG (Directed Acyclic Graph) |
|---|---|---|
| Definition | Tree with operators at internal nodes and operands at leaves. | Graph like a syntax tree but with common subexpressions shared as one node. |
| Common subexpressions | Repeated as separate subtrees. | Shared using a single node. |
| Node parents | Each node has exactly one parent. | A node may have multiple parents. |
| Space usage | More (duplication). | Less (sharing). |
| Redundancy detection | Does not expose redundant computation. | Explicitly reveals repeated computations. |
| Typical use | Semantic analysis, syntax-directed translation. | Code optimization (common subexpression elimination). |
Example: A + A * B
Syntax Tree (A duplicated):
+
/ \
A *
/ \
A B
DAG (A shared):
+
/ \
| *
\ / \
A B
3. Quadruples and Triples for A = B + C - D * E + G (4 marks)
Three-Address Code
$$ \begin{aligned} t_1 &= B + C \ t_2 &= D * E \ t_3 &= t_1 - t_2 \ t_4 &= t_3 + G \ A &= t_4 \end{aligned} $$
Quadruple Representation: (op, arg1, arg2, result)
| Index | op | arg1 | arg2 | result |
|---|---|---|---|---|
| (0) | + | B | C | $t_1$ |
| (1) | * | D | E | $t_2$ |
| (2) | - | $t_1$ | $t_2$ | $t_3$ |
| (3) | + | $t_3$ | G | $t_4$ |
| (4) | = | $t_4$ | - | A |
Triple Representation: (op, arg1, arg2) (result implied by position)
| Index | op | arg1 | arg2 |
|---|---|---|---|
| (0) | + | B | C |
| (1) | * | D | E |
| (2) | - | (0) | (1) |
| (3) | + | (2) | G |
| (4) | = | A | (3) |
Quadruple vs Triple
| Quadruple | Triple | |
|---|---|---|
| Result | Explicit named temporary | Implicit (position index) |
| Fields | 4 | 3 |
| Instruction reordering | Easy | Hard (position references break) |
asked 2xavg 6 marks · 2080, 2075AnswerHideWhat is three-address code? How high level code is converted to three address code? Illustrate with an example. [5]
What is three-address code? How high level code is converted to three address code? Illustrate with an example. [5]
Three-address code is an intermediate code representation where each instruction uses at most three addresses: two for operands and one for the result. Each instruction in three-address code is described as a 4-tuple: (operator, operand1...
asked 2xavg 5 marks · 2081, 2078AnswerHideCompute the FIRST and FOLLOW of the non-terminals in the following grammar. S→(L)∣1S \rightarrow (L) \mid 1S→(L)∣1L→L;S∣εL \rightarrow L;S \mid \varepsilonL→L;S∣ε_[5]_
Compute the FIRST and FOLLOW of the non-terminals in the following grammar. S→(L)∣1S \rightarrow (L) \mid 1S→(L)∣1L→L;S∣εL \rightarrow L;S \mid \varepsilonL→L;S∣ε_[5]_
Grammar: $$S \rightarrow (L) \mid 1$$ $$L \rightarrow L,;,S \mid \varepsilon$$ - Non-terminals: $S$, $L$ - Terminals: $($, $)$, $1$, $;$ - Start symbol: $S$ --- FIRST(S): - $S \rightarrow (L)$ gives first symbol $($ - $S \rightarrow 1$...
asked 2xavg 6 marks · 2078, 2076AnswerHideWhat are the disadvantages of shift reduce parsing. Perform shift reduce parsing of string w = (x-x). (x/x) for given grammar. E→E−E∣E/E∣(E)∣xE \rightarrow E-E | E/E |
(E) | xE→E−E∣E/E∣(E)∣x_[5]_
What are the disadvantages of shift reduce parsing. Perform shift reduce parsing of string w = (x-x). (x/x) for given grammar. E→E−E∣E/E∣(E)∣xE \rightarrow E-E | E/E |
(E) | xE→E−E∣E/E∣(E)∣x_[5]_
Grammar: $$E \rightarrow E - E \mid E / E \mid (E) \mid x$$ Input string: $w = (x-x).(x/x)$ Terminals visible in string: (, ), x, -, /, . Note on missing data: The grammar defines operators - and / only. The string contains a . (dot) ope...
Study every one of these with model answers, flashcards, and MCQs.
Open CSC376 study modes