Sem 5 Major
Sem 5 Major
In Compiler Design, regular expressions are concise notations used to define and
recognize patterns in source code. They play a crucial role in lexical analysis,
where they are used to identify and extract tokens (e.g., keywords, identifiers)
from code. Regular expressions help in defining the syntax of programming
languages, facilitating the transformation of human-readable code into machine-
readable forms during compilation.
(a) Left recursion is a challenge in top-down parsers.
(b) The leftmost derivation is a derivation where the leftmost non-terminal is
expanded first.
(c) Grammar which produces more than one parse tree is ambiguous grammar.
(d) The replacement of the right side of a production by the left side is called
reduction.
(e) The four parts of predictive parsers are input buffer, stack, parsing table,
and output.
Two examples of one-pass compilers are:
Q15: What is left recursion? Eliminate left recursion in the given examples.
An LR parser is a type of bottom-up parser used in compiler design to parse context-free grammars.
It reads the input from left to right (L) and produces a rightmost derivation in reverse (R). LR parsers
are highly efficient and can handle a wide range of grammars, including those not suitable for top-
down parsing.
Key Features:
1. Deterministic Parsing: Uses a deterministic finite automaton (DFA) to efficiently parse inputs.
2. Handles Conflicts: Can manage shift-reduce and reduce-reduce conflicts better than simpler
parsers.
3. Parsing Table: Relies on a parsing table with actions like shift, reduce, accept, and
error.
Types of LR Parsers:
Workflow:
Use Case: LR parsers are widely used in compilers for programming languages like C, C++, and Java
due to their robustness and ability to handle complex grammars.
cfg
Example: E → E + T | T
Formal Definition:
Process of SDT:
• Explanation: This refers to the code generated for an expression E during intermediate code
generation.
• Answer: E.code has instructions representing the evaluation of E. For example, E → E1 +
E2 might generate the code:
makefile
Copy code
t1 = E1.code
t2 = E2.code
t3 = t1 + t2
Q8: Write the SDT (Syntax-Directed Translation) for any Boolean expression.
mathematica
Copy code
E → E1 AND E2 { E.code = E1.code || E2.code }
Example:
Input: a AND b OR c
Output (Three-address code):
css
Copy code
t1 = a AND b
t2 = t1 OR c
Example: For a function int sum(int a, int b), the activation record includes:
• Parameters a and b.
• Local variable for the result.
• Return address for the caller.
A parsing table is a data structure used in syntax analysis to guide the parsing process.
1. In LL parsers: It maps a combination of a non-terminal and input token to a production rule.
2. In LR parsers: It contains actions (shift, reduce, accept) and goto states.
Q11: Regular expression for the language where w∈{0,1}∗w \in \{0,
1\}^*w∈{0,1}∗ such that www has no consecutive 1's.
1. Regular Expression:
markdown
Copy code
(0+1)*0*
2. NFA:
States: q0,q1q_0, q_1q0 ,q1 .
Transitions:
lua
Copy code
q_0 -- 0 --> q_0
q_0 -- 1 --> q_1
q_1 -- 0 --> q_0
3. DFA: Optimize the NFA to remove ε-transitions and ensure deterministic behavior.
1. Transition Diagram: States for integers (e.g., q0,q1,q2q_0, q_1, q_2q0 ,q1 ,q2 ) representing
digits 0−90-90−9.
2. Code: Check for numeric input; reject invalid characters.
Q13: How are self-organizing lists useful for symbol table management?
• Frequently accessed symbols are moved to the front of the list, improving search efficiency.
• Common strategies: Move-to-front, Transpose, and Count.
A Directed Acyclic Graph (DAG) is used for intermediate code optimization by removing duplicate
computations and common sub-expressions.
Example:
For a=b+c;d=a+e;f=b+ca = b + c; d = a + e; f = b + c a=b+c;d=a+e;f=b+c:
css
Copy code
b c
\ /
(+)
/ \
a f
\
(+)
|
d
Solution:
css
Copy code
A → aA'
A' → BαA' \ | aA' \ | ε
Solution:
mathematica
Copy code
E → TE'
E' → +TE' \ | ε
vbnet
Copy code
T → FT'
T' → *FT' \ | ε
4o
You said:
### **Q14: What is DAG? Explain with an example.** A **Directed Acyclic Graph (DAG)** is used for
intermediate code optimization by removing duplicate computations and common sub-expressions.
**Example**: For a\=b+c;d\=a+e;f\=b+ca = b + c; d = a + e; f = b + ca\=b+c;d\=a+e;f\=b+c: css Copy
code `b c \ / (+) / \ a f \ (+) | d`
ChatGPT said:
ChatGPT
A DAG (Directed Acyclic Graph) is a representation used in compilers for intermediate code
optimization. It helps to remove duplicate computations, optimize the use of temporary variables,
and identify common subexpressions.
Purpose of DAG:
Example:
css
Copy code
a = b + c
d = a + e
f = b + c
DAG Representation:
css
Copy code
b c
\ /
(+)
/ \
a f
\
(+)
|
d
Explanation:
makefile
Copy code
t1 = b + c
a = t1
f = t1
t2 = a + e
d = t2
4o
You said:
ChatGPT said:
ChatGPT
Here are comprehensive notes on the requested topics from the chapter Syntax Directed Translation
in Compiler Design:
1. Syntax Directed Translation Scheme
A Syntax Directed Translation (SDT) scheme is a method that uses a context-free grammar to specify
the syntax of a language along with semantic rules to define its meaning. The semantic rules are
associated with grammar productions and guide the translation process.
Key Features:
1. Attributes: Each grammar symbol is associated with attributes that store information.
a. Synthesized Attributes: Computed from children nodes.
b. Inherited Attributes: Computed from parent or sibling nodes.
2. Semantic Rules: Define how attributes are evaluated and are written as code snippets in the
production rules.
Components of SDT:
Example:
kotlin
Copy code
E → E1 + T
Semantic Rule: E.val = E1.val + T.val
1. Parsing Phase:
a. Constructs a Parse Tree based on the grammar.
b. Guides attribute evaluation based on syntax rules.
2. Translation Phase:
a. Uses semantic rules to generate intermediate code or target code.
1. Define a Grammar:
a. Write a grammar for the language.
2. Attach Semantic Rules:
a. Add semantic actions for each production.
3. Design an Attribute Evaluation Scheme:
a. Use an evaluation order (e.g., Postorder for Synthesized Attributes).
4. Code Generation:
a. Generate intermediate or target code during attribute evaluation.
3. Intermediate Code
Intermediate code is a representation of a program that serves as a bridge between high-level and
machine-level code. It is independent of the target architecture.
Example of TAC:
makefile
Copy code
t1 = c * d
t2 = b + t1
a = t2
4. Postfix Notation
Postfix notation (Reverse Polish Notation) is a representation of expressions where the operator
follows its operands. It eliminates the need for parentheses.
Rules:
Example:
5. Parse Tree
Features:
Example:
r
Copy code
E → E + T | T
T → id
bash
Copy code
E
/ | \
E + T
| |
T id
|
id
6. Syntax Tree
A Syntax Tree is a simplified version of a parse tree where nodes represent meaningful constructs
rather than grammar symbols. It abstracts unnecessary details and focuses on the structure.
• Parse trees show all grammar symbols, including terminals and non-terminals.
• Syntax trees show only the essential operations and operands.
Example:
css
Copy code
+
/ \
a *
/ \
b c
Summary Table
These notes provide a structured overview of Syntax Directed Translation and its related concepts in
Compiler Design. Let me know if you need additional examples or further clarifications!
4o
Algorithm for Minimization of DFA (Simple Steps)
1. Start from the initial state and find all states that can be reached by any sequence of inputs.
2. Remove all states that are not reachable.
1. For each input symbol, check where states in the same group transition.
2. If two states in the same group transition to different groups, split them into separate
groups.
3. Repeat this process until no group can be split further.
Operator precedence parsing is used to parse expressions based on operator precedence and
associativity rules. Below are the steps in simple terms:
• Compare the top of the stack with the current input symbol:
o If the stack symbol has lower precedence, push the input symbol onto the stack.
o If the stack symbol has higher or equal precedence, reduce by applying a grammar
rule.
• Reduction means replacing the handle (a part of the string that matches the right-hand side
of a production rule) with the left-hand side of the rule.
• Repeat reductions until the stack symbol has lower precedence than the input symbol.
• If the stack and input tape both contain $, the input is accepted.
• Otherwise, the input is rejected.
Algorithm for Removing Left Recursion
Left recursion occurs in a grammar when a non-terminal refers to itself as the first symbol on the
right-hand side of a production. It can cause problems in top-down parsers like recursive descent.
Here's how to eliminate it:
Given a production: A → Aα | β
Example:
Input Grammar:
A → Aα | β
Transformed Grammar:
• A → βA'
• A' → αA' | ε
Steps to Remove Indirect Left Recursion
Example:
Input Grammar:
A → Bα | β
B → Aγ | δ
Step 1: Substitute B in A:
A → (Aγ | δ)α | β
Step 2: Simplify:
A → Aγα | δα | β
• A → δαA' | βA'
• A' → γαA' | ε
Input Grammar:
E → E + T | T
Steps:
1. Separate:
a. Left-recursive part: E + T
b. Non-left-recursive part: T
2. Rewrite:
a. E → T E'
b. E' → + T E' | ε
Output Grammar:
• E → T E'
• E' → + T E' | ε
This algorithm ensures that the resulting grammar is free of left recursion and can be used for top-
down parsing techniques like recursive descent.