0% found this document useful (0 votes)
39 views18 pages

Compiler Answers

The document discusses various concepts related to compilers and parsing including: 1. An ambiguous grammar is defined as one that allows multiple leftmost or rightmost derivations for the same input string. 2. Language translators like compilers and interpreters convert source code between programming languages, while compilers specifically transform source code into machine-readable formats. 3. Left factoring is a technique to eliminate common prefixes in grammar productions.

Uploaded by

Anupam Vats
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39 views18 pages

Compiler Answers

The document discusses various concepts related to compilers and parsing including: 1. An ambiguous grammar is defined as one that allows multiple leftmost or rightmost derivations for the same input string. 2. Language translators like compilers and interpreters convert source code between programming languages, while compilers specifically transform source code into machine-readable formats. 3. Left factoring is a technique to eliminate common prefixes in grammar productions.

Uploaded by

Anupam Vats
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

2 Marks

1. Describe an ambiguous grammar with example.

A Grammar that makes more than one Leftmost Derivation (or Rightmost Derivation) for the similar
sentence is called Ambiguous Grammar.

Example − E → E+E|E ∗∗ E|id


Solution

∴ Two different parse trees exist for string id + id * id.


∴ Grammar is Ambiguous.
2. Define the terms Language Translator and compiler.

Language translator is a program that converts source code written in one programming language into another
programming language, typically with a different syntax or structure. It can include compilers, interpreters, and other
tools.

Compiler is a specific type of language translator that transforms the entire source code of a program into machine
code or bytecode, which can be directly executed by a computer without the need for further translation during
runtime.

3. Demonstrate left factoring of grammars through an example.

Left factoring is a technique used to eliminate common prefixes in the productions of a grammar.

Example

Do left factoring in the following grammar-

A → aAB / aBc / aAc

Solution-

Step-01:

A → aA’

A’ → AB / Bc / Ac

Again, this is a grammar with common prefixes.

Step-02:

A → aA’
A’ → AD / Bc

D→B/c

This is a left factored grammar.

4. Distinguish between Ambiguous and Unambiguous grammar?

Ambiguous Grammar Unambiguous Grammar

A grammar that allows for multiple parse A grammar that produces only one unique parse
Definition
trees for the same input string. tree for any given input string.

Can have multiple valid parse trees for a Has only one valid parse tree for a given input
Parse Trees
single input string. string.

Allows for more than one interpretation or


Ambiguity Ensures a single interpretation or meaning.
meaning.

Can be more difficult to understand due to Tends to be easier to understand as there is only
Readability
multiple possible interpretations. one possible interpretation.

Requires disambiguation techniques or Can be parsed using standard parsing algorithms


Parsing additional context to determine the without the need for additional techniques or
intended meaning. context.

Challenging to implement in programming


Easier to implement in programming languages
Programming languages as it requires resolving the
as it has a clear structure.
ambiguity.

Examples The grammar S → SS S→a

5. Analyse Augmented Grammar with an example

An augmented grammar is a modified version of a context-free grammar that includes a distinguished start symbol
and a new production rule to derive it. The augmented grammar helps in formalizing and analyzing the language.

For example, consider the grammar G: S → aS | ε. The augmented grammar G': S' → S, S → aS | ε adds a new start
symbol S' and a production rule to derive it.

6. Compare S-Attribute and L-Attribute SDT?

S-attribute and L-attribute syntax-directed translation (SDT) differ in the order in which semantic actions are
performed. S-attribute SDT performs actions in a bottom-up order, while L-attribute SDT performs actions in a top-
down order. S-attribute SDT is based on synthesized attributes, while L-attribute SDT is based on inherited attributes.

7. Describe the following terms 1. Quadruples 2. Triples

1. Quadruples: Quadruples are data structures consisting of four components or fields that store information related
to a programming language. They are commonly used in compilers and interpreters to represent various aspects of a
program, such as operations, operands, and results, for efficient processing.

