Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
3 views

CD Lab

The document outlines the laboratory work for the Compiler Design course at Anna University, detailing various experiments related to lexical analysis, symbol table creation, and parsing of arithmetic expressions and control structures using LEX and YACC tools. Each experiment includes the aim, algorithm, program code, and results indicating successful execution and verification. The document serves as a bonafide record of the practical work conducted during the academic year 2023-24.

Uploaded by

Sathyan P
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

CD Lab

The document outlines the laboratory work for the Compiler Design course at Anna University, detailing various experiments related to lexical analysis, symbol table creation, and parsing of arithmetic expressions and control structures using LEX and YACC tools. Each experiment includes the aim, algorithm, program code, and results indicating successful execution and verification. The document serves as a bonafide record of the practical work conducted during the academic year 2023-24.

Uploaded by

Sathyan P
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 39

ANNA UNIVERSITY

UNIVERSITY COLLEGE OF ENGINEERING-DINDIGUL

DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING

CS3501 –COMPILER DESIGN LABORATORY


ANNA UNIVERSITY
UNIVERSITY COLLEGE OF ENGINEERING – DINDIGUL
DINDIGUL – 62422

BONAFIDE CERTIFICATE
This is to certify that is a bonafide record of work done by
Mr./Ms.
in
laboratory during the academic year 2023-24

University Registration no.:

Staff In charge Head of the Department

Submitted for the university Practical Examination held on

INTERNAL EXAMINER EXTERNAL EXAMINER


INDEX
EXPT NAME OF THE EXPERIMENT PAGE DATE OF SIGNATURE
NO. NO. COMPLETION
EXP NO:1a LEXICAL ANALYZER TO RECOGNIZE
PATTERNS IN C
DATE:

AIM:
To develop a lexical analyzer to recognize a few patterns in C. (Ex. identifiers, constants,
comments, operators etc.)

ALGORITHM:
Step 1: Start the program.
Step 2: Include the header files.
Step 3: Allocate memory for the variable by dynamic memory allocation function.
Step 4: Use the file accessing functions to read the file.
Step 5: Get the input file from the user.
Step 6: Separate all the file contents as tokens and match it with the functions.
Step 7:Define all the keywords in a separate file and name it as key.c
Step 8: Define all the operators in a separate file and name it as open.c
Step 9: Give the input program in a file and name it as input.c
Step 10:Finally print the output after recognizing all the tokens.
Step 11: Stop the program.

PROGRAM:
Lex.l

