Anda di halaman 1dari 27

INDEX

S.NO PROGRAM DATE SIGN


PROGRAM-1
AIM - Compiler Writing Tools: Lex & Yacc

COMPILER
A compiler or interpreter for a programinning language is often decomposed into two
parts:

 Read the source program and discover its structure.


 Process this structure, e.g. to generate the target program.

Lex and Yacc can generate program fragments that solve the first task.

The task of discovering the source structure again is decomposed into subtasks:-

 Split the source file into tokens (Lex).


 Find the hierarchical structure of the program (Yacc).

LEX - A Lexical Analyzer Generator


Lex is a program that generates lexical analyzers ("scanners" or "lexers"). Lex is
commonly used with the yacc parser generator. Lex, originally written by Mike Lesk and
Eric Schmidt], is the standard lexical analyzer generator on many Unix systems

Lex reads an input stream specifying the lexical analyzer and outputs source code
implementing the lexer in the C programming language.

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 is not a complete language, but rather a generator representing a new language
feature which can be added to different programming languages, called ``host languages.''
At present, the only supported host language is C, although FORTRAN has been
available in the past. Lex itself exists on UNIX, GCOS, and OS/370; but the code
generated by Lex may be taken anywhere the appropriate compilers exist.

Structure Of A Lex File:


The structure of a lex file is intentionally similar to that of a yacc file; files are divided up
into three sections, separated by lines that contain only two percent signs, as follows:

Definition section
%%
Rules section
%%
C code section

 The definition section is the place to define macros and to import header files
written in C. It is also possible to write any C code here, which will be copied
verbatim into the generated source file.
 The rules section is the most important section; it associates patterns with C
statements. Patterns are simply regular expressions. When the lexer sees some
text in the input matching a given pattern, it executes the associated C code. This
is the basis of how lex operates.
 The C code section contains C statements and functions that are copied verbatim
to the generated source file. These statements presumably contain code called by
the rules in the rules section. In large programs it is more convenient to place this
code in a separate file and link it in at compile time.

Example Of A Lex File:


The following is an example lex file for the flex version of lex. It recognizes strings of
numbers (integers) in the input, and simply prints them out.

/*** Definition section ***/

%{
/* C code to be copied verbatim */
#include <stdio.h>
%}

/* This tells flex to read only one input file */


%option noyywrap

%%
/*** Rules section ***/

/* [0-9]+ matches a string of one or more digits */


[0-9]+ {
/* yytext is a string containing the matched text. */
printf("Saw an integer: %s\n", yytext);
}
. { /* Ignore all other characters. */ }

%%
/*** C Code section ***/

int main(void)
{
/* Call the lexer, then quit. */
yylex();
return 0;
}

If this input is given to flex, it will be converted into a C file, lex.yy.c. This can be
compiled into an executable which matches and outputs strings of integers.

For example, given the input:

abc123z.!&*2ghj6

the program will print:

Saw an integer: 123


Saw an integer: 2
Saw an integer: 6

Use:
Lex is good at pattern matching.

Lex’s Limitations
LEX cannot be used to recognize nested structures such as parentheses. Nested
structures are handled by incorporating a stack. Whenever we encounter a "(" we push it
on the stack. When a ")" is encountered we match it with the top of the stack and pop the
stack. However lex only has states and transitions between states. Since it has no stack it
is not well suited for parsing nested structures.
YACC: Yet Another Compiler-Compiler
The computer program yacc is a parser generator developed by Stephen C. Johnson at
AT&T for the Unix operating system. It generates a parser (the part of a compiler that
tries to make syntactic sense of the source code) based on an analytic grammar written in
a notation similar to BNF. Yacc generates the code for the parser in the C programming
language.