2. Triples: Triples are data structures composed of three fields that store information in the context of programming
languages or compilers. They are used to represent operations, operands, and results in a concise manner. Triples are
often generated during the compilation process to facilitate code optimization and execution.

8. Explain the concept of left recursion and left factoring.


Left recursion refers to a situation in a grammar where a non-terminal symbol can directly or indirectly produce a
derivation of itself as the leftmost symbol. This can lead to infinite loops in parsing.

Left factoring is a technique used to eliminate ambiguity in a grammar by identifying common prefixes among
different productions and factoring them out. It helps in making the grammar more efficient and easier to parse.

9. Classify different types of LR parser?

The different types of LR parsers are:

• LR(0) parser: Examines zero lookahead symbols.


• SLR(1) parser: Uses a simplified version of LR(1) with a parsing table that may contain conflicts.
• LALR(1) parser: Merges states with identical core sets in LR(1) to reduce table size.
• LR(1) parser: Looks ahead one symbol to make parsing decisions.
• Canonical LR(1) parser: Constructs the most powerful parser using the full LR(1) algorithm without state
merging.
10. Define a DAG?

A directed acyclic graph (DAG) is a graph that is directed and without cycles connecting the other edges. This means
that it is impossible to traverse the entire graph starting at one edge. The edges of the directed graph only go one
way. The graph is a topological sorting, where each node is in a certain order.

11. Define peephole optimization?

Peephole optimization is an optimization technique performed on a small set of compiler generated instructions; the
small set is known as the peephole optimization in compiler design or window.

The objectives of peephole optimization are as follows:

a) Improve performance
b) Reduce memory footprint
c) Reduce code size.

12. How many tokens in the following statement.

main()

int x==10, y<=10;

printf("%d%d%d Correct answer is",x);

}
13. Define tokens, patterns and lexemes.
- Tokens: Individual units of meaning in a program or text, such as keywords, identifiers, numbers, or symbols.
- Patterns: Rules or templates used to identify and match specific sequences of tokens in a program or text.
- Lexemes: Sequences of characters in a program or text that form a single unit identified by a pattern, which is
typically associated with a token.
14. List out the phases of a compiler.

The phases of a compiler are as follows:

1. Lexical Analysis: Breaks the source code into tokens.


2. Syntax Analysis: Checks the syntax and generates a parse tree.
3. Semantic Analysis: Performs type checking and verifies the meaning of statements.
4. Intermediate Code Generation: Transforms the source code into an intermediate representation.
5. Code Optimization: Improves the efficiency of the generated code.
6. Code Generation: Translates the intermediate code into target machine code.
7. Symbol Table Management: Manages information about variables and functions.
8. Error Handling: Identifies and reports any errors encountered during compilation.
15. Show how many tokens in the following grammar

int max(x, y)

int x, y;

/* Find max of x & y */

return (x>y? x:y);

16. Point out the characteristics of peephole optimization.

Peephole optimization is a technique used in compiler optimization. Its characteristics are:

1. Localized: It analyzes a small section of code at a time.


2. Pattern-based: It identifies specific patterns or sequences of instructions.
3. Targeted: It focuses on eliminating redundant or inefficient code.
4. Iterative: It can be applied multiple times to improve code efficiency.
5. Code transformation: It modifies the code to generate more optimized versions.
17. Define LR(0) items in bottom up parsing?

LR(0) items in bottom-up parsing are the augmented production rules of a grammar that include a dot (.) to indicate
the current position in the production. These items represent possible configurations of the parser, showing what the
parser expects to see next in order to reduce the input to a valid parse tree.

18. Analyse conflicts in shift reduce parsing

Conflicts in shift-reduce parsing occur when the parser encounters a state where it has multiple options: either to
shift (move the next input symbol onto the stack) or to reduce (apply a production rule). These conflicts can lead to
ambiguity and require additional rules or strategies to resolve them.

19. Explain the term code optimization.