%{
#include <stdio.h>
}
%%
[a-zA-Z][a-zA-Z0-9_]* { printf("Identifier: %s\n", yytext); }
[0-9]+ { printf("Integer: %s\n", yytext); } 0-9]+.[0-9]+ { printf("Float: %s\n", yytext); }
[ [/]{1}[/]{1}[a-zA-Z0-9]* {printf("Single Line Comment");}
[/]{1}[]{1}[a-zA-Z0-9][*]{1}[/]{1} printf("Multiline Comment");
[-,+]?[0-9]+ printf("Constants");
[+/-] printf("operator");
%%
int yywrap(void) {return 0;}
int main()
{
yylex();
return 0;
}

RESULT:
Thus, the above developed lexical analyzer to recognize a few patterns in C by using the LEX
tool (Ex. identifiers, constants, comments, operators etc.) was executed successfully and thoutput
was verified.
EXP NO:1b
CREATE A SYMBOL TABLE, WHILE RECOGNIZING
DATE: IDENTIFIERS

AIM:
To create a symbol table, while recognizing identifiers.

ALGORITHM:
Step 1: Start the program.
Step 2: Get the input from the user with the terminating symbol ‘$’.
Step 3: Allocate memory for the variable by dynamic memory allocation function.
Step 4: If the next character of the symbol is an operator then only the memory is allocated.
Step 5: While reading, the input symbol is inserted into symbol table along with its memory address.
Step 6: The steps are repeated till ‘$’ is reached.
Step 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.
Step 8: Stop the program

PROGRAM:
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
void main()
{
int i=0,j=0,x=0,n;
void *p,*add[5];
char ch,srch,b[15],d[15],c;
printf("Expression 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 addr \t type");
while(j<=n)
{
c=b[j];
if(isalpha(toascii(c)))
{
p=malloc(c);
add[x]=p;
d[x]=c;
printf("\n%c \t %p \t identifier\n",c,p);
x++;
j++;
}
else
{
ch=c;
if(ch=='+'||ch=='-'||ch=='*'||ch=='=')
{
p=malloc(ch);
add[x]=p;
d[x]=ch;
printf("\n %c \t %p \t operator\n",ch,p);
x++;
j++;
}
}
}
}

RESULT:
Thus symbol table to recognize identifiers was created and executed successfully and the
output is verified.
EXP NO:02
Lexical Analyzer using LEX Tool
DATE:

AIM:
To write a program to implement a Lexical Analyzer using LEX Tool.

ALGORITHM:
Step 1: Initialize COMMENT and cmt to zero.
Step 2: Analysis the lexical values,
Step 2.1: Identify and print preprocessor directives, keywords.
Step 2.2: Detect the start of a comment.
Step 2.3: Identify and print function definitions, special characters, assignment operator,
relational operators, identifiers and strings in double quotes, numbers (integers).
Step 3: Identify the functions,
Step 3.1: Check for a command-line input file argument.
Step 3.2: If provided, open the file and set yyin to read from it.
Step 3.3: Perform lexical analysis by calling.
Step 3.4: Print the total count of comments.
Step 4: To identify the function yywrap(),
Step 4.1: Return 1 to indicate the end of input.

PROGRAM:
Lex.l

%{
int COMMENT=0;
int cnt=0;
%}
identifier [a-zA-Z][a-zA-Z0-9]*
%%
#.* { printf("\n%s is a PREPROCESSOR DIRECTIVE",yytext);}
int |
float |
char |
double |
while |
for |
do |
if |
break |
continue |
void |
switch |
case |
long |
struct |
const |
typedef |
return |
else |
goto {printf("\n\t%s is a KEYWORD",yytext);}
"/*" {COMMENT = 1;}
"*/" {COMMENT = 0; cnt++;}
{identifier}\( {if(!COMMENT)printf("\n\nFUNCTION\n\t%s",yytext);}
\{ {if(!COMMENT) printf("\n BLOCK BEGINS");}
\} {if(!COMMENT) printf("\n BLOCK ENDS");}
{identifier}(\[[0-9]*\])? {if(!COMMENT) printf("\n %s IDENTIFIER",yytext);}
\".*\" {if(!COMMENT) printf("\n\t%s is a STRING",yytext);}
[0-9]+ {if(!COMMENT) printf("\n\t%s is a NUMBER",yytext);}
\)(\;)? {if(!COMMENT) printf("\n\t");ECHO;printf("\n");}
\( ECHO;
= {if(!COMMENT)printf("\n\t%s is an ASSIGNMENT OPERATOR",yytext);}
\<= |
\>= |
\< |
== |
\> {if(!COMMENT) printf("\n\t%s is a RELATIONAL OPERATOR",yytext);}
%%
int main(int argc,char **argv)
{
if (argc> 1)
{
FILE *file;
file = fopen(argv[1],"r");
if(!file)
{
printf("could not open %s \n",argv[1]);
exit(0);
}
yyin = file;
}
yylex();
printf("\n\n Total No.Of comments are %d",cnt);
return 0;
}
int yywrap()
{
return 1;
}

RESULT:
Thus a program to implement a Lexical Analyzer using LEX Tool was executed successfully and
the output is verified.
EX NO: 3a PROGRAM TO RECOGNIZE A VALID
ARITHMETIC EXPRESSION
DATE:

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

ALGORITHM:
Step 1: Read the given expression.
Step 2: If there are parentheses then they must appear in pairs, as ( ... ), and ( must be immediately
before a number and ) must be immediately after a number.
Step 3: Apart from parentheses a valid arithmetic expression is a sequence of numbers with one
operator symbol between successive numbers. Then print it is valid.
Step 4: Otherwise print it as not valid.

PROGRAM:
3a.l

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

3a.y
%{
#include <stdio.h>
#include <stdlib.h>
int yylex(void);
void yyerror(char const *);
%}
%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;
}
void yyerror(const char *s)
{
printf("Invalid Expression");
exit(0);
}

RESULT:
Thus a program to recognize a valid arithmetic expression that uses operator +, -, * and / was
executed successfully and the output is verified.
EXP NO:3b
PROGRAM TO RECOGNIZE A VALID VARIABLE

DATE:

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

ALGORITHM:
Step 1: Read the given input string.
Step 2: Check the initial character of the string is numerical or any special character except ‘_’ then
print it is not a valid identifier.
Step 3: Otherwise print it as valid identifier if remaining characters of string doesn’t contains any
special characters except ‘_’.

PROGRAM:
3b.l

%{
#include "y.tab.h"
%}
%%
[0-9]+ {return DIGIT;}
[a-zA-Z]+ {return LETTER;}
[ \t] {;}
\n { return 0;}
. {return yytext[0];}
%%
int yywrap() {
// Return 1 to indicate the end of input
return 1;
}

3b.y
%{
#include<stdio.h>
#include<stdlib.h>
int yylex(void);
void yyerror(char const *);
%}
%token DIGIT LETTER
%%
stmt:A
;
A: LETTER B
;
B: LETTER B
| DIGIT B
| LETTER
| DIGIT
;
%%
void main(){
printf("enter string \n");
yyparse();
printf("valid");
exit(0);
}
void yyerror(const char *s)
{
printf("invalid");
exit(0);
}

RESULT:
Thus a program to recognize a valid variable which starts with a letter followed by any
number of letters or digits was executed successfully and the output is verified.
EX NO: 3c Program to recognize a valid control
structures syntax of C language
DATE:

AIM:
To write a YACC program to recognize a valid control structures syntax of C language (For
loop,while loop, if-else, if-else-if, switch-case, etc.).

ALGORITHM:
Step 1: Start the program.
Step 2: Read the statement.
Step 3:Validating the given statement according to the rule using yacc.
Step 4: Using the syntax rule print the result of the given syntax.
Step 5: Stop the program.

FOR LOOP

PROGRAM:
For.l
%{
#include<stdio.h>
#include "y.tab.h"
%}
alpha [A-Za-z]
digit [0-9]
%%
[\t \n]
for return FOR;
{digit}+ return NUM;
{alpha}({alpha}|{digit})* return ID;
"<=" return LE;
">=" return GE;
"==" return EQ;"
!=" return NE;
"||" return OR;
"&&" return AND;
. return yytext[0];
%%yywrap()
{}

For.y
%{
#include <stdio.h>
#include <stdlib.h>
%}
%token ID NUM FOR LE GE EQ NE OR AND
%right '='
%left OR AND
%left '>' '<' LE GE EQ NE
%left '+' '-'
%left '*' '/'
%right UMINUS
%left '!'
%%S
: ST {printf("Input accepted\n"); exit(0);};
ST : FOR '(' E ';' E2 ';' E ')' DEF
;
DEF : '{' BODY '}'
| E';'
| ST
|
;
BODY : BODY BODY
| E ';'
| ST
|
;
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
;
%%
main() {
printf("Enter the expression:\n");
yyparse();
}
yyerror()
{
printf("\nEntered arithmetic expression is Invalid\n\n");
}

WHILE LOOP
PROGRAM:
While.l

%{
#include<stdio.h>
#include "y.tab.h"
%}
alpha [A-Za-z]
digit [0-9]
%%
[\t \n]
while return WHILE;
{digit}+ return NUM;
{alpha}({alpha}|{digit})* return ID;
"<=" return LE;
">=" return GE;
"==" return EQ;
"!=" return NE;
"||" return OR;
"&&" return AND;
. return yytext[0];
%%yywrap()
{}

While.y

%{
#include <stdio.h>
#include <stdlib.h>
%}
%token ID NUM WHILE LE GE EQ NE OR AND
%right '='
%left AND OR
%left '<' '>' LE GE EQ NE
%left '+''-'
%left '*''/'
%right UMINUS
%left '!'
%%
S : ST1 {printf("Input accepted.\n");exit(0);};
ST1 : WHILE'(' E2 ')' '{' ST '}'
ST : ST ST
| E';'
;
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
| 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();
}
yyerror()
{
printf("\nEntered arithmetic expression is Invalid\n\n");
}
IF ELSE

