0% found this document useful (0 votes)
165 views83 pages

CC Record

The document describes a lexical analyzer program written in C that takes a C program as input and produces a tokenized output by identifying various lexical units like identifiers, keywords, operators, digits etc. and writes them to an output file along with their line numbers and token numbers. It uses functions like fopen, fgetc, fprintf to read input character by character, recognize patterns and write the output. Keywords are checked against a predefined list to identify them. The program then prints the output file to verify the tokens identified.

Uploaded by

Dumb
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
165 views83 pages

CC Record

The document describes a lexical analyzer program written in C that takes a C program as input and produces a tokenized output by identifying various lexical units like identifiers, keywords, operators, digits etc. and writes them to an output file along with their line numbers and token numbers. It uses functions like fopen, fgetc, fprintf to read input character by character, recognize patterns and write the output. Keywords are checked against a predefined list to identify them. The program then prints the output file to verify the tokens identified.

Uploaded by

Dumb
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 83

Qwertyuiopasdfghjklzxcvbnmqwertyu

iopasdfghjklzxcvbnmqwertyuiopasdfg
hjklzxcvbnmqwertyuiopasdfghjklzxcv
bnmqwertyuiopasdfghjklzxcvbnmqwe
rtyuiopasdfghjklzxcvbnmqwertyuiopa
Compiler Construction

sdfghjklzxcvbnmqwertyuiopasdfghjklz
Lab Manual
2019-20

xcvbnmqwertyuiopasdfghjklzxcvbnmq
wertyuiopasdfghjklzxcvbnmqwertyuio
pasdfghjklzxcvbnmqwertyuiopasdfghj
klzxcvbnmqwertyuiopasdfghjklzxcvbn
mq

Table of Contents

1.Scanner program using C 7


2.Scanner programs using LEX 13
1.Lex program to count number of vowels and consonants 15

2.Lex program to count the number of words,characters,blank spaces and lines 16

3.Lex program to covert upper case in to lower case 17

wertyuiopasdfghjklzxcvbnmqwertyuio
4. lex program for reverse of a string 18

5.LEX program to identify REAL PRECISION of the given number 19

6.Lex program to count the type of numbers 20

7. LEX program to implement the lexical analyzer. 21

3. Finding first and follow set of productions 30


4. Top Down Parser

a.Recursive Decent Parser 38

LL(1) Parser 43

5.SLR parser 47
6.Parser programs using YACC 55
a. Program to evaluate an arithmetic expression involving operating +, -, * and /. 57

b. Program to recognize nested IF control statements and display thelevels of nesting. 59

c. Program to recognize strings using grammar (anbn, n>=0) 61

d. Program to recognize the grammar (anb, n>=10) 62

e.write a program for the LALR parser for the following grammar 64

f. program for the basic calculator using lex and yacc 66

f.Program for testing balanced parentheses.………………………………… 71

7.Intermediate code generation 72


8.Code Optimization: 78
TRANSLATOR

A translator is a program that takes as input a program written in one language and produces as output a
program in another language. Beside program translation, the translator performs another very important
role, the error-detection. Any violation of d HLL specification would be detected and reported to the
programmers. Important role of translator are:

1, translating the HLL program input into an equivalent ML program.


2, providing diagnostic messages wherever the programmer violates specification of the HLL.
TYPE OF TRANSLATORS:-

 INTERPRETOR
 COMPILER
 PREPROSSESSOR
COMPILER :-
Compiler is a translator program that translates a program written in (HLL) the source program and
translate it into an equivalent program in (MLL) the target program. As an important part of a compiler is
error showing to the programmer.

Source Program Compiler


target program

Error message
Executing a program written n HLL programming language is basically of two parts. the source program
must first be compiled translated into a object program. Then the results object program is loaded into a
memory executed.
Source program object program
compiler

Object program input object program output


Obj pgm

STRUCTURE OF THE COMPILER DESIGN :-


Compilation process is partitioned into no-of-sub processes called ‘phases’.
Source program
Lexical Analyzer

Syntax Analyzer
token
parse tree

Table Management Error Handling

inter mediate code

improved IMC

Lexical Analysis:-
LA or Scanners reads the source program one character at a time, carving the
source program into a sequence of automic units called tokens.
Syntax Analysis:-
The second stage of translation is called Syntax analysis or parsing. In this phase
expressions, statements, declarations etc… are identified by using the results of lexical analysis. Syntax
analysis is aided by using techniques based on formal grammar of the programming language.
Intermediate Code Generations:-
An intermediate representation of the final machine language code is produced.
This phase bridges the analysis and synthesis phases of translation.
Code Optimization :-
This is optional phase described to improve the intermediate code so that the
output runs faster and takes less space.
Code Generation:-
The last phase of translation is code generation. A number of optimizations to
reduce the length of machine language program are carried out during this phase. The output of the
code generator is the machine language program of the specified computer.
Table Management (or) Book-keeping:-
This is the portion to keep the names used by the program and records essential
information about each. The data structure used to record this information called a ‘Symbol Table’.
Error Handlers:-
It is invoked when a flaw error in the source program is detected.
Passes:-
One (or) more phases one combined into a module called a pass.
Single-pass Compiler:-
All the phases are combined into a single
Multi-pass Compiler:-
More than one phase are combined into a number of groups called multi-pass.
(Multi pass compiler can be made to use less space than single pass compiler.).

LEXICAL ANALYSER:
Lexical analyser is the first phase of compiler. Which takes the source program as input and
produces the stream of tokens as output.

Week1

1.Scanner program using C

Viva Questions

1. What is the purpose of lexical analysis?

1. Explain the phases of a compiler?


2. Define token?
3. What is the purpose of ungetc() function?
4. Define symbol table?