Code optimization refers to the process of improving the efficiency and performance of a computer program by
making changes to the code. It involves techniques such as removing unnecessary operations, reducing memory
usage, and improving algorithms to make the code run faster and consume fewer resources.

20. Explain the concept of peephole optimization.

Answer 11

5 Marks

21. Analyse various types of top-down parsing?

Top-down parsing is a technique used in computer programming to analyze and understand the structure of a given
input based on a grammar. There are various types of top-down parsing algorithms:

1. Recursive Descent Parsing: It starts with the start symbol and applies production rules recursively to generate the
input string. It's simple but can be inefficient for ambiguous grammars.

2. LL(1) Parsing: It is an extension of recursive descent parsing where LL stands for Left-to-right, Leftmost derivation.
It uses a lookahead of one symbol to make parsing decisions.

3. LL(k) Parsing: Similar to LL(1) parsing, but with a lookahead of k symbols. It is more powerful and can handle a
wider range of grammars.

4. Predictive Parsing: It's a type of LL parsing where a predictive parsing table is used to determine which production
rule to apply based on the current input symbol.

These top-down parsing techniques help break down complex inputs into a parse tree or a sequence of tokens based
on the given grammar rules.

22. Examine recursive descent parser with suitable example.

A recursive descent parser is a top-down parsing technique used to analyze the structure of a sentence based on a
grammar. Here's a brief explanation in easy language:

• Recursive descent parsing starts with the highest-level rule of the grammar and recursively breaks it down
into smaller sub-rules until the entire sentence is analyzed.
• Each rule in the grammar is associated with a corresponding function in the parser.
• The parser reads the input from left to right and uses the functions to match the input with the grammar
rules.
• If a match is found, the parser moves to the next rule. If not, it backtracks and tries an alternative rule.
• The process continues until either a successful match is found for the entire sentence or an error is
encountered.
• This technique is called "recursive" because the parser calls itself recursively to analyze nested or sub-rules.

For example, consider a simple grammar for arithmetic expressions: E → E + T | T. The recursive descent parser
would recursively call procedures for E, +, and T to parse and evaluate expressions like "3 + 4 * 2".
23. Build CLR(1) parsing table for the following grammar

E --> BB

B --> cB | d

24. Analyse operator precedence grammar with proper example.

A grammar that satisfies the following 2 conditions is called as Operator Precedence Grammar–
• There exists no production rule which contains ε on its RHS.
• There exists no production rule which contains two non-terminals adjacent to each other on its RHS.
• It represents a small class of grammar.
• But it is an important class because of its widespread applications.

25. Solve First and Follow for the following grammar.

S --> aABb

A --> c | ε

B --> d | ε

26. Consider the following grammar: S→B|SabS, B→bB|ε Compute FOLLOW(B)


27. Discuss about the following: a) Induction Variable b) Dead-code Elimination c) Code motion

a) Induction Variable: An induction variable is a variable used in a loop that undergoes a regular increment or
decrement pattern. It is typically used to control the number of loop iterations. By analyzing the induction variable,
compilers can optimize loop operations and improve performance.

b) Dead-code Elimination: Dead-code elimination is a compiler optimization technique that identifies and removes
unnecessary code that does not contribute to the program's final output. This includes variables, statements, or
entire blocks of code that are never used or executed. By eliminating dead code, the compiler can reduce the
program's size and improve its efficiency.

c) Code Motion: Code motion is a compiler optimization technique that involves moving computations or operations
from their original location to a new location within the program. The goal is to minimize redundant computations
and improve performance by reducing the number of instructions executed. Code motion can involve hoisting
expressions out of loops or moving computations closer to their points of use.

In easy language, an induction variable is a special variable used in loops that helps control the number of iterations.
Dead-code elimination is when the compiler removes unnecessary code that doesn't affect the final output. Code
motion is the act of moving calculations or operations to more efficient locations in the program to make it run faster.

6 Marks

28. Examine shift reduce parsing with appropriate example