PROGRAM:
If.l

%{
#include<stdio.h>
#include "y.tab.h"
%}
alpha [A-Za-z]
digit [0-9]
%%
[ \t\n]
if return IF;
then return THEN;
else return ELSE;
{digit}+ return NUM;
{alpha}({alpha}|{digit})* return ID;
"<=" return LE;
">=" return GE;
"==" return EQ;
"!=" return NE;
"||" return OR;
"&&" return AND;
. return yytext[0];
%%
yywrap()
{}

If.y

%{
#include <stdio.h>
#include <stdlib.h>
%}
%token ID NUM IF THEN LE GE EQ NE OR AND ELSE
%right '='
%left AND OR
%left '<' '>' LE GE EQ NE
%left '+''-'
%left '*''/'
%right UMINUS
%left '!'
%%
S : ST {printf("Input accepted.\n");exit(0);};
ST : IF '(' E2 ')' THEN ST1';' ELSE ST1';'
| IF '(' E2 ')' THEN ST1';'
;
ST1 : ST
|E
;
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
| 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();
}
yyerror(){
printf("\nEntered arithmetic expression is Invalid\n\n");
}

IF ELSE IF
PROGRAM:
Elseif.l

%{
#include<stdio.h>
#include "y.tab.h"
%}
alpha [A-Za-z]
digit [0-9]
%%
[ \t\n]
if return IF;
then return THEN;
else return ELSE;
elseif return ELSEIF;
{digit}+ return NUM;
{alpha}({alpha}|{digit})* return ID;
"<=" return LE;
">=" return GE;
"==" return EQ;
"!=" return NE;
"||" return OR;
"&&" return AND;
. return yytext[0];
%%yywrap()
{}