Program: 1
Aim: To develop a lexical analyzer to recognize a few patterns
Algorithm for lexical analyzer:
function lexan: integer ; [ Returns an integer encoding of token]
var lexbuf : array[ 0 .. 100 ] of char ;
c: char ;
begin
loop begin
read a character into c ;
if c is a blank or a tab then
do nothing
else if c is a newline then
lineno : = lineno + 1
else if c is a digit then begin
set tokenval to the value of this and following digits ;
return NUM
end
else if c is a letter then begin
place c and successive letters and digits into lexbuf ;
p : = lookup ( lexbuf ) ;
if p = 0 then
p : = insert ( lexbf, ID) ;
tokenval : = p
return the token field of table entry p
end
else
set tokenval to NONE ; / * there is no attribute * /
return integer encoding of character c
end
end
Program:
1.
Standalone lexical analyzer program for identifying identifiers, keywords, operators, digits;

/*STANDALONE lexical analyzer PROGRAM*/

#include<stdio.h>
#include<ctype.h>
#include<string.h>
int main()
{
FILE *input,*output;
int l=1;
int t=0;
int j=0;
int i,flag;
char ch,str[20];
char keyword[30][30]={"int","main","if","else","do","while","struct","goto"};
input=fopen("input.txt","r");
output=fopen("output.txt","w");
fprintf(output,"Line no. \t Token no.\t Token\t Lexeme\n\n");
while(!feof(input))
{
i=0;
flag=0;
ch=fgetc(input);
if( ch=='+' || ch== '-' || ch=='*' || ch=='/' || ch=='<' || ch=='>')
{
fprintf(output,"%6d\t\t %6d\t\t Operator\t %6c\n",l,t,ch);
t++;
}
else if( ch==';' || ch=='{' || ch=='}' || ch=='(' || ch==')' || ch=='?' || ch=='@' ||
ch=='!' || ch=='%')
{
fprintf(output,"%6d\t\t %6d\t\t Special symbol\t %6c\n",l,t,ch);
t++;
}
else if(isdigit(ch))
{
fprintf(output,"%d6\t\t %6d\t\t Digit\t\t %6c\n",l,t,ch);
t++;
}
else if(isalpha(ch))
{
str[i]=ch;
i++;
ch=fgetc(input);
while(isalnum(ch)&& ch!=' ')
{
str[i]=ch;
i++;
ch=fgetc(input);
}
str[i]='\0';
for(j=0;j<=30;j++)
{
if(strcmp(str,keyword[j])==0)
{
flag=1;
break;
}
}
if(flag==1)
{
fprintf(output,"%6d\t\t %6d\t\t Keyword\t %6s\n",l,t,str);
t++;
}
else
{
fprintf(output,"%6d\t\t %6d\t\t Identifier\t %6s\n",l,t,str);
t++;
}

}
else if(ch=='\n')
{
l++;
}
}
fclose(input);
fclose(output);
output=fopen("output.txt","r");
while(!feof(output))
{
ch=fgetc(output);
printf("%c",ch);
}
fclose(output);
return 0;
}

INPUT.TXT
#include < stdio.h >
void main ()
{
int a,b,c ;
c = a + 9 ;
}

OUTPUT.TXT
Line no. Token no. Token Lexeme

1 0 Identifier include
1 1 Operator <
1 2 Identifier stdio
1 3 Identifier h
1 4 Operator >
2 5 Identifier void
2 6 Keyword main
2 7 Special symbol (
2 8 Special symbol )
3 9 Special symbol {
4 10 Keyword int
4 11 Identifier a
4 12 Identifier b
4 13 Identifier c
4 14 Special symbol ;
5 15 Identifier c
5 16 Special symbol =
5 17 Identifier a
5 18 Operator +
5 19 Digit 9
5 20 Special symbol ;
6 21 Special symbol }
2.Scanner programs using LEX
LEX: LEX is one of the compiler construction tools. Through this we can generate stream of
tokens from the given input stream. Compilation process of it is shown bellow.

Lex source program Lex compiler lex.yy.c


lex.l
lex.yy.c C compiler a.out

input stream a.out stream of tokens

Structure of lex specification File:


It contains three parts
%{
Declaration part
%}
%%
Rule section --------- patterns { Action }
Auxalary functions

First, a specification of a lexical analyzer is prepared by creating a program lex.1 in the


Lex language. Then, lex.I is run through the Lex compiler to produce a C
program lex. yy. c. The program lex. yy. c consists of a tabular represen-
tation of a transition diagram constructed from the regular expressions of
lex. 1, together with a standard routine that uses the table to recognize lex-
emes. The actions associated with regular expressions in lex.1 are pieces of
C code and are carried over directly to lex.yy. c. Finally, lex.yy. c is run
through the C compiler to produce an object program a.oat, which is the
lexical analyzer that transforms an input stream into a sequence of tokens.

LEX TOOL programs

1) LEX program to count no of vowels and consonants


2) LEX program to count the number of words, characters, blank spaces and line
3) LEX program to covert upper case in to lower case
4) LEX program to reverse a given string
5) LEX Program to identify real precision of a given number?
6) LEX program to count the type of numbers
7) LEX program to implement the lexical analyzer?

Viva Questions

1) What is LEX lexical analyzer generator?

2) Differentiate token,lexeme,pattern?

3) What rule section contains ?

4) What Declaration section contains?

5) What Auxiliary procedure section contains?


1.Lex program to count number of vowels and consonants

%{

int v=0,c=0;

%}

%%

[aeiouAEIOU] v++;

[a-zA-Z] c++;

%%

