Documente Academic
Documente Profesional
Documente Cultură
NO:
DATE:
Description:
Yacc stands for “yet another compiler computer” reflecting the popularity of parser generators
in the early 1970’s when the first version of yacc was created on the UNIX system and has been used to
keys implementation of hundreds of compilers.
A translator can be constructed using YACC. First a file, say translate y, containing a YACC
specification of the translator is required.
The UNIX system command,
Yacc translate.y
Transform the file translate.y into c program y.tab.c using the LALR method. The program
y.tab.c is a representation of LALR method.The y.tab.c is written in c along with another c routines that
the user may prepared.By compiling y.tab.c along with the library that contains the LR parsing program
using the command,
Cc y.tab.c –ly
We obtain the desired objects program a.out that perform the translation by the original yacc
program. If other procedure are needed they can be compiled or loaded with y.tab.c, they stands with
any c program.
A yacc source program has three parts .
Declaration.
%%
` Translation files
%%
Supporting C routines.
Yacc specification of a simple desk calculator.consider the grammer for arithmetic expressions.
E ->E+T/T
T ->T*F/F
F ->(E)/digit
The token digit is a single digit between 0 and 7.
Lex:
Lex is a program generator designed for lexical processing of character input streams. It accepts a high-
level, problem oriented specification for character string matching, and produces a program in a general
purpose language which recognizes regular expressions. The regular expressions are specified by the
user in the source specifications given to Lex. The Lex written code recognizes these expressions in an
input stream and partitions the input stream into strings matching the expressions. At the boundaries
between strings program sections provided by the user are executed. The Lex source file associates the
regular expressions and the program fragments. As each expression appears in the input to the program
written by Lex, the corresponding fragment is executed.
Lex turns the user's expressions and actions into the host general-purpose language; the generated
program is named yylex.The yylex program will recognize expressions in a stream (called input in this
memo) and perform the specified actions for each expression as it is detected.
+-------+
Source -> | Lex | -> yylex
+-------+
+-------+
Input -> | yylex | -> Output
+-------+
An overview of Lex
Figure 1
For a trivial example, consider a program to delete from the input all blanks or tabs at the ends of lines.
%%
[ \t]+$ ;
is all that is required. The program contains a %% delimiter to mark the beginning of the rules, and one
rule. This rule contains a regular expression which matches one or more instances of the characters
blank or tab (written \t for visibility, in accordance with the C language convention) just prior to the
end of a line. The brackets indicate the character class made of blank and tab; the + indicates ``one or
more ...''; and the $ indicates ``end of line,'' as in QED. No action is specified, so the program generated
by Lex (yylex) will ignore these characters. Everything else will be copied. To change any remaining
string of blanks or tabs to a single blank, add another rule:
%%
[ \t]+$ ;
[ \t]+ printf(" ");
The finite automaton generated for this source will scan for both rules at once, observing at the
termination of the string of blanks or tabs whether or not there is a newline character, and executing the
desired rule action. The first rule matches all strings of blanks or tabs at the end of lines, and the second
rule all remaining strings of blanks or tabs.
Lex can be used alone for simple transformations, or for analysis and statistics gathering on a lexical
level. Lex can also be used with a parser generator to perform the lexical analysis phase; it is
particularly easy to interface Lex and Yacc [3]. Lex programs recognize only regular expressions; Yacc
writes parsers that accept a large class of context free grammars, but require a lower level analyzer to
recognize input tokens. Thus, a combination of Lex and Yacc is often appropriate. When used as a
preprocessor for a later parser generator, Lex is used to partition the input stream, and the parser
generator assigns structure to the resulting pieces. The flow of control in such a case (which might be
the first half of a compiler, for example) is shown in Figure 2. Additional programs, written by other
generators or by hand, can be added easily to programs written by Lex.
lexical grammar
rules rules
| |
v v
+---------+ +---------+
| Lex | | Yacc |
+---------+ +---------+
| |
v v
+---------+ +---------+
Input -> | yylex | -> | yyparse | -> Parsed input
+---------+ +---------+
Yacc users will realize that the name yylex is what Yacc expects its lexical analyzer to be named, so
that the use of this name by Lex simplifies interfacing.
Lex is not limited to source which can be interpreted on the basis of one character lookahead. For
example, if there are two rules, one looking for ab and another for abcdefg, and the input stream is
abcdefh, Lex will recognize ab and leave the input pointer just before cd. . . Such backup is more costly
than the processing of simpler languages.
Coding:
%s
#include<ctype.h>
%s}
%token DIGIT
%%
line:expr\n’{printf(“%d\n”,$1);}
;
expr:expr’+’term{$$=$1+$3;}
| term
;
term:term’*’factor{$$=$1*$3;}
| factor
;
Factor:’{‘expr’}’{$$=$2;}
| DIGIT
;
yylex(){
int c;
C=getchar();
If(is digit()){
yy val=c-‘0’;
Return DIGIT;
}
Return C;
}
The Declaration Part:
The declaration part of yacc program is delimited by %s and %y.There are two optional
selections in the declaration.In the first section, we put ordinary c declaration.Here we place declaration
of any temporaries used by the translation rules or procedures of the second and third sections.
The include statement #include <ctype.h>causes the c processor to include the std.Header
file <ctype.h>that contains the predicates its DIGIT.
Also in the declaration part ,are declared of grammer tokens.The statement
% token DIGIT to be token.Tokens declared in this section can be used in second and third parts of the
yacc specification.
In tacc production,a quoted single character ‘C’ is taken to be the terminal symbol ‘c’ and the
unquoted string of letter and DIGIT not declared to the token and nonterminals
A yacc semantic action is the sequence of c statements.In a semantic action the symbol $$ refers to
the attribute value associated with the nonterminal on the left ,while $i refers to the value associated on
the right.
In a yacc specification we have two ‘E’ productions,
EE+T/T
And the associative semantic actions are,
Epr:expr’+’term{$$=$1+$3;}
|term
;
Error Handling:
The token error is reserved for error handling. The parser will detect the symbol error when it is
in a state when the action associated with the look ahead symbol is error.
A semantic action can cause a parser to initiate error handling. When YYERROR is executed semantic
action will cause the control to the parser. YYERROR can’t be used outside the semantic action.
Interface To The Lexical Analyzer:
The yylex() function is an integer valued function that return a token number representing the
kind of token read. If there is a value associated with token return yylex(), it will be assigned to the
external variables yyval().
If the parser and yylex() do not agree on this token numbers reliable communication between them
cannot occur. For (one character) literals, the token is simply a numerical values of the character in the
current character set.
If the token numbers are chosen by yacc the token other than end marker which has a token number
that is zero.
Computing The Program:
In addition to the yyparse() and yylex(), the function YYERROR are required to make a
complete program.
Yacc library:
Int main(void)
This function can run yyparse() and exit with an unspecified value.
Int yyerror(const char*s)
This function will return null terminal argument to standard errors followed by a new line
character.
Limit:
The yacc utility may have several internal tables. The exact value of these values are
implementation dependent. The implementation will define the relationship between the values
inbetween them. Any error manages that the implementation may combine groups of this resources into
as long as the total available to the user does not fact below the sum of the sizes.
LIMIT MINIMUM ALLOCATION DESCRIPTION
EXIT STATUS:
The following EXIT values are extended.
0 ->successful completion.
0 ->error occurs.
Result:
Thus the parser generator(YACC) has been studied.
EX.NO
DATE:
AIM:
ALGORITHM:
PROGRAM:
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
void main()
{
char expr[50];
char iden[20][20],oper[20][20],num[20][20];
int i=0,j,k,ir=0,ic=0,or=0,oc=0,nr=0,nc=0;
clrscr();
printf("Enter the expression\n");
expr[0]='a';
for(i=0;expr[i]!='\n';i++)
{
scanf("%c",&expr[i]);
if(expr[i]=='\n')
break;
}
for(k=0;k<i;k++)
{
if((expr[k]=='+')||(expr[k]=='*')||(expr[k]=='/')||(expr[k]=='-'))
{
printf("%c is an operator\n",expr[k]);
oper[or][oc]=expr[k];
or++;
}
else if((expr[k]==':')&&(expr[k+1]=='='))
{
printf("%c%c is an operator\n",expr[k],expr[k+1]);
oper[or][oc]=expr[k];
oper[or][oc+1]=expr[k+1];
k++;
or++;
}
else if(isalpha(expr[k]))
{
while(k>j)
{
printf("%c",expr[k]);
iden[ir][ic]=expr[k];
k++;
ic++;
if((expr[k]=='+')||(expr[k]=='*')||(expr[k]=='/')||(expr[k]=='- ')||(expr[k]==':')||(expr[k]=='=')||
(expr[k]==' '))
break;
}
ir++;
k--;
printf(" is an identifier\n");
ic=0;
}
else if(isdigit(expr[k]))
{
while(k>j)
{
printf("%c",expr[k]);
num[nr][nc]=expr[k];
nc++;
k++;
if((expr[k]=='+')||(expr[k]=='*')||(expr[k]=='/')||(expr[k]=='-')||(expr[k]==':')||
(expr[k]=='=')||(expr[k]==' ')||(isalpha(expr[k]))||(expr[k]=='\n'))
break;
}
k--;
printf(" is a number\n");
nr++;
nc=0;
}
}
printf("IDENTIFIERS IN TABLE FORMAT\n");
for(i=0;i<ir;i++)
printf("%d\t%s\n",i+1,iden[i]);
printf("OPERATORS IN TABLE FORMAT\n");
for(i=0;i<or;i++)
printf("%d\t%s\n",i+1,oper[i]);
printf("NUMBERS IN TABLE FORMAT\n");
for(i=0;i<nr;i++)
printf("%d\t%s\n",i+1,num[i]);
getch();
}
OUTPUT:
RESULT;
Thus the implementation of token separation was designed and verified
successfully
EX.NO:
DATE: LEXICAL ANALYSIS USING LEXTOOL
AIM:
To write a Lex program for lexical Analysis using Lextool in Linux.
ALGORITHM:
1.Start the program.
2.Get the input file.
3.Identify the preprocessor directive, function and keywords.
4.Display the output.
5.Terminate the program.
PROGRAM:
$ vi lexp.l
/* Lexical Analysis Using Lex Tool */
identifier [_a-zA-Z][_a-zA-Z0-9]*
%%
#.* { printf("\n %s is a Preprocessor Directive",yytext); }
void |
int |
float |
double |
char |
do |
while |
for |
switch |
case |
break |
continue |
return |
goto { printf("\n\t%s is a Keyword",yytext); }
if\( { printf("\n\tif is a Keyword ( "); }
\/\*.*\*\/ |
\/\/.* { printf("\n\n Comment %s\n ",yytext); }
{identifier}\( { printf("\n\n\tFunction %s",yytext); }
\{ { printf("\n Block Begins %s",yytext); }
\} { printf("\n %s Block Ends",yytext); }
{identifier}(\[0-9\]*)? { printf("\n\t%s is an Identifier",yytext); }
\".*\" { printf("\n\t%s is a String",yytext); }
[0-9]+ { printf("\n\t%s is a Number",yytext); }
\)(\;)? ECHO;
\( ECHO;
\+ |
\- |
\* |
\/ |
\% { printf("\n\t%s is an Operator",yytext); }
= { printf("\n\t%s is an Assignment Operator",yytext); }
\> |
\< |
\>= |
\<= |
\== |
\!= { printf("\n\t%s is a Relational Operator",yytext); }
. |\n
%%
main(int argc,char **argv)
{
if(argc>1)
{
FILE *file;
file = fopen(argv[1],"r");
if(!file)
{
printf("\n Could not open the Specified file %s \n",argv[1]);
exit(0);
}
yyin = file;
}
yylex();
printf("\n\n");
}
int yywrap()
{
return 1;
}
INPUT FILE:
$cat>ip.c
#include<stdio.h>
#include<conio.h>
float great();
{
if(a>b)
return a;
else
return b;
}
void main()
{
int a,b;
float c;
c=great(a,b); //Function Call
}
COMPILATION PROCEDURE:
OUTPUT:
OUTPUT:
RESULT:
Thus a Lex program for lexical analysis is executed successfully and the output
was verified.
EX.NO:
DATE:
IMPLEMENTATION OF SYNTAX ANALYZER
Aim:
To execute a ‘C’ program for the implementation of Syntax Analyzer.
Algorithm:
Coding:
//SYNTAX ANALZER
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
char input[20][100],str[100];
char test[100];
char var[20][20];
int n,vptr,a,b,c,d;
getfile()
{
int i=0;
FILE *f1;
f1=fopen("hello.txt","r");
while(!feof(f1))
fgets(input[i++],100,f1);
n=i;
return;
}
int nochar(char ch)
{
int i,j,noc=0;
for(i=0;i<n;i++)
for(j=0;input[i][j]!='\0';j++)
if(input[i][j]==ch)
noc++;
return noc;
}
void main()
{
int i,j,temp,offset;
char *cp,m;
vptr=0;
clrscr();
getfile();
for(i=0;i<n;i++)
if(input[i][0]=='#')
if(!strstr(input[i],"include")||!strpbrk(input[i],"<")||strpbrk(input[i],">"))
printf("\n line=%d error include line",i+1);
for(i=0;i<n;i++)
if(strstr(input[i],"main"))
{
if(!strpbrk(input[i],"("))
printf("\n line%d:error in main statement missing(",i+1);
else
if(!strpbrk(input[i],")"))
printf("\n line%d:error in main statement missing)",i+1);
break;
}
a=abs(nochar('{')-nochar('}'));
b=abs(nochar('}')-nochar('{'));
c=abs(nochar('(')-nochar(')'));
d=abs(nochar(')')-nochar('('));
if(nochar('{')<nochar('}'))
printf("\n error unmatched%d}paranthesis",a);
else
if(nochar('}')>nochar('{'))
printf("\n error unmatched%d{paranthesis",b);
else
if(nochar('(')<nochar(')'))
printf("\n error unmatched%d)paranthesis",c);
else
if(nochar(')')>nochar('('))
printf("\n error unmatched%d(paranthesis",d);
printf("\n");
getch();
}
void main()
int a,b,c;
a=b+c;
printf(“%d”,a);
}
Output:
RESULT:
Thus the ‘C’ program to implement the Syntax Analyzer was executed.
EX.NO:
DATE:
AIM:
ALGORITHM:
PROGRAM:
%{
#include<ctype.h>
#include<stdio.h>
#define YYSTYPE double
%}
%token NUMBER
%left '+' '-'
%left '*' '/'
%right '^'
%right UMINUS
%%
lines : lines expr '\n' {printf("%lf",$2);}
| lines '\n'
|
;
expr : expr '+' expr {$$=$1+$3;}
| expr '-' expr {$$=$1-$3;}
| expr '*' expr {$$=$1*$3;}
| expr '/' expr {if($3!=0) {$$=$1/$3;}
else yyerror("divident should be a positive no.\n");
}
| expr '^' expr { int i,sum=1;
for(i=1;i<=$3;i++)
{sum *= $1;}
$$=sum;
}
| '(' expr ')' {$$=$2;}
| '-' expr %prec UMINUS {$$= $2;}
| NUMBER
;
%%
yylex()
{
int c;
while((c=getchar())==' ');
if((c=='.')||(isdigit(c)))
{
ungetc(c,stdin);
scanf("%lf",&yylval);
return NUMBER;
}
return c;
}
OUTPUT:
RESULT:
Thus the above program is compiled and executed successfully and output is verified.
EX.NO:
DATE:
Aim:
To construct NFA for the given regular expression.
Algorithm:
Coding:
#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<graphics.h>
#include<math.h>
void a(int,int);
void p();
void main()
{
int gd=DETECT, gm;
initgraph(&gd,&gm, “e:\\tc\\bgi\\);
int ch;
while(ch!=6)
{
printf(“Menu \n 1. Empty Input \n 2. a \n 3. a|b \n 4. ab\n 5. (a|b)^* \n Enter the exp “);
scanf(“%d”, &ch);
switch(ch)
{
case 1:
a(150,150);
circle(210,150,15);
outtextxy(180,135,”e”;
outtetxy(125,147,”>”);
line(115,150,140,150);
getch();
cleardevice();
break;
case 2:
a(150,150);
circle(210,150,15);
line(115,150,140,150);
outtextxy(125,147,”>”);
outtextxy(180,135,”a”);
getch();
cleardevice();
break;
case 3:
circle(245,200,15);
p();
getch();
cleardevice();
break;
case 4:
a(150,150);
a(275,150);
line(220,150,265,150);
circle(335,150,15);
outtextxy(175,140,”a”);
outtextxy(300,140,”b”);
outextxy(235,140,”e”);
outtextxy(125,147,”>”);
line(110,150,140,150);
line(315,150,310,145);
line(245,150,240,145);
line(245,150,240,155);
getch();
cleardevice();
break;
case 5:
p();
circle(300,200,10);
circle(300,200,15);
circle(65,200,10);
line(25,200,55,200);
line(255,200,285,200);
outtexty(65,200,”I”);
outtextxy(35,197,”>”);
outetxtxy(300,200,”F”);
arc(185,215,180,0,120);
outtextxy(185,332,”>”);
outextxy(265,185,”e”);
outtextxy(265,197,”>”);
outtextxy(85,185,”e”);
outtextxy(185,110,”e”);
outtextxy(185,320,”e”);
getch();
cleardeive();
}
}
getch();
closegraph();
}
Result
Thus the program for Constructing NFA for the given regular expression is executed
successfully
EX.NO:
DATE:
AIM:
ALGORITHM:
PROGRAM:
#include<stdio.h>
#include<conio.h>
void pus(char);
void reduce();
char inp1[5][10]={"E+E","E*E","(E)","a"},stk[50],inpt1[10],stk1[50];
int ct=0;
void main()
{
int k,len;
char inpt[10];
clrscr();
printf("Enter The Input String\n\n");
gets(inpt);
printf("\n\n");
len=strlen(inpt);
inpt[len++]='$';
inpt[len]='\0';
strcpy(inpt1,inpt);
len=strlen(inpt);
inpt[len++]='$';
inpt[len++]='\0';
pus('$');
pus(inpt[0]);
for(k=1;k<len-1;k++)
{
if(!isupper(inpt[k-1]))
{
reduce();
if(inpt[k]!='$')
pus(inpt[k]);
}
}
if(stk[0]=='$' && stk[1]=='E' && stk[2]=='0' && inpt1[0]=='$')
printf("\n\n\n\t\tString Accepted");
else
printf("\n\n\n\t\tNot Accepted");
getch();
}
void pus(char inpt)
{
int i,n;
n=strlen(inpt1);
if(ct>0)
{
for(i=0;i<n;i++)
inpt1[i-1]=inpt1[i];
inpt1[n-1]='\0';
}
stk[ct++]=inpt;
i=0;
while(stk[i]!='0' && stk[i]!='\0')
printf("%c",stk[i++]);
printf("\t%s\tShift\n",inpt1);
}
void reduce()
{
int j=0,ct1,i,ct2,t,ct3,true=0;
char temp[10],tmp;
strcpy(stk1,stk);
for(i=0;i<5;i++)
{
if(stk[ct-1]==inp1[i][0])
{
if(stk[ct-1]!='('&&stk[ct-1]!=')')
stk[ct-1]='E';
i=0;
while(stk[i]!='0' && stk[i]!='\0')
printf("%c",stk[i++]);
printf("\t%s\tReduce\n",inpt1);
true=1;
}
}
for(i=0;i<4 ;i++)
{
j=0;
ct1=ct-strlen(inp1[i]);
ct2=ct1;
ct3=0;
while(ct1<ct && ct1>0 && stk[ct1]!=0)
temp[j++]=stk[ct1++];
temp[j]='\0';
if(strcmp(temp,inp1[i])==0)
{
stk[ct2]='E';
t=ct2;
while(ct2<=ct)
stk[++ct2]='0';
ct=t;
ct++;
true=0;
}
}
i=0;
while(stk[i]!='0' && stk[i]!='\0' && true==0)
printf("%c",stk[i++]);
if(true==0)
printf("\t%s\tReduce\n",inpt1);
}
OUTPUT:
RESULT:
Thus the above program is compiled and executed successfully and output is verified.
EX.NO:
DATE: IMPLEMENTATION OF LR PARSING
AIM:
ALGORITHM:
♦ Input: An input string w and an LR parsing table with functions action and goto for a grammar
G.
♦ Output: If w is in L(G), a bottom – up parse for w; otherwise an error indication.
♦ Method: Initially, the parser has s0 on its stack, s0 is the initial state, and w$ in the input buffer.
The parser then executes the program until accept or error action is encountered.
PROGRAM:
char stk[10],inp[10],pat[20][20][20],prod[10][10],ipsymb[10];
int sp,ip,tp;
char c,v;
int i,k,t;
void gettable()
{
int i,j,k,n;
char c;
strcpy(pat[0][0],"s5");strcpy(pat[0][3],"s4");strcpy(pat[0][6],"1");
strcpy(pat[0][7],"2");strcpy(pat[0][8],"3");
strcpy(pat[1][5],"A"); strcpy(pat[1][1],"s6");
strcpy(pat[2][1],"r2");strcpy(pat[2][2],"s7");strcpy(pat[2][4],"r2");
strcpy(pat[2][5],"r2");
strcpy(pat[3][1],"r4");strcpy(pat[3][2],"r4");strcpy(pat[3][4],"r4"); strcpy(pat[3][5],"r4");
strcpy(pat[4][0],"s5");strcpy(pat[4][3],"s4");strcpy(pat[4][6],"8");
strcpy(pat[4][7],"2");strcpy(pat[4][8],"3");
strcpy(pat[5][2],"r6");strcpy(pat[5][1],"r6");strcpy(pat[5][4],"r6");
strcpy(pat[5][5],"r6");
strcpy(pat[6][0],"s5");strcpy(pat[6][3],"s4");strcpy(pat[6][7],"9");
strcpy(pat[6][8],"3");
strcpy(pat[7][0],"s5");strcpy(pat[7][3],"s4");strcpy(pat[7][8],"a");
strcpy(pat[8][1],"s6");strcpy(pat[8][4],"sb");
strcpy(pat[9][1],"r1");strcpy(pat[9][2],"s7");strcpy(pat[9][4],"r1");
strcpy(pat[9][5],"r1");
strcpy(pat[10][1],"r3");strcpy(pat[10][2],"r3");strcpy(pat[10][4],"r3");
strcpy(pat[10][5],"r3");
strcpy(pat[11][1],"r5");strcpy(pat[11][2],"r5");strcpy(pat[11][4],"r5");
strcpy(pat[11][5],"r5");
ipsymb[0]='i';ipsymb[1]='+';ipsymb[2]='*';ipsymb[3]='(';ipsymb[4]=')';
ipsymb[5]='$';ipsymb[6]='E';ipsymb[7]='T';ipsymb[8]='F';
strcpy(prod[0],"E'->E");strcpy(prod[1],"E->E+T");strcpy(prod[2],"E->T");
strcpy(prod[3],"T->T*F");strcpy(prod[4],"T->F");
strcpy(prod[5],"F->(E)");strcpy(prod[6],"F->i");
}
int ipnum(char c)
{
int i;
for(i=0;i<strlen(ipsymb);i++)
{
if(ipsymb[i]==c)
break;
}
return i;
}
int stknum(char c)
{
char t[10];
int i;
if(c<='9')
{
t[0]=c;t[1]='\0';
return atoi(t);
}
else
{
return(c-97+10);
}
}
void shift()
{
char t;
t=pat[i][k][1];
stk[++sp]=inp[ip++];
stk[++sp]=t;
}
void reduce()
{
int b,prev,z;
char t,pr[10],subs[10];
t=pat[i][k][1];
strcpy(pr,prod[t-48]);
b=2*(strlen(pr)-3);
sp=sp-b;
t=stk[sp];
prev=stknum(t);
stk[++sp]=pr[0];
z=ipnum(pr[0]);
stk[++sp]=pat[prev][z][0];
stk[sp+1]='\0';
}
void main()
{
int q;
clrscr();
printf("ENTER THE INPUT...");
scanf("%s",inp);
t=strlen(inp);
inp[t]='$';
inp[t+1]='\0';
stk[0]='0';
gettable();
printf("\n\n\nSTACK\t\tINPUT\t\tOPERATION\n");
while(1)
{
c=inp[ip];
v=stk[sp];
k=ipnum(c);
i=stknum(v);
if(pat[i][k][0]=='s')
shift();
else if(pat[i][k][0]=='r')
reduce();
else if(pat[i][k][0]=='A')
{
printf("\n\nVALID...");
getch();
exit(0);
}
else
{
printf("\n\nINVALID...");
getch();
exit(0);
}
printf("%s\t\t",stk);
q=ip;
while(inp[q]!='\0')
printf("%c",inp[q++]);
if(pat[i][k][0]=='s')
printf("\t\tShift\n");
else if(pat[i][k][0]=='r')
printf("\t\tReduced by %s\n",prod[pat[i][k][1]-48]);
}
}
OUTPUT:
RESULT:
Thus the above program is compiled and executed successfully and output is verified.
EX.NO:
DATE: IMPLEMENTATION OF INTERMEDIATE CODE GENERATION
AIM:
To write a C program to implement the intermediate code for the given set of input
expressions.
ALGORITHM:
PROGRAM:
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
void small();
void dove(int );
int p[5]={0,1,2,3,4},c=1,i,k,l,m,pi;
char sw[5]={'=','-','+','/','*'},j[20],a[5],b[5],ch[2];
void main()
{
clrscr();
printf("Enter the expression:");
scanf("%s",j);
printf("\n\n\tThe Intermediate code is:\n");
small();
}
void dove(int i)
{
a[0]='\0';b[0]='\0';
I f(!isdigit(j[i+2]) && !isdigit(j[i-2]))
{
a[0]=j[i-1];
b[0]=j[i+1];
}
if(isdigit(j[i+2]))
{
a[0]=j[i-1];
b[0]='t';
b[1]=j[i+2];
}
if(isdigit(j[i-2]))
{
b[0]=j[i+1];
a[0]='t';
a[1]=j[i-2];
b[1]='\0';
}
if(isdigit(j[i+2]) && isdigit(j[i-2]))
{
a[0]='t';
b[0]='t';
a[1]=j[i-2];
b[1]=j[i+2];
itoa(c,ch,10);
j[i+2]=j[i-2]=ch[0];
}
if(j[i]=='*')
printf("\tt%d=%s*%s\n",c,a,b);
if(j[i]=='/')
printf("\tt%d=%s/%s\n",c,a,b);
if(j[i]=='+')
printf("\tt%d=%s+%s\n",c,a,b);
if(j[i]=='-')
printf("\tt%d=%s-%s\n",c,a,b);
if(j[i]=='=')
printf("\t%c=t%d",j[i-1],--c);
itoa(c,ch,10);
j[i]=ch[0];
c++;
small();
}
void small()
{
pi=0;l=0;
for(i=0;i<strlen(j);i++)
{
for(m=0;m<5;m++)
if(j[i]==sw[m])
if(pi<=p[m])
{
pi=p[m];
l=1;
k=i;
}
}
if(l==1)
dove(k);
else
{
getch();
exit (0);
}
}
OUTPUT:
RESULT:
Thus the above program is compiled and executed successfully and output is verified.
EX.NO:
DATE: IMPLEMENTATION OF CODE GENERATION
AIM:
To write a C program to implement the code generation algorithm.
ALGORITHM:
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:
i. 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. We shall describe getreg shortly.
j. 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.
k. Generate the instruction OP z, L where z is a current location of z. Again, prefer a
register to a 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.
l. 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<string.h>
char exp[10][10],*ope;
int i,j,n,s[10],flag2,flag3,r1,r2;
void check();
void oper();
void main()
{
clrscr();
printf("\nEnter the No. of Expressions:\n");
scanf("%d",&n);
printf("\nEnter The Expression (In Three Address Code):\n");
for(i=0;i<n;i++)
{
scanf("%s",exp[i]);
s[i]=i;
}
printf("\n\nGenerated Code Is:\n\n");
oper();
getch();
}
void oper()
{
for(i=0;i<n;i++)
{
flag2=0;
flag3=0;
if(exp[i][3]=='*')
ope="MUL";
if(exp[i][3]=='/')
ope="DIV";
if(exp[i][3]=='+')
ope="ADD";
if(exp[i][3]=='-')
ope="SUB";
check();
printf("MOV R%d,%c\t(Result Moved To %c)\n",s[i],exp[i][0],exp[i][0]);
}
}
void check()
{
for(j=0;j<i;j++)
{
if(exp[i][2]==exp[j][0])
{
flag2=1;
r1=s[j];
}
if(exp[i][4]==exp[j][0])
{
flag3=1;
r2=s[j];
}
}
if(flag2==1&&flag3==1)
{
s[i]=0;
printf("%s R%d,R%d\t(Result In R%d)\n",ope,r2,r1,r1);
} else if(flag2==1&&flag3!=1)
{
s[i]=r1;
printf("%s %c,R%d\t(Result In R%d)\n",ope,exp[i][4],r1,r1);
} else if(flag2!=1&&flag3==1)
{
s[i]=r2;
printf("%s %c,R%d\t(Result In R%d)\n",ope,exp[i][2],r2,r2);
} else
{
printf("MOV %c,R%d\t(%c Moved To R%d)\n",exp[i][2],s[i],exp[i][2],s[i]);
printf("%s %c,R%d\t(Result In R%d)\n",ope,exp[i][4],s[i],s[i]);
}
}
OUTPUT:
RESULT:
Thus the above program is compiled and executed successfully and output is verified.
EX.NO:
DATE:
SYMBOL TABLE
AIM:
To implement the symbol table concept using the c programs.
ALGORITHM:
PROGRAM:
//Symbol table
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
void main()
{
int i,j,k,n;
char e[10],st[10],as[10][10];
clrscr();
printf("\n Symbol Table\n");
printf("\n Enter the expression:");
scanf("%s",e);
for(i=0,j=0;i<strlen(e);i++)
{
if(isalpha(e[i]))
{
st[j]=e[i];
j++;
}
}
st[j]='\0';
fflush(stdin);
for(i=0;i<strlen(st);i++)
{
printf("Datatypes of %c:",st[i]);
scanf("%s",as[i]);
}
printf("\n Enter the base address:");
scanf("%d",&k);
printf("\n\n");
printf("\n ****************************************");
printf("\n The symbol table for datatype");
printf("\n ****************************************");
printf("\n\n");
printf("\n Variable \tDatatype Bytes Base Address\n");
for(i=0;i<strlen(st);i++)
{
if(as[i][0]=='i')
{
k+=10;
printf("\n %c\t\t %s\t %d\t%d",st[i],as[i],2,k);
printf("\n\n");
}
else if(as[i][0]=='f')
{
k+=32;
printf("\n %c\t\t %s\t %d\t d",st[i],as[i],4,k);
printf("\n\n");
}
else if(as[i][0]=='c')
{
k+=8;
printf("\n %c\t\t %s\t %d\t%d",st[i],as[i],1,k);
printf("\n\n");
}
else if(as[i][0]=='d')
{
k+=256;
printf("\n %c\t\t %s\t %d\t%d",st[i],as[i],4,k);
printf("\n\n");
}
else if(as[i][0]=='l')
{
k+=32;
printf("\n %c\t\t %s\t %d\t%d",st[i],as[i],8,k);
printf("\n\n");}}
;
}
OUTPUT:
Symbol Table
Enter the expression:p=i+r*6
Datatypes of p:int
Datatypes of i:int
Datatypes of r:int
Enter the base address:3000
****************************************
The symbol table for datatype
****************************************
Variable Datatype Bytes Base Address
p int 2 3010
i int 2 3020
r int 2 3030
RESULT:
Thus the above program is compiled and executed successfully and output is verified.