Elseif.y

%{
#include <stdio.h>
#include <stdlib.h>
%}
%token ID NUM IF THEN LE GE EQ NE OR AND ELSE
%right '='
%left AND OR
%left '<' '>' LE GE EQ NE
%left '+''-'
%left '*''/'
%right UMINUS
%left '!'
%%
S : ST {printf("Input accepted.\n");exit(0);};
ST : IF '(' E2 ')' THEN ST1';' ELSEIF '(' E2 ')' THEN ST1';'ELSE ST1';'
| IF '(' E2 ')' THEN ST1';'
;
ST1 : ST
|E
;
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
| 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();
}
yyerror(){
printf("\nEntered arithmetic expression is Invalid\n\n");
}

SWITCH
PROGRAM:
Switch.l

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

Switch.y

%{
#include<stdio.h>
#include<stdlib.h>
%}
%token ID NUM SWITCH CASE DEFAULT BREAK LE GE EQ NE AND OR IF THEN WHILE
%right '='
%left AND OR
%left '<' '>' LE GE EQ NE
%left '+''-'
%left '*''/'
%right UMINUS
%left '!'
%%
S : ST{printf("\nInput accepted\n");exit(0);};
;
ST : SWITCH'('ID')''{'B'}'
;
B :C
|CD
;
C :CC
| CASE NUM':'ST1 BREAK';'
;
D : DEFAULT':'ST1 BREAK';'
| DEFAULT':'ST1
;
ST1 : WHILE'('E2')' E';'
| IF'('E2')'THEN E';'
| ST1 ST1
| E';'
;
E2 : E'<'E
| E'>'E
| E LE E
| E GE E
| E EQ E
| E NE E
| E AND E
| E OR E
;
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 AND E
| E OR E
| ID
| NUM
;
%%
main()
{
printf("Enter the exp: ");
yyparse();
}
yyerror()
{
printf("\nEntered arithmetic expression is Invalid\n\n");
}

RESULT:
Thus, the given program to recognize valid control structures is executed successfully and the
output is verified.
EXP NO:3d
CALCULATOR USING LEX AND YACC
DATE:

Aim:
To implementation of calculator using LEX and YACC.

ALGORITHM:
Step 1: Start the program.
Step 2: Perform the calculation using both the lex and yacc.
Step 3: In the lex tool, if the given expression contains numbers and letters then they are displayed.
Step 4: In the same way, the digits, letters and u minus are identified and displayed using yacc tool.
Step 5: The calculation is performed and the result is displayed.
Step 6: Stop the program.

PROGRAM:
Calc.l

%{
#include <stdio.h>
#include "y.tab.h"
int c;
extern int yylval;
%}
%%
"";
[a-z] {
c = yytext[0];
yylval = c - 'a';
return(LETTER);
}
[0-9] {
c = yytext[0];
yylval = c - '0';
return(DIGIT);
}
[^a-z0-9\b] {
c = yytext[0];
return(c);
}

