Professional Documents
Culture Documents
Com 413 Ammar Usman Sabo H21CS018
Com 413 Ammar Usman Sabo H21CS018
a b
0 1 2
a+b:
a b r
1
2 5
0
3 4
(b+aa) b+
*ab
a b
0 1 2 3
S S
O S O S
1 S S
1 ϵ
The first phase of compiler splits the source code into lexemes, which are
individual code fragments that represent specific patterns in the code. The
lexemes are then tokenized in preparation for syntax and semantic analyses.
The next phase is called the syntax analysis or parsing. The compiler verifies that
the codes syntax is correct, based on the rules for the source language. This
process is also referred to as parsing. During this step, the compiler typically
creates abstract syntax trees that represent the logical structures of specific code
elements.
In this phase, the compiler generates the final output code, using the optimized
IR code.
Compiler Interpreter
It scan the entire program first and translate it It scan the program line by line and translate it into
into machine code machine code
Shows all area and warning at the same time Show one area at a time
Error occurs after scanning the whole program Error occurs after scanning each line
Debugging is slow Debugging is faster
Execution time is less Execution time is more
Is used by language such as C, C++, etc. Is used by language such as Java, python etc.
Answer: The advantage of Compiler over and Interpreter and Interpreter over a
compiler was given a table below:
Q7. Write the quadruple, triple, indirect triple for the expression -(a*b) + (c+d)-
(a+b+c+d)
Answer: There are four common error-recovery strategies that can be implemented in the
parser to deal with errors in the code. Panic Mode, Statement Mode, Error Productions and
Global Corrections all are error recovery strategies in predictive parsing.
The error recovery strategy depends on the specific error that is encountered. For example,
panic-mode error recovery is a good choice for recovering from syntax errors, while phrase-
level error recovery is a good choice for recovering from semantic errors.
Error recovery strategies, there are a number of other techniques that can be used to improve
the robustness of predictive parsers. For example, the parser can be designed to generate
more informative error messages. The parser can also be designed to collect more
information about the input during the parsing process. This information can be used to
improve the accuracy of error recovery.
Q10. Explain the role of semantic preserving transformations and dominator in code
optimization
Answer: Semantic preserving transformations are transformations that change the form of a
program without changing its meaning. These transformations can be used to improve the
efficiency of a program by making it smaller, faster, or easier to understand.
i. Loop unrolling: This technique involves duplicating the loop body multiple times
to reduce the overhead of loop control instructions. For example, if a loop iterates
10 times, unrolling it by a factor of 2 would result in two copies of the loop body,
each iterating 5 times.
ii. Loop fusion: This technique involves combining multiple loops that operate on the
same data into a single loop. This can reduce the overhead of loop control
instructions and improve cache locality.
iii. Loop interchange: This technique involves changing the order of nested loops to
improve cache locality. For example, if a loop iterates over rows of a matrix and
another loop iterates over columns, interchanging the loops can improve cache
performance.
iv. Loop-invariant code motion: This technique involves moving code that does not
depend on the loop index outside of the loop. This can reduce the number of
instructions executed inside the loop and improve performance.
v. Strength reduction: This technique involves replacing expensive operations inside
the loop with cheaper operations. For example, replacing multiplication with
addition or bit shifting can improve performance.
vi. Loop tiling: This technique involves dividing a large loop into smaller loops that
operate on blocks of data. This can improve cache performance and reduce the
overhead of loop control instructions.
Answer: The LR parser is a type of bottom-up parser that uses a wide class of context-free
grammar, making it the most efficient syntax analysis technique. Here are some properties of
the LR parser:
i. Efficiency: The LR parser is the most efficient syntax analysis technique, as it can
handle a wide class of context-free grammar.
ii. Non-recursive: The LR parser is a non-recursive parser, which means that it does
not use recursion to parse the input.
iii. Shift-reduce: The LR parser uses a shift-reduce technique to parse the input. In the
shift step, the input pointer is advanced to the next input symbol, which is pushed
onto the stack. In the reduce step, the parser finds a complete grammar rule and
replaces it with the left-hand side non-terminal symbol.
iv. Bottom-up: The LR parser is a bottom-up parser, which means that it starts from
the leaf nodes of a tree and works in an upward direction until it reaches the root
node.
v. LR(k): The LR parser is also known as LR(k) parser, where L stands for left-to-
right scanning of the input stream, R stands for the construction of right-most
derivation in reverse, and k denotes the number of lookahead symbols to make
decisions.
vi. Three algorithms: There are three widely used algorithms available for constructing
an LR parser: SLR(1), LR(1), and LALR(1). The SLR(1) algorithm works on the
smallest class of grammar, while the LR(1) algorithm works on the complete set of
LR(1) grammar. The LALR(1) algorithm works on an intermediate size of grammar.
By using LR parser, compilers can efficiently parse the input and generate the parse tree, which
is used for further analysis and optimization.
Q14. What advantages are there to a language-processing system in which the compiler
produces assembly language rather than machine language?
Q15. A compiler that translate high-level language into another high-level language is called
source-to-source translator, explain this process.
Lexical analysis: The input program is broken down into a sequence of tokens, which are basic
units of the language such as keywords, identifiers, and operators.
Syntactic analysis: The sequence of tokens is parsed to create a syntax tree, which is a
representation of the structure of the program.
Semantic analysis: The syntax tree is analyzed to check for semantic errors, such as undeclared
variables and type mismatches.
Code generation: The IR is translated into the target language. A source-to-source translator
converts between programming languages that operate at approximately the same level
of abstraction, while a traditional compiler translates from a higher level programming
language to a lower level programming language. For example, a source-to-source translator
Q16. What advantage are there to using C as a target language for a compiler
• low level
• easy to generate
• can be written in an architecture-independent manner
• highly available
• has good optimizers
Q17. Describe some of the task that the compiler needs to perform
The task that the Assembler needs to be perform among of these are:
• The assembler takes its source code as assembly language program.
• Making direct hardware access for device driver.
• Produce machine code.
• Generate machine code
• Provide error information for the assembly language programmer
• Provide machine code information for the assembly language programmer
• Assign memory for instruction and data
Q18. Define preprocessor. What are the functions of pre-processor?
The Preprocessor is not a part of the compiler, but is a separate step in the compilation
process. In simple terms, a preprocessor is just a text substitution tool and it instructs the
compiler to do required pre-processing before the actual compilation. We'll refer to the
Preprocessor as CPP.
All preprocessor commands begin with a hash symbol (#). It must be the first nonblank
character, and for readability, a preprocessor directive should begin in the first column. The
following section lists down all the important preprocessor directives
What are the functions of pre-processor?
Preprocessor directives in C programming language are used to define and replace tokens in
the text and also used to insert the contents of other files into the source file.
When we try to compile a program, preprocessor commands are executed first and then the
program gets compiled.
Q19. Discuss about the syntax error handling
Shift Reduce Parser is a type of Bottom-Up Parser. It generates the Parse Tree from Leaves
to the Root. In Shift Reduce Parser, the input string will be reduced to the starting symbol. This
reduction can be produced by handling the rightmost derivation in reverse, i.e., from starting
symbol to the input string.
An operator precedence parser is a bottom-up parser that interprets an operator grammar.
This parser is only used for operator grammars. Ambiguous grammars are not allowed in any
parser except operator precedence parser.
Q21. What are the benefits of intermediate code generation.
The code optimization in the synthesis phase is a program transformation technique, which
tries to improve the intermediate code by making it consume fewer resources (i.e. CPU,
Memory) so that faster-running machine code will result. Compiler optimizing process
should meet the following objectives:
The optimization must be correct, it must not, in any way, change the meaning of the
program.
Optimization should increase the speed and performance of the program.
The compilation time must be kept reasonable.
The optimization process should not delay the overall compiling process.
Q24. Discuss in detail the role of dead code elimination and strength reduction during code
optimization of a compiler.
Dead code is a section in the source code of a program, which is executed but whose result is
never used in any other computation.
Dead code execution prevents from wastes of computation time and memory.
Strength reduction often eliminates all uses of an induction variable, except for an end-of-
loop test. In that case, the compiler may be able to rewrite the end-of-loop test to use another
induction variable found in the loop. If the compiler can remove this last use, it can eliminate
the original induction variable as dead code
Lexical Error
During the lexical analysis phase this type of error can be detected.
Lexical error is a sequence of characters that does not match the pattern of any token. Lexical
phase error is found during the execution of the program.
o Spelling error.
o Exceeding length of identifier or numeric constants.
o Appearance of illegal characters.
o To remove the character that should be present.
o To replace a character with an incorrect character.
o Transposition of two characters.
Q26. Write regular expressions for the set of words having a,e,i,o,u appearing in that order,
although not necessarily consecutively.
a (?:[^aeiou]*a[^aeiou]*e) [^aeiou]*i[^aeiou]*o[^aeiou]*u[^aeiou]*
Q27. Define lexeme, token and pattern. Identify the lexemes that make up the tokens in the
following program segment. Indicate corresponding token and pattern. void swap(int i, int
j) { int t; t=i; i=j; j=t; }
( left parenthesis (
i identifier [a-zA-Z_][a-zA-Z0-9_]*
, comma ,
j identifier [a-zA-Z_][a-zA-Z0-9_]*
) right parenthesis )
; semicolon ;
t identifier [a-zA-Z_][a-zA-Z0-9_]*
= assignment operator =
i identifier [a-zA-Z_][a-zA-Z0-9_]*
; semicolon ;
i identifier [a-zA-Z_][a-zA-Z0-9_]*
= assignment operator =
j identifier [a-zA-Z_][a-zA-Z0-9_]*
; semicolon ;
Q28. Compare bottom up approach of parsing with all top down approach
Top down parsing technique is a parsing technique which starts from the top of the parse tree,
move downwards, evaluates rules of grammar.
Bottom Up Parsing
Top down parsing technique is again a parsing technique which starts from the lowest level of
the parse tree, move upwards and evaluates rules of grammar.
Following are some of the important differences between Top Down Parsing and Bottom Up
Parsing.
Q29. Construct the syntax tree and draw the DAG for the expression (a*b) + (c-d) * (a*b) + b
tokenizer. The program takes a string as input and tokenizes it into keywords, identifiers,
numbers, and operators. In the program code the parse serves as function as main logic of
the program. A string serve as input also the strings iterates by any character. The parse
function is the main logic of the program. It takes a string as input and iterates through each
character.