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

CD final Lab manual

The document outlines the record notebook for a student in the Compiler Design Laboratory at the Government College of Engineering for the academic year 2023-2024. It includes a series of experiments related to lexical analysis, symbol tables, and implementation using tools like LEX and YACC, along with sample programs and their outputs. Each experiment aims to teach students about various aspects of compiler design and programming in C.

Uploaded by

cse2026gce
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)
8 views

CD final Lab manual

The document outlines the record notebook for a student in the Compiler Design Laboratory at the Government College of Engineering for the academic year 2023-2024. It includes a series of experiments related to lexical analysis, symbol tables, and implementation using tools like LEX and YACC, along with sample programs and their outputs. Each experiment aims to teach students about various aspects of compiler design and programming in C.

Uploaded by

cse2026gce
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
You are on page 1/ 44

GOVERNMENT COLLEGE OF ENGINEERING

ERODE-638316

RECORD NOTE BOOK


REGISTER NUMBER

Certified that this is the Bonafide record of work done by Selvan / Selvi
………………………. of the Fifth Semester Computer Science and Engineering Branchduring the
academic year 2023-2024 in the Compiler Design(CS3501) Laboratory.

STAFF INCHARGE HEAD OF THE DEPARTMENT

Submitted for the university practical examination on ...................... at Government College of


Engineering.
Date………………..

INTERNAL EXAMINER EXTERNAL EXAMINER


INDEX

S.NO DATE LIST OF EXPERIMENTS PAGE NO SIGNATURE


DEVELOP A LEXICAL
01(a) ANALYZER TO RECOGNIZE A
FEW PATTERN IN C
IMPLEMENTATION OF SYMBOL
01(b) TABLE
IMPLEMETATION OF LEXICAL
02 ANALYSIS OF USING LEX TOOL
RECOGNIZE A VALID ARITHMETIC
03(a) EXPRESSION THAT USES OPERATOR
+, - , * AND /.
RECOGNIZING A VALID
03(b) VARIABLE WHICH STARTS WITH
A LETTER FOLLOWED BY
ANY NUMBER OF LETTERS OR
DIGITS.

TO RECOGNIZE A VALID
03(c) CONTROL STRUCTURES SYNTAX
OF C LANGUAGE.
IMPLEMENTATION OF
03(d) CALCULATOR USING LEX AND
YACC
GENERATE THREE ADDRESS
04 CODE FOR A SIMPLE PROGRAM
USING LEX AND YAAC.
IMPLEMENTATION OF TYPE
05 CHECKING USING LEX AND YAAC.

IMPLEMENT SIMPLE CODE


06(a)
OPTIMIZATION TECHINQUES
06(b) CODEOPTIMIZATION- CONSTANT
FOLDING
IMPLEMENT BACK-END OF THE
07 COMPILER FOR WHICH THE
ADDRESS CODE IS GIVEN AS
INPUT AND THE 8086 ASSEMBLY
LANGUAGE CODE IS PRODUCED
AS OUTPUT.
Ex.No:1a) DEVELOP A LEXICAL ANALYZER TO RECOGNIZE A
Date: FEW PATTERNS IN C

AIM:
To write and execute a C program to implement the lexical analyzer to
recognize a few patterns.

ALGORITHM:
1. Start the program.
2. Declare the file pointer and necessary variables.
3. Open the input file in the read mode.
4. Use the analyze function to analyze the input program and store the identifiers,
keywords and operator on idhd, keyhd, ophd respectively.
5. Stores the tokens in data structure linked lists.
6. Increment the line number of each token and its occurrences.
7. Using the show function print the linked lists in a tabular format.
8. Stop the program.

PROGRAM:

