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

Compiler design program

The document outlines the implementation of a symbol table and a lexical analyzer in C, including algorithms and code samples. It describes the purpose of a symbol table in language translation and the process of lexical analysis, which converts character sequences into tokens. Additionally, it includes the construction of a Non-deterministic Finite Automaton (NFA) from regular expressions using C++.

Uploaded by

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

Compiler design program

The document outlines the implementation of a symbol table and a lexical analyzer in C, including algorithms and code samples. It describes the purpose of a symbol table in language translation and the process of lexical analysis, which converts character sequences into tokens. Additionally, it includes the construction of a Non-deterministic Finite Automaton (NFA) from regular expressions using C++.

Uploaded by

Ranjith Kumar
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 26

EX.

NO: 1 IMPLEMENTATION OF SYMBOL TABLE

AIM:

To write a C program to implement a symbol table.

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:

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 its address is displayed as
result.
8. Stop the program.

PROGRAM: (IMPLEMENTATION OF SYMBOL TABLE)

#include<stdio.h>

#include<conio.h>

#include<malloc.h>

#include<string.h>

#include<math.h>

#include<ctype.h>

void main()
{
int i=0,j=0,x=0,n,flag=0; void *p,*add[15]; char

ch,srch,b[15],d[15],c; //clrscr();

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("symbol table\n");

printf("symbol\taddr\ttype\n");

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\n",c,p);

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 is to be searched\n");

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: 2 DEVELOP A LEXICAL ANALYZER TO RECOGNIZE
A FEW PATTERNS IN C

AIM:

To Write a C program to develop a lexical analyzer to recognize a few patterns in C.

INTRODUCTION:
Lexical analysis is the process of converting a sequence of characters (such as in a
computer program of web page) into a sequence of tokens (strings with an identified
“meaning”). A program that perform lexical analysis may be called a lexer, tokenize or
scanner.

TOKEN
A token is a structure representing a lexeme that explicitly indicates its categorization
for the Purpose of parsing. A category of token is what in linguistics might be called a part-
of-speech. Examples of token categories may include “identifier” and “integer literal”,
although the set of Token differ in different programming languages.

The process of forming tokens from an input stream of characters is called tokenization.
Consider this expression in the C programming language:
Sum=3 + 2;
Tokenized and represented by the following table:

Lexeme Token category


Sum “identifier”
= “assignment operator”
3 “integer literal”
+ “addition operator”
2 “integer literal”
; “end of the statement”

ALGORITHM:

1. Start the program


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

PROGRAM: (DEVELOP A LEXICAL ANALYZER TO RECOGNIZE A FEW


PATTERNS IN C)

#include<stdio.h>
#include<conio.h>
#include<ctype.h>

#include<string.h>

void main()

FILE *fi,*fo,*fop,*fk;

int flag=0,i=1;

char c,t,a[15],ch[15],file[20];

clrscr();

printf("\n Enter the File Name:");

scanf("%s",&file);
fi=fopen(file,"r");

fo=fopen("inter.c","w");

fop=fopen("oper.c","r");

fk=fopen("key.c","r");

c=getc(fi);

while(!feof(fi))
{
if(isalpha(c)||isdigit(c)||(c=='['||c==']'||c=='.'==1))
fputc(c,fo);
else
{
if(c=='\n')
fprintf(fo,"\t$\t");
else fprintf(fo,"\t%c\t",c);
}
c=getc(fi);
}
fclose(fi);
fclose(fo);
fi=fopen("inter.c","r");
printf("\n Lexical Analysis");
fscanf(fi,"%s",a);
printf("\n Line: %d\n",i++);
while(!feof(fi))
{
if(strcmp(a,"$")==0)
{
printf("\n Line: %d \n",i++);
fscanf(fi,"%s",a);
}
fscanf(fop,"%s",ch);
while(!feof(fop))
{
if(strcmp(ch,a)==0)
{
fscanf(fop,"%s",ch);
printf("\t\t%s\t:\t%s\n",a,ch);
flag=1;
} fscanf(fop,"%s",ch);
}
rewind(fop);
fscanf(fk,"%s",ch);
while(!feof(fk))
{
if(strcmp(ch,a)==0)
{
fscanf(fk,"%k",ch);
printf("\t\t%s\t:\tKeyword\n",a);
flag=1;
}
fscanf(fk,"%s",ch);
}
rewind(fk);
if(flag==0)
{
if(isdigit(a[0]))
printf("\t\t%s\t:\tConstant\n",a);
else
printf("\t\t%s\t:\tIdentifier\n",a);
}
flag=0; fscanf(fi,"%s",a); }
getch();
}
Key.C:
int void
main
char
if
for
while
else
printf
scanf
Include
stdio.h
conio.h