YACC provides a general tool for describing the input to a computer program. The Yacc
user specifies the structures of his input, together with code to be invoked as each such
structure is recognized. Yacc turns such a specification into a subroutine that handles the
input process; frequently, it is convenient and appropriate to have most of the flow of
control in the user's application handled by this subroutine. The input subroutine
produced by Yacc calls a user-supplied routine to return the next basic input item. Thus,
the user can specify his input in terms of individual input characters or in terms of higher
level constructs such as names and numbers. The user-supplied routine may also handle
idiomatic features such as comment and continuation conventions, which typically defy
easy grammatical specification.

Yacc is written in portable C. In addition to compilers for C, APL, Pascal, RATFOR, etc.,
Yacc has also been used for less conventional languages.

Structure Of A Yacc File:


The structure of a Yacc file is intentionally similar to that of a Lex file; files are divided
up into three sections, separated by lines that contain only two percent signs, as follows:

Definition section
%%
Rules section
%%
C code section

 The definition section is the place to define macros and to import header files
written in C. Lex file is concerned with characters while YACC file is concerned
with tokens.
 The rules section is the most important section; it associates patterns with C s
was the case of lex.
 The C code section contains is the call to yyparse,the grramatical parse.

Use:
YACC augments an FSA with a stack and can process constructs such as parentheses
with ease. The important thing is to use the right tool for the job. YACC is appropriate
for more challenging tasks.
PROGRAM-2
AIM - WAP to check whether a string belong to the grammar or not.

#include<iostream.h>
#include<conio.h>
#include<string.h>
#include<process.h>

void main()
{
clrscr();
char str[20];
char ch;
cout<<"The grammar is ASB"<<endl;
cout<<"A->a\n"<<"B->b\n"<<"C->c\n";
do
{
clrscr();
cout<<"\nThe String is:";
cin>>str;
int k=0,h=0;
for(int i=0;i<strlen(str);i++)
{
if(str[i]=='a'||str[i]=='A')
{
k++;
}
}
cout<<"\nThe no. of a in string is: "<<k;

for(i=0;i<strlen(str);i++)
{
if(str[i]=='b'||str[i]=='B')
{
h++;
}
}
cout<<"\nThe no. of b in string is: "<<h;

if(h==k)
cout<<"\n\n\tThe Grammar has equal no. of a and b";
else
cout<<"\n \n\tString has incorrect Grammar";
cout<<"\n\n Do You To Continue: ";
cin>>ch;
}while(ch=='y');
if(ch!='y')
cout<<"\n\nOK!!!!";
getch();
}

OUTPUT
PROGRAM-3
AIM: WAP to generate a parse tree.
#include<iostream.h>
#include<conio.h>
#include<string.h>
#include<graphics.h>

void main()
{
clrscr();
char s[5],a[5][5],b[5][2],cq[5][2],z[5];
int p=0;
cout<<"\nEnter the productions for S -> ";
cin>>s;
int len=strlen(s);
cout<<"\nProductions for S -> "<<s;
for(int i=0;i<5;i++)
if((s[i]>='A')&&(s[i]<='Z'))
{ z[p]=s[i]; p++; }
int o=p;
cout<<"\nValue: "<<o;
for(p=0;p<o;p++)
{
cout<<"\nEnter the productions for "<<z[p]<<" -> ";
cin>>a[p];
cout<<"\nProduction for "<<z[p]<<" -> "<<a[p];
}
clrscr();
int driver,mode;
driver=DETECT;
initgraph(&driver,&mode,"c:\\tc\\bgi");
outtextxy(320,50,"S");
int count;
int g=0,h=-100,c,u,y=200;
p=0;
for(u=0;u<len;u=u+1)
{
y=y+50;
lineto(y,100);
b[u][0]=s[u];
b[u][1]='\0';
outtext(*(b+u));
if((s[u]>='A')&&(s[u]<='Z'))
{
count=strlen(a[g]);
a[g][count+1]='\0';
c=0;
for(int q=0;q<count;q++)
{
h=h+50;
moveto(y,100);
linerel(h,100);
cq[p][0]=*(*(a+g)+c);
cq[p][1]='\0';
outtext(cq[p]);
++p;
++c;
}
g++;
}
moveto(320,50);
}
getch();
}
OUTPUT
PROGRAM-4
AIM: WAP to compute FIRST of non-terminals.