#include<string.h>
#include<ctype.h>
#include<stdio.h>
void keyword(char str[10])
{
if(strcmp("for",str)==0||strcmp("while",str)==0||strcmp("do",str)==0||
strcmp("int",str)==0||strcmp("float",str)==0||strcmp("char",str)==0||
strcmp("double",str)==0||strcmp("static",str)==0||
strcmp("switch",str)==0||
strcmp("case",str)==0)
printf("\n%s is a keyword",str);
else
printf("\n%s is an identifier",str);
}
main()
{
FILE *f1,*f2,*f3;
char c,str[10],st1[10];
int num[100],lineno=0,tokenvalue=0,i=0,j=0,k=0;
printf("\nEnter the c program");/*gets(st1);*/
f1=fopen("input","w");
while((c=getchar())!=EOF)
putc(c,f1);
fclose(f1);
f1=fopen("input","r");
f2=fopen("identifier","w");
f3=fopen("specialchar","w");
while((c=getc(f1))!=EOF)
{
if(isdigit(c))
{
tokenvalue=c-'0';
c=getc(f1);
while(isdigit(c))
{
tokenvalue*=10+c-'0';
c=getc(f1);
}
num[i++]=tokenvalue;
ungetc(c,f1);
}
else
if(isalpha(c))
{
putc(c,f2);
c=getc(f1);
while(isdigit(c)||isalpha(c)||c=='_'||c=='$')
{
putc(c,f2);
c=getc(f1);
}
putc(' ',f2);
ungetc(c,f1);
}
else
if(c==' '||c=='\t')
printf(" ");
else
if(c=='\n')
lineno++;
else
putc(c,f3);
}
fclose(f2);
fclose(f3);
fclose(f1);
printf("\nThe no's in the program are : ");
for(j=0;j<i;j++)
printf("%d",num[j]);
printf("\n");
f2=fopen("identifier","r");
k=0;
printf("The keywords and identifiers are :");
while((c=getc(f2))!=EOF)
{
if(c!=' ')
str[k++]=c;
else
{
str[k]='\0';
keyword(str);
k=0;
}
}
fclose(f2);
f3=fopen("specialchar","r");
printf("\nSpecial characters are :");
while((c=getc(f3))!=EOF)
printf("%c",c);
printf("\n");
fclose(f3);
printf("Total no. of lines are:%d",lineno);
}

INPUT & OUTPUT :


Enter the c program

void main()
{
int a=10,b=20;
float f;
char ch;
}
^Z

The no's in the program are10 20


The keywords and identifiers are:
void is a keyword
main is an identifier
int is a keyword
a is an identifier
b is an identifier
float is a keyword
f is an identifier
b is an identifier
char is a keyword
ch is an identifier
Special characters are : (){=,=;;;}
Total no. of lines are : 7

RESULT:
Thus the C program for lexical analyzer to recognize few patterns was executed
and verified successfully.
Ex.no:1(b)
Date: IMPLEMENTATION OF SYMBOL TABLE

AIM :
To write a C program to implement a symbol table.

ALGORITHM:

1) Start the program.


2) Get the input from the user with the terminating symbol ‘$’.
3) Allocate memory for the variable by dynamic memory allocation function.
4) If the next character of the symbol is an operator then only the memory is allocated.
5) While reading, the input symbol is inserted into symbol table along with its
memory address.
6) The steps are repeated till ‘$’ is reached.
7) To reach a variable, enter the variable to the searched and symbol table has
been checked for corresponding variable, the variable along with its address is
displayed as result.
8) Stop the program.

PROGRAM:
#include <stdio.h>
#include<conio.h>
#include<ctype.h>
#include<alloc.h>
#include<string.h>
#include<math.h>
void main()
{
int i=0,j=0,x=0,n,flag=0;
void *p,*add[5];
char ch,srch,b[15],d[15],c;
clrscr();
printf("Enter the expression and it is terminated by $ : ");
while((c=getchar())!='$')
{
b[i]=c;i++;
}
n=i-1;
printf("Given Expression : ");
i=0;
while(i<=n)
{
printf("%c",b[i]);
i++;
}
printf("\n Symbol Table\n");
printf("Symbol\t\t Address \t\t Type");
while(j<=n)
{
c=b[j];
if(isalpha(toascii(c)))
{
if(j==n)
{
p=malloc(c);
add[x]=p;
d[x]=c;
printf("%c\t%d\tidentifier",c,p);
}
else
{
ch=b[j+1];
if(ch=='+'||ch=='-'||ch=='*'||ch=='=')
{
p=malloc(c);
add[x]=p;
d[x]=c;
printf("\n%c\t%d\t identifier\n",c,p);
x++;
}
}
}
j++;
}
printf("\nThe symbol is to be searched :");
srch=getch();
for(i=0;i<=x;i++)
{
if(srch==d[i])
{
printf("\nSymbol Found");
printf("\n%c%s%d\n",srch," @address ",add[i]);
flag=1;
}
}
if(flag==0)
printf("\nSymbol Not Found");
getch();
}
OUTPUT:
Enter the expression and it is terminated by $ : c=a+b$
Given Expression : c=a+b
Symbol Table
Symbol Address Type
c 1900 identifier
a 2004 identifier
b 2106 identifier
The symbol is to be searched: b
Symbol Found
b @address 2106

RESULT :
Thus the C program to implement the symbol table was executed and verified
successfully.
Ex.no:2 IMPLEMENTATION OF LEXICAL ANALYZER USING LEX
Date: TOOL

AIM :
To implement the lexical analyzer using lex tool for a subset of C language.

ALGORITHM:
1. Start the program.
2. Declare necessary variables and creates token representation using Regular.
3. Print the pre processor or directives, keywords by analysis of the input program.
4. In the program check whether there are arguments.
5. Declare a file and open it as read mode.
6. Read the file and if any taken in source program matches with RE that all returned as
integer value.
7. Print the token identified using YYdex() function.
8. Stop the program.

