CD Lab
CD Lab
LIST OF EXPERIMENTS:
1. Using the LEX tool, Develop a lexical analyzer to recognize a few patterns in C. (Ex.
identifiers, constants, comments, operators etc.). Create a symbol table, while recognizing
identifiers.
2. Implement a Lexical Analyzer using LEX Tool.
b) Program to recognize a valid variable which starts with a letter followed by any
number of letter or digits.
c) Program to recognize a valid control structures syntax of C language (For loop, while
loop, if-else, if-else-if, switch-case, etc.).
d) Implementation of calculator using LEX and YACC.
4. Generate three address code for a simple program using LEX and YACC.
INDEX
SIGNATURE OF
S.No DATE NAME OF THE EXPERIMENT REMARKS
THE STAFF
5 Type Checking
INTRODUCTION:
A Symbol table is a data structure used by a language translator such as a compiler or
interpreter, where each identifier in a program’s source code is associated with information
relating to its declaration or appearance in the source
Possible entries in a symbol table:
Name : a string
Attribute:
1. Reserved word
2. Variable name
3. Type Name
4. Procedure name
5. Constant name
Data type
Scope information: where it can be used.
Storage allocation
SYMBOL TABLE
ALGORITHM:
2. Get the input from the user with the terminating symbol ‘$’.
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 its address is displayed as result.
8. Stop the program.
#include<stdio.h>
#include<conio.h>
#include<malloc.h>
#include<string.h>
#include<math.h>
#include<ctype.h>
void main()
{
b[i]=c; i++;
n=i-1;
printf("%c",b[i]); i++;
}
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
printf("symbol table\n"); printf("symbol\taddr\ttype\n");
while(j<=n)
{
c=b[j]; if(isalpha(toascii(c)))
{
if(j==n)
else
{
ch=b[j+1];
if(ch=='+'||ch=='-'||ch=='*'||ch=='=')
p=malloc(c); add[x]=p;
d[x]=c; printf("%c\t%d\tidentifier\n",c,p); x++;
}}
} j++;
}
printf("the symbol \ins")t;o be searched srch=getch();
for(i=0;i<=x;i++)
{
if(srch==d[i])
{
printf("symbol found\n");
printf("%c%s%d\n",srch,"@address",add[i]);
flag=1;
}
}
if(flag==0)
printf("symbol not found\n");
//getch();
OUTPUT:
RESULT:
Thus the C program to implement the symbol table was executed and the output is verified.
EX. NO:1.b
DATE:
INTRODUCTION:
TOKEN
ALGORITHM:
6. Separate all the file contents as tokens and match it with the functions.
10. Finally print the output after recognizing all the tokens.
#include<string.h>
#include<ctype.h>
#include<stdio.h>
#include<stdlib.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("printf",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);
}
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
void main()
{
FILE *f1,*f2,*f3;
char c,str[10],st1[10];
int num[100],lineno=0,tokenvalue=0,i=0,j=0,k=0;
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);
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
printf("\n the no's in the program are:");
for(j=0;j<i;j++)
printf("\t%d",num[j]);
printf("\n");
f2=fopen("identifier","r");
k=0;
printf("the keywords and identifier 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("\n Special Characters are");
while((c=getc(f3))!=EOF)
printf("\t%c",c);
printf("\n");
fclose(f3);
printf("Total no of lines are:%d",lineno);
}
OUTPUT:
RESULT:
Thus the above program for developing the lexical the lexical analyzer and recognizing
the few pattern s in C is executed successfully and the output is verified.
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
EX.NO:2
DATE:
AIM:
INTRODUCTION:
THEORY:
There is a wide range of tools for construction of lexical analyzer. The majority of these
tools are based on regular expressions.
The one of the traditional tools of that kind is lex.
LEX:
The lex is used in the manner depicted. A specification of the lexical analyzer is
preferred by creating a program lex.1 in the lex language.
Then lex.1 is run through the lex compiler to produce a ‘c’ program lex.yy.c.
LEX SOURCE:
ALGORITHM:
3. Declaration %%
4. Translation rules %%
5. Auxiliary procedure.
6. The declaration section includes declaration of variables, main test, constants and
regular
7. Definitions.
9. P1{action}
15. Compile the lex program with lex compiler to produce output file as lex.yy.c.
18. Compile that file with C compiler and verify the output.
OUTPUT
RESULT:
Thus the program for the exercise on lexical analysis using lex has been successfully
executed and output is verified.
EX.NO:3
DATE:
AIM :
To write a c program to do exercise on syntax analysis using YACC.
INTRODUCTION :
YACC (yet another compiler) is a program designed to produce designed to compile a
LALR (1) grammar and to produce the source code of the synthetically analyses of the
language produced by the grammar.
ALGORITHM :
1. Start the program.
PROGRAM:
#include<stdio.h>
#include<conio.h>
void main()
{ char s[5];
clrscr();
printf("\n Enter any operator:"); gets(s);
switch(s[0])
{
case'>': if(s[1]=='=')
printf("\n Greater than or equal"); else
printf("\n Greater than"); break;
case'<': if(s[1]=='=')
printf("\n Less than or equal"); else
printf("\nLess than"); break;
case'=': if(s[1]=='=')
printf("\nEqual to"); else printf("\nAssignment");
break; case'!': if(s[1]=='=')
printf("\nNot Equal"); else
printf("\n Bit Not"); break;
case'&': if(s[1]=='&')
printf("\nLogical AND"); else
printf("\n Bitwise AND"); break;
case'|': if(s[1]=='|')
printf("\nLogical OR"); else
printf("\nBitwise OR"); break;
case'+': printf("\n Addition"); break;
case'-': printf("\nSubstraction"); break;
case'*': printf("\nMultiplication"); break;
case'/': printf("\nDivision"); break;
case'%': printf("Modulus");
break;
default: printf("\n Not a operator");
}
getch();
}
OUTPUT:
RESULT:
Thus the program for the exercise on the syntax using YACC has been executed
successfully and Output is verified.
EX.NO:3. b
DATE:
PROGRAM :
variable_test.l
%{
/* This LEX program returns the tokens for the Expression */
#include "y.tab.h"
%}
%%
"int " {return INT;}
"float" {return FLOAT;}
"double" {return DOUBLE;}
[a-zA-Z]*[0-9]*{
printf("\nIdentifier is %s",yytext);
return ID;
}
return yytext[0];
\n return 0;
int yywrap()
{
return 1;
}
variable_test.y
%{
#include
/* This YACC program is for recognising the Expression*/
%}
%token ID INT FLOAT DOUBLE
%% D;T L
; L:L,ID
|ID
; T:INT
|FLOAT
|DOUBLE
;
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
%%
extern FILE *yyin;
main()
{
do
{
yyparse();
}while(!feof(yyin));
}
yyerror(char*s)
{
}
OUTPUT:
RESULT:
Thus the program for the exercise on the syntax using YACC has been executed
successfully and Output is verified.
EX.NO.3.c
DATE:
PROGRAM :
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int yylex();
int yyerror(char *s);
%}
%%
program: statement
factor: INTEGER
| IDENTIFIER
%%
int yyerror(char *s)
{
fprintf(stderr, "%s\n", s);
return 0;
}
int main()
{
yyparse();
return 0;
}
OUTPUT:
RESULT:
Thus, the given program to recognize valid control structures is executed successfully.
PROGRAM:
OUTPUT:
Lex calc.l
cc lex.yy.c ./a.out
4*8
The result=32
RESULT:
Thus the program for the exercise on the syntax using YACC has been executed
Successfully and Output is verified.
EX.NO:4
DATE:
GENERATE THREE ADDRESS CODE FOR A SIMPLE PROGRAM USING
LEX AND YACC
AIM:
To write a C program for Intermediate code generation using LEX and YACC
INTRODUCTION:
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.
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.
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.
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.
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.
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.
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
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.
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.
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. Call yyparse() to initiate the parsing process.
yyerror() function is called when all productions in the grammar in second section
doesn't match to the input statement
5. yyerror() function is called when all productions in the grammar in second section
doesn't match to the input statement.
6. Make_symtab_entry() function to make the symbol table entry.
PROGRAM:
LEX PROGRAM:
%{
#include<stdio.h>
#include<string.h>
#include "ex4.tab.h"
%}
%%
[ \n\t]+ ;
main {return MAIN;}
int|float|double|char {strcpy(yylval.string,yytext); return TYPE; }
[a-zA-Z][a-zA-Z0-9_]* {strcpy(yylval.string,yytext);return ID; }
[0-9]+ |
[0-9]+\.[0-9]+ {
yylval.dval=atof(yytext);
return NUMBER;
}
. return yytext[0];
%%
int yywrap(){
return 1;
}
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
YACC program:
%{
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct Symbol_Table
{
char sym_name[10];
char sym_type[10];
double value;
}Sym[10];
int sym_cnt=0;
int Index=0;
int temp_var=0;
int search_symbol(char []);
void make_symtab_entry(char [],char [],double);
void display_sym_tab();
void addQuadruple(char [],char [],char [],char []);
void display_Quadruple();
void push(char*);
char* pop();
struct Quadruple
{
char operator[5];
char operand1[10];
char operand2[10];
char result[10];
}QUAD[25];
struct Stack
{
char *items[10];
int top;
}Stk;
%}
%union
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
{
int ival;
double dval;
char string[10];
}
| ID'='NUMBER {
int i;
i=search_symbol($1);
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
if(i!=-1)
printf("\n Multiple Declaration of Variable");
else
make_symtab_entry($1,$<string>0,$3);
}
int i;
i=search_symbol($3);
if(i!=-1)
printf("\n Multiple Declaration of Variable");
else
make_symtab_entry($3,$<string>0,$5);
}
|ID { int i;
i=search_symbol($1);
if(i!=-1)
printf("\n Multiple Declaration of Variable");
else
make_symtab_entry($1,$<string>0,0);
}
;
{
char temp[10];
if(strcmp(Sym[i].sym_type,"int")==0)
sprintf(temp,"%d",(int)$3);
else
}
}
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
| ID '=' ID ';'{
snprintf(temp,10,"%f",$3);
addQuadruple("=","",temp,$1);
int i,j;
i=search_symbol($1);
j=search_symbol($3);
if(i==-1 || j==-1)
}
| ID '=' expr ';' { addQuadruple("=","",pop(),$1); }
else push($1);
}
i=search_symbol($1);
if(i==-1)
printf("\n Undefined Variable");
}
;
%%
extern FILE *yyin; int
main()
{
Stk.top = -1;
yyin = fopen("input.txt","r");
yyparse(); display_sym_tab();
printf("\n\n");
display_Quadruple();
printf("\n\n"); return(0);
}
void display_sym_tab()
{
int i;
printf("\n\n The Symbol Table \n\n");
printf(" Name Type Value");
for(i=0;i<sym_cnt;i++)
printf("\n %s %s %f",Sym[i].sym_name,Sym[i].sym_type,Sym[i].value);
}
void display_Quadruple()
{
int i;
printf("\n\n The INTERMEDIATE CODE Is : \n\n");
printf("\n\n The Quadruple Table \n\n");
printf("\n Result Operator Operand1 Operand2 ");
for(i=0;i<Index;i++)
printf("\n%d%s%s%s
%s",i,QUAD[i].result,QUAD[i].operator,QUAD[i].operand1,QUAD[i].operand2;
}
int yyerror()
{
Result:
Thus the three address code was generated successfully for a simple program using
LEX and YACC.
INTRODUCTION:
The type analysis and type checking is an important activity done in the semantic
analysis phase. The need for type checking is
1. To detect the errors arising in the expression due to incompatible operand.
ALGORITHM:
1. Start a program.
4. Get the expression from the user and separate into the tokens.
#include<stdio.h>
char str[50],opstr[75];
int f[2][9]={2,3,4,4,4,0,6,6,0,1,1,3,3,5,5,0,5,0};
int col,col1,col2; char c;
swt()
{
switch(c)
{
case'+':col=0;break; case'-':col=1;break; case'*':col=2;break; case'/':col=3;break;
case'^':col=4;break; case'(':col=5;break; case')':col=6;break; case'd':col=7;break;
case'$':col=8;break;
default:printf("\nTERMINAL MISSMATCH\n"); exit(1);
}
}
while(str[i]!='$')
{
c=str[i];
swt(); col1=col; c=str[++i]; swt(); col2=col;
opstr[j]=str[--i]; j++;
if(f[0][col1]>f[1][col2])
{
opstr[j]='>'; j++;
}
else if(f[0][col1]<f[1][col2])
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
{
opstr[j]='<'; j++;
}
else
{
opstr[j]='=';j++;
} i++;
}
opstr[j]='$';
opstr[++j]='\0';
printf("\nPrecedence Input:%s\n",opstr); i=0;
j=0;
while(opstr[i]!='\0')
{
foundg=0; while(foundg!=1)
{
if(opstr[i]=='\0')goto redone; if(opstr[i]=='>')foundg=1; t1=i;
i++;
}
if(foundg==1) for(i=t1;i>0;i--)
if(opstr[i]=='<')break; if(i==0){printf("\nERROR\n");exit(1);}
cn=i; j=0; i=t1+1;
while(opstr[i]!='\0')
{
temp[j]=opstr[i]; j++;i++;
}
temp[j]='\0';
opstr[cn]='E'; opstr[++cn]='\0'; strcat(opstr,temp); printf("\n%s",opstr);
i=1;
}
redone:k=0;
while(opstr[k]!='\
{
k++;
if(opstr[k]=='<')
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
{
Printf("\nError"); exit(1);
}
}
if((opstr[0]=='$')&&(opstr[2]=='$'))goto sue; i=1
while(opstr[i]!='\0')
{
c=opstr[i]; if(c=='+'||c=='*'||c=='/'||c=='$')
{
temp[j]=c;j++;} i++;
}
temp[j]='\0'; strcpy(str,temp); goto come;
sue:
printf("\n success"); return 0;
}
OUTPUT:
RESULT:
Thus the program has been executed successfully and Output is verified.
EX.NO:6
DATE:
AIM:
INTRODUCTION:
In optimization, high-level general programming constructs are replaced by very efficient low
level programming codes. A code optimizing process must follow the three rules given
below:
The output code must not, in any way, change the meaning of the program.
Optimization should increases the speed of the program and if possible, the program
should demand less number of resources.
Optimization should itself be fast and fast and should not delay the overall compiling
process.
Efforts for an optimized code can be made at various levels of compiling the process.
At the beginning, users can change/rearrange the code or use better algorithms to write
the code.
After generating intermediate code, the compiler can modify the intermediate code by
address calculations and improving loops.
While producing the target machine code, the compiler can make use of memory
hierarchy and cpu registers.
Optimization can be categorized broadly into two types: Machine independent and Machine
dependent.
In this optimization, the compiler takes in the intermediate code and transforms a part of the
code that does not involve any CPU registers and/or absolute memory locations.
For Example:
do
item=10; value=value+item;
}while(value<100);
This code involves repeated assignment of the identifier item, which if we put this way:
item=10; do
{
value=value+item;
}while(value<100);
Should not only save the cpu cycles, but can be used on any processor.
Machine dependent optimization is done after the target code has been generated and when
the code is transformed according to the target machine architecture. It involves CPU registers
and may have absolute memory references rather than relative references. Machine-
dependent optimizers put efforts to take maximum advantage of memory hierarchy.
ALGORITHM:
4. Calculate the variables b & c with ‘temp’ and store it in f1 and f2.
#include<iostream.h>
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
#include <conio.h>
int main()
{
cin>>n;
for(i=n;i>=1;i--)
fact=fact *i;
cout<<"The factoral value is: "<<fact; getch();
return 0;
OUTPUT:
Using do-while:
#include<iostream.h>
#include<conio.h>
void main()
f=1;
cin>>n;
do
getch();
}
OUTPUT:
RESULT:
EX.NO.7
Date:
AIM:
To 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 a 8086
assembler. The target assembly instructions can be simple move, add, sub, jump. Also
simple addressing modes are used.
INTRODUCTION:
A compiler is a computer program that implements a programming language specification to
“translate” programs, usually as a set of files which constitute the source code written in
source language, into their equivalent machine readable instructions(the target language, often
having a binary form known as object code). This translation process is called compilation.
BACK END:
Some local optimization
Register allocation
Peep-hole optimization
Code generation
Instruction scheduling
ALGORITHM:
#include<stdio.h> #include<stdio.h>
//#include<conio.h> #include<string.h> void main()
{
do
scanf("%s",icode[i]);
strcpy(str,icode[i]);
DEPARTMENT OF COMPUTER SCIENCE AND
COMPILER D E S I G N LABORATORY
switch(str[3])
{
printf("\n\tMov %c,R%d",str[2],i);
printf("\n\t%s%c,R%d",opr,str[4],i);
printf("\n\tMov R%d,%c",i,str[0]);
}
while(strcmp(icode[++i],"exit")!=0);
//getch();
OUTPUT:
RESULT:
Thus the program was implemented to the TAC has been successfully executed.