Professional Documents
Culture Documents
CSL 411 Compiler
CSL 411 Compiler
CSL411
COMPILER LAB
Lab Manual(2019 Scheme)
Royal College of Engineering and Technology
NAAC Accredited Institution
(Affiliated to APJ Abdul Kalam Technological University)
Akkikavu, Chiramanangad PO., Thrissur – 680 604.
(Sponsored by Royal Educational Society & Research Foundation)
Compiler Lab
(Academic Year – 20__ / 20__)
2
Royal College of Engineering and Technology
NAAC Accredited Institution
(Affiliated to APJ Abdul Kalam Technological University)
Akkikavu, Chiramanangad PO., Thrissur – 680 604.
(Sponsored by Royal Educational Society & Research Foundation)
…………........
1.
2.
3
Department Vision
Department Mission
Ability to analyze, design and implement ethical sustainable solutions in the field
of computer science.
Ability to use problem solving skills in the broad area of programming concepts
and manage different projects in interdisciplinary field.
Ability to understand the evolutionary changes in computing and creating an
innovative career path to be an entrepreneur and lifelong learner with moral values
and ethics.
Program Outcomes(POs)
2.Problem Analysis: Identify, formulate, review research literature, and analyse complex
engineering problems reaching substantiated conclusions using first principles of
mathematics, natural sciences and engineering sciences.
4
3.Design/Development of Solutions: Design solutions for complex engineering problems
and design system components or processes that meet the specified needs with appropriate
consideration for the public health and safety, and the cultural, societal, and environmental
considerations.
5.Modern Tool Usage: Create, select, and apply appropriate techniques, resources, and
modern engineering and IT tools including prediction and modelling to complex engineering
activities with an understanding of the limitations.
6.The Engineer and Society: Apply reasoning informed by the contextual knowledge to
assess societal, health, safety, legal and cultural issues and the consequent responsibilities
relevant to the professional engineering practice.
8.Ethics: Apply ethical principles and commit to professional ethics and responsibilities and
norms of the engineering practice.
12.Life-long Learning: Recognize the need for, and have the preparation and ability to
engage in independent and lifelong learning in the broadest context of technological change.
5
Syllabus(As per University)
Course Outcomes
Implement lexical analyzer using the tool LEX. (Cognitive Knowledge Level:Apply)
Design NFA and DFA for a problem and write programs to perform operations on
it.(Cognitive Knowledge Level: Apply)
6
Syllabus (As per University)
All students should wear neat and clean uniform with ID Cards in the lab.
Students are not allowed to use footwear inside the lab.
Student should enter the roll number, name, login time, logout time, and system
number in the issue register.
Students should submit the rough record & fair record on time.
Mobile phones are strictly prohibited inside the Lab.
Perfect order and silence must be maintained with in the lab
No student is permitted to enter and leave the lab without the permission of the
faculty concerned.
Students should shut down the system and arrange the chair in proper place before
leaving the lab.
If any damage is caused to any of the mission in the lab by any student of group of
students - the cost of the same will be recovered with fine from the particular student
or group of students.
Students are requested to be in their lab a few minutes prior to the stroke of the bell.
Personal chatting, mail checking, accessing unnecessary sites of not allowed in the lab
7
CONTENTS
Exp
Name of the Experiment Page No:
No:
8
Practical Report Card
Contin
uous Viva- Contin
Atte
Evaluat Voice uous Signature
Sl Page nda Remar
Name of the Experiment Date ion in Mark assess of
No No nce ks
Lab(30 s ment(1 Faculty
(15)
) (15) 5)
Avg Marks
9
Experiment No: 1 Date: ....................
Aim:
Design and implement a lexical analyzer using C language to recognize all valid tokens in the
input program. The lexical analyzer should ignore redundant spaces, tabs and newlines. It
should also ignore comments.
Practice questions:
1. Design and implement a lexical analyzer using C language to recognize all valid
tokens in the input program. The lexical analyzer should ignore redundant spaces, tabs
and newlines. It should also ignore comments
Algorithm
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
int isKeyword(char buffer[]){char keywords[32]
[10]={"int","char","float","for","do","double","else","if","for","goto","long","register","void"
,"whil
e","switch","return","printf"};
int i, flag = 0;
for(i = 0; i < 32; ++i){
if(strcmp(keywords[i], buffer) == 0){
flag = 1;
break;
}
}
return flag;
}
int main(){
char ch, buffer[15], operators[] = "+-*/%=";
FILE *fp;
int i,j=0;
fp=fopen("program.txt","r");
if(fp==NULL){
printf("error while opening the file\n");
exit(0);
}
while((ch=fgetc(fp))!=EOF){
for(i=0;i<6;++i){
if(ch==operators[i])
printf("%c is operator\n",ch);
}
if(isalnum(ch)){
buffer[j++] = ch;
}
else if((ch == ' ' || ch == '\n') && (j != 0)){
buffer[j] = '\0';
j = 0;
if(isKeyword(buffer) == 1)
printf("%s is keyword\n",buffer);
else
printf("%s is indentifier\n",buffer);
}
}
fclose(fp);
return 0;
}
Input
File name : program.txt
void main()
{
int a,ab,sum;
11
sum=a+ab;
printf("sum);
}
output
void is keyword
main is identifier
int is keyword
a is identifier
b is identifier
c is identifier
= is operator
+ is operator
Result:The student is able to get knowledge about designing and implementation of a lexical
analyzer using C language to recognize all valid tokens in the input program.
12
Experiment No: 2 Date: ....................
Practice questions:
2.a.Implement a Lexical Analyzer for a given program using Lex Tool.
2.b.Write a lex program to display the number of lines, words and characters in an input text.
2.c. Write a LEX Program to convert the substring abc to ABC from the given input string.
2.d.Write a lex program to find out total number of vowels and consonants from the given
input string
Lex Tool
Lex helps write programs whose control flow is directed by instances of regular expressions
in the input stream. It is well suited for editor-script type transformations and for segmenting
input in preparation for a parsing routine.Lex source is a table of regular expressions and
corresponding program fragments. The table is translated to a program which reads an input
stream, copying it to an output stream and partitioning the input into strings which match the
given expressions. As each such string is recognized the corresponding program fragment is
executed. The recognition of the expressions is performed by a deterministic finite automaton
generated by Lex.
The program fragments written by the user are executed in the order in which the
corresponding regular expressions occur in the input stream.The lexical analysis programs
written with Lex accept ambiguous specifications and choose the longest match possible at
each input point. If necessary, substantial lookahead is performed on the input, but the input
stream will be backed up to the end of the current partition, so that the user has general
freedom to manipulate it.Lex can generate analyzers in C .
A token is a string of characters, categorized according to the rules as a symbol (e.g.,
IDENTIFIER, NUMBER, COMMA). The process of forming tokens from an input stream of
characters is called tokenization, and the lexer categorizes them according to a symbol type.
A token can look like anything that is useful for processing an input text stream or text file.
13
Algorithm:
1: Lex program contains three sections: definitions, rules, and user subroutines. Each section
must be separated from the others by a line containing only the delimiter, %%. The format
is as follows: definitions %% rules %% user_subroutines
2: In definition section, the variables make up the left column, and their definitions make up
the right column. Any C statements should be enclosed in %{..}%. Identifier is defined such
that the first letter of an identifier is alphabet and remaining letters are alphanumeric.
3: In rules section, the left column contains the pattern to be recognized in an input file to
yylex(). The right column contains the C program fragment executed when that pattern is
recognized. The various patterns are keywords, operators, new line character, number, string,
identifier, beginning and end of block, comment statements, preprocessor directive
statements etc.
4: Each pattern may have a corresponding action, that is, a fragment of C source code to
execute when the pattern is matched.
5: When yylex() matches a string in the input stream, it copies the matched text to an external
character array, yytext, before it executes any actions in the rules section.
6: In user subroutine section, main routine calls yylex(). yywrap() is used to get more input.
7: The lex command uses the rules and actions contained in file to generate a program,
lex.yy.c, which can be compiled with the cc command. That program can then receive input,
break the input into the logical pieces defined by the rules in file, and run program fragments
contained in the actions in file.
Program2.a
%option noyywrap
%{
#include<stdio.h>
%}
%%
"#include<"[a-zA-Z]+.h">" {fprintf(yyout, "%s is a header file\n",yytext);}
"main"/"int"|"float"|"for"|"if"|"printf" {fprintf(yyout, "%s is a keyword\n",yytext);}
[a-zA-Z] {fprintf(yyout, "%s is a identifier\n",yytext);}
^[a-zA-Z]+ {fprintf(yyout, "%s is a identifier\n",yytext);}
"{" {fprintf(yyout, "%s is a left brace\n",yytext);}
"}" {fprintf(yyout, "%s is a right brace\n",yytext);}
"(" {fprintf(yyout, "%s is a left paranthesis\n",yytext);}
")" {fprintf(yyout, "%s is a right paranthesis\n",yytext);}
[0-9]+ {fprintf(yyout, "%s is a number \n",yytext);}
"=" {fprintf(yyout, "%s is a assignment operator\n",yytext);}
"+"|"-"|"*"|"/" {fprintf(yyout, "%s is a operator\n",yytext);}
"++"|"--" {fprintf(yyout, "%s is a unary operator\n",yytext);}
[;:"] {fprintf(yyout, "%s is a delimiter or terminal\n",yytext);}
"&"|"|"|"&&"|"-" {fprintf(yyout, "%s is a logical operator\n",yytext);}
14
%%
int main()
{
yyin=fopen("a.c","r");
yylex();
return 0;
}
Input:
File name : a.c
a=(b+c)-(d+f)
Output:
lex lexical.l
gcc lex.yy.c
./a.out
program 2.b
Lex program to display number of lines,words and characters
%{
#include<stdio.h>
int sc=0,wc=0,lc=0,cc=0;
%}
%%
[\n] { lc++; cc+=yyleng;}
[ \t] { sc++; cc+=yyleng;}
[^\t\n ]+ { wc++; cc+=yyleng;}
%%
int yywrap( )
{
return 1;
}
Output:
lex lw.l
gcc lex.yy.c
./a.out
15
we are fine
The number of lines=2
The number of spaces=6
The number of words=8
The number of characters are=34
Program 2.c
%{
#include
#include
int i;
%}
%%
[a-z A-Z]* {
for(i=0;i<=yyleng;i++)
{
if((yytext[i]=='a')&&(yytext[i+1]=='b')&&(yytext[i+2]=='c'))
{
yytext[i]='A';
yytext[i+1]='B';
yytext[i+2]='C';
}
}
printf("%s",yytext);
}
[\t]* return;
.* {ECHO;}
\n {printf("%s",yytext);}
%%
main()
{
yylex();
}
int yywrap()
{
return 1;
}
Output:
abc
ABC
16
Program 2.d:
/*Lex program to count the number of vowels & consonants from the given input
string.*/
%{
int ac=0;
int bc=0;
%}
%%
[aeiouAEIOU] {ac++;}
[a-zA-z] {bc++;}
%%
int yywrap() {}
int main()
{
printf("Enter the string \n");
yylex();
printf("THe number of vowels are %d\n",ac);
printf("The number of consonant is %d",bc);
return 0;
}
Output
lex demo.l
gcc lex.yy.c
./a.out
Enter some input string:Hello everyone(press contol+d after input)
Number of vowels:6
Number of consonants:7
Result:
Program to implement Lexical Analyzer using Lex is implemented and concept of Lex tool is
understood.Application programs like displaying the number of lines, words and characters in
an input text,conversion of substring abc to ABC from the given input string and counting
total number of vowels and consonants from the given input string
17
Experiment No: 3 Date: ....................
Aim:
Generate a YACC specification to recognize a valid arithmetic expression that uses operators
+, – , *,/ and parenthesis
Practice questions:
3.a Generate a YACC specification to recognize a valid arithmetic expression that
uses
operators +, – , *,/ and parenthesis.
3.b Generate a YACC specification to recognize a valid identifier which starts with a
letter followed by any number of letters or digits.
Program 3.a:
Algorithm:
2: Reading an expression .
3: Checking the validating of the given expression according to the rule using yacc.
Lex part
%{
#include<stdio.h>
#include "y.tab.h"
extern int yylval;
%}
%%
[0-9]+ {
yylval=atoi(yytext);
18
return NUMBER;
}
[\t] ;
[\n] return 0;
. return yytext[0];
%%
int yywrap()
{
return 1;
}
yacc part:
%{
#include<stdio.h>
int flag=0;
%}
%token NUMBER
19
| NUMBER {$$=$1;}
;
%%
void main()
{
printf("\nEnter Any Arithmetic Expression which can have operations Addition, Subtraction,
Multiplication, Divison, Modulus and Round brackets:\n");
yyparse();
if(flag==0)
printf("\nEntered arithmetic expression is Valid\n\n");
}
void yyerror()
{
printf("\nEntered arithmetic expression is Invalid\n\n");
flag=1;
}
Output:
lex h.l
yacc -d h.y
h.y:25 parser name defined to default :"parse"
gcc lex.yy.c y.tab.c -w
./a.out
Enter Any Arithmetic Expression which can have operations Addition, Subtraction,
Multiplication, Divison, Modulus and Round brackets:
(3+4)*5
Result=35
Entered arithmetic expression is Valid
20
program 3.b:
Algorithm:
Step1: Start the program
Step3: Checking the validating of the given expression according to the rule using yacc.
Step4: Using expression rule print the result of the given values
LEX PART:
%{
#include "y.tab.h"
%}
%%
. return yytext[0];
\n return 0;
%%
int yywrap()
return 1;
YACC PART:
%{
#include<stdio.h>
21
int valid=1;
%}
%%
start : letter s
s :letter s
digit s
%%
int yyerror()
{
printf("\nIts not a identifier!\n");
valid=0;
return 0;
}
int main()
{
printf("\nEnter a name to tested for identifier ");
yyparse();
if(valid)
{
printf("\nIt is a identifier!\n");
}}
output:
22
Program 3.c:
Algorithm:
1:A Yacc source program has three parts as follows:
Declarations %% translation rules %% supporting C routines
iv. Define the tokens used by the parser. v. Define the operators and their precedence.
3: Rules Section: The rules section defines the rules that parse the input stream. Each rule of
a grammar production and the associated semantic action.
4: Programs Section: The programs section contains the following subroutines. Because
these subroutines are included in this file, it is not necessary to use the yacc library when
processing this file.
5: Main- The required main program that calls the yyparse subroutine to start the program.
7: yywrap -The wrap-up subroutine that returns a value of 1 when the end of input occurs.
The calc.lex file contains include statements for standard input and output, as programmar
file information if we use the -d flag with the yacc command. The y.tab.h file contains
definitions for the tokens that the parser program uses.
8: calc.lex contains the rules to generate these tokens from the input stream.
LEX PART:
%{
#include<stdio.h>
#include "y.tab.h"
%}
23
%%
[0-9]+ {
yylval=atoi(yytext);
return NUMBER;
[\t] ;
[\n] return 0;
. return yytext[0];
%%
int yywrap()
return 1;
YACC PART:
%{
#include<stdio.h>
int flag=0;
%}
%token NUMBER
ArithmeticExpression: E{
printf("\nResult=%d\n",$$);
return 0;
};
E:E'+'E {$$=$1+$3;}
|E'-'E {$$=$1-$3;}
|E'*'E {$$=$1*$3;}
|E'/'E {$$=$1/$3;}
|E'%'E {$$=$1%$3;}
|'('E')' {$$=$2;}
| NUMBER {$$=$1;}
%%
void main()
{
printf("\nEnter Any Arithmetic Expression which can have operations Addition, Subtraction,
Multiplication, Divison, Modulus and Round brackets:\n");
yyparse();
if(flag==0)
printf("\nEntered arithmetic expression is Valid\n\n");
}
void yyerror()
{
printf("\nEntered arithmetic expression is Invalid\n\n");
flag=1;
}
25
output
Result:
Implementation of YACC programs and application problems including
calculator,verification of identifier,checking valid arithmetic expression etc are done.
26
Experiment No: 4 Date: ....................
Aim:
To compile a program to find epsilon closure of all states of any given nfa with epsilon
transition.
Program
#include<stdio.h>
#include<string.h>
char result[20][20],copy[3],states[20][20];
int main(){
FILE *INPUT;
INPUT=fopen("input.dat","r");
char state[3];
int end,i=0,n,k=0;
char state1[3],input[3],state2[3];
printf("n Enter the no of states: ");
scanf("%d",&n);
printf("n Enter the states n");
for(k=0;k<3;k++){
scanf("%s",states[k]);
for( k=0;k<n;k++){
i=0;
strcpy(state,states[k]);
strcpy(copy,state);
27
add_state(state,i++);
while(1){
end = fscanf(INPUT,"%s%s%s",state1,input,state2);
if (end == EOF ){
break;
}
if( strcmp(state,state1) == 0 ){
if( strcmp(input,"e") == 0 ) {
add_state(state2,i++);
strcpy(state, state2);
}
}
}
display(i);
rewind(INPUT);
}
return 0;
}
Output:
input.dat
q0 0 q0
q0 1 q1
q0 e q1
q1 1 q2
q1 e q2
q0
q1
q2
Epsilon closure of q0 = { q0 q1 q2 }
Epsilon closure of q1 = { q1 q2 }
Epsilon closure of q2 = { q2 }
Result: The program was executed successfully and output was obtained.
The student was able to gain the concept regarding epsilon closure,i.e, it is the initial state
and all states that can be reached directly by one or more epsilon moves.
28
4 b) C program to minimize any given dfa
Algorithm:
Let the given DFA be D(Q, Σ, q0, δ, F). The output of DFA minimization D’(Q’, Σ, q0, δ’,
F’) can be created by compressing equivalent states. Two states (p, q) are called equivalent
if for every string w, either {δ(p, w), δ(q, w)} belongs to F or does not belong to F. We can
find equivalent states using the following:
1. Remove all the states that are unreachable from the initial start state.
2. Create a table of pairs (p, q) where p, q denotes some two states of Q. Initially, all the
table cells are unmarked.
3. Mark all the pairs (p, q) such that p belongs to F and q does not belong to F, or vice
versa.
4. If (p, q) is unmarked and there exists a symbol such that {δ(p, a), δ(q, a)} is marked,
then mark p and q.
5. Repeat step-4 until no new pairs get marked.
6. After completing the above process, p is equivalent to q if and only if (p, q) is
unmarked. The equivalent states can be compressed to get the minimum number of
states.
After this, we will just compress the equivalent states into a single state to get the DFA with
the minimum number of states. The above DFA minimization algorithm is called Moore’s
Algorithm.
Program:
#include <stdio.h>
#include <string.h>
#define STATES 99
#define SYMBOLS 20
int DFAtab[STATES][SYMBOLS];
29
char StateName[STATES][STATES+1]; /* state-name table
*/
int OptDFA[STATES][SYMBOLS];
char NEW_finals[STATES+1];
/*
*/
void print_dfa_table(
char *finals)
int i, j;
printf(" | ");
printf("\n-----+--");
30
printf("\n");
printf("\n");
/*
*/
void load_DFA_table()
DFA_finals = "EF";
N_DFA_states = 6;
N_symbols = 2;
31
}
/*
*/
int i, ch;
*nextstates++ = dfa[cur_states[i]-'A'][symbol];
*nextstates = '\0';
/*
*/
int i;
32
/*
Return value:
*/
while (*s) {
s++;
int i;
33
char state_flags[STATES+1]; /* next state info. */
state_flags[i] = '\0';
if (i=is_one_nextstate(state_flags))
else {
return (*pn)++;
/*
*/
int i, j;
34
strcpy(statename[0], finals);
return 1;
if (i == *finals-'A') {
finals++;
statename[0][j] = '\0';
return 2;
/*
*/
int i, j;
char nextstate[STATES+1];
35
for (j = 0; j < n_sym; j++) { /* for each input symbol */
return n2;
/*
*/
int n=strlen(s);
*(s+n) = ch;
*(s+n+1) = '\0';
int i, j;
char temp[STATES+1];
36
if (stnt[i][0] > stnt[j][0]) {
strcpy(temp, stnt[i]);
strcpy(stnt[i], stnt[j]);
strcpy(stnt[j], temp);
/*
Algorithm:
*/
37
for (i=0; i < STATES; i++) newstates[i][0] =
'\0';
chr_append(newstates[vec[i]-'0'], old[i]);
if (newstates[i][0]) {
if (!flag) { /* stnt[i1] = s1 */
strcpy(stnt[i1], newstates[i]);
strcpy(stnt[n2++], newstates[i]);
/*
*/
int i, j, k;
38
for (i = 0; i < n; i++) {
return n;
int i;
printf("\n");
/*
*/
int optimize_DFA(
39
int dfa[][SYMBOLS], /* DFA state-transition table */
char nextstate[STATES+1];
while (1) {
print_equiv_classes(stnt, n);
if (n != n2)
/*
*/
40
int is_subset(char *s, char *t)
int i;
return 1;
/*
*/
void get_NEW_finals(
int i;
*newfinals++ = '\0';
void main()
41
load_DFA_table();
Output:
| 0 1
-----+------------
A | B C
B | E F
C | A A
D | F E
E | D F
F | D E
Final states = EF
| 0 1
-----+------------
A | B C
B | D D
C | A A
D | B D
Final states = D
Result: The program was executed successfully and output was obtained. The student was
able to gain the idea about Moore’s law and the concept of DFA Minimization by
compressing equivalent states.Eevery pair of states are compared to check for equivalence
until no new equivalent states are found.
43
Experiment No: 5 Date: ....................
ALGORITHM:
FIRST (α) is defined as the collection of terminal symbols which are the first letters of
strings derived from α.
If Y1 does not derive to an empty string i.e., If FIRST (Y 1) does not contain ε then,
FIRST (X) = FIRST (Y1, Y2, Y3) = FIRST(Y1)
(c) If FIRST (Y1) contains ε, then.
FIRST (X) = FIRST (Y1, Y2, Y3) = FIRST(Y1) − {ε} ∪ FIRST(Y2, Y3)
Similarly, FIRST (Y2, Y3) = {Y2}, If Y2 is terminal otherwise if Y2 is Non-terminal then
FIRST (Y2, Y3) = FIRST (Y2), if FIRST (Y2) does not contain ε.
Similarly, this method will be repeated for further Grammar symbols, i.e., for Y4, Y5, Y6
… . YK.
Computation of FOLLOW
Follow (A) is defined as the collection of terminal symbols that occur directly to the
right of A.
FOLLOW(A) = {a|S ⇒* αAaβ where α, β can be any strings}
44
If production is of form A → α B β, β ≠ ε.
(a) If FIRST (β) does not contain ε then, FOLLOW (B) = {FIRST (β)}
Or
Program:
#include<stdio.h>
#include<string.h>
int i,j,l,m,n=0,o,p,nv,z=0,x=0;
char str[10],temp,temp2[10],temp3[20],*ptr;
struct prod
char lhs[10],rhs[10][10],ft[10],fol[10];
int n;
}pro[10];
void findter()
int k,t;
for(k=0;k<n;k++)
if(temp==pro[k].lhs[0])
for(t=0;t<pro[k].n;t++)
{
45
if( pro[k].rhs[t][0]<65 || pro[k].rhs[t][0]>90 )
pro[i].ft[strlen(pro[i].ft)]=pro[k].rhs[t][0];
temp=pro[k].rhs[t][0];
if(temp=='S')
pro[i].ft[strlen(pro[i].ft)]='#';
findter();
break;
void findfol()
int k,t,p1,o1,chk;
char *ptr1;
for(k=0;k<n;k++)
chk=0;
for(t=0;t<pro[k].n;t++)
ptr1=strchr(pro[k].rhs[t],temp);
if( ptr1 )
p1=ptr1-pro[k].rhs[t];
46
{
for(o1=0;o1<n;o1++)
if(pro[o1].lhs[0]==pro[k].rhs[t][p1+1])
strcat(pro[i].fol,pro[o1].ft);
chk++;
else if(pro[k].rhs[t][p1+1]=='\0')
temp=pro[k].lhs[0];
if(pro[l].rhs[j][p]==temp)
continue;
if(temp=='S')
strcat(pro[i].fol,"$");
findfol();
chk++;
else
pro[i].fol[strlen(pro[i].fol)]=pro[k].rhs[t][p1+1];
chk++;
if(chk>0)
break;
47
int main()
FILE *f;
//clrscr();
for(i=0;i<10;i++)
pro[i].n=0;
f=fopen("tab5.txt","r");
while(!feof(f))
fscanf(f,"%s",pro[n].lhs);
if(n>0)
if( strcmp(pro[n].lhs,pro[n-1].lhs) == 0 )
pro[n].lhs[0]='\0';
fscanf(f,"%s",pro[n-1].rhs[pro[n-1].n]);
pro[n-1].n++;
continue;
fscanf(f,"%s",pro[n].rhs[pro[n].n]);
pro[n].n++;
n++;
48
for(i=0;i<n;i++)
for(j=0;j<pro[i].n;j++)
pro[0].ft[0]='#';
for(i=0;i<n;i++)
for(j=0;j<pro[i].n;j++)
pro[i].ft[strlen(pro[i].ft)]=pro[i].rhs[j][0];
temp=pro[i].rhs[j][0];
if(temp=='S')
pro[i].ft[strlen(pro[i].ft)]='#';
findter();
printf("\n\nFIRST\n");
for(i=0;i<n;i++)
for(j=0;j<strlen(pro[i].ft);j++)
49
for(l=j-1;l>=0;l--)
if(pro[i].ft[l]==pro[i].ft[j])
break;
if(l==-1)
printf("%c",pro[i].ft[j]);
for(i=0;i<n;i++)
temp2[i]=pro[i].lhs[0];
pro[0].fol[0]='$';
for(i=0;i<n;i++)
for(l=0;l<n;l++)
for(j=0;j<pro[i].n;j++)
ptr=strchr(pro[l].rhs[j],temp2[i]);
if( ptr )
p=ptr-pro[l].rhs[j];
for(o=0;o<n;o++)
if(pro[o].lhs[0]==pro[l].rhs[j][p+1])
strcat(pro[i].fol,pro[o].ft);
else if(pro[l].rhs[j][p+1]=='\0')
50
temp=pro[l].lhs[0];
if(pro[l].rhs[j][p]==temp)
continue;
if(temp=='S')
strcat(pro[i].fol,"$");
findfol();
else
pro[i].fol[strlen(pro[i].fol)]=pro[l].rhs[j][p+1];
printf("\n\nFOLLOW\n");
for(i=0;i<n;i++)
for(j=0;j<strlen(pro[i].fol);j++)
for(l=j-1;l>=0;l--)
if(pro[i].fol[l]==pro[i].fol[j])
break;
if(l==-1)
printf("%c",pro[i].fol[j]);
printf("\n");
//getch();
51
}
Output:
gedit tab5.txt
S ABE
Sa
Ap
At
B Aq
Sf
Aw
S -> ABE
S -> a
A -> p
A -> t
B -> Aq
S -> f
A -> w
->
FIRST
S -> #pta
A -> pt
B -> pt
52
S -> f
A -> w
->
FOLLOW
S -> $
A -> ptq
B ->
S ->
A -> ptq
Result:
The program was executed successfully and output was obtained. The student was able to
gain the concept of First and Follow.
FIRST is a function that gives the set of terminals that begin the strings derived from the
production rule.
FOLLOW (A) is defined as the collection of terminal symbols that occur directly to the
right of A.
Aim: To write a C program to design and implement a recursive descent parser for a given
language.
Algorithm:
Recursive-descent parsing is one of the simplest parsing techniques that is used in practice.
Recursive-descent parsers are also called top-down parsers, since they construct the parse
tree top down (rather than bottom up).
53
To match a terminal symbol, the procedure compares the terminal symbol to the
input; if they agree, then the procedure is successful, and it consumes the terminal
symbol in the input (that is, moves the input cursor over one symbol).
Program:
#include<stdio.h>
#include<string.h>
#include<ctype.h>
char input[10];
int i,error;
void E();
void T();
void Eprime();
void Tprime();
void F();
main()
i=0;
error=0;
gets(input);
E();
if(strlen(input)==i&&error==0)
printf("\nAccepted..!!!\n");
else printf("\nRejected..!!!\n");
54
void E()
T();
Eprime();
void Eprime()
if(input[i]=='+')
i++;
T();
Eprime();
void T()
F();
Tprime();
void Tprime()
if(input[i]=='*')
i++;
F();
Tprime();
55
}
void F()
if(isalnum(input[i]))i++;
else if(input[i]=='(')
i++;
E();
if(input[i]==')')
i++;
else error=1;
else error=1;
Output:
Accepted..!!!
Rejected..!!!
Result:
The program was executed successfully and output was obtained. The student was able to
gain the concept and come to conclusion that :
56
Experiment No: 6 Date: ....................
Aim:
To simulate code optimization technique for constant propagation
Practice questions:
1.Write a program to perform constant propagation.
Algorithm:
1. For all 4-tuples do
1.1 get next 4-tuple
1.2 If the operator is "Label" then
1.2.1 free the constant table
1.2.2 write the 4-tuple
1.3 If either or both of the operands are in the constant table then
1.3.1 substitute the constant value(s) for the operand(s)
1.3.2 if either of the operands are intermediate results then
1.3.2.1 remove those operand(s) from the constant table.
1.4 if 4-tuple operand(s) are constant then
1.4.1 if operator is "JPCT" then
1.4.1.1 if the operand is true then
1.4.1.1.1 replace the JPCT with JP
1.4.1.1.2 write the new 4-tuple else
1.4.1.1.3 eliminate the 4-tuple
1.4.2 if operator is "=" then
1.4.2.1 place the variable and constant in the constant table
57
1.4.2.2 write the 4-tuple with the constant operand
1.4.3 else
1.4.3.1 Perform the operation.
1.4.3.2 Place the intermediate result name and constant value in the constant
table.Else
1.4.4 write the 4-tuple Consider the following sequence.
PROGRAM:
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<conio.h>
void input();
void output();
void change(int p,char *res);
void constant();
struct expr
{
char op[2],op1[5],op2[5],res[5];
int flag;
}arr[10];
int n;
void main()
{
clrscr();
input();
constant();
output();
getch();
}
void input()
{
int i;
printf("\n\nEnter the maximum number of expressions : ");
scanf("%d",&n);
printf("\nEnter the input : \n");
for(i=0;i<n;i++)
{
scanf("%s",arr[i].op);
scanf("%s",arr[i].op1);
scanf("%s",arr[i].op2);
scanf("%s",arr[i].res);
arr[i].flag=0;
}
}
58
void constant()
{
int i;
int op1,op2,res;
char op,res1[5];
for(i=0;i<n;i++)
{
if(isdigit(arr[i].op1[0]) && isdigit(arr[i].op2[0]) || strcmp(arr[i].op,"=")==0) /*if both digits,
store them in variables*/
{
op1=atoi(arr[i].op1);
op2=atoi(arr[i].op2);
op=arr[i].op[0];
switch(op)
{
case '+':
res=op1+op2;
break;
case '-':
res=op1-op2;
break;
case '*':
res=op1*op2;
break;
case '/':
res=op1/op2;
break;
case '=':
res=op1;
break;
}
sprintf(res1,"%d",res);
arr[i].flag=1; /*eliminate expr and replace any operand below that uses result of this expr */
change(i,res1);
}
}
}
void output()
{
int i=0;
printf("\nOptimized code is : ");
for(i=0;i<n;i++)
{
if(!arr[i].flag)
{
printf("\n%s %s %s %s",arr[i].op,arr[i].op1,arr[i].op2,arr[i].res);
}
}
59
}
void change(int p,char *res)
{
int i;
for(i=p+1;i<n;i++)
{
if(strcmp(arr[p].res,arr[i].op1)==0)
strcpy(arr[i].op1,res);
else if(strcmp(arr[p].res,arr[i].op2)==0)
strcpy(arr[i].op2,res);
}
}
INPUT:
OUTPUT:
Optimized code is :
+ 3 b t1
+ 3 c t2
+ t1 t2 t3
Result:
optimization using constant propagation is implemented and optimized code is obatined.
60
Experiment No: 7 Date: ....................
Intermediate code generation for simple expressions.
Aim:
Implement Intermediate code generation for simple expressions.
Practice question:
1.Generate code for intermediate code generation of a simple expression.
Algorithm
1.Start
2.Read variables,
3.Open file input.txt and output.text
4.Read the contents of the file input.text and evaluate the expression
5.Close the files
6.Stop
PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<string.h>
char op[2],arg1[5],arg2[5],result[5];
void main()
{
FILE *fp1,*fp2;
fp1=fopen("input.txt","r");
fp2=fopen("output.txt","w");
while(!feof(fp1))
{
fscanf(fp1,"%s%s%s%s",op,arg1,arg2,result);
if(strcmp(op,"+")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nADD R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"*")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nMUL R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"-")==0)
{
61
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nSUB R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"/")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nDIV R0,%s",arg2);
fprintf(fp2,"\nMOV %s,R0",result);
}
if(strcmp(op,"=")==0)
{
fprintf(fp2,"\nMOV R0,%s",arg1);
fprintf(fp2,"\nMOV %s,R0",result);
}
}
fclose(fp1);
fclose(fp2);
getch();
}
}
Input.txt
+ a b t1
* c d t2
- t1 t2 t
=t?x
Output.txt
MOV R0,a
ADD R0,b
MOV t1,R0
MOV R0,c
MUL R0,d
MOV t2,R0
MOV R0,t1
SUB R0,t2
MOV t,R0
MOV R0,t
MOV x,R0
Result:
Intermediate code generation for simple expressions is implemented.
62
Experiment :8 Date……………..
Aim:
Practice question:
Implement the back end of the compiler which takes the three address code and produces the
8086 assembly language instructions that can be assembled and run using an 8086 assembler.
The target assembly instructions can be simple move, add, sub, jump etc.
ALGORITHM:
1. Start the program
2. Open the source file and store the contents as quadruples.
3. Check for operators, in quadruples, if it is an arithmetic operator generator it or if
assignment operator generates it, else perform unary minus on register C.
4. Write the generated code into output definition of the file in outp.c
5. Print the output.
6. Stop the program.
Program
#include <stdio.h>
#include <stdio.h>
//#include<conio.h>
#include <string.h>
void main()
int i = 0;
//clrscr();
printf("\n Enter the set of intermediate code (terminated by exit) :\n ");
do
63
{
scanf("%s", icode[i]);
printf("\n************************");
i = 0;
do
strcpy(str, icode[i]);
switch (str[3])
case '+':
strcpy(opr, "ADD");
break;
case '-':
strcpy(opr, "SUB");
break;
case '*':
strcpy(opr, "MUL");
break;
case '/':
strcpy(opr, "DIV");
break;
//getch();
64
}
Result:
Program for the back end of the compiler which takes the three address code and produces
the 8086 assembly language instructions that can be assembled and run using an 8086
assembler is implemented.
65
66