Shift-reduce parsing is a bottom-up parsing technique used to analyze the structure of a sentence based on a given
grammar. Here's an explanation in easy language using points:

• Shift-reduce parsing involves two actions: shift and reduce.


• Shift means shifting the next input symbol onto the stack.
• Reduce means replacing a sequence of symbols on the stack with a non-terminal symbol, according to a
production rule of the grammar.
• The goal is to reduce the stack until it contains only the start symbol, indicating a successful parse.
• Initially, the stack is empty, and the input contains the sentence to be parsed.
• At each step, the parser decides whether to shift the next input symbol or reduce a sequence of symbols on
the stack.
• The decision is based on the current state of the parser and the grammar rules.
• The process continues until the stack is reduced to the start symbol or no further actions are possible.
• If the stack cannot be reduced to the start symbol, the sentence is not valid according to the given grammar.
• For example, let's consider the input string "2 + 3 * 4". In shift-reduce parsing, the parser would shift "2" onto
the stack, then shift "+" onto the stack. At this point, it can reduce the stack by replacing "2 +" with a non-
terminal symbol representing an arithmetic expression. The parser then shifts "3" onto the stack, followed by
"*". Finally, it can reduce the stack again by replacing "3 *" with another non-terminal symbol representing
an arithmetic expression. The process continues until the entire input is parsed and a complete parse tree is
constructed.

In shift-reduce parsing, the parser shifts input symbols onto the stack and reduces them based on the grammar rules
until the start symbol is reached, indicating a valid parse.

29. Analyse the following terms


i. Ambiguous grammar
ii. Left recursion
iii. Left factoring
iv. Multipass compiler

i. Ambiguous grammar:
- A grammar that allows for multiple parse trees and interpretations for a given sentence.
- It can lead to confusion and ambiguity in the meaning of sentences.
- Ambiguous grammars provide more flexibility and expressiveness in language use but may result in multiple
meanings.

ii. Left recursion:

- It occurs in a grammar when a non-terminal can directly or indirectly produce itself as the leftmost symbol in its
production rules.
- Left recursion can cause issues in parsing and can lead to infinite loops in recursive descent parsing.
- It needs to be eliminated or transformed into a non-left-recursive form to ensure efficient parsing and avoid
infinite recursion.

iii. Left factoring:

- It is a technique used to eliminate redundancy in a grammar by identifying common prefixes in the production
rules.
- Left factoring helps in reducing ambiguity and improving parsing efficiency.
- It involves creating new production rules and introducing new non-terminals to factor out the common prefixes
in the grammar.

iv. Multipass compiler:

- A compiler that goes through the source code multiple times during the compilation process.
- Each pass focuses on a specific task, such as lexical analysis, syntax analysis, semantic analysis, optimization, and
code generation.
- The results of one pass may be used by subsequent passes to improve the overall efficiency and quality of the
compiled code.
- Multipass compilers allow for more sophisticated analysis and optimization techniques but may require more
computational resources and time.
30. Write the algorithm for finding FIRST and FOLLOW.

Here is a simplified algorithm for finding the FIRST and FOLLOW sets in a grammar:

Finding FIRST Set:

1. Initialize the FIRST set for each non-terminal as an empty set.

2. For each non-terminal:

- If it derives a terminal, add that terminal to its FIRST set.


- If it derives another non-terminal, recursively find the FIRST set for that non-terminal and add all its terminals to
the FIRST set.
- If it derives ε (empty string), add ε to the FIRST set.

3. Repeat step 2 until there are no more changes in the FIRST sets.

Finding FOLLOW Set:

1. Initialize the FOLLOW set for each non-terminal as an empty set.

2. Mark the start symbol's FOLLOW set as $ (end of input symbol).

3. For each non-terminal A:

- For each production of the form A → αBβ (where B is a non-terminal):


- Add the FIRST set of β (excluding ε) to the FOLLOW set of B.
- If ε is in the FIRST set of β, add the FOLLOW set of A to the FOLLOW set of B.
- If A appears at the end of a production or as the only symbol on the right side, add the FOLLOW set of A to the
FOLLOW set of the preceding non-terminal in that production.

