CD Lab
CD Lab
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
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);
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.