main()
{

printf("ENTER INTPUT : \n");

yylex();

printf("VOWELS=%d\nCONSONANTS=%d\n",v,c);

2.Lex program to count the number of words,characters,blank spaces and lines


%{

int c=0,w=0,l=0,s=0;

%}

%%

[\n] l++;

[' '\n\t] s++;

[^' '\t\n]+ w++; c+=yyleng;

%%

int main(int argc, char *argv[])

{
if(argc==2)

yyin=fopen(argv[1],"r");

yylex();

printf("\nNUMBER OF SPACES = %d",s);

printf("\nCHARACTER=%d",c);

printf("\nLINES=%d",l);

printf("\nWORD=%d\n",w);

else
printf("ERROR");
}

3.Lex program to covert upper case in to lower case

%{
#include<stdio.h>
#include<ctype.h>
%}
let [a-z]|[A-Z]
str {let}+
%%
{str} { int i;
for(i=0;i<yyleng;i++)
yytext[i]=tolower(yytext[i]);
printf("lower case\t %s",yytext);
}
%%
main()
{
printf("enter input");
yylex();

}
4. lex program for reverse of a string

%{
#include<stdio.h>
#include<ctype.h>
%}
let [a-z]|[A-Z]
str {let}+
%%
{str} { int i=0,j=yyleng-1;
char rev[50];
for(i=0;i<=yyleng;i++)
{

rev[i]=yytext[j];
j--;
}
puts(rev);
//printf("reverse string%s",rev);
}
%%
main()
{
printf("enter input");
yylex();

5.LEX program to identify REAL PRECISION of the given number

%{
/*Program to identify a real/float precision*/
%}
integer ([0-9]+)
float ([0-9]+\.[0-9]+)|([+|-]?[0-9]+\.[0-9]*[e|E][+|-][0-9]*)

%%
{integer}
printf("\n %s is an integer.\n",yytext);
{float} printf("\n %s is a floating number.\n",yytext);
%%

main()
{
yylex();
}
int yywrap()
{
return 1;
}

6.Lex program to count the type of numbers

%{

int pi=0,ni=0,pf=0,nf=0;

%}

%%

\+?[0-9]+ pi++;

\+?[0-9]*\.[0-9]+ pf++;

\-[0-9]+ ni++;

\-[0-9]*\.[0-9]+ nf++;

%%

main()

{
printf("ENTER INPUT : ");

yylex();

printf("\nPOSITIVE INTEGER : %d",pi);

printf("\nNEGATIVE INTEGER : %d",ni);

printf("\nPOSITIVE FRACTION : %d",pf);

printf("\nNEGATIVE FRACTION : %d\n",nf);

7. LEX program to implement the lexical analyzer.

ALGORITHM:

1. Start the program

2. Open a file file.c in read and include the yylex() tool for input scanning.

3. Define the alphabets and numbers.

4. Print the preprocessor, function, keyword using yytext.lex tool.

5. Print the relational, assignment and all the operator using yytext() tool.

6. Also scan and print where the loop ends and begins.

7. Use yywrap() to enter an error.

8. Stop the program.

Program
/*program name is lexp.l*/

%{

/*program to recognize a c program*/

int COMMENT=0;

%}

identifier [a-zA-Z][a-zA-Z0-9]*

%%

#.* {printf ("\n%s is 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 KEYWORD",yytext);}

"*/" {COMMET=1;}

/*{printf("\n\n\t%s is a COMMENT\n",yytext);}*/

{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);

|\n ;

%%
int main(int argc,char **argv) /* MAIN FUNCTION */

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”);

return 0;

int yywrap()

return 0;

/*-------------------End of lexp.l----------------------*/
/*Program named as area.c*/

#include<stdio.h>

#include<stdlib.h>

double area_of_circle(double r);

int main()

if(argc<2) /*this is a single line comment*/

printf("usage: %s radius\n",argv[0]);

exit(1);

else

/*this is a double line comment */

double radius=atof(argv[1]);

double area=area_of_circle(radius);

printf("Area of circle with radius %f=%f\n",radius,area);


}

return 0; /*returning 0 */

OUTPUT:

[localhost@sireesha]#lex lexp.l

[localhost@sireesha]#cc lex.yy.c

[localhost@sireesha]#./a.out area.c

#include<stdio.h> is a PREPROCESSOR DIRECTIVE

#include<stdlib.h> is a PREPROCESSOR DIRECTIVE

double is a KEYWORD

Function

area_of_circle(

double is KEYWORD

r is an IDENTIFIER

);

int is a KEYWORD

Function

main

int is a KEYWORD

argc IDENTIFIER
char is a KEYWORD

argv[] IDENTIFIER

BLOCK BEGINS

if is a KEYWORD

argc IDENTIFIER

< is a RELATIONAL OPERATOR

2 is a NUMBER

/*This is a single line comment*/ is a COMMENT

BLOCK BEGINS

FUNCTION

printf(

“Usage: %s radius \n” is a STRING

argv[0] IDENTIFIER

);

FUNCTION

exit(

1 is a NUMBER

);
BLOCK ENDS

else is Akeyword

BLOCK BEGINS

double is KEYWORD

radius IDENTIFIER

= is an ASSIGNMENT OPERATOR

FUNCTION

atof(

argv[1] IDENTIFIER

);

double is a KEYWORD

area IDENTIFIER

=is an ASSIGNMENT OPERATOR

FUNCTION

printf(

“Area of circle with radius %f=%f\n” is a STRING

radius IDENTIFIER

area IDENTIFIER

);

BLOCK ENDS

return is a KEYWORD

0 is a NUMBER
//Returning 0 is a COMMENT

BLOCK ENDS

3. Finding first and follow set of productions


Program:
#include<stdio.h>
#include<string.h>
#include<ctype.h>
//#include<conio.h>
char first1(char);
void follow1(char);
void null(char);
void parsingtable(void);
int n,j,i,id,c,k;
static int t=0,nt=0;
char prod[15][10], first[15][30], follow[15][30], x,px=-1,check,temp;
void main()
{
char ch;
//clrscr();
printf("total number of productions\n");
scanf("%d",&n);
printf("\n\nenter production in this format LEFT-->RIGHT\n");
for(i=0;i<n;i++)
{
printf("\nenter production%d \n", i+1);
scanf("%s",&prod[i]);
}

//calculate FIRST
for(i=0;i<n;i++)
{
ch=prod[i][4];
j=i;
x=first1(ch);
// printf("%c\t",x);
first[i][0]=x;
}
printf("\n");
//Calculate FOLLOW
for(id=0;id<n;id++)
{
follow1(prod[id][0]);
if(id==0)
strcat(follow[0],"$");
}
//if NULL then change FOLLOW A-->xBT then follow(B)=first(T) if first(T) contains null
then follow(B)=follow(A)
for(id=0;id<n;id++)
{
x=prod[id][strlen(prod[id])-1];
if(isupper(x)&&x!=px)
{
px=x;
null(x);
}
}
//copying FOLLOW of Non terminals
for(c=0;c<n;c++)
{
if(prod[c][0]==prod[c-1][strlen(prod[c-1])-1])
strcpy(follow[c],follow[c-1]);
}
//printing FIRST after clubbing and removing duplicates
for(j=0;j<n-1;j++)
{
if(prod[j][0]==prod[j+1][0])
{
strcat(first[j],first[j+1]);
strcpy(first[j+1],first[j]);
}
}
for(j=n-1;j>0;j--)
{
for(c=j-1;c>=0;c--)
if(first[j][0]==first[c][0])
strcpy(first[c],first[j]);
}
for(c=0;c<n;c++)
{
if(prod[c][0]==prod[c+1][0])
{

printf("FIRST(%c)= { %s }\n",prod[c][0],first[c]);
c++;
}
else
{

printf("FIRST(%c)= { %s }\n",prod[c][0],first[c]);
}
}
//Similar printing of FOLLOW
for(c=0;c<n;c++)
{
if(prod[c][0]==prod[c+1][0])
{
printf("FOLLOW(%c)= { %s }\n",prod[c][0],follow[c]);
c++;
}
else
{
printf("FOLLOW(%c)= { %s }\n",prod[c][0],follow[c]);

}
}

}
char first1(char ch)
{
if(isupper(ch)&&j<n)
{
for(c=j+1;c<n;c++)
{
if(prod[c][0]==ch)

{
first1(prod[c][4]);
break;
}

}
}
else
return ch;

}
void follow1(char ch)
{
for(i=0;i<n;i++)

{
for(j=4;j<strlen(prod[i]);j++)

{
if(ch==prod[i][j])

{
if(prod[i][j+1]!='\0')

{
if(isupper(prod[i][j+1]))

{
for(c=0;c<n;c++)
if(prod[c][0]==prod[i][j+1])

{
strcpy(follow[id],first[c]);
break;
}
}
else
follow[id][0]=prod[i][j+1];
}
else
{
strcpy(follow[id],follow[i]);
}
}
}
}
}
void null(char ch)

{
int q=id,k;
q++;
while(q<n)

{
if(prod[q][4]=='#'&&prod[q][0]==ch)

{
for(k=0;k<n;k++)

{
if(prod[k][0]==prod[id][strlen(prod[id])-2])

{
strcat(follow[k],follow[id]);
break;
}
}
}
q++;
}
}

OUTPUT:

total number of productions


8

enter production in this format LEFT-->RIGHT

enter production1
E-->TA

enter production2
A-->+TA

enter production3
A-->#

enter production4
T-->FB

enter production5
B-->*FB

enter production6
B-->#

enter production7
F-->(E)

enter production8
F-->i

FIRST(E)= { (i }
FIRST(A)= { +# }
FIRST(T)= { (i }
FIRST(B)= { *# }
FIRST(F)= { (i }
FOLLOW(E)= { )$ }
FOLLOW(A)= { )$ }
FOLLOW(T)= { +)$ }
FOLLOW(B)= { +)$ }
FOLLOW(F)= { *+)$ }
Press any key to continue . . .
4.Recursive Decent Parser
1. Implementation of Recursive Descent Parser for the following grammar
1. S->cAd
2. A->ab/a
2. Implementation of Recursive Descent Parser for the following grammar
E->numT
T->*numT/€
Viva Questions

1. Explain Back Tracking?

2. Why we call syntax analyzer as parser?

3. What are the problems in Top Down Parser?

4. Define CFG?

5. Define ambiguity?
1.Implementation of Recursive Descent Parser for the following grammar
S->cAd
A->ab/a

Program:

#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
char str[50];
int i;
void S(void);
void A(void);

main()
{
printf("enter a string");
gets(str);
i=0;
S();
}
void S(void)
{
if (str[i]=='c')
{
i++;
A();
if(str[i]=='d')
i++;
}
if(str[i]=='$')
{
printf("success");
}
else
printf("error");
}
void A(void)
{
if(str[i]=='a')
{
i++;
if(str[i]=='b')
{
i++;

}
else
i++;
}
}

OUTPUT:
[root@localhost ~]# ./a.out
enter a stringcabd$
success[root@localhost ~]# ./a.out
enter a stringbcd$
error[root@localhost ~]

2)Implementation of Recursive Descent Parser for the following grammar