Calc.y
%{
#include <stdio.h>
int yylex(void);
void yyerror(char const *);
int regs[26];
int base;
%}
%start list
%token DIGIT LETTER
%left '|'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left UMINUS /*supplies precedence for unary minus */
%% /* beginning of rules section */
list: /*empty */
|
list stat '\n'
|
list error '\n'
{
yyerrok;
}
;
stat: expr
{
printf("%d\n",$1);
}
|
LETTER '=' expr
{
regs[$1] = $3;
}
;
expr: '(' expr ')'
{
$$ = $2;
}
|
expr '*' expr
{
$$ = $1 * $3;
}
|
expr '/' expr
{
$$ = $1 / $3;
}
|
expr '%' expr
{
$$ = $1 % $3;
}
|
expr '+' expr
{
$$ = $1 + $3;
}
|
expr '-' expr
{
$$ = $1 - $3;
}
|
expr '&' expr
{
$$ = $1 & $3;
}
|
expr '|' expr
{
$$ = $1 | $3;
}
|
'-' expr %prec UMINUS
{
$$ = -$2;
}
|
LETTER
{
$$ = regs[$1];
}
|
number
;
number: DIGIT
{
$$ = $1;
base = ($1==0) ? 8 : 10;
}|
number DIGIT
{
$$ = base * $1 + $2;
}
;
%%
int main()
{
return(yyparse());
}
void yyerror(const char *s)
{
fprintf(stderr, "%s\n",s);
}
int yywrap()
{
return(1);
}
RESULT:
Thus the implementation of calculator using LEX and YACC was executed successfully and the
output is verified.
EXP NO:04
THREE ADDRESS CODE FOR SIMPLE PROGRAM
DATE: USING LEX AND YACC
AIM:
To generate three address code for a simple program using LEX and YACC.

ALGORITHM:
Step 1: Begin the program
Step 2: The expression is read from the file using a file pointer
Step 3: Each string is read and the total no. of strings in the file is calculated.
Step 4: Each string is compared with an operator; if any operator is seen then the previous string and
next string are concatenated and stored in a first temporary value and the three address code
expression is printed
Step 5: Suppose if another operand is seen then the first temporary value is concatenated to the next
string using the operator and the expression is printed.
Step 6 The final temporary value is replaced to the left operand value.
Step 7: End the program.

PROGRAM:
Three.l

%{
#include "y.tab.h"
%}
%%
[0-9]+? {yylval.sym=(char)yytext[0]; return NUMBER;}
[a-zA-Z]+? {yylval.sym=(char)yytext[0];return LETTER;}
\n {return 0;}
. {return yytext[0];}
%%
int yywrap()
{
return 1;
}

Three.y

