Ilovepdf Merged
Ilovepdf Merged
Compiler Design
Assignment - Week 0
TYPE OF QUESTION:MCQ
Number ofquestions:11 Total mark: 11 X 1 = 11
Q1.
Task of a compiler is to
Explanation: A compiler is a program that translates the entire source code of a program
written in a high-level programming language into machine code or an intermediate language
in one go. The resulting code can then be executed by the machine.
Q2.
In a computer system, number of compilers for a particular programming language may
Be
a) Two
b) Three
c) Four
d) Many
ANS: d)
Explanation:
There can be many compilers for a particular programming language in a computer system.
This is because:
Platform-specific compilers: Different compilers are designed for different hardware
architectures or operating systems. For example, compilers like GCC, Clang, and Microsoft
C++ Compiler all support the C++ language but are optimized for different platforms.
Optimization and feature differences: Some compilers offer specific optimizations or
additional features that others do not. Developers may choose a compiler based on their
project's needs.
Open-source vs. proprietary: Both open-source compilers (like GCC or LLVM) and
proprietary compilers (like Intel C++ Compiler or Oracle's Java Compiler) exist for many
languages.
Specialized use cases: Some compilers are tailored for education, embedded systems, or
research purposes.
Thus, for a single programming language, there can be many compilers available.
Q3.
Natural language constructs are
a) Ambiguous
b) Unambiguous
c) May be Unambiguous or ambiguous
d) None of the other options
ANS: c)
Explanation:
Q4.
Suppose there is a compiler for C language that can generate code for Computer A. Which of
the following statements is true
ANS: c)
a) Array
b) Link List
c) Tree
d) Hash Table
ANS: d)
Explanation: A Hash Table is efficient for frequent searches, insertions, and deletions
because it provides O(1) average time complexity for all these operations. Data is quickly
accessed, inserted, or deleted using a key and a hash function, making it highly efficient for
dynamic data handling.
Q6.
Task of an interpreter is to
ANS: b)
Q7.
If an Infinite language is passed to Machine M, the subsidiary which gives a finite
solution to the infinite input tape is ______________
a) Compiler
b) Interpreter
c) Loader and linkers
d) None of the mentioned
ANS : a)
Q8.
Languages of a automata is
a) If it is accepted by automata
b) If it halts
c) If automata touch final state in its life time
d) All language are language of automata
ANS: a)
Q9.
Finite automata requires minimum _______ number of stacks.
a) 1
b) 0
c) 2
d) None of the mentioned
ANS: b)
Explanation: Finite automata doesn’t require any stack operation .
Q10.
The basic limitation of finite automata is that
ANS: a)
a) Regular languages
b) Context-free languages
c) Context-sensitive languages
d) None of the mentioned
ANS: a)
Explanation: Finite automata are limited to recognizing regular languages, which are defined
by regular expressions. They cannot handle languages requiring memory, such as context-
free or context-sensitive languages.
END of Assignment
NPTEL Online Certification Courses Indian
Institute of Technology Kharagpur
Compiler Design
Assignment - Week 1
TYPE OF QUESTION:MCQ
Number ofquestions:12 Total mark: 12 X 1 = 12
Q1.
• a) Code generation:
• The symbol table is essential in the code generation phase. It holds information about
variables, functions, and their memory addresses, which are needed to generate the final
code.
• b) Syntax Analysis:
• During syntax analysis (parsing), the symbol table is used to store and retrieve information
about the program's symbols (e.g., variables, functions). It helps track the symbols'
declarations and scopes.
• c) Lexical Analysis:
• Even during lexical analysis (tokenization), the symbol table may be used to track
identifiers and keywords, especially for checking whether a variable has been declared and
to associate it with its type.
• All three phases mentioned (code generation, syntax analysis, and lexical analysis) make
use of the symbol table in some capacity.
Q2.
1. Lexical Analysis:
o First phase of the compiler.
o Converts source code into tokens.
2. Syntax Analysis (Answer: b) :
o Second phase.
o Uses tokens from lexical analysis to check if they conform to the grammatical rules of the
programming language.
o Builds a parse tree (or syntax tree).
3. Semantic Analysis:
o Third phase.
o Checks for semantic errors (e.g., type checking) and annotates the syntax tree.
4. Intermediate Code Generation:
o Converts the syntax tree into an intermediate representation.
5. Code Optimization (Optional):
o Improves the intermediate code for better performance.
6. Code Generation:
o Produces the target machine code.
7. Code Linking and Loading:
o Links different modules and prepares the code for execution.
Q3.
ANS: A) parse tree
• The syntax analysis phase (or parsing) constructs a hierarchical tree structure called a parse
tree (or syntax tree).
• It represents the grammatical structure of the source code as per the rules of the language's
grammar.
• Other Options:
Q4.
ANS: c) Semantic Analysis
Q6.
Q7.
Q9.
ANS : B) loop body is repeated several times
Detailed Solution: This is true because the loop body executes multiple times during the program's
execution. Optimizing loops can significantly improve the performance of a program since even small
improvements in the loop body can lead to substantial time savings.
Q10.
Detailed Solution: • Registers are the fastest storage locations available in a computer because
they are part of the CPU itself.
• Allocating temporary variables to registers minimizes memory access time and speeds up
Q11.
• Intermediate code is an abstraction between the source code and the target machine code.
• It is platform-independent, allowing the compiler to generate target code for multiple
architectures without reanalyzing or rewriting the source program.
• Program Analysis:
• While intermediate code may assist in program analysis (like semantic checks), this is not
its primary purpose.
• Code Optimization:
• Intermediate code simplifies optimization, but the main focus is retargeting for multiple
architectures.
• Code Check:
Q12.
Answer: b
Explanation: This Produce the file “myfile.yy.c” which we can then compile with g++.
END of Assignment
Compiler Design
Assignment 2
No. of Question 13
Q1.
Detailed Solution: Regular expressions are used to define patterns that match strings in a language.
They describe the set of strings (constituent strings) that belong to a specific language. For example,
the regular expression a*b represents strings in the form of zero or more occurrences of a followed by
a single b, such as b, ab, aab, etc.
Q2.
Ans : c)
Explanation:
Lexeme
Token category
Sum “Identifier”
= “Assignment operator”
3 “Integer literal”
+ “Addition operator”
2 “Integer literal”
; “End of statement”
Q3.
Ans: C)
Q4.
Ans : d)
Ans: d)
Deatiled Solution: Regular expressions are used to define patterns for regular languages.
However, the language that accepts strings with exactly one more 1 than 0s is not a regular
language. This is because keeping track of the difference between the number of 1s and 0s
requires a form of counting or memory, which regular expressions (and finite automata) cannot
handle.
This type of language can only be recognized by more powerful computational models, such as a
pushdown automaton (for context-free languages) or a Turing machine. Hence, it is not
possible to write a regular expression for this condition.
Q6.
Ans : C)
Explanation: The regular expression has two 0′s surrounded by (0+1)* which means
accepted strings must have at least 2 0′s.
Deatiled Solution: Finite automata (both deterministic and non-deterministic) are mathematical
models used to recognize or implement regular languages, which are the types of languages
described by regular expressions.
• Regular expressions provide a way to describe patterns in strings, while finite automata
serve as the computational model that accepts or rejects strings based on those patterns.
• There is a direct correspondence between regular expressions and finite automata: for
every regular expression, there exists an equivalent finite automaton, and vice versa.
Q7.
Ans: A)
Deatiled Solution: Finite automata (both deterministic and non-deterministic) are mathematical
models used to recognize or implement regular languages, which are the types of languages
described by regular expressions.
• Regular expressions provide a way to describe patterns in strings, while finite automata
serve as the computational model that accepts or rejects strings based on those patterns.
• There is a direct correspondence between regular expressions and finite automata: for
every regular expression, there exists an equivalent finite automaton, and vice versa.
Q8.
Ans: A)
• NFA: Allows epsilon transitions, which means the automaton can move to a new state
without reading any input.
• DFA (Deterministic Finite Automaton): Does not allow epsilon transitions; every
transition in a DFA must consume an input symbol.
• Pushdown Automaton: While it allows stack operations, epsilon transitions are not
specifically related to finite state machines like NFAs.
• All of the mentioned: Incorrect because DFA does not support epsilon transitions.
Q9.
Ans: A)
Explanation: The ε-closure of a set of states, P, of an NFAis defined as the set of states
reachable from any state in P following e-transitions.
Q10.
Ans: c)
While an NFA may appear more "flexible," any NFA can be converted into an equivalent DFA.
The DFA might have exponentially more states in the worst case, but it recognizes the exact
same language as the NFA.
Thus, NFAs and DFAs are equally powerful in terms of the languages they can recognize.
Q11.
Ans: A)
Q12.
Ans: C)
Q13.
Ans: D)
Detailed Solution: n the scenario where a compiler automatically corrects errors like changing
"fi" to "if," the error correction involves transposing the characters.
Q1.
Ans: d)
Detailed Solution: Lex: A lexical analyzer generator that was one of the first tools used to
create scanners in Unix environments.
All of these tools are used for lexical analysis, which involves breaking input text into
tokens as part of the compilation process.
Q2.
Ans: d)
Detailed Solution: In a Lex specification file, "?" is not a valid operator. Common operators
in Lex include:
Q3.
Ans: a)
Detailed Solution:
A DFA can potentially have more states than an NFA. When converting an NFA to a DFA
(using the subset construction algorithm), the number of states in the DFA can be
exponentially larger in the worst case. For example, an NFA with n states could result in a
DFA with up to 2^n states.
Q4.
Ans: d)
Deatiled Solution:
Q5.
Ans: d)
Deatiled Solution:
Definition Section
%%
Rules Section
%%
Q6.
Ans: a)
Detailed Solution:
ε-closure (epsilon-closure) of a state in an NFA is the set of all states that can be
reached starting from that state using only ε (epsilon) transitions, including the state
itself.
Deatiled Solution: Let’s analyze each option regarding the ε-closure of a subset S of states
Q:
1. a) Every element of S:
This is true because the ε-closure of S includes every element of S itself.
2. b) For any q∈ε-closure, every element of δ(q,ε)\ is in ε-closure:
This is true because the ε-closure of a state includes all states reachable by ε-
transitions.
3. c) No other element is in ε(S):
This is true because the ε-closure of S is precisely defined as the set of all states
reachable by ε-transitions, and no other states are included.
Q8.
Ans: b)
Detailed Solution: When a Lex program is processed, the Lex tool generates a C source
code file containing the lexical analyzer. By default, this file is named lex.yy.c.
• This file includes the code for the scanner based on the rules defined in the Lex
specification file.
Q9.
Ans: b)
1. i) DFA:
DFAs can represent all regular languages, but there may be regular languages that
are easier to describe using NFAs or regular expressions.
2. ii) NFA:
NFAs can represent all regular languages. They are equivalent to DFAs in expressive
power but are often more concise.
3. iii) Regular Expressions:
Regular expressions can describe all regular languages. They provide a more
compact and human-readable way to define patterns.
Q 10.
Ans: c)
Detailed Solution:
1. Definition Section:
This section contains declarations, macros, and regular definitions. These are used
to define constants, patterns, or reusable components.
2. Rules Section:
Contains the core of the Lex program, where regular expressions are associated
with actions (C code) to execute when the patterns are matched.
3. User Code Section:
An optional section that includes any additional C code or functions that support the
Lex program.
Definitions Section
%%
Rules Section
%%
User Code Section
NPTEL Online Certification Courses Indian
Institute of Technology Kharagpur
Compiler Design
Assignment- Week 4
TYPE OF QUESTION:MCQ
Number ofquestions:11 Total mark: 11 X 1 = 11
1.
Ans: a)
2.
Ans: a)
Solution:
A grammar is ambiguous if a single string (sentence) derived from the grammar has
more than one distinct parse tree or derivation.
E→E+E ∣ E∗E ∣ id
allows multiple ways to derive the same expression. For example, for the string id + id *
i, we can have two different parse trees:
3.
• These two distinct parse trees show that the grammar does not enforce a unique
structure for the expression, making it ambiguous.
Ans: a)
Explanation: Deterministic CFGs are always unambiguous , and are an important
subclass of unambiguous CFGs; there are non-deterministic unambiguous CFGs,
however.
4. A language that admits only ambiguous grammar:
• This means that no unambiguous grammar can be written for such a language.
• Some context-free languages (CFLs) are inherently ambiguous, meaning that
ambiguity cannot be removed by rewriting the grammar.
5.
Ans: b)
Solution:
6. For the grammar rules {S Aa | bB, A c |ε}, FIRST(S) is
Ans: c)
Solution:
Explanation:
1. S → Aa | bB
2. A → c | e (where e represents ε, i.e., an empty string)
• S → Aa
o A can be c or ε
o If A → c, then Aa starts with c
o If A → ε, then Aa starts with a
o Thus, from this production, FIRST(S) includes {c, a}
• S → bB
o The first symbol is b, so FIRST(S) includes {b}
Ans: b)
Solution:
A grammar is unambiguous if every string in the language has a unique parse tree (or
derivation).
Given Grammar:
1. E → E + T | T
2. T → T * F | F
3. F → id
Using the given grammar, the only valid parse tree follows standard precedence rules:
r
CopyEdit
E
/ \
E + T
| / \
T T * F
| | |
F F id
| |
id id
• The multiplication (*) happens first, followed by addition (+), which is correct
operator precedence.
• There is only one unique parse tree, meaning the grammar is unambiguous.
8.
Ans: a)
Solution:
A top-down parser constructs the parse tree from the start symbol (root) to the leaves,
applying production rules from left to right.
Example:
1. S → A B
2. A → a
3. B → b
1. S ⇒ A B (Expand S)
2. A B ⇒ a B (Expand A first, leftmost non-terminal)
3. a B ⇒ a b (Expand B)
Here, the leftmost non-terminal is always expanded first, confirming leftmost derivation.
9.
Ans: a)
Solution:
Left recursion removal is mandatory for top-down parsing because top-down parsers
(like Recursive Descent and LL(1) parsers) cannot handle left-recursive grammars.
A grammar has left recursion if a non-terminal refers to itself as the leftmost symbol in
its production.
Example of left recursion:
Here, the non-terminal A appears at the beginning of its own production (A → Aα),
causing an infinite recursion in a top-down parser.
A→Aα∣
A→βA
A′→αA′∣ε
This transformation eliminates left recursion, making the grammar suitable for top-
down parsing.
10
.
Ans: b)
Solution:
A grammar is ambiguous if there exists at least one string that has more than one
distinct parse tree or derivation.
11
.
Ans: a)
Explanation: Backtracking problem is solved by constructing a tree of choices called as
the state-space tree. Its root represents an initial state before the search for a solution
begins.
END of Assignment
NPTEL Online Certification Courses Indian
Institute of Technology Kharagpur
Compiler Design
Assignment- Week 5
TYPE OF QUESTION:MCQ
Number ofquestions:10 Total mark: 10 X 1 = 10
1. Ans: a)
Solution: In shift-reduce parsing, a handle is the substring of the input that matches the right
side of a production rule and whose reduction to the non-terminal on the left side of the rule
represents one step in the reverse of a rightmost derivation.
2. Ans: c)
1. Shift-Reduce Conflict:
o This occurs when the parser cannot decide whether to shift the next input
symbol onto the stack or reduce the handle on top of the stack.
o Common in ambiguous grammars.
2. Reduce-Reduce Conflict:
o This happens when the parser finds two or more possible reductions at the
same point, and it cannot decide which production to use.
3. Shift-Shift Conflict (Not Possible):
o This is not possible because shifting means reading the next input symbol, and
there is no ambiguity about which symbol to shift. The parser always shifts if
shifting is allowed, with no competing shift operations.
3. Ans: c)
Explanation:
In shift-reduce parsing, a viable prefix is a string of symbols that can appear at the top
of the stack and still be a part of a valid rightmost derivation of the input.
• The stack in shift-reduce parsing maintains a viable prefix of the input string.
• A viable prefix is a prefix of a right-sentential form that does not extend
beyond a handle (the substring that can be reduced).
• This ensures that every step taken in shift-reduce parsing leads to a valid
derivation.
• a) At the bottom we find the prefixes ❌ (Incorrect, because the bottom of the
stack holds the start symbol or intermediate derivations, not necessarily a
prefix.)
• b) None of the mentioned ❌ (Incorrect, since option c is correct.)
• d) Stack consists of viable prefixes ❌ (Incorrect wording— the stack does not
consist of multiple viable prefixes, it contains only the current viable prefix.)
4. Answer: b)
Solution: Solution:
The Follow(A) set consists of symbols that can appear immediately after A in some
derivation.
1. Bottom-up Parsing
o Shift-reduce parsing begins with the input string and attempts to build the parse tree
by reducing the input symbols to the start symbol of the grammar.
o It works in reverse order of a rightmost derivation, meaning it traces the derivation
backwards from leaves (input symbols) to the root (start symbol).
2. How Shift-Reduce Parsing Works:
o Shift: Move the next input symbol onto the stack.
o Reduce: If a handle (substring that matches the right side of a production rule) is on
top of the stack, replace it with the corresponding non-terminal.
o Accept: If the entire input is reduced to the start symbol, the parser accepts the
input.
o Error: If no valid move exists (shift or reduce), the parser reports an error.
6.
Answer: a)
Solution: In shift-reduce parsing, a handle is a substring that matches the right-hand side of a
grammar production and whose reduction represents one step in the reverse of a rightmost
derivation.
• During parsing, symbols are pushed onto the stack as part of the shift operation.
• When the parser identifies a handle at the top of the stack, it performs a reduce
operation, replacing the handle with the corresponding non-terminal.
Thus, the handle is always located at the top of the stack when it's ready for reduction.
7.
Answer: c)
Solution: In Operator Precedence Parsing, special symbols like <• and •> are used to
denote the precedence relationship between terminals.
• <• (Left Precedence) indicates that the terminal on the left has lower precedence than
the one on the right.
• •> (Right Precedence) indicates that the terminal on the left has higher precedence
than the one on the right.
The handle is the substring located between <• and •>, as this represents the part of the
input that corresponds to a reducible substring (i.e., it matches the right-hand side of a
production and can be replaced by the corresponding non-terminal).
id <• + •> id
• The handle is located between <• and •>, which corresponds to id in this case. This
is the part that can be reduced based on a grammar rule.
Thus, the handle in operator precedence parsing is always between <• and •>.
8.
Ans: b)
• a ≐ b: Since a and b are adjacent in the production abbS, it implies that a and b have
equal precedence (≐).
• b ≐ b: The two consecutive b symbols in abbS indicate that b has equal precedence
with another b, as they form part of the same handle.
9.
Ans: d)
Solution: Explanation:
1. Shift-Reduce Parser ✅
o Operator-precedence parsers use shift (to push operators and operands
onto the stack) and reduce (to apply grammar rules).
o This confirms that it follows a shift-reduce parsing strategy.
2. Bottom-Up Parser ✅
o It starts from the input (tokens) and constructs the parse tree from
leaves to root, making it a bottom-up parser.
o Unlike top-down parsers, it does not predict rules but instead reduces
input based on precedence.
3. Constructs Derivation in Reverse ✅
o Bottom-up parsers construct rightmost derivations in reverse.
o That means the derivation is built from leaf nodes to the start symbol.
o Since operator-precedence parsers fall under bottom-up parsing, they
also construct derivations in reverse order.
10.
Ans: d)
Solution: Bottom-up parsing is a method that constructs the parse tree starting from the input
symbols and works its way up to the start symbol of the grammar. It involves the following key
techniques:
1. Shift-Reduce Parsing:
o This technique shifts symbols onto a stack and reduces them when a handle (a
substring that matches the right-hand side of a production) is found.
o Shift: Move the next input symbol onto the stack.
o Reduce: Replace the handle on the stack with the corresponding non-terminal.
2. Handle Pruning:
o Handle pruning is the process of identifying and reducing handles during bottom-up
parsing.
o It involves recognizing the substring that corresponds to the right-hand side of a
grammar rule and replacing it with the left-hand side (a non-terminal). This builds
the parse tree in reverse order.
END of Assignment
NPTEL Online Certification Courses Indian
Institute of Technology Kharagpur
Compiler Design
Assignment- Week 6
TYPE OF QUESTION:MCQ
Number ofquestions:11 Total mark: 11 X 1 = 11
1.
Ans: c)
Solution:
S' → S
S → CC
C → cC | d
The LR(1) parsing algorithm starts with the closure of the initial state containing the
augmented production:
[S' → .S, $]
[S' → .S, $]
[S → .CC, $]
Now, since C appears immediately after the dot (.), we need to expand C. Looking at the
production C → cC | d, we add:
C → .cC, (lookahead: Follow(C))
C → .d, (lookahead: Follow(C))
To determine Follow(C):
From the closure computation, we see that the item C → .cC has lookahead {c, d},
meaning the correct item is:
C → .cC, c, d
2.
Ans: c)
Solution:
S' → S
S → CC
C → cC | d
[S' → .S, $]
Expanding S → CC gives:
[S' → .S, $]
[S → .CC, $]
Since C appears immediately after the dot (.), we expand C → cC | d and determine the
look ahead.
C → .cC, {c, d}
C → .d, {c, d}
From the closure computation, we see that the item C → .d has lookahead {c, d},
meaning the correct item is:
C → .d, c, d
3. Ans: c)
Solution:
4. Ans: b)
Additionally, we know:
A reduce-reduce conflict occurs when two or more reductions are possible in the same
parser state for the same input symbol.
Here, both A → α and B → δ are ready for reduction, and since Follow(A) and Follow(B)
both contain 'a', the parser will not be able to decide which reduction to apply when 'a'
appears in the input.
• Canonical LR has more states than both because it does not merge states with
the same core items.
6. Ans: b)
7. Ans: a)
Solution:
E' → .E
E → .aEbE
E → .bEaE
E→.
Since E → . (i.e., E → ε) is a completed item, it means that E can be reduced whenever the
lookahead belongs to Follow(E).
Shift Possibility:
• The items E → .aEbE and E → .bEaE indicate that we can shift 'a' and 'b'.
• The First(aEbE) = {a} and First(bEaE) = {b}, so both 'a' and 'b' can be shifted.
Reduce Possibility:
Follow(E') = { $ }
Follow(E) = { a, b, $ } (Since E appears in recursive positions)
Since 'a' and 'b' are in Follow(E), the parser will try to reduce E → ε whenever it
encounters 'a' or 'b'.
8. Ans: a)
Solution:
9. Ans: b)
Solution:
S → .B
S → .SabS
B → .bB
B→.
Shift Possibility:
Reduce Possibility:
• The item B → . (i.e., B → ε) means that B can be reduced whenever the lookahead
belongs to Follow(B).
• Follow(B) is computed using:
o S → B, so Follow(B) contains Follow(S).
o Follow(S) = { $, a, b } (since S appears at the start and within SabS).
Thus, Follow(B) = { a, b, $ }.
For 'b':
For 'a':
Since both shift (S → .SabS) and reduce (B → ε) actions are possible on 'a', a shift-reduce
conflict occurs for 'a'.
10. Which of the following parser types is the most powerful in terms of recognizing a
broader class of grammars?
a) LL(1)
b) SLR(1)
c) LALR(1)
d) LR(1)
Ans: d)
Explanation:
• LL(1) is the weakest among these as it only looks one symbol ahead and is top-
down.
• SLR(1) is more powerful than LL(1) but can still fail for some grammars.
11. Ans: a)
END of Assignment
NPTEL Online Certification Courses Indian
Institute of Technology Kharagpur
Compiler Design
Assignment- Week 7
TYPE OF QUESTION:MCQ
Number ofquestions:12 Total mark: 12 X 1 = 12
1.
Ans: c)
Explanation:
• The name follows the tradition of humorous naming in computer science, where
"Yet Another" was commonly used to describe new tools (e.g., YAML: Yet Another
Markup Language).
• YACC generates parsers, which are a part of compiler construction, hence
"Compiler Compiler."
2.
Ans: b)
Explanation:
• YACC (Yet Another Compiler Compiler) generates a C source file (y.tab.c) that
contains the parser code.
• Additionally, YACC produces a header file (y.tab.h), which defines token
identifiers for use by Lex (Lexical Analyzer).
• Lex uses y.tab.h to ensure that the token values assigned in YACC are consistent
in the lexical analyzer.
File Descriptions:
Explanation:
A YACC (Yet Another Compiler Compiler) specification file is divided into three sections,
separated by %% mar
kers:
%{
#include <stdio.h>
%}
%token NUMBER
%left '+' '-'
%%
expr : expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| NUMBER { $$ = $1; }
;
%%
• Contains additional C functions, such as the yyerror() function and the main()
function.
• Example:
int main() {
yyparse();
return 0;
}
4.
Ans: c)
Explanation:
In YACC's rules section, $$ refers to the value of the non-terminal on the left-hand
side (LHS) of a production rule.
• YACC uses semantic actions inside { } to associate C code with grammar rules.
• Each grammar rule's LHS non-terminal receives a value based on the right-
hand side (RHS) expressions.
• $$ is used to assign a value to the LHS non-terminal.
Example:
expr : expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| NUMBER { $$ = $1; }
;
$$ represents the value of expr (LHS non-terminal).
$1, $2, $3 refer to RHS elements (expr, '+', expr respectively).
The action { $$ = $1 + $3; } means the value of expr (LHS) is set to the sum of the first
and third symbols.
5.
Ans: a)
Explanation:
An annotated parse tree is a parse tree where each node is associated with attributes
that store information relevant to semantic analysis. These attributes help in syntax-
directed translation (SDT) and are used in syntax-directed definitions (SDD).
Example:
Consider the grammar:
E
/|\
E + T
| |
T 5
|
3
If attributes are added to store values:
E (8)
/|\
E(3) + T(5)
| |
T(3) 5
|
3
This annotated parse tree shows attribute values (val) computed at each step.
6.
Ans: c)
Explanation:
In YACC's rule section, positional notation ($n) is used to refer to elements on the
right-hand side (RHS) of a production rule.
A→BbC
Explanation:
8.
Ans: c)
Explanation:
When YACC (Yet Another Compiler Compiler) processes a grammar file (e.g.,
parser.y), it generates the following files:
1. y.tab.c
o This contains the C source code for the parser.
o It includes the parsing function yyparse(), which is used in syntax
analysis.
2. y.tab.h
o This is a header file containing token definitions.
o It defines token names and their corresponding numerical values.
o It is used by Lex (Lexical Analyzer) to ensure consistency between Lex
and YACC.
9.
Ans: d)
Explanation:
• yylval is a global variable used by Lex and YACC to store the attribute value of a
token.
• It is used in semantic analysis where tokens carry additional information (like
numerical values, variable names, etc.).
• When a token is identified by the Lexical Analyzer (Lex), its associated value
(attribute) is stored in yylval and passed to YACC.
• a) yytext
o yytext stores the actual string representation of the token, but not its
attribute value.
o It is useful in Lex but does not return token attributes.
• b) yylen
o yylen is not a standard YACC or Lex variable.
o There is no such variable that handles token attributes.
• c) yyval
o yyval is used in YACC for handling semantic values within grammar rules,
but it does not store token attributes.
a) Stack
b) Token
c) Input
d) Queue
Ans: a)
Explanation:
• YYSTYPE is a data type definition used in YACC (Yet Another Compiler Compiler) to
define the type of values stored in the parser's stack.
• Since YACC supports semantic values (like integers, floats, or complex structures),
YYSTYPE allows users to define the type of attributes that are stored in the parsing
stack.
• By default, YYSTYPE is defined as int, but it can be customized using a union to store
multiple data types.
• Example
%union {
int ival;
float fval;
char *sval;
}
%token <ival> NUMBER
%token <sval> IDENTIFIER
• Here, YYSTYPE can store integers, floats, and strings, depending on the token type.
• b) Token ❌
o YYSTYPE does not define a token, it defines the data type associated with
tokens.
• c) Input ❌
o YYSTYPE is not related to the input, which is handled by yytext and yylval.
• d) Queue ❌
o YYSTYPE is used in the parsing stack, not in a queue.
Q11.
Ans: (b)
Explanation:
YACC (Yet Another Compiler Compiler) is a parser generator used for syntax analysis in
compilers. It takes a context-free grammar (CFG) and generates a C program that performs
parsing based on the specified grammar. Lex/Flex is used for lexical analysis, while YACC is
used for syntax analysis.
Q12.
Ans: (b)
Explanation:
The function yyparse() is the main parsing function in YACC, automatically generated from
the grammar rules. It retrieves tokens from Lex (using yylex()) and applies grammar rules to
build a syntax tree or process the input. It does not perform lexical analysis itself (which is
done by Lex/Flex).
END of Assignment
NPTEL Online Certification Courses Indian
Institute of Technology Kharagpur
Compiler Design
Assignment- Week 8
TYPE OF QUESTION:MCQ
Number ofquestions:13 Total mark: 13 X 1 = 13
1.
Ans: b)
Explanation:
Type checking is a part of semantic analysis in a compiler, where it ensures that operations
are performed on compatible data types.
2. Ans: c)
Explanation:
The type expression for an argument list follows the order in which the arguments are passed
to the function. Given that:
The correct notation for the type expression is: Integer X Real X Integer
3. Ans: c)
Explanation:
Array bound checking ensures that an array index is within valid limits to prevent out-of-
bounds errors. This can be done in two ways:
int arr[5];
arr[10] = 20; // Compiler may warn about out-of-bounds access
• • Languages like Ada, Rust, and some static analysis tools in C/C++ support static
bound checking.
• When arrays are allocated dynamically or indices depend on user input, bound
checking happens at runtime.
• Example (Python – automatic bound checking)
arr = [1, 2, 3]
print(arr[5]) # Raises Index Error at runtime
Languages like Python, Java, and C++ (with std::vector::at() method) perform dynamic
bound checking.
4. Ans: a)
Explanation:
Type equivalence is the process of determining whether two type expressions represent the
same type. This is an important part of type checking in programming languages.
• Structural Equivalence: Two types are considered equivalent if they have the same
structure.
• Name Equivalence: Two types are equivalent only if they have the same declared
name.
typedef struct {
int x;
float y;
} A;
typedef struct {
int x;
float y;
} B;
A var1;
B var2;
// Structural equivalence: var1 and var2 have the same structure, but name equivalence would
say they are different.
Since type equivalence checks if two type expressions are the same.
5. Ans: c)
Explanation:
In programming languages, a statement typically performs an action but does not return a
value. Therefore, its type is usually void. However, if the statement contains an invalid
operation, it results in a type error.
Cases:
• Example (Python)
x = "hello" + 5 # Type Error: can only concatenate str (not "int") to str
6. Ans: a)
Explanation:
Type checking ensures that operations are performed on compatible data types. The type
checking done by the compiler is called static type checking because it happens at compile
time before the program runs.
Key Points:
7. Ans: c)
Explanation:
A weakly typed language is one where type rules are more flexible, allowing implicit type
conversions (type coercion) and catching some type errors only at runtime.
• In weakly typed languages, type errors may not be detected at compile time and are
instead caught at runtime.
• Example (Python – runtime type checking):
8. Ans: c)
9. Ans: b)
Explanation:
Type casting is the process of converting a value from one data type to another. It can be
explicit (manual) or implicit (automatic, called type coercion).
• Type Coercion refers to the automatic conversion of a value from one data type to
another by the language itself.
o Example (JavaScript - implicit coercion)
• Explicit Type Casting is a manual conversion where the programmer enforces type
conversion.
Explanation:
F takes two arguments: an Integer and a Real.F returns another function (G), where G:
o Takes an Integer
o Returns a Real
11.
Ans: (b)
Explanation: Type inference is the process by which a compiler automatically
determines the type of an expression without explicit type annotations. Many modern
languages (e.g., Haskell, Scala, and TypeScript) use type inference to make coding more
concise while still maintaining strong typing.
12.
Which of the following statements about type conversion is TRUE?
Ans: (c )
Explanation: Implicit type conversion, also known as type promotion, is automatically
handled by the compiler when a smaller data type is converted to a larger data type
(e.g., int to float). Explicit type conversion (also called type casting, not coercion)
requires manual intervention by the programmer.
13.
Dynamic type checking is necessary in languages that:
Ans: (b)
Explanation: Dynamic type checking is used in languages where variables can hold
values of different types at runtime (e.g., Python, JavaScript). It ensures type safety
during execution, unlike static type checking, which happens at compile-time.
END of Assignment
NPTEL Online Certification Courses Indian
Institute of Technology Kharagpur
Compiler Design
Assignment- Week 9
TYPE OF QUESTION:MCQ
Number ofquestions:13 Total mark: 13 X 1 = 13
Ans: (c)
Explanation:
2.
Ans: d)
Explanation:
A symbol table is a crucial data structure used by a compiler to store information about
identifiers (variables, functions, etc.) encountered in the source code. The most frequent
operation performed on a symbol table is lookup, for the following reasons:
3.
Ans: b)
Explanation:
The main motivation behind using a self-organizing list (SOL) for a symbol table is to
take advantage of program locality, which improves lookup efficiency. This is because:
4.
Ans: c)
Explanation:
The symbol table is a critical data structure in a compiler, used for storing and retrieving
information about identifiers efficiently. To minimize access time, the best choice is a
hash table, because:
5.
Ans: c)
Explanation:
An activation record (also called an activation frame) is a data structure used in stack-
based function calls to manage information related to a procedure (function). It typically
stores:
6.
And: d)
Explanation:
The symbol table is a crucial data structure in a compiler, used across multiple phases to
store and retrieve information about identifiers (variables, functions, types, etc.). Let’s
analyze how each phase uses the symbol table:
7.
Ans: c)
Explanation:
When two types have the same name, they can be:
1. Name Equivalent:
o In name equivalence, two types are considered the same if they have the
same name, regardless of their structure.
• Here, myInt and anotherInt may not be name equivalent unless explicitly
defined as the same type.
Structurally Equivalent:
• In structural equivalence, two types are considered equivalent if they have the
same structure, even if their names are different.
• Example
struct A { int x; };
struct B { int x; };
• Here, A and B are structurally equivalent but not name equivalent because
they have different names.
• If two types have the same name and the same structure, they are both name and
structurally equivalent.
8. Which type of compiler typically benefits from using a separate symbol table for each
scope?
a) Single-pass compilers
b) Multi-pass compilers
c) Both single and multi-pass compilers
d) None of the given options
Ans: a)
9.
Ans: c)
Explanation:
10.
Ans: d)
Explanation:
1. (A) Name
o The identifier name (e.g., variable names, function names, class names,
etc.).
2. (B) Location
o The memory address or relative location of the identifier in storage
(stack, heap, or static memory).
3. (C) Scope
o The visibility and lifetime of the identifier (e.g., global, local, block scope).
Since all the given options are commonly stored in a symbol table, the correct answer is:
11.
Ans: (c)
Explanation:
Which of the following data structures is best suited for managing scope information in
a symbol table?
a) Stack
b) Queue
c) Linked List
d) Heap
Ans : (a)
• When a new scope (e.g., function, block) is encountered, a new symbol table is
pushed onto the stack.
• When the scope ends, the table is popped, ensuring that variables from an inner
scope do not conflict with those in outer scopes.
• This method efficiently handles nested scopes, making lookup and removal of
variables efficient.
13.
Which optimization technique benefits the most from information stored in a symbol
table?
a) Constant propagation
b) Loop unrolling
c) Dead code elimination
d) Instruction pipelining
Ans: (a)
Explanation:
• The symbol table stores constant values assigned to variables, which helps the
compiler identify opportunities for constant propagation.
• Example
int x = 10;
int y = x + 5; // Can be optimized to y = 15;
• The symbol table helps track that x = 10, allowing the compiler to replace y = x +
5 with y = 15.
• Other optimizations (loop unrolling, dead code elimination, instruction
pipelining) may use symbol table data, but constant propagation relies on it the
most.
END of Assignment
NPTEL Online Certification Courses Indian
Institute of Technology Kharagpur
Compiler Design
Assignment- Week 10
TYPE OF QUESTION:MCQ
Number ofquestions:13 Total mark: 13 X 1 = 13
1.
Ans: c)
Explanation:
If the activation record is static, this means that each function has a fixed memory
location allocated at compile time rather than dynamically allocating space on the stack
during execution. This has significant implications:
2.
Ans: b)
Explanation:
The control link (also known as the dynamic link) in an activation record is a pointer to
the activation record of the calling (parent) function. It helps maintain the correct
function call sequence and is crucial for returning to the correct activation record after a
function call completes.
3.
Ans: b)
Explanation:
Ans: a)
Explanation:
5.
Ans: b)
Explanation:
6. Access link points to the
The access link (also called a static link) is used in languages that support nested
procedures or static scoping. It points to the activation record of the lexically enclosing
function (parent function) rather than the function that called it.
• In static scoping, a function can be nested inside another function, and it needs
access to the non-local variables of the lexically enclosing function.
• The access link helps in reaching these non-local variables.
• The control link (dynamic link), on the other hand, helps with returning to the
caller, but that's different from the access link.
Ans: b)
Explanation:
High-level languages (HLL) like C, C++, and Rust support pointers explicitly. However,
the intermediate language (IL) used in a compiler does not necessarily have to support
pointers in the same way. Instead, the IL might represent pointers using addresses,
references, or other constructs that serve a similar purpose without direct pointer
manipulation.
For example:
8.
Ans: a)
9.
Ans: c)
Explanation:
Explanation:
The frame pointer (FP) is a register that points to the current activation record (stack
frame) in memory. It serves as a stable reference point for accessing local variables,
function parameters, and saved registers within the current function call.
Explanation:
11.
Which of the following is a key purpose of the stack pointer in an activation record?
Answer: (C)
Explanation: The stack pointer (SP) keeps track of the top of the stack, ensuring that
function calls, local variable allocation, and return addresses are managed properly. It
helps in pushing and popping activation records dynamically during execution.
12.
Answer: (B)
Explanation: A static activation record means that activation records are allocated in a
fixed location, making it impossible to handle multiple function calls at different
recursion depths. When recursion is attempted, new function calls overwrite the existing
activation record, leading to incorrect execution.
13.
END of Assignment
NPTEL Online Certification Courses Indian
Institute of Technology Kharagpur
Compiler Design
Assignment- Week 11
TYPE OF QUESTION:MCQ
Number ofquestions:13 Total mark: 13 X 1 = 13
(A) Null
(B) Some value
(C) Constant
(D) None of the other options
Ans: B
Solution:
3. When generating code for the Boolean expression "(x ≥ y) AND (p ≠ q)", which locations
are left for back patching?
a) Falselist of x≥y
b) Falselist of x≥y and falselist of p q
c) Falselist of x≥y, falselist of p q, truelist of p q
d) Truelist of x≥y, falselist of x≥y, truelist of p q, falselist of p q
Ans: B
Explanation:
(A) B1.truelist
(B) B1.falselist
(C) B2.truelist
(D) B2.falselist
Ans: B
Explanation:
6. For the rule B B1 and B2, the operation "B1.false = B.false" requires two passes as
7. In the rule C→C1 AND NC2 the non terminal N is used to remember the start address of:
(A) C
(B) C₁
(C) Both C₁ and C
(D) None of the other options
Ans: B
Explanation:
(A) then-part
(B) else-part
(C) both then- and else-part
(D) None of the other options
Ans: A
Explanation:
9. In the rule S if B then M S1, M holds the start address for
(A) S1
(B) S
(C) B
(D) None of the other options
Ans: A
Explanation:
10 For three address code generation of rule “S while M1 B do M2 S1”, B.falselist is
. backpatched with
(A) M1.quad
(B) M2.quad
(C) Cannot be backpatched at this point
(D) None of the other options
Ans: C
Explanation:
11.
Ans: B
Solution:
In TAC, arrays are accessed using their base address and an index offset.
The address of an array element is computed as:
Address=Base Address+(Index×Element Size)
This ensures efficient memory access and supports multi-dimensional arrays using similar
calculations.
12.
In the rule S → while M1 B do M2 S1, the non-terminal M2 is used to remember the start
address of:
(A) S
(B) B
(C) S1
(D) None of the other options
Explanation:
• (A) S → Incorrect, because S is the entire statement, not just the body.
• (B) B → Incorrect, because B is a condition, not the loop body’s start point.
13.
Ans: B
END of Assignment
NPTEL Online Certification Courses Indian
Institute of Technology Kharagpur
Compiler Design
Assignment- Week 12
TYPE OF QUESTION:MCQ
Number ofquestions:12 Total mark: 12 X 1 = 12
(A) Callee
(B) Caller
(C) Both Caller and Callee
(D) None of the other options
Ans: B
Explanation:
In most programming languages, the caller is responsible for evaluating actual
parameters before passing them to the function. This is known as call-by-value (used in
languages like C, Java for primitives) or call-by-reference (used in C++ with references
and Java for objects). The callee simply receives the already evaluated arguments and
uses them.
(A) Caller
(B) Callee
(C) Both Caller and Callee
(D) None of the above
"In a callee-save register convention, who is responsible for saving registers?"
Ans: B
Explanation:
How it works:
• In the System V AMD64 ABI (used in Linux), registers like RBX, RBP, and R12-
R15 are callee-saved, meaning the callee must preserve them.
• In Windows stdcall and fastcall conventions, specific registers follow this rule as
well.
(A) Callee
(B) Caller
(C) Both Caller and Callee
(D) None of the other options
Ans: A
Explanation:
Local storage (such as local variables and stack frames) is typically created by the callee
when a function is invoked. This is done by:
1. Allocating space on the stack (or another memory region) for local variables.
2. Adjusting the stack pointer (e.g., decrementing the stack pointer in architectures
like x86).
3. Storing saved registers, return addresses, and function parameters as needed.
8. For a switch statement, the expression can result into values in the range -5 to +6.
Number of entries in the jump table should be
(A) 5
(B) 6
(C) 11
(D) 12
Ans: D
Explanation:
A jump table is an array indexed based on the possible values of the expression in a
switch statement. The number of entries in the jump table is determined by the range of
values, calculated as:
• Maximum value = +6
• Minimum value = -5
• Total entries = (6−(−5))+1 = 6+5+1 = 12
9. For a switch statement implemented as a jump table, default_case is
In a switch statement implemented using a jump table, the default case is not a
direct part of the jump table. Instead, the jump table only maps valid case values to
their corresponding addresses.
10. For pair of goto based storage allocation for functions, the second goto statement
transfers control to the beginning of
1. First goto → Jumps to a location where storage (e.g., stack space) is allocated for
the function.
2. Second goto → Transfers control to the beginning of the function code, where
execution begins.
11.
In a jump table-based switch statement, how is the index for the jump table calculated
when the case values include negative numbers?
Ans : B
Explanation:
A jump table works by using an array where each index corresponds to a case label.
However, arrays cannot have negative indices, so all case values are shifted by
subtracting the smallest case value.
12.
Which of the following occurs during the calling sequence of a function call?
Ans: A
Explanation:
The calling sequence is the set of actions performed before transferring control to the
function. These include:
• Saving the return address (so execution can resume after the function
completes).
• Passing arguments to the function (via registers or the stack).
• Allocating stack space for local variables.
• Transferring control to the function.
END of Assignment