0% found this document useful (0 votes)
13 views3 pages

COSC 327 Compiler Construction Exam

Uploaded by

chukauniversiity
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)
13 views3 pages

COSC 327 Compiler Construction Exam

Uploaded by

chukauniversiity
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

COSC 327

CHUKA UNIVERSITY

UNIVERSITY EXAMINATIONS

EXAMINATION FOR THE AWARD OF DEGREE OF BACHELOR OF SCIENCE


IN COMPUTER SCIENCE
COSC 327: COMPILER CONSTRUCTION

STREAMS: BSC (COMP. SCI) Y3S2 TIME: 2 HOURS

DAY/DATE: MONDAY 08/4/2019 2.30 P.M. – 4.30 P.M.


INSTRUCTIONS: Answer Question One and any other two questions

Question One (Compulsory) (30 marks)


(a) Explain the difference between a compiler and an interpreter. (4 marks)

(b) Explain when a grammar G is said to be ambiguous. Give an example to illustrate your
answer together with a demonstration that it’s indeed ambiguous. (4 marks)

(c) At a given point in the execution of a program, what can be considered as garbage? How
can garbage be located in memory? (4 marks)

(d) Explain two reasons why stack is used for storing procedure calls in compiler
construction. (4 marks)

(e) Using a C sample code illustration, explain the difference between formal parameters
and actual parameters in functions. (4 marks)

(f) Identify four reasons of creating intermediate code during compilation as opposed to
directly translating source code to machine code. (4 marks)

(g) Discuss the three rules of code optimization. (6 marks)

Page 1 of 3
COSC 327

Question Two (20 marks)


(a) State and explain the two major operations on a symbol table. (4 marks)

(b) Consider an optimization that replaces any expression of the form

0xe

with 0, where e is an arbitrary expression. Why might this rule be useful in a


compiler's optimization phase? Is it always correct? (6 marks)

(c) Let G be the following grammar:

S -> A
A ->B | B a A
B -> b C
C -> Cb | Cc | ε

Modify G to produce a new grammar, G’. Show that G’ is LL(1). Describe the
condition(s) that G’ meets that makes it LL(1). (10 marks)

Question Three (20 marks)

(a) Explain what a symbol table is and state its importance in compilation process.(4 marks)

(b) Describe four optimizations likely to be performed on a piece of code during compilation.
(8 marks)
(d) Consider the following grammar:
S → (L)
|a
L → L,S
|S
Under this grammar, derive the parse tree of the sentence (a, ((a, a), a)) (8 marks)

Question Four (20 marks)

(a) Given production rules, generate a parse tree for the input string:
b = a * x / y + z * x/y;

Use left most derivation. Show all the steps involved. (10 marks)
The production rules:
E→E+E
E→E/E
E→E*E
E → id
E → num

Page 2 of 3
COSC 327

(c) For each of the production rules (c) above, write their corresponding semantic rules.
(4 marks)
(d) Generate a Directed Acyclic Graph from the syntax tree in (a) above. (6 marks)

Question Five (20 marks)

(a) Outline four semantic errors that a compiler should check and report. (4 marks)

(b) Explain the following compilation stages. (8 marks)

(i) Syntax analysis


(ii) semantic analysis
(iii) code generation
(iv) code optimization

(c) Three address code and instructions for the instructions shown below and represent them
in a quadruple. (8 marks)

y = z * x
while (y > z){
x = y * z
y = z – x
z = y * z
}

------------------------------------------------------------------------------------------------------

Page 3 of 3

Common questions

Powered by AI

The optimization rule of replacing '0 * e' with '0' simplifies computations by eliminating unnecessary operations, potentially improving execution time. However, it may be problematic in cases where 'e' has side effects or is a function call, as eliminating 'e' also removes any associated side effects or evaluations, which could alter the program's behavior. Hence, this optimization requires careful consideration of the context in which expressions are evaluated .

A compiler translates an entire program into machine code before the program is executed, which means it processes the source code all at once, generating an executable that can be run independently. In contrast, an interpreter translates and executes the program one line at a time, meaning it processes the source code line-by-line or statement-by-statement without producing an intermediate machine code file .

Creating intermediate code serves multiple purposes: it improves portability by allowing the intermediate code to run on different machine architectures; it simplifies optimization by providing a platform-independent representation; and it eases the translation of high-level source code by decoupling the process into manageable stages. Moreover, it reduces complexity by separating concerns between front-end and back-end compilation processes .

Syntax analysis, or parsing, involves checking the source code against grammatical structure defined by the language's syntax rules. It ensures that constructs are syntactically correct, generating a parse tree or abstract syntax tree. Semantic analysis uses the parse tree output to check for semantic correctness, such as type-checking, and ensures that operations conform to the language's semantics. While syntax analysis is concerned with form, semantic analysis is concerned with meaning, and together they validate the input program before code generation .

A grammar is ambiguous when there exists at least one string that can be generated by the grammar in more than one parse tree or derivation sequence. For example, consider a grammar with the production rules: E -> E + E | E * E | id. The expression 'id + id * id' can result in two different parse trees, representing (id + id) * id and id + (id * id), making the grammar ambiguous because the parse trees can represent different computations .

Stacks are used to store procedure calls primarily because they naturally support the last-in, first-out (LIFO) order of function invocations in programming languages. They facilitate the management of function calls and returns, allowing the compiler to maintain the state and local variables of each function invocation effectively and efficiently. This also allows for straightforward implementation of recursive function calls and backtracking .

The three fundamental rules of code optimization are: (1) Eliminate common subexpressions to avoid redundant calculations. (2) Perform loop transformations to improve the performance of iterative structures. (3) Apply inlining and other transformations to reduce function call overhead. These rules are essential as they enhance the efficiency and execution speed of the compiled code, contributing to overall performance improvements without altering functionality .

Garbage is defined as data in memory that is no longer accessible in any part of the program. It is typically identified using garbage collection algorithms that track references to objects. When an object has no remaining references, it is considered unreachable and thus identifies as garbage. Algorithms like mark-and-sweep and reference counting are used to locate such objects and clean them up to free memory .

Formal parameters are the variables defined in the function declaration or definition that specify the inputs required by the function. They act as placeholders for the input values, which are actual parameters passed during the function call. For instance, in a C function defined as `int add(int x, int y)`, `x` and `y` are formal parameters. In a call like `add(5, 10)`, the numbers `5` and `10` are the actual parameters given to the function .

Symbol tables function as a data structure that a compiler uses to store and manage information about the various identifiers (such as variable and function names) encountered in the source program. The two major operations they support are 'insert', to add new identifiers and associated information, and 'lookup', to retrieve stored information for existing identifiers. These operations are crucial for semantic analysis, allowing for type checking and scope management .

You might also like