%{
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
int yylex(void);
void yyerror(char const *);
void ThreeAddressCode();
void triple();
void qudraple();
char AddToTable(char ,char, char);
int ind=0;//count number of lines
char temp = '1';//for t1,t2,t3.....
struct incod
{
char opd1;
char opd2;
char opr;
};
%}
%union
{
char sym;
}
%token <sym> LETTER NUMBER
%type <sym> expr
%left '+'
%left '*''/'
%left '-'
%%
statement: LETTER '=' expr ';' {AddToTable((char)$1,(char)$3,'=');}
| expr ';'
;
expr:
expr '+' expr {$$ = AddToTable((char)$1,(char)$3,'+');}
| expr '-' expr {$$ = AddToTable((char)$1,(char)$3,'-');}
| expr '*' expr {$$ = AddToTable((char)$1,(char)$3,'*');}
| expr '/' expr {$$ = AddToTable((char)$1,(char)$3,'/');}
| '(' expr ')' {$$ = (char)$2;}
| NUMBER {$$ = (char)$1;}
| LETTER {$$ = (char)$1;}
|'-' expr {$$ = AddToTable((char)$2,(char)'\t','-');}
;
%%
void yyerror(const char *s)
{
printf("%s",s);
exit(0);
}
struct incod code[20];
char AddToTable(char opd1,char opd2,char opr)
{
code[ind].opd1=opd1;
code[ind].opd2=opd2;
code[ind].opr=opr;
ind++;
return temp++;
}
void ThreeAddressCode()
{
int cnt = 0;
char temp = '1';
printf("\n\n\t THREE ADDRESS CODE\n\n");
while(cnt<ind)
{
if(code[cnt].opr != '=')
printf("t%c : = \t",temp++);
if(isalpha(code[cnt].opd1))
printf(" %c\t",code[cnt].opd1);
else if(code[cnt].opd1 >='1' && code[cnt].opd1 <='9')
printf("t%c\t",code[cnt].opd1);
printf(" %c\t",code[cnt].opr);
if(isalpha(code[cnt].opd2))
printf(" %c\n",code[cnt].opd2);
else if(code[cnt].opd2 >='1' && code[cnt].opd2 <='9')
printf("t%c\n",code[cnt].opd2);
cnt++;
}
}
void quadraple()
{
int cnt = 0;
char temp = '1';
printf("\n\n\t QUADRAPLE CODE\n\n");
while(cnt<ind)
{
printf(" %c\t",code[cnt].opr);
if(code[cnt].opr == '=')
{
if(isalpha(code[cnt].opd2))
printf(" %c\t \t",code[cnt].opd2);
else if(code[cnt].opd2 >='1' && code[cnt].opd2 <='9')
printf("t%c\t \t",code[cnt].opd2);
printf(" %c\n",code[cnt].opd1);
cnt++;
continue;
}
if(isalpha(code[cnt].opd1))
printf(" %c\t",code[cnt].opd1);
else if(code[cnt].opd1 >='1' && code[cnt].opd1 <='9')
printf("t%c\t",code[cnt].opd1);
if(isalpha(code[cnt].opd2))
printf(" %c\t",code[cnt].opd2);
else if(code[cnt].opd2 >='1' && code[cnt].opd2 <='9')
printf("t%c\t",code[cnt].opd2);
else printf(" %c",code[cnt].opd2);
printf("t%c\n",temp++);
cnt++;
}
}
void triple()
{
int cnt=0;
char temp='1';
printf("\n\n\t TRIPLE CODE\n\n");
while(cnt<ind)
{
printf("(%c) \t",temp);
printf(" %c\t",code[cnt].opr);
if(code[cnt].opr == '=')
{
if(isalpha(code[cnt].opd2))
printf(" %c \t \t",code[cnt].opd2);
else if(code[cnt].opd2 >='1' && code[cnt].opd2 <='9')
printf("(%c)\n",code[cnt].opd2);
cnt++;
temp++;
continue;
}
if(isalpha(code[cnt].opd1))
printf(" %c \t",code[cnt].opd1);
else if(code[cnt].opd1 >='1' && code[cnt].opd1 <='9')
printf("(%c)\t",code[cnt].opd1);
if(isalpha(code[cnt].opd2))
printf(" %c \n",code[cnt].opd2);
else if(code[cnt].opd2 >='1' && code[cnt].opd2 <='9')
printf("(%c)\n",code[cnt].opd2);
else printf(" %c\n",code[cnt].opd2);
cnt++;
temp++;
}
}
int main()
{
printf("\n Enter the Expression : ");
yyparse();
ThreeAddressCode();
quadraple();
triple();
}

RESULT:
Thus three address code for a simple program using LEX and YACC and was executed
successfully and the output is verified.
EX NO:05
TYPE CHECKING USING LEX AND YACC
DATE:

AIM:
To Implement type checking using Lex and Yacc.

ALGORITHM:
Step1: Track the global scope type information (e.g. classes and their members)
Step2: Determine the type of expressions recursively, i.e. bottom-up, passing the resulting types
upwards.
Step3: If type found correct, do the operation.
Step4: Type mismatches, semantic error will be notified.

PROGRAM:
Type.l

%{
#include "y.tab.h"
%}
%%
[a-zA-Z][a-zA-Z0-9]* { yylval.str = strdup(yytext); return IDENTIFIER; }
":" { return ':'; }
"int" { return INT_TYPE; }
"+" { return PLUS; }
[0-9]+ { yylval.str = strdup(yytext); return INT_TYPE; }
"" ; /* ignore whitespace */
\n ; /* ignore newline */
. { printf("Invalid character: %s\n", yytext); }
%%
int yywrap() {
return 1;
}

Type.y

%{
#include <stdio.h>
/* Function prototype for lexer */
extern int yylex();
/* Error handling function */
void yyerror(const char *s);

/* Symbol table to store variable types */


struct SymTable {
char name[30];
char type[30];
};
struct SymTable sym_table[100];
int sym_index = 0;
%}
%union {
char *str;
}
%token <str> IDENTIFIER
%token <str> INT_TYPE
%token <str> PLUS
%left PLUS
%type <str> expression
%type <str> statement
%type <str> declaration
%%
program: statement
| program statement
statement: expression ';'
| declaration ';'
declaration: IDENTIFIER ':' INT_TYPE
expression: IDENTIFIER
| expression PLUS expression
| INT_TYPE
%%
void yyerror(const char *s) {
printf("Error: %s\n", s);
}
int main() {
yyparse();
printf("Parsing complete.\n");
return 0;
}

