Q.1
14 MarksAlso asked in Winter 2025 Q2a
A compiler translates the whole source program into machine code in one go, before the program runs. An interpreter translates and runs the program one statement at a time.
Both are translators that take a high-level language program as input and both report errors in it.
| Point | Compiler | Interpreter |
|---|---|---|
| Translation | Whole program at once | One statement at a time |
| Output | Creates an object file | Creates no object file |
| Errors | Shown together after compilation | Shown one by one, stops at the first |
| Speed of running | Fast | Slow |
| Example | C, C++ | Python, BASIC |
Also asked in Winter 2025 Q2b, Winter 2024 Q3b
Left factoring is a change made to a grammar when two or more productions of a non-terminal start with the same symbols (a common prefix). The common prefix is taken out and the different endings are moved to a new non-terminal.
Rule:
A → αβ1 | αβ2
becomes
A → αA'
A' → β1 | β2Significance:
- A top-down parser sees only the next input symbol. With a common prefix it cannot decide which production to use.
- After left factoring the choice is delayed until enough input has been seen, so no backtracking is needed.
- It is a required step to make a grammar suitable for predictive (LL(1)) parsing.
Example:
S → iEtS | iEtSeS | a
E → bBoth productions of S start with iEtS. Taking it out gives:
S → iEtSS' | a
S' → eS | ε
E → bNow the parser reads iEtS first and then chooses eS or ε by looking at the next symbol.
Explain phases of compiler in context of front end and back end with example. Give the significance of both.
Also asked in Winter 2025 Q1c, Winter 2024 Q1c, Winter 2023 Q1c, Summer 2023 Q1c
A compiler works in six phases. They are grouped into two parts: the front end and the back end.
Source program
|
[Lexical analysis] \
[Syntax analysis] | Front end
[Semantic analysis] | (analysis)
[Intermediate code] /
|
[Code optimisation] \ Back end
[Code generation] / (synthesis)
|
Target programThe symbol table and the error handler work with all six phases.
Front end
The front end depends on the source language and not on the target machine.
- Lexical analysis: reads characters and groups them into tokens.
- Syntax analysis: checks the grammar and builds a parse tree.
- Semantic analysis: checks meaning, such as types, and adds type conversions.
- Intermediate code generation: produces a machine-independent code, such as three address code.
Back end
The back end depends on the target machine and not on the source language.
- Code optimisation: improves the intermediate code so that it runs faster or uses less memory.
- Code generation: produces the target assembly or machine code and assigns registers.
Example
Statement: position = initial + rate * 60, where all three variables are of type float.
| Phase | Output |
|---|---|
| Lexical | id1 = id2 + id3 * 60 |
| Syntax | Tree with = at the root, + below it and * below + |
| Semantic | 60 is changed to inttofloat(60) |
Intermediate code:
t1 = inttofloat(60)
t2 = id3 * t1
t3 = id2 + t2
id1 = t3After code optimisation:
t1 = id3 * 60.0
id1 = id2 + t1After code generation:
LDF R2, id3
MULF R2, R2, #60.0
LDF R1, id2
ADDF R1, R1, R2
STF id1, R1Significance
- Front end: it finds the errors in the program and gives a code that does not depend on any machine. To support a new machine, the same front end is used again.
- Back end: it gives fast and small target code for one machine. To support a new language, the same back end is used again.
- For languages and machines, only front ends and back ends are needed, in place of full compilers.
The front end (lexical, syntax, semantic analysis and intermediate code) understands the source program. The back end (optimisation and code generation) builds the target program. Keeping them separate makes a compiler easy to move to a new language or a new machine.