E->numT
T->*numT/€

PROGRAM

#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
char str[50];
int i;
void E(void);
void T(void);

main()
{
printf("enter a string");
gets(str);
i=0;
E();
}
void E(void)
{
if (isdigit(str[i]))
{
i++;
T();
}
if(str[i]=='$')
{
printf("success");
}
else
printf("error");
}
void T(void)
{
if(str[i]=='*')
{
i++;
if(isdigit(str[i]))
{
i++;
T();
}
else
i++;
}

OUTPUT:
[root@localhost ~]# ./a.out
enter a string3*4$
success[root@localhost ~]# ./a.out
enter a string2+3$
error[root@localhost ~]
LL(1) Parser
Implementation of LL(1) parsing table

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

void main()
{
int i,j,h,k,r,m,n,t,nt;
char prod[15][10], first[15][30], follow[15][30],terminals[10],nonterminals[10];
static char table[10][10][10]={" "};

*table[0][0]='X';
//clrscr();
printf("total no of productions\t no of terminals and \t nonterminals");
scanf("%d%d%d",&n,&t,&nt);
printf("\n\nenter production in this format LEFT-->RIGHT\n");
for(i=0;i<n;i++)
{
printf("\nenter production%d \n", i+1);
scanf("%s",&prod[i]);
}
printf("\nenter the values of non terminals\n");

scanf("%s",nonterminals);

printf("\nenter the values of terminals\n");

scanf("%s",terminals);

printf("\nenter the first values\n");


for(i=0;i<n;i++)
{
scanf("%s",&first[i]);
}
printf("\nenter the follow values\n");
for(i=0;i<n;i++)
{
scanf("%s",&follow[i]);
}
for(i=1,j=1;i<=nt,j<=t;i++,j++)
{

*table[i][0]=nonterminals[i-1];
*table[0][j]=terminals[j-1];
}
h=t;
*table[0][h+1]='$';
for(i=0;i<=n;i++)
{
//check=prod[i][0];
for(j=1;j<=nt;j++)
{
if(prod[i][0]==(*table[j][0]))
r=j;
}
for(k=0;k<=strlen(first[i]);k++)
{

if(prod[i][4]!='#')

{
for(j=1;j<=t+1;j++)
{
if(isupper(prod[i][4]))
{
if(first[i][k]==*table[0][j])
strcpy(table[r][j],prod[i]);
}
else
{
if(first[i][k]==*table[0][j] && prod[i][4]==first[i][k])
strcpy(table[r][j],prod[i]);
}
}

}
else
{
for(m=0;m<=strlen(follow[i]);m++)
{
for(j=1;j<=t+1;j++)
{ if(follow[i][m]==*table[0][j])
strcpy(table[r][j],prod[i]);
}
}
}
}

printf("-----------------------------------------------------------");
for( i=0;i<=nt;i++)
{
printf("\n\n");
for(j=0;j<=t+1;j++)
{

printf("%s\t",table[i][j]);

printf("\n----------------------------------------------------------");

Output:
5.SLR parser

DESCRIPTION:

1. Declare parser table which contains the parser actions.


2. Initialize a input buffer for storing input string and a stack for storing the string to be parsed.
3. Check the entry in the parser table by taking the values of stack pointer and input buffer.
4. If the entry in the parser table is “shift” push the input string token into stack.
5 .If the entry in the parser table is “reduce” perform the reduction of the corresponding production rule
by doing pop and push operations on stack.
6.Repeat it until we reach the accept state which represents the acceptance of string.

Program:
#include<stdio.h>
#include<string.h>
#include<ctype.h>

/* SLR parser for the grammar


E->E+T (1)
E->T (2)
T->T*F (3)
T->F (4)
F->(E) (5)
F->ID (6)
*/

/* Stack structure and fuctions */

/* The only thing important here is that the value associated


with each name of the macro should be unique. They have no realtion to
the states in the dfa */

#define S4 1
#define S5 2
#define S6 3
#define S7 4
#define R1 5
#define R2 6
#define R3 7
#define R4 8
#define R5 9
#define R6 10
#define S11 11
#define AC 11 /* ACCEPT */
#define ER -1 /* ERROR */

/* the parsing table */


int table[][9]= {
{S5,ER,ER,S4,ER,ER,1,2,3},
{ER,S6,ER,ER,ER,AC,ER,ER,ER},
{ER,R2,S7,ER,R2,R2,ER,ER,ER},
{ER,R4,R4,ER,R4,R4,ER,ER,ER},
{S5,ER,ER,S4,ER,ER,8,2,3},
{ER,R6,R6,ER,R6,R6,ER,ER,ER},
{S5,ER,ER,S4,ER,ER,ER,9,3},
{S5,ER,ER,S4,ER,ER,ER,ER,10},
{ER,S6,ER,ER,S11,ER,ER,ER,ER},
{ER,R1,S7,ER,R1,R1,ER,ER,ER},
{ER,R3,R3,ER,R3,R3,ER,ER,ER},
{ER,R5,R5,ER,R5,R5,ER,ER,ER}
};
#define STRING_SIZE 20

char string[STRING_SIZE];
int i=0;
int save;

#define STACK_SIZE 40

typedef struct {
int list[STACK_SIZE];
int top;
}Stack;

void initialize(Stack *s) {


s->top=-1;
}
void push(int value,Stack *s) {
s->list[++(s->top)]=value;
}
int pop(Stack *s) {
return(s->list[(s->top)--]);
}
int isempty(Stack *s) {
return(s->top==-1);
}
int peek(Stack *s) {
return(s->list[s->top]);
}
int stacksize(Stack *s) {
return((s->top)+1);
}

#define ID 0
#define ADD 1
#define MULT 2
#define OPBR 3
#define CLBR 4
#define DOLLAR 5
#define E 6
#define T 7
#define F 8

short int gettoken() {


/* ignore blanks */
while(string[i]==' ')
i++;
/* definition for identifier */
if(isalpha(string[i])) {
save=i;
i++;
while(string[i]!=0 && string[i]!='*' && string[i]!='+' && string[i]!=')' && string[i]!='(') {
if(!isalnum(string[i++]))
error();
}
return ID;

}
else if(string[i]=='+') {
save=i;
i++;
return ADD;
}
else if(string[i]=='*') {
save=i;
i++;
return MULT;
}
else if(string[i]=='(') {
save=i;
i++;
return OPBR;
}
else if(string[i]==')') {
save=i;
i++;
return CLBR;
}
else if(string[i]==0) {
return DOLLAR;
}
}
error() {
printf("Bad Bad error.\n");
exit(0);
}
int parse() {
int token;
Stack stack;
int state;
int j;
int action;
int previous;
initialize(&stack);
push(0,&stack);
token=0;
while(1) {
token=gettoken();
action=table[peek(&stack)][token];
switch(action) {
case S4:
push(token,&stack);
push(4,&stack);
break;
case S5:
push(token,&stack);
push(5,&stack);
break;
case S6:
push(token,&stack);
push(6,&stack);
break;
case S7:
push(token,&stack);
push(7,&stack);
break;
case AC:
return 1;
case ER:
error();

}
if(action>=5 && action <=10) {
while(action>=5 && action <=10) {
action=table[peek(&stack)][token];
switch(action) {
case R1:
for(j=0;j<6;j++)
pop(&stack);
state=table[peek(&stack)][E];
if(state!=ER) {
push(E,&stack);
push(state,&stack);
}
else
error();
break;
case R2:
pop(&stack);
pop(&stack);
state=table[peek(&stack)][E];
if(state!=ER) {
push(E,&stack);
push(state,&stack);
}
else
error();
break;
case R3:
for(j=0;j<6;j++)
pop(&stack);
state=table[peek(&stack)][T];
if(state!=ER) {
push(T,&stack);
push(state,&stack);
}
else
error();
break;
case R4:
pop(&stack);
pop(&stack);
state=table[peek(&stack)][T];
if(state!=ER) {
push(T,&stack);
push(state,&stack);
}
else
error();
break;
case R5:
for(j=0;j<6;j++)
pop(&stack);
state=table[peek(&stack)][F];
if(state!=ER) {
push(F,&stack);
push(state,&stack);
}
else
error();
break;
case R6:
pop(&stack);
pop(&stack);
state=table[peek(&stack)][F];
if(state!=ER) {
push(F,&stack);
push(state,&stack);
}
else
error();
break;
case AC:
return 1;
case ER:
error();
}
}
i=save;
}
}
return 0;
}
int main() {
printf("Enter the string: ");
scanf("%s",string);
if(parse()) {
printf("Success in parsing.\n");
}
else
error();
}

Output:

[localhost@sireesha]#cc slr.c
[localhost@sireesha]# ./a.out
Enter the strinh to be par sed.Press Ctrl Z at the end
A+B
Success in parsing
Prasuna
Success in parsing
Ctrl Z
[localhost@sireesha]#

6.Parser programs using YACC

1. Program to evaluate an arithmetic expression involving operating +, -, * and /.

2. Program to recognize nested IF control statements and display the levels of


nesting.

3. Program to recognize strings using grammar (anbn, n>=0)

4. Write a program for the basic calculator using lex and yacc
5. This Yacc specification and lex specification program’s are for testing balanced
parentheses.

YACC tool:
YACC is one of the compiler construction Tools which will produce a parser for a given grammar.
Yacc (Yet Another Compiler-Compiler) is a parser-generator for LALR-languages. The Yacc
specification is compiled to a C program and the execution of that program acts as the parser. The
specification contains the three parts:
declarations
%%
translation rules
%%
supporting C routines
The declaration part has two sections, the first one contains ordinary C declarations delimited by
%{ and %}.
The second section contains declaration of grammar tokens, which can be used in the later parts.
If Lex is used with Yacc then these tokens will be available also in Lex.

MOTIVATION

The LALR ( Look Ahead-LR ) parsing method is between SLR and Canonical LR both in terms
of power of parsing grammars and ease of implementation. This method is often used in practice
because the tables obtained by it are considerably smaller than the Canonical LR tables, yet most
common syntactic constructs of programming languages can be expressed conveniently by an LALR
grammar. The same is almost true for SLR grammars, but there are a few constructs that can not be
handled by SLR techniques
YACC PROGRAMS

a. Program to evaluate an arithmetic expression involving operating +, -, *


and /.
Lex Part

%{
#include “y.tab.h”
extern int yylval;
%}
%%
[0-9]+ { yylval=atoi(yytext); return NUMBER; }
\n { return NL ;}
. { return yytext[0]; }
%%
Yacc Part
%token NUMBER ID
%left ‘+’ ‘-‘
%left ‘*’ ‘/’
%%
stmt : exp NL { printf(“Value = %d\n”,$1); exit(0);}
;
exp : exp ‘+’ exp { $$=$1+$3; }
| exp ‘-‘ exp { $$=$1-$3; }
| exp ‘*’ exp { $$=$1*$3; }
| exp ‘/’ exp { if($3==0)
{
printf(“Cannot divide by 0”);
exit(0);
}
else
$$=$1/$3;
}
| ‘(‘ exp ‘)’ { $$=$2; }
| ID { $$=$1; }
| NUMBER { $$=$1; }
;
%%
int yyerror(char *msg)
{
printf(“Invalid Expression\n”);
exit(0);
}
main ()
{
printf(“Enter the expression\n”);
yyparse();
}
b. Program to recognize nested IF control statements and display the

levels of nesting.
Lex Part

%{
#include “y.tab.h”
%}
%%
“if” { return IF; }
[sS][0-9]* {return S;}
“<”|”>”|”==”|”!=”|”<=”|”>=” { return RELOP; }
[0-9]+ { return NUMBER; }
[a-zA-Z][a-zA-Z0-9_]* { return ID; }
\n { ; }
. { return yytext[0]; }
%%

Yacc Part
%token IF RELOP S NUMBER ID
%{
int count=0;
%}
%%
stmt : if_stmt { printf(“No of nested if statements=%d\n”,count); exit(0);}
;
if_stmt : IF ‘(‘ cond ‘)’ if_stmt {count++;}
| S;
;
cond : x RELOP x
;
x : ID
| NUMBER
;
%%
int yyerror(char *msg)
{
printf(“Invalid Expression\n”);
exit(0);
}
main ()
{
printf(“Enter the statement”);
yyparse();
}
c. Program to recognize strings using grammar (anbn, n>=0)

Lex Part

%{
#include “y.tab.h”
%}
%%
[aA] { return A; }
[bB] { return B; }
\n { return NL ;}
. { return yytext[0]; }
Yacc Part

%token A B NL
%%
stmt : s NL { printf(“Valid String\n”); exit(0) ;}
;
s:AsB
|
;
%%
int yyerror(char *msg)
{
printf(“Invalid String\n”);
exit(0);
}
main ()
{printf(“Enter the String\n”);
yyparse();
}

d. Program to recognize the grammar (anb, n>=10)

Lex Part

%{
#include “y.tab.h”
%}
%%
[aA] { return A; }
[bB] { return B; }
\n { return NL ;}
. { return yytext[0]; }
%%
Yacc Part
%token A B NL
%%
stmt : A A A A A A A A A A s B NL
{
Printf(“Valid”); exit(0);
}
;
s:sA
|
;
int yyerror(char *msg)
{
printf(“Invalid String\n”);
exit(0);
}
main ()
{
printf(“Enter the String\n”); yyparse();}
e.write a program for the LALR parser for the following grammar

/* lex specification file parser.*/


%{
#include<stdio.h>
#include "y.tab.h"
%}
%%
[0-9]+ {yylval.dval=atof(yytext);
return DIGIT;
}
\n|. return yytext[0];
%%
/* yacc specification file parser.y*/
%{
/*This YACC specification file generates the LALR parser for the program */
#include<stdio.h>
%}
%union
{
double dval;
}
%token <dval> DIGIT
%type <dval> expr
%type <dval> term
%type <dval> factor
%%
line: expr '\n' {
printf("%g\n",$1);
}
;
expr: expr '+' term {$$=$1 + $3 ;}
| term
;
term: term '*' factor {$$=$1 * $3 ;}
| factor
;
factor: '(' expr ')' {$$=$2 ;}
| DIGIT

;
%%
int main()
{
yyparse();
}
yyerror(char *s)
{
printf("%s",s);
}
Output:
[localhost@sireesha]#lex LALAR.l
[localhost@sireesha]# yacc –d LALR.y
[localhost@sireesha]#cc lex.yy.c y.tab.c
[localhost@sireesha]# ./a.out
2+3
5.0000
5*4
20

f.Write a program for the basic calculator using lex and yacc

LEX SPECIFICATION FILE


%{
#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);
}
%%

YACC SPECIFICATION FILE FOR CALCULATOR(file.y)

%{
#include <stdio.h>
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;
}
;

%%
main()
{
return(yyparse());
}

yyerror(s)
char *s;
{
fprintf(stderr, "%s\n",s);
}
yywrap()
{
return(1);
}

"calsi2.y" 121L, 1682C written


[sireesha@linuxserver ~]$ lex calsi2.l
[sireesha@linuxserver ~]$ yacc -d calsi2.y
[sireesha@linuxserver ~]$ cc lex.yy.c y.tab.c
[sireesha@linuxserver ~]$ ./a.out
2+3
5
4/6
f.This Yacc specification and lex specification program’s are for testing
balanced parentheses.

Yacc Specification File (bp.y)

%{
#include <ctype.h>
#include <stdio.h>
#include "y.tab.h"
extern int yydebug;
%}
%token OPEN CLOSE
%%
lines : s '\n' {printf("OK\n"); }
;
s:
| OPEN s CLOSE s
;
%%
void yyerror(char * s)
{
fprintf (stderr, "%s\n", s);
}
int yywrap(){return 1; }
int main(void) {
yydebug=1;
return yyparse();}

Lex Specification File (bp.lex)

%{
#include"y.tab.h"
%}
%%
[ \t] { /* skip blanks and tabs */ }
"(" return OPEN;
")" return CLOSE;
\n|. { return yytext[0]; }

7.Intermediate code generation


Three-address code is a sequence of instructions of the form
x - y op z
where x, y, and z are names, constants, or compiler-generated
temporaries; and op stands for an operator.
Data structures for implementing three address code are as follows
 Quadruples
 Has four fields: op, arg1, arg2 and result
 Triples
 Temporaries are not used and instead references to
instructions are made
 Indirect triples
 In addition to triples we use a list of pointers to triples
Program:
//Inter.l

%{

#include "y.tab.h"

extern char yyval;

%}

NUMBER [0-9]+

LETTER [a-zA-Z]+

%%

{NUMBER} {yylval.sym=(char)yytext[0];

return NUMBER;}

{LETTER} {yylval.sym=(char)yytext[0];return LETTER;}

\n {return 0;}

. {return yytext[0];}

//inter.y

%{

#include<stdio.h>

#include<string.h>

int nIndex=0;

struct InterCode

char operand1;
char operand2;

char opera;

};

%}

%union

char sym;

%token <sym> LETTER NUMBER

%type <sym> expr

%left '-' '+'

%right '*' '/'

%%

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;}

%%

yyerror(char *s)

printf("%s",s);
exit(0);

struct InterCode Code[20];

char AddToTable(char operand1,char operand2,char opera){

char temp='A';

Code[nIndex].operand1=operand1;

Code[nIndex].operand1=operand2;

Code[nIndex].opera=opera;

nIndex++;

temp++;

return temp;

ThreeAddressCode()

int nCnt=0;

char temp='A';

printf("\n\n\tTHREE ADDRESS CODE");

temp++;

while(nCnt<nIndex)

printf("%c:=\t",temp);

if(isalpha(Code[nCnt].operand1))

printf("%c\t",Code[nCnt].operand1);

else

printf("%c\t",temp);

printf("%c\t",Code[nCnt].opera);

if(isalpha(Code[nCnt].operand2))

printf("%c\t",Code[nCnt].operand2);
else

printf("%c\t",temp);

printf("\n");

nCnt++;

temp++;

void Quadruples()

int nCnt=0;

char temp='A';

temp++;

printf("\n\n\tQuadruples\n");

printf("\n ID OPERATOR OPERAND1 OPERAND2 RESULT\n");

while(nCnt<nIndex)

printf("\n(%d) \t %c\t",nCnt,Code[nCnt].opera);

if(isalpha(Code[nCnt].operand1))

printf("%c\t",Code[nCnt].operand1);

else

printf("%c\t",temp);

if(isalpha(Code[nCnt].operand2))

printf("%c\t",Code[nCnt].operand2);

else

printf("%c\t",temp);

printf("%c\t",temp);

printf("\n");

nCnt++;
temp++;

main()

printf("\nEnter the expression\n");

yyparse();

ThreeAddressCode();

Quadruples();

yywrap()

return 1;

8.Code Optimization:
If the compiler is an optimizing compiler, one of these stages "optimizes" the machine language code so
that it either takes less time to run or occupies less memory or sometimes both. Of course, whatever
optimizations the compiler does, it must not affect the logic of the program i.e. the optimization must
preserve the meaning of the program. One might wonder what type of optimizations the compiler uses to
produce efficient machine code? Since in no case the meaning of the program being compiled should be
changed, the compiler must inspect the program very thoroughly and find out the suitable optimizations
that can be applied. As we may wonder, such a thorough analysis of the program and then finding and
applying suitable optimizations is a complex and time consuming process.
A few type of code optimizations that the GNU C Compiler uses so that we can understand how the code
is optimized and appreciate the complexity of the optimization process. The GNU C Compiler is a
sophisticated optimizing C compiler that uses a large array of optimization techniques to produce
efficient code. It may not be possible to describe all of them, so I have chosen some that are interesting
and also easy to understand.
 Constant Folding
 Common Subexpression Elimination
 Dead Code Elimination
 Strength Reduction using Induction Variable
 The GNU C Compiler is a sophisticated optimizing C compiler that uses a large array of
optimization techniques to produce efficient code.
 The GNU C Compiler (called GCC henceforth) reads a C program source file, however,
it can also produce assembly language source code for the program instead of the object
code, so that we can read it and understand how the assembly language program looks.
 We will be generating such assembly language files to see the optimizations being used
by the compiler, so it would be beneficial if we see how the assembly language code for a
simple C program looks like.
This is optional phase described to improve the intermediate code so that the
output runs faster and takes less space. Its output is another intermediate code program that does the
some job as the original, but in a way that saves time and / or spaces.

1, Local Optimization:-
There are local transformations that can be applied to a program to make an improvement. For example,
If A > B goto L2
Goto L3
L2 :
This can be replaced by a single statement
If A < B goto L3
Another important local optimization is the elimination of common sub-expressions
A := B + C + D
E := B + C + F
Might be evaluated as
T1 := B + C
A := T1 + D
E := T1 + F
Take this advantage of the common sub-expressions B + C.
2, Loop Optimization:-
Another important source of optimization concerns about increasing the speed of loops. A typical loop
improvement is to move a computation that produces the same result each time around the loop to a
point, in the program just before the loop is entered.

In this we use gcc compiler for compiling the program. Why because in cc compiler it is not
possible to create assembly code file. To create assembly file we use –S option , through this we
generate assembly file named as filename.s. To optimize this assembly code we use -O2 option.

Aim: Showing the Code Optimization of different optimization techniques


/* This first file simply demonstrates how the assembly program that the
compiler produces looks like and some peculiarities of the GNU
assembler that follows some different conventions from MASM/TASM.
*/
#include <stdio.h>
int main()
{
printf("Hello, World\n");
return 0;
}
OUTPUT:
[sireesha@linuxserver ~]$ gcc -c –S test1.c
[sireesha@linuxserver ~]$ gcc -c –S -O2 test1.c
[sireesha@linuxserver ~]$vi test1.s
.file "test1.c"
.section .rodata
.LC0:
.string "Hello, World"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $4, %esp
movl $.LC0, (%esp)
call puts
movl $0, %eax
addl $4, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-44)"
.section .note.GNU-stack,"",@progbits
Commands for checking the optimization of code:
1.Create a file vi test1.c
2.To generate the assembly language code, create a file test1.c as shown below and give the following
command:
 $ gcc -c -S test1.c
3.To enable optimization use the following command.
 gcc -c -S -O2 test2.c
/*test2.c */
/* Demonstration of constant propagation */
#include <stdio.h>
int main()
{
int x, y, z;
x = 10;
y = x + 45;
z = y + 4;
printf("The value of z = %d", z);
return 0;
}
/* end of test2.c */
OUTPUT:
[sireesha@linuxserver ~]$ gcc -c –S test2.c
[sireesha@linuxserver ~]$ gcc -c –S -O2 test2.c
[sireesha@linuxserver ~]$vi test2.s
.file "test2.c"
.section .rodata
.LC0:
.string "The value of z = %d"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $36, %esp
movl $10, -16(%ebp)
movl -16(%ebp), %eax
addl $45, %eax
movl %eax, -12(%ebp)
movl -12(%ebp), %eax
addl $4, %eax
movl %eax, -8(%ebp)
movl -8(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
movl $0, %eax
addl $36, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-44)"
.section .note.GNU-stack,"",@progbits
/* test3.c */
/* common subexpression elimination, and also of constant propagation */
#include <stdio.h>

int main()
{
int a, b;
int x, y, z;
scanf("%d %d", &a, &b);
x = a * b;

if(b >= 4)
{
y = a * b;
z = 0;
}
else
{
z = a * b * 4;
y = 0;
}

printf("x = %d, y = %d, z = %d\n", x, y, z);


return 0;
}
OUTPUT:
[sireesha@linuxserver ~]$ gcc -c –S test3.c
[sireesha@linuxserver ~]$ gcc -c –S -O2 test3.c
[sireesha@linuxserver ~]$vi test3.s

.file "test3.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d %d"
.LC1:
.string "x = %d, y = %d, z = %d\n"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ebx
xorl %ebx, %ebx
pushl %ecx
subl $32, %esp
leal -16(%ebp), %eax
movl %eax, 8(%esp)
leal -12(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call scanf
movl -16(%ebp), %eax
movl %eax, %edx
imull -12(%ebp), %edx
cmpl $3, %eax
movl %edx, %ecx
jg .L4
leal 0(,%edx,4), %ebx
xorl %ecx, %ecx
.L4:
movl %ebx, 12(%esp)
movl %ecx, 8(%esp)
movl %edx, 4(%esp)
movl $.LC1, (%esp)
call printf
addl $32, %esp
xorl %eax, %eax
popl %ecx
popl %ebx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-44)"
.section .note.GNU-stack,"",@progbits
/* test4.c */
/* demonstration of dead code elimination */
#include <stdio.h>
int main()
{
int x;

scanf("%d", &x);

if(x < 0 && x > 0)


{
x = 99;
printf("Hello. Inside the if!!!");
}

return 0;
}
/* end of test4.c */

/* --------------------------------------------------------------- */

OUTPUT:
[sireesha@linuxserver ~]$ gcc -c –S test4.c
[sireesha@linuxserver ~]$ gcc -c –S -O2 test4.c
[sireesha@linuxserver ~]$vi test4.s

.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $36, %esp
leal -8(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call scanf
addl $36, %esp
xorl %eax, %eax
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-44)"
.section .note.GNU-stack,"",@progbits

You might also like