PROGRAM:

%{
int COMMENT=0;
%}
identifier [a-zA-Z][a-zA-Z0-9]*
%% #.* {printf ("\n %s is a Preprocessor Directive",yytext);}
int |
float |
main |
if |
else |
printf |
scanf |
for |
char |
getch |
while {printf("\n %s is a Keyword",yytext);}
"/*" {COMMENT=1;}
"*/" {COMMENT=0;}
{identifier}\( {if(!COMMENT) printf("\n Function:\t %s",yytext);}
\{ {if(!COMMENT) printf("\n Block Begins");
\} {if(!COMMENT) printf("\n Block Ends");}
{identifier}(\[[0-9]*\])? {if(!COMMENT) printf("\n %s is an Identifier",yytext);}
\".*\" {if(!COMMENT) printf("\n %s is a String",yytext);}
[0-9]+ {if(!COMMENT) printf("\n %s is a Number",yytext);}
\)(\;)? {if(!COMMENT) printf("\t");ECHO;printf("\n");}
\( ECHO;
= {if(!COMMENT) printf("\n%s is an Assignment operator",yytext);}
\<= |
\>= |
\< |
\> |
== {if(!COMMENT) printf("\n %s is a Relational Operator",yytext);}
.|\n
%%
int main(int argc, char **argv)
{
if(argc>1)
{
FILE *file;
file=fopen(argv[1],"r");
if(!file)
{
printf("\n Could not open the file: %s",argv[1]);
exit(0);
}
yyin=file;
}
yylex();
printf("\n\n");
return 0;
}
int yywrap()
{
return 0;
}

Input: test.c
#include<stdio.h>
main()
{
int fact=1,n;
for(int i=1;i<=n;i++)
{
fact=fact*i;
}
printf("Factorial Value of N is", fact);
getch();
}
OUTPUT:

$ lex lexp.l
$ cc lex.yy.c -ll
$ ./a.out test.c

#include<stdio.h> is a Preprocessor Directive


Function: main( )
Block Begins int is a Keyword
fact is an Identifier
= is an Assignment Operator
1 is a Number
n is an Identifier
Function: for(
int is a Keyword
i is an Identifier
= is an Assignment Operator
1 is a Number
i is an Identifier
<= is a Relational Operator
n is an Identifier
i is an Identifier
);
Block Begins
fact is an Identifier
= is an Assignment Operator
fact is an Identifier
i is an Identifier
Block Ends
Function: printf( "Factorial Value of N is" is a String
fact is an Identifier );
Function: getch( );
Block Ends

RESULT:
Thus the program for implementation of a lexical analyzer using lex tool was executed
and verified successfully.
Ex.no:3(a) GENERATE YACC SPECIFICATION FOR A FEW SYNTACTIC
Date: CATEGORIES

Recognize A Valid Arithmetic Expression that Uses Operator +, - , * And /.

AIM:
To write a program to recognize a valid arithmetic expression that uses operator +, - , * and / using
YACC tool.

ALGORITHM:
LEX
1. Declare the required header file and variable declaration with in ‘%{‘ and ‘%}’.
2. LEX requires regular expressions to identify valid arithmetic expression token of lexemes.
3. LEX call yywrap() function after input is over. It should return 1 when work is done or should return 0
when more processing is required.

YACC
1. Declare the required header file and variable declaration with in ‘%{‘ and ‘%}’.
2. Define tokens in the first section and also define the associativity of the operations
3. Mention the grammar productions and the action for each production.
4. $$ refer to the top of the stack position while $1 for the first value, $2 for the second value in the stack.
5. Call yyparse() to initiate the parsing process.
6. yyerror() function is called when all productions in the grammar in second section doesn't match to the
input statement.

PROGRAM:
//art_expr.l
%{
#include<stdio.h>
#include "y.tab.h"
%}
%% [a-zA-Z][0-9a-zA-Z]* {return ID;}
[0-9]+(\.[0-9]+)? {return DIG;}
[ \t]+ {;}
. {return yytext[0];}
\n {return 0;}
%%
int yywrap()
{
return 1;
}

//art_expr.y
%{
#include<stdio.h>
%}
%token ID DIG
%left '+''-'
%left '*''/'
%right UMINUS
%%
stmt:expn ;
expn:expn'+'expn
| expn'-'expn
| expn'*'expn
| expn'/'expn
| '-'expn %prec UMINUS
| '('expn')'
| DIG
| ID
;
%%
int main()
{
printf("Enter the Expression : \n");
yyparse();
printf("Valid Expression \n");
return 0;
}
int yyerror()
{
printf("Invalid Expression");
exit(0);
}

OUTPUT:

$ lex artexp.l
$ yacc –d artexp.y
$ gcc lex.yy.c y.tab.c
$ ./a.out

Enter the expression :


a+b*c-d/e
Valid Expression
$ ./a.out

Enter the expression :


a=b
Invalid Expression

RESULT:
Thus the program to recognize a valid arithmetic expression that uses operator +, - , *
and / using YACC tool was executed and verified successfully.
Ex.no:3(b) Recognizing a Valid Variable which starts with a letter followed by
Date: any number of letters or digits.

AIM:
To write a program to recognize a valid variable which starts with a letter followed by
any number of letters or digits using YACC tool.

ALGORITHM

LEX
1. Declare the required header file and variable declaration with in ‘%{‘ and ‘%}’.
2. LEX requires regular expressions or patterns to identify token of lexemes for recognize a
valid variable.
3. Lex call yywrap() function after input is over. It should return 1 when work is done or
should return 0
when more processing is required.

YACC
1. Declare the required header file and variable declaration with in ‘%{‘ and ‘%}’.
2. Define tokens in the first section and also define the associativity of the operations
3. Mention the grammar productions and the action for each production.
4. $$ refer to the top of the stack position while $1 for the first value, $2 for the second value
in the stack.
5. Call yyparse() to initiate the parsing process.
6. yyerror() function is called when all productions in the grammar in second section doesn't
match to the input statement.

PROGRAM:
//valvar.l
%{
#include "y.tab.h"
%}
%%
[a-zA-Z] {return LET;}
[0-9] {return DIG;}
. {return yytext[0];} \n {return 0;}
%%
int yywrap()
{
return 1;
}

//valvar.y
%{
#include<stdio.h>
%}
%token LET DIG
%%
variable:var
;
var:var DIG
|var LET
|LET ;
%%
int main()
{
printf("Enter the variable:\n");
yyparse();
printf("Valid variable \n");
return 0;
}
int yyerror()
{
printf("Invalid variable \n");
exit(0);
}

OUTPUT:
$ lex valvar.l
$ yacc –d valvar.y
$ gcc lex.yy.c y.tab.c
$ ./a.out

Enter the variable :


Add
Valid variable
$ ./a.out
1Add
Invalid variable
$

RESULT:
Thus the program to recognize a valid variable which starts with a letter followed
by any number of letters or digits using YACC tool was executed and verified
successfully.
Ex.no:3(c) Program to recognize a valid control structures syntax of C language
Date: (for loop, while loop, if-else, if-else-if, switch-case, etc..)

Aim:
To implement a program to recognize a valid control structures syntax of c
language(for loop, while loop, if-else, if-else-if, switch-case, etc..).

Program:
Lex:
%{
#include "y.tab.h"
%}
alpha [A-Za-z]
digit [0-9]
%%
[ \t\n]
if { return IF;}
else { return ELSE;}
while { return WHILE;}
for { return FOR;}
switch { return SWITCH;}
case { return CASE;}
break { return BREAK;}
default { return DEFAULT;}
{digit}+ { return NUM;}
{alpha}({alpha}|{digit})* { return ID;}
"<=" { return LE;}
">=" { return GE;}
"==" { return EQ;}
"!=" { return NE;}
"||" { return OR;}
"&&" { return AND;}
. return yytext[0];
%%

Yacc:
%{
#include <stdio.h>
#include <stdlib.h>
%}
%token ID NUM SWITCH CASE DEFAULT BREAK FOR IF ELSE WHILE LE GE EQ
NE OR AND
%right '='
%left AND OR
%left '<' '>' LE GE EQ NE
%left '+''-'
%left '*''/'
%right UMINUS
%left '!'
%%
S : ST {printf("Input accepted.\n");exit(0);};
ST : WHILE'('E2')''{'ST1';''}'| IF'('E2')''{' ST1';''}'ELSE'{' ST1';''}'| IF'('E2')''{'
ST1';''}' ELSE ST1|IF '(' E2 ')' '{' ST1';''}' | FOR'('E';'E2';'E')'DEF | SWITCH'('ID')''{'B'}' ;
ST1 : ST1';' E |ST
|E
;
DEF :'{' BODY '}'|E';'|ST|;
BODY :BODY BODY | E';' | ST| ;
B:C|CD;
C : C C | CASE NUM ':' E ';' | BREAK ';' ;
D : DEFAULT ':' E ';' BREAK ';' ;
E : ID'='E
| E'+'E
| E'-'E
| E'*'E
| E'/'E
| E'<'E
| E'>'E
| E LE E
| E GE E
| E EQ E
| E NE E
| E OR E
| E AND E|E '+' '+' | E '-' '-' |
| ID
| NUM
;
E2 : E'<'E
| E'>'E
| E LE E
| E GE E
| E EQ E
| E NE E
| E OR E
| E AND E
| ID
| NUM
;

%%
main()
{
printf("Enter the exp: ");
yyparse();
}

void yyerror(const char* s){


fprintf(stderr,"%s\n",s);
}

Output:
Result:
Thus the program to recognize a valid control structures syntax of c language( for
loop, while loop, if-else, if-else-if, switch-case, etc..) was executed successfully and output
were verified.
Ex.no:3(d) IMPLEMENTATION OF CALCULATOR USING LEX AND YACC
Date:

AIM:
To write a program for implementing a calculator for computing the given
expression using semantic rules of the YACC tool and LEX.

ALGORITHM:
1. Start the program.
2. Get the input from the user and Parse it token by token.
3. First identify the valid inputs that can be given for a program.
4. The Inputs include numbers, functions like LOG, COS, SIN, TAN, etc. and operators.
5. Define the precedence and the associativity of various operators like +,-,/,* etc.
6. Write codes for saving the answer into memory and displaying the result on the screen.
7. Write codes for performing various arithmetic operations.
8. Display the possible Error message that can be associated with this calculation.
9. Display the output on the screen else display the error message on the screen.
10. Stop the program.

PROGRAM:
Lex
%{
#include "y.tab.h"
%}

DIGIT [0-9]
WS [ \t\n]

%%

{DIGIT}+ {
yylval = atoi(yytext);
return NUM;
}
"=" return EQ;
"-" return MINUS;
"+" return PLUS;
"/" return DIV;
"*" return MULT;
"(" return LPAREN;
")" return RPAREN;
{WS} /* skip whitespace */

. return yytext[0];
%%

int yywrap() {
return 1;
}

Yacc:
%{
#include <stdio.h>
#include <stdlib.h>
void yyerror(const char *s);
%}

%token NUM
%token PLUS MINUS MULT DIV LPAREN RPAREN EQ

%%

calc: exp EQ { printf("Result: %d\n", $1); }


;

exp: exp PLUS term { $$ = $1 + $3; }


| exp MINUS term { $$ = $1 - $3; }
| term { $$ = $1; }
;

term: term MULT factor { $$ = $1 * $3; }


| term DIV factor {
if ($3 != 0)
$$ = $1 / $3;
else {
yyerror("Error: Division by zero");
exit(EXIT_FAILURE);
}
}
| factor { $$ = $1; }
;

factor: NUM { $$ = $1; }


| LPAREN exp RPAREN { $$ = $2; }
;

%%

void yyerror(const char *s) {


fprintf(stderr, "%s\n", s);
}

int main() {
yyparse();
return 0;
}

OUTPUT:
RESULT:
Thus the program to implement calculator using LEX and YACC tool was executed
and verified successfully.
Ex.no:4 GENERATE THREE ADDRESS CODE FOR A SIMPLE PROGRAM
Date: USING LEX AND YACC

AIM:
To write a program to generate three address code for a simple program using LEX
and YACC.

ALGORITHM:
1. Start the program.
2. Declare the declarations as a header file {include<ctype.h>}
3. Token digit
4. Define the translations rules like line, expr, term, factor
Line:exp „\n‟ {print(“\n %d \n”,$1)} Expr:expr‟+‟ term ($$=$1=$3}
Term:term „+‟ factor($$ =$1*$3}
Factor
Factor:‟(„enter‟) „{$$ =$2)
%%
5. Define the supporting C routines
6. Stop the program

PROGRAM:
Program Name : three.l

%{
#include<stdio.h>
#include"y.tab.h"
int k=1;
%}

%%
[0-9]+ {
yylval.dval=yytext[0];
return NUM;
}
\n {return 0;}
. {return yytext[0];}
%%

void yyerror(char* str)


{
printf("\n%s",str);
}
char *gencode(char word[],char first,char op,char second)
{
char temp[10];
sprintf(temp,"%d",k);
strcat(word,temp);
k++;
printf("%s = %c %c %c\n",word,first,op,second);
return word; //Returns variable name like t1,t2,t3... properly
}
int yywrap()
{
return 1;
}
main()
{
yyparse();
return 0;
}

Program Name : three.y

%{
#include<stdio.h>
int aaa;
%}

%union{
char dval;
}
%token <dval> NUM
%type <dval> E
%left '+' '-'
%left '*' '/' '%'

%%
statement : E {printf("\nt = %c \n",$1);}
;
E : E '+' E
{
char word[]="t";
char *test=gencode(word,$1,'+',$3);
$$=test;
}

| E '-' E
{
char word[]="t";
char *test=gencode(word,$1,'-',$3);
$$=test;
}

| E '%' E {
char word[]="t";
char *test=gencode(word,$1,'%',$3);
$$=test;
}

| E '*'E
{
char word[]="t";
char *test=gencode(word,$1,'*',$3);
$$=test;
}
| E '/' E
{
char word[]="t";
char *test=gencode(word,$1,'/',$3);
$$=test;
}
| '('E ')'
{
$$=$2;
}| NUM {
$$=$1;
}
;
%%

OUTPUT:
$ lex three.l
$ yacc -d three.y
$ cc lex.yy.c y.tab.c -ll
$ ./a.out
Enter Expression x => 1+2-3*3/1+4*5
A = 1+2
B = 3*3
C = B/1
D = A-C
E = 4*5
F = D+E
X=F
$

RESULT:
Thus the program to generate three address code for a simple program using LEX and
YACC tool was executed and verified successfully.
Ex.no:5 TYPE CHECKING USING LEX AND YACC
Date:

AIM:
To generate a simple program for type checking using LEX and YACC.
ALGORITHM:
Step 1: Start the program.
Step 2: Define the YACC grammar rules.
Step 3: Define the lex rules.
Step 4: Compile the YACC and Lex files.
Step 5: Link the compile files.
Step 6: Run the program.
Step 7: Prompt the user to enter an expression.
Step 8: Read the input expression.
Step 9: Parse the expression using the YACC parser.
Step 10: If the expression is valid, display the resulting type of input.
Step 11: If there are any errors, display the error message.
Step 12: Repeat steps 7 to 11 if the user wants to check more input.
Step 13: Stop the program.
PROGRAM:
#include<stdio.h>
#include<string.h>
#include<conio.h>
int count=1,i=0,j=0,l=0,findval=0,k=0,kflag=0;
char key[4][12]= {"int","float","char","double"};
char dstr[100][100],estr[100][100];
char token[100],resultvardt[100],arg1dt[100],arg2dt[100];
void entry();
int check(char[]);
int search(char[]);
void typecheck();
struct table
{
char var[10];
char dt[10];
};
struct table tbl[20];
void main()
{
clrscr();
printf(" \n IMPLEMENTATION OF TYPE CHECKING \n");
printf(" \n DECLARATION \n \n");
do{
printf(" \t");
gets(dstr[i]); i++;
} while(strcmp(dstr[i -1],"END"))
printf(" \n EXPRESSION \n \n");
do{
printf(" \t");
gets(estr[l]);
l++;
}while(strcmp(estr[l -1],"END"));
i=0;
printf(" \n SEMANTIC ANALYZER(TYPE CHECKING): \n");
while(strcmp(dstr[i],"END"))
{ entry();
printf(" \n");
i++;
}
l=0;
while(strcmp(estr[l],"END")) { typecheck() ;
printf(" \n");
l++;
}
printf(" \n PRESS ENTER TO EXIT FROM TYPE CHECKING \n");
getch();
}
void entry()
{ j=0;
k=0;
memset(token,0,sizeof(token));
while(dstr[i][j]!=' ')
{
token[k]=dstr[i][j];
k++;
j++;
}
kflag=check(token);
if(kflag==1)
{
strcpy(tbl[count].dt,token);
k=0;
memset(token,0,strlen(token));
j++;
while(dstr[i][j]!=';')
{ token[k]=dstr[i][j];
k++;
j++;
}
findval=search(token);
if(findval==0)
{
strcpy(tbl[count].var,token);
}
else
{ printf("The variable %s is already declared",token);
}
kflag=0;
count++;
}
else
{
printf("Enter valid datatype \n");
}
}
void typecheck()
{
memset(token,0,strlen(token));
j=0;
k=0;
while(estr[l][j]!='=')
{
token[k]=estr[l][j];
k++;
j++;
}
findval=search(token);
if(findval>0)
{
strcpy(resultvardt,tbl[findval].dt);
findval=0;
}
else
{
printf("Undefined Variable \n");
}
k=0;
memset(token,0,strlen(token));
j++;
while(((estr[l][j]!='+')&&(estr[l][j]!=' -')&&(estr[l][j]!='*')&&(estr[l][j]!='/')))
{
token[k]=estr[l][j];
k++;
j++;
}
findval=search(token);
if(findval>0)
{ strcpy(arg1dt,tbl[finalval].dt);
findval=0;
}
else
{
printf("Undefined Variable \n");
}
k=0;
memset(token,0,strlen(token));
j++;
while(estr[l][j]!=';')
{
token[k]=estr[l][j];
k++;
j++;
}
findval=search(token);
if(findval>0)
{
strcpy(arg2dt,tbl[findval].dt);
findval=0;
}
else
{
printf("Undefined Variable \n");
}
if(!strcmp(arg1dt,arg2dt))
{
if(!strcmp(resultvardt,arg1dt))
{
printf("\tThere is no type mismatch in the expression %s ",estr[l]);
}
else
{
printf("\tLvalue and Rvalue should be same\n");
}
}
else
{
printf("\tType Mismatch\n");
}
}
int search(char variable[])
{ int i; for(i=1;i<=count;i++)
{ if(strcmp(tbl[i].var,variable) == 0)
{ return i;
}
}
return 0;
}
int check(char t[])
{ int in;
for(in=0;in<4;in++)
{
if(strcmp(key[in],t)==0)
{
return 1;
}
}
return 0;
Output:

Result:
Thus, type checking using YACC and LEX has been implemented and executed
successfully with the verified output.
Ex.no:06 CODE OPTIMIZATION-REDUCTION IN STRENGTH OF OPERATOR
Date:

AIM:

To implement the code optimization technique reduction in strength of operator


using algebraic identity.
PROGRAM:

#include <stdio.h>
#include<stddef.h>
#include<string.h>
#include<stdlib.h>
char input[20];
void getinput();
void reduces();
void display();
FILE *fin;
int i,j;
char token[50][50];
int main(int argc,char *argv[])
{
if(argc>1)
{
fin=fopen(argv[1],"r");
if(!fin)
{
printf("can't open");
exit(0);
}
}
getinput();
reduces();
display();
}
void getinput()
{
char c[1024];
char *str;
i=0;
while (fgets(c,1024, fin) != NULL)
{
str=strtok (c," ");
while(str!=NULL)
{
strcpy(token[i],str);
str=strtok (NULL," ");
i++;
}
}
fclose(fin);
}
void reduces()
{
int k,j;
j=0;
char temp[10];
for(k=0;k<i;k++)
{
if(token[k+1][0]=='=')
{
switch (token[k+3][0])
{
case '+':
case '-':
if (strcmp(token[k+4],"0")==0)
{
token[k+3][0]='\0';
token[k+4][0]='\0';
k=k+5;
}
break;
case '/':
if (strcmp(token[k+4],"1")==0)
{
token[k+3][0]='\0';
token[k+4][0]='\0';
k=k+5;
}
break;
case '*':
switch (token[k+4][0])
{
case '0':
strcpy(token[k+2],"0");
token[k+3][0]='\0';
token[k+4][0]='\0';
break;
case '1':
token[k+3][0]='\0';
token[k+4][0]='\0';
break;
case '2':
strcpy(token[k+3],"+");
strcpy(token[k+4],token[k+2]);
break;
}
k=k+5;
break;
case '^':
switch (token[k+4][0])
{
case '0':
strcpy(token[k+2],"1");
token[k+3][0]='\0';
token[k+4][0]='\0';
break;
case '1':
token[k+3][0]='\0';
token[k+4][0]='\0';
break;
case '2':
strcpy(token[k+3],"*");
strcpy(token[k+4],token[k+2]);
break;
}
k=k+5;
break;
}
}
}
}
void display()
{
int k;
for(k=0;k<i;k++)
{
if(token[k][0]!='\0')
{
if(strcmp(token[k],")")!=0 && strcmp(token[k],";")!=0)
{
printf("%s\t",token[k]);
}
else
{
printf("\n");
}
}
}
}

INPUT:
In3.c
while ( a <= b )
{
x=x+0;
y=y-0;
t=x*0;
z=x+2;
t=x*1;
r=y/1;
t=x^0;
r=y^1;
y=y^2;
}
OUTPUT:

RESULT:
Thus the program to implement the code optimization technique using reduction in
strength of operator using algebraic identity has been executed successfully.
Ex.no: 06(B) CODE OPTIMIZATION- CONSTANT FOLDING
Date:

AIM:
To implement the code optimization technique constant folding.
PROGRAM:
#include <stdio.h>
#include<stddef.h>
#include<string.h>
#include<stdlib.h>
char input[20];
void getinput();
void codemotion();
FILE *fin;
int i,j;
char token[50][50];
int main(int argc,char *argv[])
{
if(argc>1)
{
fin=fopen(argv[1],"r");
if(!fin)
{
printf("can't open");
exit(0);
}
}
getinput();
codemotion();
}
void getinput()
{
char c[1024];
char *str;
i=0;
while (fgets(c,1024, fin) != NULL)
{
str=strtok (c," ");
while(str!=NULL)
{
strcpy(token[i],str);
str=strtok (NULL," ");
i++;
}
}
fclose(fin);
}
void codemotion()
{
char identifier[20][20],opcode[20][20];
char ch,temp[4];
char unique[20][20];
int l=0;
int k=0;j=0;
int flag=0,m,n,a,x;
while(k<i)
{
ch=token[k][j];
if(toascii(ch)>96 && toascii(ch)<123 )
{
if(strcmp(token[k],"while")!=0)
{
strcpy(identifier[l],token[k]);
l++;
}
}
k++;
}
j=0;
for(k=0;k<l-1;k++)
{
for(m=k+1;m<l;m++)
{
if(strcmp(identifier[k],identifier[m])==0)
{
flag=1;
}
}
if(flag!=1)
{
strcpy(unique[j],identifier[k]);
j++;
}
flag=0;
}
m=0;n=0,x=0;
for(k=0;k<i;k++)
{
if(strcmp(token[k],unique[m])==0)
{
if(strcmp(token[k+1],"=")!=0)
{
sprintf(temp, "t%d", n);
n++;
strcat(opcode[x],temp);
strcat(opcode[x],"=");
strcat(opcode[x],token[k]);
strcpy(token[k],temp);
k++;
while(token[k][0]!=')' && token[k][0]!=';')
{
strcat(opcode[x],token[k]);
token[k][0]='\0';
k++;
}
strcat(opcode[x],";");
x++;
m++;
}
else
{
m++;
}
}
}
printf("\nOPTIMIZED CODE AFTER CONSTANT FOLDING:\n");
for(a=0;a<x;a++)
{
printf("%s\n",opcode[a]);
}
for(k=0;k<i;k++)
{
if(token[k][0]!='\0')
{
if(strcmp(token[k],")")!=0 && strcmp(token[k],";")!=0)
{
printf("%s\t",token[k]);
}
else
{
printf("\n");
}
}
}
}
INPUT: space sensitive
In.c
while ( i <= limit - 2 )
{
j=c-3;
i=i+2;
}
OUTPUT:

RESULT:
Thus the program for code optimization using constant folding is executed successfully.
Ex.no:7 IMPLEMENT BACK-END OF THE COMPILER FOR WHICH THE
Date: ADDRESS CODE IS GIVEN AS INPUT AND THE 8086 ASSEMBLY
LANGUAGE CODE IS PRODUCED AS OUTPUT

Aim:
To Implement back-end of the compiler for which the three address code is given as input
and the 8086 assembly language code is produced as output.

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 output.c
5. Print the output.
6. Stop the program

Program:
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<ctype.h>
#include<graphics.h>
typedef struct
{
char var[10];
int alive;
}
regist;
regist preg[10];
void substring(char exp[],int st,int end)
{
int i,j=0;
char dup[10]="";
for(i=st;i<end;i++)
dup[j++]=exp[i];
dup[j]='0';
strcpy(exp,dup);
}

int getregister(char var[])


{
int i;
for(i=0;i<10;i++)
{
if(preg[i].alive==0)
{
strcpy(preg[i].var,var);
break;
}
}
return(i);
}

void getvar(char exp[],char v[])


{
int i,j=0;
char var[10]="";
for(i=0;exp[i]!='\0';i++)
if(isalpha(exp[i]))
var[j++]=exp[i];
else
break;
strcpy(v,var);
}
void main()
{
char basic[10][10],var[10][10],fstr[10],op;
int i,j,k,reg,vc,flag=0;
clrscr();
printf("\nEnter the Three Address Code:\n");
for(i=0;;i++)
{
gets(basic[i]);
if(strcmp(basic[i],"exit")==0)
break;
}
printf("\nThe Equivalent Assembly Code is:\n");
for(j=0;j<i;j++)
{
getvar(basic[j],var[vc++]);
strcpy(fstr,var[vc-1]);
substring(basic[j],strlen(var[vc-1])+1,strlen(basic[j]));
getvar(basic[j],var[vc++]);
reg=getregister(var[vc-1]);
if(preg[reg].alive==0)
{
printf("\nMov R%d,%s",reg,var[vc-1]);
preg[reg].alive=1;
}
op=basic[j][strlen(var[vc-1])];
substring(basic[j],strlen(var[vc-1])+1,strlen(basic[j]));
getvar(basic[j],var[vc++]);
switch(op)
{
case '+': printf("\nAdd"); break;
case '-': printf("\nSub"); break;
case '*': printf("\nMul"); break;
case '/': printf("\nDiv"); break;
}
flag=1;
for(k=0;k<=reg;k++)
{
if(strcmp(preg[k].var,var[vc-1])==0)
{
printf("R%d, R%d",k,reg);
preg[k].alive=0;
flag=0;
break;
}
}
if(flag)
{
printf(" %s,R%d",var[vc-1],reg);

printf("\nMov %s,R%d",fstr,reg);
}
strcpy(preg[reg].var,var[vc-3]);
getch();
}
}

OUTPUT:

Enter the Three Address code:


A=b+c
B=d-e
C=f*g
D=h/i
exit

Equivalent Assemble code is:

Mov R0,b
Add C, R0
Mov A, R0
Mov R1,d
Sub e,R1
Mov B,R1
Mov R2,f
Mul g,R2
Mov C,R2
Mov R3,h
Div i,R3
Mov D,R3

Result:
Thus the program to implement back-end of the compiler for which the address code is
given as input and the 8086 assembly language code is produced as output.

You might also like