#include<conio.h>
#include<iostream.h>
#include<string.h>
void first(char s[10]);
void main()
{
clrscr();
char s[10];
int r=1;
while(r==1)
{
cout<<"\n\nenter the symbol: ";
cin>>s;
first(s);
cout<<" is First of "<<s[0]<<"\n";
cout<<"\n\npress 1 for another production:";
cin>>r;
}
getch();
}

void first(char s[])


{
int i,j,len;
char a[10],b[10],c,d;
cout<<"enter production value for "<<s[0]<<"--> ";
cin>>a;

int k=0;

i=0;
if(a[i] >= 'A' && a[i] <= 'Z')
{
first(a);
}
else
{
b[k]=a[i];
cout<<"\n"<<b[0];
}
}
OUTPUT
EXPERIMENT NO 5
AIM - WAP to compute FOLLOW of non-terminals.

#include<iostream.h>
#include<conio.h>
#include<graphics.h>
#include<string.h>

char s[5];
char a[5][10];
char f[5][10];
void follow( int d);
void main()
{
clrscr();
int i,p1=-1,p2=-1;
//char a[5][10],f[5][10];
for(i=0;i<5;i++)
{
cout<<"\n\nenter the symbol"<<(i+1)<<": ";
cin>>s[i];
cout<<"enter production value for "<<s[i]<<"--> ";
cin>>a[i];
}
cout<<"\n\n";
for(i=0;i<5;i++)
{
p1=-1;
p2=-1;
for(int j=0;j<5;j++)
{
int len1 = strlen(a[j]);
for(int k=0;k<len1;k++)
{
if(s[i]==a[j][k])
{
p1=j;
p2=k;
}
}
}
if(p1==-1 && p2==-1)
{
if(i!=0)
{
cout<<"\n null";
}
else
{}
}
else if(a[p1][p2+1]!=NULL)
{
char first[10];
cout<<"\nenter first of "<<a[p1][p2+1]<<"\n";
cin>>first;
cout<<"\n "<<first;
}
else
{
cout<<"\n ";
follow(p1);
}
if(i==0)
{
cout<<" $";
}
cout<<" is FOLLOW of "<<s[i]<<"\n\n";
}
getch();
}

void follow( int p)


{
int i,p1=-1,p2=-1;
i=p;
for(int j=0;j<5;j++)
{
int len1 = strlen(a[j]);
for(int k=0;k<len1;k++)
{
if(s[i]==a[j][k])
{
p1=j;
p2=k;
}
}
if(p1==-1 && p2==-1)
{
if(i!=0)
{
cout<<"\n null";
}
else
{}
}
else if(a[p1][p2+1]!=NULL)
{
char first[10];
cout<<"\nenter first of "<<a[p1][p2+1]<<"\n";
cin>>first;
cout<<"\n "<<first;
}
else
{
cout<<"\n ";
follow(p1);
}
if(j==0)
{
cout<<" $ ";
}
}
}
OUTPUT
PROGRAM-6
AIM - WAP to check a grammar is left recursive and remove it.

#include<iostream.h>
#include<conio.h>
#include<string.h>
void main()
{
clrscr();
char a[10],b[10],s;
cout<<"\nEnter the symbol:";
cin>>s;
cout<<"\nEnter the first RHS for"<<s<<"->";
cin>>a;
cout<<"\nEnter the second RHS for:"<<s<<"->";
cin>>b;
int len1,len2;
len1=strlen(a);
len2=strlen(b);
if(s==a[0])
{
for(int i=0;i<len1;i++)
{
a[i]=a[i+1];
}
cout<<"\n Grammar is Left Recursive\n";
cout<<"\n Apply the rule for \n A->Aa\n A->b\n like \n A->bA'\n A'->aA'\n A'->NULL";
cout<<"\n\n The solution is \n"<<s<<"->"<<b<<s<<"'\n"<<s<<"'-
>"<<a<<s<<"'\n"<<s<<"'->NULL";
}
else
{
cout<<"\n Grammar is NOT Left Recursive";
}
getch();
}
OUTPUT
PROGRAM-7
AIM - WAP to remove left factoring.

