0% found this document useful (0 votes)
11 views

Compiler Design Assignment(1)

This assignment explores fundamental concepts in compiler design, including abstract stack machines, context-free grammars, Lex specifications, LR parsers, and dynamic storage allocation. It emphasizes the importance of these theoretical models and practical tools in creating efficient compilers that translate high-level programming languages into machine code. The document also discusses various parsing techniques and memory management strategies essential for compiler functionality.

Uploaded by

surafel123emiru
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

Compiler Design Assignment(1)

This assignment explores fundamental concepts in compiler design, including abstract stack machines, context-free grammars, Lex specifications, LR parsers, and dynamic storage allocation. It emphasizes the importance of these theoretical models and practical tools in creating efficient compilers that translate high-level programming languages into machine code. The document also discusses various parsing techniques and memory management strategies essential for compiler functionality.

Uploaded by

surafel123emiru
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

Borana university

College of engineering and technology


Department of
Computer science
Assignment of:-
Course:compiler design
Group name :-

1.Reta shibeshi
2.Surafel Emiru
3.Abduba Boru
4.Bamlak Abebayu

Instructor: Dawit H
Submission date:30/5/2017
Yabello,Ethiopia
Table of contents

Introduction ····································································································· 1
1: Define and discuss the term “Abstract Stack Machines” ········································2
2: Consider the context-free grammar ·································································3
3: From a language for specifying lexical analyzers, discuss Lex specifications. ·············· 5
4: Discuss LR Parser, the LR Parsing algorithms, and Error Recovery in LR Parsing. ······· 6
5: Discuss language facilities for dynamic storage allocation in compiler design briefly. ···· 7
summary ·········································································································9
References: ···································································································· 10

I
Introduction

Compiler design is a cornerstone of computer science, enabling the translation of high-level


programming languages into machine code that can be executed by a computer. It bridges the
gap between human-readable code and the binary instructions understood by hardware. This
assignment delves into critical aspects of compiler design, including theoretical frameworks like
abstract stack machines, the application of context-free grammars, and the practical
implementation of lexical analyzers and parsers. By exploring these areas, we gain insights into
how compilers manage memory, resolve syntactic ambiguities, and optimize code execution. A
thorough understanding of these concepts is essential for creating efficient, reliable, and robust
compilers that support modern programming languages.Compiler design is a fundamental area in
computer science that focuses on creating programs capable of translating high-level
programming languages into machine-readable code. This assignment explores various core
concepts of compiler design, including theoretical models like abstract stack machines, practical
tools such as Lex, and parsing techniques like LR parsing. Understanding these topics helps in
building efficient and robust compilers.

1
1: Define and discuss the term “Abstract Stack Machines”

Abstract stack machines are a theoretical model of computation that simulate the behavior of real
machines but operate at a higher level of abstraction. These machines use a stack as their primary
data structure for storing intermediate values during computations. Abstract stack machines are
commonly employed in the design and implementation of compilers, particularly for executing
intermediate representations of code.

Key characteristics of abstract stack machines include:

1.Stack-Based Operations:

o They rely on a stack for storing operands and results of operations. The last-in,
first-out (LIFO) structure of the stack simplifies the implementation of arithmetic
and logical operations.

2.Instruction Set:

o Instructions are designed to push values onto the stack, pop values from the stack,
and perform operations using the topmost stack elements.

3.Platform Independence:

o Abstract stack machines are not tied to specific hardware, making them useful for
intermediate representations in compilers.

4.Applications:

o Abstract stack machines are used in the interpretation of bytecode languages like
Java bytecode (executed by the Java Virtual Machine) and .NET Common
Intermediate Language.

2
Advantages:

 Simplicity in design and implementation.


 Compact representation of operations.

Disadvantages:

 Performance can be slower compared to register-based architectures due to frequent stack


accesses.

2: Consider the context-free grammar

S→SS+|SS*|a

a) Show how the string “aa+a” can be generated by this grammar.*

To generate the string “aa+a”, we follow these steps:

1 Start with the initial non-terminal: S

2 Apply the production S → S S *:

 S→SS*

3 For the first S on the right-hand side, apply S → S S +:

 S → (S S +) S *

4 Replace each remaining S with 'a' using S → a:

 S → (a a +) a *

Thus, the string aa+a* is generated by this grammar.

3
b) Construct a parse tree for this string.

The parse tree for the string aa+a* is as follows:

S
/|\
/|\
S S *
/|\
/|\
S S +
/ \
a a

c) What language is generated by this grammar? Justify your answer.

The language generated by this grammar consists of strings in postfix notation (also known as
Reverse Polish Notation) using the terminal “a” as the operand and the operators “+” and “*”. In
postfix notation, operators follow their operands, eliminating the need for parentheses to specify
the order of operations.

Justification:

 The production rules ensure that each operator (“+” or “*”) is applied to two operands,
maintaining the postfix structure.
 Examples of strings generated by the grammar include a, aa+, aa*, aa+a*, etc.

4
3: From a language for specifying lexical analyzers, discuss Lex specifications.