RESULT:
Thus a, program to implement type checking using Lex and Yacc was executed successfully
and the output is verified.
EX NO:06
CODE OPTIMIZATION TECHNIQUES
DATE:

AIM:
To implement simple code optimization techniques.

ALGORITHM:
Step 1: The code generation algorithm takes as input a sequence of three – address statements
constituting a basic block. For each three – address statement of the form x = y op z we perform the
following actions:
Step 2: Invoke a function getreg to determine the location L where the result of the computation y op
z should be stored. L will usually be a register, but it could also be a memory location.
Step 3: Consult the address descriptor for y to determine y , (one of) the current location(s) of y.
prefer the register for y, if the value of y is currently both in memory and a register. If the value of y is
not already in L, generate the instruction MOV y , L to place a copy of y in L.
Step 4: Generate the instruction OP z ,L where z is a current location of z. Again, prefer a register to
a where z memory location if z is in both. Update the address descriptor of x to indicate that x is in
location L. If L is a register, update its descriptor to indicate that it contains the value of x, and
remove x from all other register descriptors.
Step 5: If the current values of y and/or z have no next users, are not live on exit from the block, and
are in register descriptor to indicate that, after execution of x = y op z, those registers no longer will
contain y and/or z, respectively.

PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
void main()
{
char a[25][25],u,op1=’*’,op2=’+’,op3=’/’,op4=’-‘;
int p,q,r,l,o,ch,i=1,c,k=1,j,count=0;
FILE *fi,*fo;
// clrscr();
printf(“Enter three address code”);
printf(“\nEnter the ctrl-z to complete:\n”);
fi=fopen(“infile.txt”,”w”);
while((c=getchar())!=EOF)
fputc(c,fi);
fclose(fi);
printf(“\n Unoptimized input block\n”);
fi=fopen(“infile.txt”,”r”);
while((c=fgetc(fi))!=EOF)
{
k=1;
while(c!=’;’&&c!=EOF)
{
a[i][k]=c;
printf(“%c”,a[i][k]);
k++;
c=fgetc(fi);
}
printf(“\n”);
i++;
}
count=I;
fclose(fi);
i=1;
printf(“\n Optimized three address code”);
while(i<count)
{
if(strcmp(a[i][4],op1)==0&&strcmp(a[i][5],op1)==0)
{
printf(“\n Type 1 reduction in strength “);
if(strcmp(a[i][6],’2’)==0)
{
for(j=1;j<=4;j++)
printf(“%c”,a[i][j]);
printf(“%c”,a[i][3]);
}
}
else if(isdigit(a[i][3])&&isdigit(a[i][5]))
{
printf(“\n Type2 constant folding “);
p=a[i][2];
q=a[i][4];
if(strcmp(a[i][3],op1)==0)
r=p*q;
if(strcmp(a[i][3],op2)==0)
r=p+q;
if(strcmp(a[i][3],op3)==0)
r=p/q;
if(strcmp(a[i][3],op4)==0)
r=p-q;
for(j=1;j<=2;j++)
printf(“%c”,a[i][j]);
printf(“%d”,r);
printf(“\n”);
}
else if(strcmp(a[i][5],’0’)==0||strcmp(a[i][5],’1’)==0)
{
printf(“\n Type3 algebraic expression elimation “);
if((strcmp(a[i][4],op1)==0&&strcmp(a[i][5],’1’)==0)||(strcmp(a[i][4],op3)==0&&strcmp(a[i][5],’1’)
==0))
{
for(j=1;j<=3;j++)
printf(“%c”,a[i][j]);
printf(“\n”);
}
else
printf(“\n sorry cannot optimize\n”);
}
else
{
printf(“\n Error input”);
}
i++;
}
getch();
}

RESULT:
Thus a, program implement simple code optimization techniques was executed successfully
and the output is verified.
EX NO:07 CONVERSION OF INTERMEDIATE CODE INTO ASSEMBLY
LANGUAGE INSTRUCTION
DATE:

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:
Step 1: Start the program.
Step 2: Open the source file and store the contents as quadruples.
Step 3: Check for operators, in quadruples, if it is an arithmetic operator generate it or if an
assignment operator generate it, else perform unary minus on register c.
Step 4: Write the generated code into output definition of the file.
Step 5: Print the output.
Step 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();
}
}

RESULT:
Thus 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.

You might also like