#include<iostream.h>
#include<conio.h>
void main()
{
char A,K,L,M,N;
clrscr();
cout<<"enter the value for start symabol :";
cin>>A;
cout<<"enter the Alpha before \ : \n";
cin>>K;
cout<<"enter the Beta value :\n ";
cin>>L;
cout<<"enter the Alpha after \ : \n";
cin>>N;
cout<<"enter the Gama value :\n ";
cin>>M;
cout<<"prod is\n"<<A<<"->"<<K<<L<<"/"<<N<<M;

if(K==N)
{
cout<<"\n\n grammar is left factored";
cout<<"\n\n after removal of left factoring :\n\n";
cout<<A<<"->"<<K<<A<<"\'";
cout<<"\n\n";
cout<<A<<"\'"<<"->"<<L<<"/"<<M;
}
getch();
}
OUTPUT
PROGRAM-8
AIM - WAP to show all the operations of a stack.

ALGORITHM:

INSERTION

PUSH (item)
1. if (item=max of stack)
print "overflow"
Return
2. top=top+1
3. stack [top]=item
4. return

DELETION

POP (item)
1. if (top=-1)
print "underflow"
return
2. Item=stack [top]
3. top=top-1
4. return

DISPLAY

1. if top = -1
print "underflow"
2. Repeat step 3 for i=top to i>=0
3. print stack[i]
4. return
PROGRAM:

#include<stdio.h>
#include<conio.h>
#include<process.h>
#define MAXSIZE 10

void push();
int pop();
void traverse();
int stack[MAXSIZE];
int Top=-1;
void main()
{
int choice;
char ch;
do
{
clrscr();
printf("\n1.PUSH");
printf("\n2.POP");
printf("\n3.TRAVERSE");
printf("\n\nEnter your choice: ");
scanf("%d",&choice);
switch(choice)
{
case 1: push();
break;
case 2: printf("\n\nThe deleted element is: %d",pop());
break;
case 3: traverse();
break;
default:printf("\n\nYou entered a wrong choice");
}
printf("\nDo you wish to continue(Y/N): ");
fflush(stdin);
scanf("%c",&ch);
}
while(ch=='Y' || ch=='y');
}
void push()
{
int item;
if(Top==MAXSIZE - 1)
{
printf("\n\nThe Stack is Full");
getch();
exit(0);
}
else
{
printf("\nEnter the element to be inserted: ");
scanf("%d",&item);
Top=Top+1;
stack[Top]=item;
}
}
int pop()
{
int item;
if(Top== -1)
{
printf("\nThe stack is Empty");
getch();
exit(0);
}
else
{
item=stack[Top];
Top=Top-1;
}
return(item);
}
void traverse()
{
if(Top== -1)
{
printf("\nThe stack is empty");
getch();
exit(0);
}
else
{
for(int i=Top;i>=0;i--)
printf("\nTraverse the element");
printf("\n%d" ,stack[i]);
}
}
OUTPUT
PROGRAM-9
AIM - WAP to show various operations i.e. red, write and modify in a
text file.

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main()

{
FILE *fp;
int i,num;
clrscr();
fp=fopen("INTEGER.DAT","w");
if(fp==NULL)
{
printf("error opening file");
exit(1);
}
for(i=0;i<5;i++)
{
scanf("%d",&num);
if(num==-99)
break;
putw(num,fp);
}
fclose(fp);
fp=fopen("INTEGER.DAT","r");
if(fp==NULL)
{
printf("error opening file");
exit(1);
}
while((num=getw(fp)) !=EOF)
{
printf("%d",num);
fclose(fp);
}
getch();

}
OUTPUT

Anda mungkin juga menyukai