Lex is a tool used for generating lexical analyzers (scanners) in compiler design. It transforms
regular expressions and corresponding actions into a C program that reads input, matches
patterns, and executes associated actions.

Components of Lex Specifications:

1. Definition Section:
o Contains declarations and macros to define patterns and variables.
o Example:
o DIGIT [0-9]
o LETTER [a-zA-Z]
2. Rules Section:
o Specifies patterns (regular expressions) and actions (code) to be executed when a
pattern is matched.
o Example:
o {DIGIT}+ { printf("Number: %s\n", yytext); }
o {LETTER}+ { printf("Word: %s\n", yytext); }
3. User Code Section:
o Contains C code to support the lexical analyzer, such as the main function.
o Example:
o int main() {
o yylex();
o return 0;
o }

How Lex Works:

1. Input: Regular expressions and associated actions.


2. Output: A C program implementing the lexical analyzer.

5
3. Execution: The generated program reads input, matches patterns, and executes
corresponding actions.

Advantages:

 Simplifies the creation of lexical analyzers.


 Handles complex patterns using regular expressions.
 Integrates seamlessly with parser generators like Yacc.

4: Discuss LR Parser, the LR Parsing algorithms, and Error Recovery in LR


Parsing.

LR Parser:

 An LR parser is a bottom-up parser used for analyzing deterministic context-free


languages.
 It constructs a rightmost derivation in reverse by scanning the input from left to right.

Types of LR Parsers:

1. SLR (Simple LR) Parser:


o Simplest form, with smaller parsing tables.
o Less powerful and may fail for certain grammars.
2. CLR (Canonical LR) Parser:
o Uses complete lookahead sets, making it more powerful.
3. LALR (Look-Ahead LR) Parser:
o Combines states with identical cores to reduce table size.
o Balances power and efficiency.

LR Parsing Algorithm:

1. Initialization: Start with an empty stack and initial state.


2. Action:

6
o Shift: Push the current input symbol and state onto the stack.
o Reduce: Apply a grammar rule, replacing symbols on the stack.
o Accept: Successfully parse the input.
o Error: Handle syntax errors.
3. Repeat: Continue until the input is fully parsed or an error is encountered.

Error Recovery in LR Parsing:

 Techniques to handle errors during parsing:


1. Panic Mode Recovery: Discard input symbols until a synchronizing token is
found.
2. Phrase Level Recovery: Replace incorrect constructs with valid ones based on
predefined rules.
3. Error Productions: Extend the grammar with rules for common errors.
4. Global Correction: Modify the input minimally to ensure successful parsing.

5: Discuss language facilities for dynamic storage allocation in compiler design


briefly.

Dynamic storage allocation refers to the ability of a program to request and release memory
during runtime. In compiler design, this involves managing heap memory efficiently.

Facilities for Dynamic Storage Allocation:

1. Heap Memory Management:


o Compilers generate code to allocate memory from the heap for data structures like
arrays and objects.
2. Garbage Collection:
o Automates memory deallocation to prevent memory leaks.

7
o Examples include mark-and-sweep, reference counting, and generational garbage
collection.
3. Memory Allocation Functions:
o Languages provide built-in functions for memory management:
 C: malloc(), calloc(), realloc(), free().
 C++: new and delete operators.
 Java: Automatic garbage collection.
4. Stack vs. Heap Allocation:
o Stack: Used for local variables with fixed lifetimes.
o Heap: Used for dynamic objects with variable lifetimes.

Challenges:

 Avoiding fragmentation.
 Ensuring efficient memory usage.
 Preventing memory leaks and dangling pointers.

8
summary

This assignment has provided a comprehensive exploration of fundamental concepts in compiler


design. We began by discussing abstract stack machines, highlighting their role in simulating
computation and supporting intermediate representations in compilers. The analysis of context-
free grammars illustrated their application in generating and parsing strings in postfix notation,
emphasizing the structured approach to language processing. The Lex tool was introduced as a
powerful mechanism for specifying lexical analyzers, showcasing its utility in handling complex
patterns. LR parsers were examined in detail, including their types, algorithms, and error
recovery methods, demonstrating their importance in constructing deterministic context-free
parsers. Lastly, we addressed dynamic storage allocation, underlining its significance in efficient
memory management during runtime.

In summary, this assignment underscores the interconnectedness of theoretical models, practical


tools, and algorithmic techniques in compiler design. Together, they form the foundation for
developing compilers that efficiently translate and optimize high-level code into executable
programs.

9
References:

1. Aho, A. V., Lam, M. S., Sethi, R., & Ullman, J. D. (2006). Compilers: Principles,
Techniques, and Tools (2nd ed.). Pearson Education.
2. Appel, A. W. (2002). Modern Compiler Implementation in C. Cambridge University
Press.
3. Lex & Yacc Documentation. Retrieved from https://dinosaur.compilertools.net/
4. Stanford University Lecture Notes on Compiler Design. Retrieved from
https://infolab.stanford.edu/~ullman/ialc.html

10

You might also like