4. Repeat step 3 until there are no more changes in the FOLLOW sets.

This algorithm helps in determining the FIRST and FOLLOW sets, which are essential for constructing predictive
parsers and analyzing the behavior of a grammar.

31. Discuss the tasks performed by a lexical analyser.

A lexical analyzer, also known as a lexer, performs the following tasks in simple terms:

- Tokenization: It breaks the input source code into smaller units called tokens, such as keywords, identifiers,
operators, and literals.
- Removal of Whitespace: It eliminates unnecessary spaces, tabs, and line breaks, which are not significant in the
programming language.
- Removal of Comments: It filters out comments from the source code, as they are meant for human
understanding and not essential for the computer.
- Identification of Keywords: It recognizes reserved words in the programming language, like "if," "while," and
"for," which have predefined meanings.
- Identification of Identifiers: It identifies user-defined names for variables, functions, and classes in the source
code.
- Handling Constants: It recognizes and categorizes constants, such as numeric literals or string literals, used in the
program.
- Error Handling: It detects and reports lexical errors, such as invalid characters or misspelled tokens, to help
programmers identify and correct mistakes.

Overall, a lexical analyzer plays a vital role in breaking down the source code into meaningful components for further
processing by the compiler or interpreter.

32. Find first and follow for the following grammar

S -> ACB | CbB | Ba

A -> da | BC

B -> g | ε

C -> h | ε
33. Explain Recursive descent parser with proper example

A recursive descent parser is a top-down parsing technique that uses recursive procedures to analyze and parse the
input based on a given grammar. Here's an explanation in 100 words with easy language and points:

- Recursive descent parsers start with the top-level non-terminal symbol of the grammar and recursively break
down the input into smaller subparts.
- Each non-terminal in the grammar corresponds to a procedure in the parser.
- The parser matches the input against the grammar rules by calling the appropriate procedures.
- It starts with the first rule of the non-terminal symbol and tries to match the input.
- If a match is found, it continues recursively with the sub-rules until the entire input is parsed.
- If no match is found, the parser backtracks and tries an alternative rule.
- This process continues until the entire input is successfully parsed or until no more rules are left.

Example:

Consider a simple grammar for arithmetic expressions:

E→E+T|T

T→T*F|F

F → ( E ) | id

Given the input expression "id + id * id," a recursive descent parser would break it down as follows:

1. E → E + T → T + T → id + T → id + T * F → id + F → id + ( E ) → id + ( E + T ) → id + ( T + T ) → id + ( id + T ) → id + ( id
+ T * F ) → id + ( id + F ) → id + ( id + id )

The parser recursively matches the input with the grammar rules until the entire expression is parsed, building a
parse tree in the process.

34. Construct Stack implementation of shift reduce parsing for the grammar

E->E+E

E->E*E

E->(E)

E->id and the input string id1+id2*id3


35. Discuss about the following
i. Copy propagation

Copy propagation is a compiler optimization technique that replaces uses of a variable with its assigned value,
effectively propagating the value throughout the program, reducing the need for unnecessary variable copies.

ii. Dead code elimination

Answer 27

iii. Code motion

Answer 27

8 Marks

36. Classify various types of parsers in details.

Here's a classification of various types of parsers, including Recursive Descent, LALR, LR, LL, CLR, and SLR, explained in
easy language using bullet points:

1. Recursive Descent Parser:

- Top-down parsing technique.


- Matches the input with a set of recursive procedures or functions.
- Each non-terminal symbol has a corresponding procedure.
- Requires a separate procedure for each production rule.
- Simple to implement but not suitable for left-recursive grammars.

2. LALR (Look-Ahead LR) Parser:

- Bottom-up parsing technique.


- Uses a table-driven approach to parse the input.
- Combines LR(0) and SLR(1) parsing methods.
- Handles a large class of grammars efficiently.
- Constructs a deterministic finite automaton (DFA) for parsing.