iostream.h

Open.C:
( open para
) closepara
{ openbrace
} closebrace
< lesser
> greater
" doublequote
' singlequote
: colon
; semicolon
# preprocessor
= equal
== asign
% percentage
^ bitwise
& reference
* star
+ add

- sub
\ backslash
/ slash

Input.C:
#include "stdio.h"
#include "conio.h"
void main()
{
int a=10,b,c;
a=b*c;
getch();
}
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.
3. IMPLEMENTATION OF LEXICAL ANALYZER USING LEX
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:

%{
%}
identifier[a-zA-Z][a-zA-Z0-9]*
%%
#.* {printf("\n%s is a preprocessor directive",yytext);}
int |
float |
char |
double |
while |
do |
if |
break |
continue |
void |
switch |
return |
else |
goto {printf("\n%s is a keyword",yytext);}
{identifier}\( {printf("\n function %s",yytext);}
\{ {printf("\nblock begins");}
\} {printf("\nblock ends");}
\( {printf("\n");ECHO;}
{identifier}(\[[0-9]*\])* {printf("\n%s is an identifier",yytext);}
\".*\" {printf("\n %s is a string ",yytext);}
[0-9]+ {printf("\n%s is a number",yytext);
}
\<= |
\>= |
\< |
\> |
\== {printf("\n %s is a relational operator",yytext);}
\= |
\+ |
\- |
\/ |
\& |
% {printf("\n %s is a operator",yytext);}
.|
\n;
%%
int main(int argc,char **argv)
{
FILE *file;
file=fopen("inp.c","r");
if(!file)
{
printf("could not open the file!!!");
exit(0);
}
yyin=file;
yylex();
printf("\n\n");
return(0);
}
int yywrap()
{
return 1;
}
OUTPUT:

C:\Documents and Settings\admin\Desktop>flex alex.l

C:\Documents and Settings\admin\Desktop>gcc lex.yy.c

C:\Documents and Settings\admin\Desktop>a.exe

#include<stdio.h> is a preprocessor directive

void is a keyword
function main(

block begins

int is a keyword
a is an identifier
b is an identifier
c is an identifier

function printf(
"enter the value for a,b" is a string

function scanf(
"%d%d" is a string
& is a operator
a is an identifier
& is a operator
b is an identifier

c is an identifier
= is a operator
a is an identifier
+ is a operator
b is an identifier

function printf(
"the value of c:%d" is a string
& is a operator
c is an identifier

block ends

RESULT:
Thus the program to implement lexical analyzer using lex tool is executed and
implemented successfully.
Ex.No: 4 CONSTRUCTION OF NFA

AIM:
To write a program for constructing an NFA from given regular expression using C++.

ALGORITHM:
1. Create a menu for getting four regular expressions input as choice.
2. To draw NFA for a, a/b, ab, a* create a routine for each regular expression.
3. For converting from regular expression to NFA, certain transition had been
made based on choice of input at the runtime.
4. Each of the NFA will be displayed in sequential order.
PROGRAM:
#include<iostream.h>
#include<conio.h>
#include<process.h>
struct node
{
char start;
charalp;
node*nstate;
}*p,*p1,*p2,*p3,*p4,*p5,*p6,*p7,*p8; char e='e';
voiddisp();
void re1()
{
p1=new(node);
p2=new(node);
p1->start='0';
p1->alp='e';
p1->nstate=p2;
p2->start='1';
p2->alp='a';
p2->nstate=NULL; disp();
getch();
}
voidre2()
{
p1=new(node);
p2=new(node);
p3=new(node);
p4=new(node);
p5=new(node);
p6=new(node);
p7=new(node);
p8=new(node);
p1->start='0';
p1->alp='e';
p1->nstate=p2;
p2->start='1';
p2->alp='a';
p2->nstate=p3;
p3->start='2';
p3->alp='e';
p3->nstate=p4;
p4->start='5';
p4->alp='';
p4->nstate=p5;
p5->start='0';
p5->alp='e';
p5->nstate=p6;
p6->start='3';
p6->alp='b';
p6->nstate=p7;
p7->start='4';
p7->alp='e';
p7->nstate=p8;
p8->start='5';
p8->alp='';
p8->nstate=NULL; disp();
getch();
}
voidre3()
{
p1=new(node);
p2=new(node);
p3=new(node);
p1->start='0';
p1->alp='a';
p1->nstate=p2;
p2->start='1';
p2->alp='b';
p2->nstate=p3;
p3->start='2';
p3->alp='';
p3->nstate=NULL; disp();
getch();
}
voidre4()
{
p1=new(node);
p2=new(node);
p3=new(node);
p4=new(node);
p5=new(node);
p6=new(node);
p7=new(node);
p8=new(node);
p1->start='0';
p1->alp='e';
p1->nstate=p2;
p2->start='1';
p2->alp='a';
p2->nstate=p3;
p3->start='2';
p3->alp='e';
p3->nstate=p4;
p4->start='3';
p4->alp='';
p4->nstate=p5;
p5->start='0';
p5->alp='e';
p5->nstate=p6;
p6->start='3';
p6->alp='';
p6->nstate=p7;
p7->start='2';
p7->alp='e';
p7->nstate=p8;
p8->start='1';
p8->alp='';
p8->nstate=NULL; disp();
getch();
}
voiddisp()
{
p=p1;
while(p!=NULL)
{
cout<<"\t"<<p->start<<"\t"<<p->alp;
p=p->nstate;
}
}
void main()
{
p=new(node);
clrscr();
int ch=1;
while(ch!=0)
{
cout<<"\nMenu"<<"\n1.a"<<"\n2.a/b"<<"\n3.ab"<<"\n4.a*”;

cout<<"\nEnter the choice:"; cin>>ch;


switch(ch)
{

case 1:
{ re1();
break; }
case 2:
{ re2();
break; }
case 3:
{ re3();
break; }
case 4:
{ re4();
break; }
default:
exit(0);
}
}
}
OUTPUT:
Menu
1. a
2. a/b
3. ab
4. a*
Enterthechoice:1
0 a 1

Menu
1. a
2. a/b
3. ab
4. a*
Enterthechoice: 2
0 e 1 a 2 e 5 0 e 3 b 4 e 5

Menu
1. a
2. a/b
3. ab
4. a*
Enterthechoice:3
0 a 1 b 2

Menu
1. a
2. a/b
3. ab
4. a*
Enterthechoice:4
0e1a2e30e32e1
Menu
1. a
2. a/b
3. ab
4. a*
Enterthechoice:5

RESULT:
Thus the program for Construction of NFA from the given regular
expression is executed and verified.
5. GENERATE YACC SPECIFICATION FOR A FEW SYNTACTIC CATEGORIES

A) PROGRAM TO RECOGNIZE A VALID ARITHMETIC EXPRESSION THAT USES


OPERATOR +, - , * AND /.

ALGORITHM:

1. Accept the token generated in lex part as input


2. Specify order of procedure
3. Define rules with end point
4. Parse input string from standard input by calling yyparse() by main function
5. Print the result of any rules matches
6. If none of results defined matches print “invalid expression”
COMPILATION STEPS:

$ lex exp.l
$ yacc –d exp.y
$ cc lex.yy.c y.tab.c –ll –ly
$ ./a.out

PROGRAM:

Yacc<Exp.y>

%token NUMBER ID NL
%left '+' '-'
%left '*' '/'
%%

stmt : exp NL { printf(“Valid Expression”); exit(0);}


;
exp : exp '+' exp
| exp '-' exp
| exp '*' exp
| exp '/' exp
| '(' exp ')'
| ID
| NUMBER
;
%%

int yyerror(char *msg)


{
printf(“Invalid Expression\n”);
exit(0);
}
main ()
{
printf(“Enter the expression\n”);
yyparse();
}

Lex<Exp.L>

%{
#include “y.tab.h”
%}
%%
[0-9]+ { return NUMBER; }
[a-zA-Z][a-zA-Z0-9_]* { return ID; }
\n { return NL ;}
. { return yytext[0]; }
%%

RESULT:
Thus the program for validating arithmetic expressions using Yacc is implemented and executed
successfully.

B) PROGRAM TO RECOGNIZE A VALID VARIABLE WHICH STARTS WITH A LETTER


FOLLOWED BY ANY NUMBER OF LETTERS OR DIGITS.

PROGRAM:

Yacc<Let.Y>

%token DIGIT LETTER NL UND


%%
stmt : variable NL { printf(“Valid Identifiers\n”); exit(0);}
;
variable : LETTER alphanumeric
;
alphanumeric: LETTER alphanumeric
| DIGIT alphanumeric
| UND alphanumeric
| LETTER
| DIGIT
| UND
;
%%
int yyerror(char *msg)
{
printf(“Invalid Expression\n”);
exit(0);
}
main ()
{
printf(“Enter the variable name\n”);
yyparse();
}

Lex<Let.L>

%{
#include “y.tab.h”
%}
%%
[a-zA-Z] { return LETTER ;}
[0-9] { return DIGIT ; }
[\n] { return NL ;}
[_] { return UND; }
. { return yytext[0]; }
%%

RESULT:
Thus the program is executed successfully.

.
C) IMPLEMENTATION OF CALCULATOR USING LEX AND YACC

PROGRAM:

Lex<Cal.L>

%{
#include"y.tab.h"
#include<math.h>
%}
%%
([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) {yylval.dval=atof(yytext);return
NUMBER;}
log |
LOG {return LOG;}
In {return nLOG;}
sin |
SIN {return SINE;}
cos |
COS {return COS;}
tan |
TAN {return TAN;}
mem {return MEM;}
[\t];
\$ return 0;
\n|. return yytext[0];
%%

Yacc<Cal.Y>

%{
double memvar;
%}
%union
{
double dval;
}
%token<dval>NUMBER
%token<dval>MEM
%token LOG SINE nLOG COS TAN
%left '-' '+'
%left '*' '/'
%right '^'
%left LOG SINE nLOG COS TAN
%nonassoc UMINUS
%type<dval>expression
%%
start:statement'\n'
|start statement'\n'
;
statement:MEM'='expression {memvar=$3;}
| expression{printf("Answer=%g\n",$1);}
;
expression:expression'+'expression {$$=$1+$3;}
| expression '-' expression {$$=$1-$3;}
| expression '*' expression {$$=$1*$3;}
| expression '/' expression
{
if($3==0)
yyerror("divide by zero");
else
$$=$1/$3;
}
|expression'^'expression {$$=pow($1,$3);}
;
expression:'-'expression %prec UMINUS{$$=-$2;}
|'('expression')'{$$=$2;}
|LOG expression {$$=log($2)/log(10);}
|nLOG expression {$$=log($2);}
|SINE expression {$$=sin($2*3.14/180);}
|COS expression {$$=cos($2*3.14/180);}
|TAN expression {$$=tan($2*3.14/180);}
|NUMBER {$$=$1;}
|MEM {$$=memvar;}
;
%%
main()
{
printf("Enter the expression");
yyparse();}
int yyerror(char *error)
{
printf("%s\n",error);
}

OUTPUT:

[linuxpert@fosslab ~]$ vi cal.l


[linuxpert@fosslab ~]$ lex cal.l
[linuxpert@fosslab ~]$ yacc -d cal.y
[linuxpert@fosslab ~]$ cc lex.yy.c y.tab.c -ll -lm
[linuxpert@fosslab ~]$ ./a.out

Enter the expression(5+2)*(3-1)/(2)


Answer=7

RESULT:
Thus the program to implement calculator using LEX and YACC tool is executed successfully
and output is verified.
6. IMPLEMENTATION OF SIMPLE CODE OPTIMIZATION
TECHNIQUES
AIM:
To write a C program to implement Code Optimization Techniques.

ALGORITHM:

Input: Set of ‘L’ values with corresponding ‘R’ values.


Output: Intermediate code & Optimized code after eliminating common expressions.

PROGRAM:

#include<stdio.h>
#include<conio.h>
#include<string.h>
struct op
{
char l;
char r[20];
}
op[10],pr[10];
void main()
{
int a,i,k,j,n,z=0,m,q;
char *p,*l;
char temp,t;
char *tem;
clrscr();
printf("Enter the Number of Values:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("left: ");
op[i].l=getche();
printf("\tright: ");
scanf("%s",op[i].r);
}
printf("Intermediate Code\n") ;
for(i=0;i<n;i++)
{
printf("%c=",op[i].l);
printf("%s\n",op[i].r);
}
for(i=0;i<n-1;i++)
{
temp=op[i].l;
for(j=0;j<n;j++)
{
p=strchr(op[j].r,temp);
if(p)
{
pr[z].l=op[i].l;
strcpy(pr[z].r,op[i].r);
z++; }}}
pr[z].l=op[n-1].l;
strcpy(pr[z].r,op[n-1].r);
z++;
printf("After Dead Code Eliminationn");
for(k=0;k<z;k++) {
printf("%ct=",pr[k].l);
printf("%sn",pr[k].r);
}
for(m=0;m<z;m++) {
tem=pr[m].r;
for(j=m+1;j<z;j++) {
p=strstr(tem,pr[j].r);
if(p) {
t=pr[j].l;
pr[j].l=pr[m].l;
for(i=0;i<z;i++) {
l=strchr(pr[i].r,t) ;
if(l) {
a=l-pr[i].r;
printf("pos: %d",a);
pr[i].r[a]=pr[m].l; }}}}}
printf("Eliminate Common Expression\n");
for(i=0;i<z;i++)
{
printf("%c\t=",pr[i].l);
printf("%s\n",pr[i].r);
}
for(i=0;i<z;i++)
{
for(j=i+1;j<z;j++)
{
q=strcmp(pr[i].r,pr[j].r);
if((pr[i].l==pr[j].l)&&!q)
{
pr[i].l='\0';
strcpy(pr[i].r,'\0');
}
}
}
printf("Optimized Code\n");
for(i=0;i<z;i++)
{
if(pr[i].l!='\0')
{
printf("%c=",pr[i].l);
printf("%s\n",pr[i].r);
}
}
getch();
}

INPUT & OUTPUT:


Enter the Number of Values:5
left: a right: 9
left: b right: c+d
left: e right: c+d
left: f right: b+e
left: r right: f
Intermediate Code
a=9
b=c+d
e=c+d
f=b+e
r=f

After Dead Code Elimination


b=c+d
e=c+d
f=b+e
r=f

Eliminate Common Expression


b =c+d
b =c+d
f =b+b
r =f
Optimized Code
b=c+d
f=b+b
r=f

RESULT:
Thus the program for code optimization is implemented and executed
successfully, and the output is verified.

You might also like