3. LR (Canonical LR) Parser:


- Bottom-up parsing technique.
- Handles a larger class of grammars than LALR parsers.
- Builds a parse table based on a canonical collection of LR(0) items.
- Supports shift-reduce and reduce-reduce actions in parsing.

4. LL (Left-to-Right, Leftmost Derivation) Parser:

- Top-down parsing technique.


- Reads the input from left to right and constructs a leftmost derivation.
- Uses a predictive parsing table to determine production rules.
- Often used for LL(k) grammars, where k denotes the number of look-ahead symbols.
5. CLR (Canonical LR) Parser:
- Bottom-up parsing technique.
- More powerful than LALR and SLR parsers.
- Constructs a canonical collection of LR(1) items.
- Handles a wide range of grammars, including those with left recursion.
6. SLR (Simple LR) Parser:
- Bottom-up parsing technique.
- Simplified version of LR(0) parser.
- Uses a simplified parsing table compared to LR and LALR parsers.
- Less powerful but easier to construct and understand.

These are the main types of parsers commonly used in language processing. Each type has its own strengths and
limitations, and their selection depends on the grammar characteristics and requirements of the language being
parsed.

37. Consider the grammar E->E + E|E *E|(E)| id. Show the sequence of moves made by the shift-reduce parser on
the input id1+id2*id3 and determine whether the given string is accepted by the parser or not.

Answer 34

38. Calculate first and follow for the following grammar

S --> aBDh

B --> cC

C --> bC | ε

D --> EF

E --> g | ε

F --> f | ε
39. Construct the predictive parsing table for the following grammar:

S→AaAb | BbBa

A→ ε

B→ ε

Show that this grammar is LL (1).

40. Analyse the common three address instruction forms with suitable example?

Three-address instructions are commonly used in computer programming to represent operations involving three
operands or addresses. Here's an analysis of the common three-address instruction forms with suitable examples:

1. Assignment Instruction:

- Syntax: `x = y op z`
- Explanation: Assigns the result of the operation `op` between operands `y` and `z` to variable `x`.
- Example: `a = b + c` assigns the sum of variables `b` and `c` to variable `a`.

2. Conditional Instruction:
- Syntax: `if x op y goto L`
- Explanation: Performs a conditional jump to label `L` if the condition `x op y` is true.
- Example: `if a < b goto L1` jumps to label `L1` if the value of `a` is less than the value of `b`.

3. Goto Instruction:

- Syntax: `goto L`
- Explanation: Unconditionally jumps to the label `L`.
- Example: `goto L2` transfers control to label `L2` without any condition.

4. Array Access Instruction:

- Syntax: `x = array[i]`
- Explanation: Assigns the value at index `i` of the array `array` to variable `x`.
- Example: `a = array[3]` assigns the value at index 3 of `array` to variable `a`.

5. Function Call Instruction:

- Syntax: `x = func(y)`
- Explanation: Calls a function `func` with argument `y` and assigns the returned value to variable `x`.
- Example: `result = square(5)` calls the function `square` with argument 5 and assigns the returned value to
`result`.

These common three-address instruction forms allow for expressing a wide range of operations and control flow in a
programming language, making it easier to represent complex algorithms and computations.

41. Build following assignment statement into three address code

D:=(a-b)*(a-c)+(a-c)
42. Define syntax tree? Discover the syntax tree for the assignment statement.

a :=b * -c + b * -c.

A syntax tree is a graphical representation of the hierarchical structure of a sentence or program, showing how its
components relate to each other according to the grammar rules.

43. Construct LR(0) parsing table for the following grammar

S --> AA

A --> aA|b
44. Remove left recursion of the following grammar and construct the LL(1) parsing table.

E --> E+T | T

T --> T*F | F

F --> (E) | id
45. Analyse LALR parsing table for the following grammar

E --> BB

B --> cB | id

You might also like