You are on page 1of 27

Ex.No:1.

AIM:
To develop a lexical analyzer to identify identifiers, constants, comments, operators etc. using C
program

ALGORITHM:

Step1: Start the program.


Step2: Declare all the variables and file pointers.
Step3: Display the input program.
Step4: Separate the keyword in the program and display it.
Step5: Display the header files of the input program
Step6: Separate the operators of the input program and display it.
Step7: Print the punctuation marks.
Step8: Print the constant that are present in input program.
Step9: Print the identifiers of the input program.

PROGRAM CODE:

#include<string.h>
#include<ctype.h>
#include<stdio.h>
#include<stdlib.h>
void keyword(char str[10])
{
if(strcmp("for",str)==0||strcmp("while",str)==0||strcmp("do",str)==0||strcmp("int",str)==0||
strcmp("float",str)==0||strcmp("char",str)==0||strcmp("double",str)==0||strcmp("printf",str)==0||
strcmp("switch",str)==0||strcmp("case",str)==0)
printf("\n%s is a keyword",str);
else
printf("\n%s is an identifier",str);
}
void main()
{
FILE *f1,*f2,*f3;
char c,str[10],st1[10];
int num[100],lineno=0,tokenvalue=0,i=0,j=0,k=0;
f1=fopen("input","r");
f2=fopen("identifier","w");
f3=fopen("specialchar","w");
while((c=getc(f1))!=EOF)
{
if(isdigit(c))
{
tokenvalue=c-'0';
c=getc(f1);
while(isdigit(c))
{
tokenvalue*=10+c-'0';
c=getc(f1);
}
num[i++]=tokenvalue;
ungetc(c,f1);
}
else
if(isalpha(c))
{
putc(c,f2);
c=getc(f1);
while(isdigit(c)||isalpha(c)||c=='_'||c=='$')
{
putc(c,f2);
c=getc(f1);
}
putc(' ',f2);
ungetc(c,f1);
}
else
if(c==' '||c=='\t')
printf(" ");
else
if(c=='\n')
lineno++;
else
putc(c,f3);
}
fclose(f2);
fclose(f3);
fclose(f1);
printf("\n the no's in the program are:");
for(j=0;j<i;j++)
printf("\t%d",num[j]);
printf("\n");
f2=fopen("identifier","r");
k=0;
printf("the keywords and identifier are:");
while((c=getc(f2))!=EOF)
if(c!=' ')
str[k++]=c;
else
{
str[k]='\0';
keyword(str);
k=0;
}
fclose(f2);
f3=fopen("specialchar","r");
printf("\n Special Characters are");
while((c=getc(f3))!=EOF)
printf("\t%c",c);
printf("\n");
fclose(f3);
printf("Total no of lines are:%d",lineno);
}

OUTPUT:

RESULT:

Thus the program for developing a lexical analyzer to recognize a few patterns in C has been executed
successfully.
Ex.No: 1 b IMPLEMENTATION OF SYMBOL TABLE
Date:

AIM:
To write a C program to implement a 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 :
#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");
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");
}

OUTPUT:
expression terminated by $:a+b+c=d$
Given expression:a+b+c = dsymbol table
Symbol addr type
a 12981096 identifier
b 12981208 identifier
c 12981320 identifier
d 12981512 identifier
The symbol is to be searched

RESULT :
Thus the C program to implement the symbol table was executed and the Output is verified
Ex.No: 2

AIM:

To write a program for implementing a Lexical analyser using LEX tool in Linux platform.

ALGORITHM:

Step 1: Lex program contains three sections: definitions, rules, and user subroutines. Each section must be
separated from the others by a line containing only the delimiter, %%.

The format is as follows:


definitions
%%
rules
%%
user_subroutines
Step 2: In definition section, the variables make up the left column, and their definitions make up the right
column. Any C statements should be enclosed in %{..}%. Identifier is defined such that the first letter of
an identifier is alphabet and remaining letters are alphanumeric.

Step 3: In rules section, the left column contains the pattern to be recognized in an input file to yylex().
The right column contains the C program fragment executed when that pattern is recognized. The various
patterns are keywords, operators, new line character, number, string, identifier, beginning and end of
block, comment statements, preprocessor directive statements etc.

Step 4: Each pattern may have a corresponding action, that is, a fragment of C source code to execute
when the pattern is matched.

Step 5: When yylex() matches a string in the input stream, it copies the matched text to an external
character array, yytext, before it executes any actions in the rules section.

Step 6: In user subroutine section, main routine calls yylex(). yywrap() is used to get more input.

Step 7: The lex command uses the rules and actions contained in file to generate a program, lex.yy.c,
which can be compiled with the cc command. That program can then receive input, break the input into
the logical pieces defined by the rules in file, and run program fragments contained in the actions in file.

2. (a) The program replaces the substring abc by ABC from the given input string:
%{
#include<stdio.h>
#include<string.h> int i;
%}
%%
[a-z A-Z]* { for(i=0;i<=yyleng;i++)
{
if((yytext[i]=='a')&&(yytext[i+1]=='b')&&(yytext[i+2]=='c'))
{
yytext[i]='A';
yytext[i+1]='B';
yytext[i+2]='C';
}
}
printf("%s",yytext);
}
[\t]* return;
.* {ECHO;}
\n {printf("%s",yytext);}
%%
main()
{
yylex();
}
int yywrap()
{
return 1;
}
OUTPUT:
[CSE@localhost ~]$ lex lex1.l
[CSE@localhost ~]$ cc lex.yy.c
[CSE@localhost ~]$. /a.out
abc
ABC

2. (b) Finding vowels and consonant in a string:

%{
int vowel_cnt=0,consonant_cnt=0;
%}
vowel [aeiou]+ consonant [^aeiou]
eol \n
%%
{eol} return 0; [\t]+ ;
{vowel} {vowel_cnt++;}
{consonant} {consonant_cnt++;}

%%
int main()
{
printf("\n Enter some input string:\n"); yylex();
printf("Vowels=%d and consonant=%d\n",vowel_cnt,consonant_cnt); return 0;
}
int yywrap()
{
return 1;
}
OUTPUT:
[CSE@localhost ~]$ lex lex2.l [CSE@localhost ~]
$ cc lex.yy.c [CSE@localhost ~]$. /a.out Enter
some input string: parth

Vowels=1 and consonant=4

RESULT:

Thus the C program for the implementation of lexical analyzer using LEX Tool was executed
successfully.
Ex.No : 3 (a)

AIM:

To write a program to recognize a valid arithmetic expression that uses operator +, - , * and / using
YACC tool.
ALGORITHM:
LEX:
1. Declare the required header file and variable declaration with in ‘%{‘ and ‘%}’.
2. LEX requires regular expressions to identify valid arithmetic expression token of lexemes.
3. LEX call yywrap() function after input is over. It should return 1 when work is done or should
return 0 when more processing is required.
YACC
1. Declare the required header file and variable declaration with in ‘%{‘ and ‘%}’.
2. Define tokens in the first section and also define the associativity of the operations
3. Mention the grammar productions and the action for each production.
4. $$ refer to the top of the stack position while $1 for the first value, $2 for the second value in the
stack.
5. Call yyparse() to initiate the parsing process.
6. yyerror() function is called when all productions in the grammar in second section doesn't match
to the input statement.

PROGRAM:

//art_expr.l
%{
#include<stdio.h>
#include "y.tab.h"
%}
%%
[a-zA-Z][0-9a-zA-Z]* {return ID;}
[0-9]+ {return DIG;}
[ \t]+ {;}
. {return yytext[0];}
\n {return 0;}
%%
int yywrap()
{
return 1;
}
//art_expr.y
%{
#include<stdio.h>
%}
%token ID DIG
%left '+''-'
%left '*''/'
%right UMINUS
%%
stmt:expn ;
expn:expn'+'expn
|expn'-'expn
|expn'*'expn
|expn'/'expn
|'-'expn %prec UMINUS
|'('expn')'
|DIG
|ID
%%
int main()
{
printf("Enter the Expression \n");
yyparse();
printf("valid Expression \n");
return 0;
}
int yyerror()
{
printf("Invalid Expression");
exit(0);
}
OUTPUT:

RESULT:
Thus the program to recognize a valid arithmetic expression that uses operator +, - , * and / using YACC tool was
executed and verified successfully
Ex.No : 3 (b)

AIM:
To write a program to recognize a valid variable which starts with a letter followed by any number of letters
or digits using YACC tool.
ALGORITHM:
LEX:
1. Declare the required header file and variable declaration with in ‘%{‘ and ‘%}’.
2. LEX requires regular expressions to identify valid arithmetic expression token of lexemes.
3. LEX call yywrap() function after input is over. It should return 1 when work is done or should return 0
when more processing is required.
YACC
1. Declare the required header file and variable declaration with in ‘%{‘ and ‘%}’.
2. Define tokens in the first section and also define the associativity of the operations
3. Mention the grammar productions and the action for each production.
4. $$ refer to the top of the stack position while $1 for the first value, $2 for the second value in the stack.
5. Call yyparse() to initiate the parsing process.
6. yyerror() function is called when all productions in the grammar in second section doesn't match to the
input statement.
PROGRAM:
//valvar.l
%{
#include "y.tab.h"
%}
%%
[a-zA-Z] {return LET;}
[0-9] {return DIG;}
. {return yytext[0];}
\n {return 0;}
%%
int yywrap()
{
return 1;
}
//valvar.y
%{
#include<stdio.h>
%}
%token LET DIG
%%
variable:var
;
var:var DIG
|var LET
|LET
;
%%
int main()
{
printf("Enter the variable:\n");
yyparse();
printf("Valid variable \n");
return 0;
}
int yyerror()
{
printf("Invalid variable \n");
exit(0);
}
OUTPUT:

RESULT:

Thus the program to recognize a valid variable which starts with a letter followed by any number of letters or
digits using YACC tool was executed and verified successfully.
Ex.No : 3 (c)

AIM:
To write a program to implement Calculator using LEX and YACC.

ALORITHM:
Step 1: Start the program.
Step 2: In the declaration part of lex, includes declaration of regular definitions as digit.
Step 3: In the translation rules part of lex, specifies the pattern and its action that is to be executed whenever a
lexeme matched by pattern is found in the input in the cal.l.
Step 4: By use of Yacc program, all the Arithmetic operations are done such as +,-,*,/.
Step 5: Display error is persist.
Step 6: Provide the input.
Step 7: Verify the output.
Step 8: End.

PROGRAM:

cal.l
DIGIT [0-9]+

%option noyywrap

%%

{DIGIT} { yylval=atof(yytext); return NUM;}


\n|. { return yytext[0];}

%%
cal.y
%{
#include<ctype.h>
#include<stdio.h>
#define YYSTYPE double

%}
%token NUM
%left ‘+’ ‘-‘
%left ‘*’ ‘/’
%right UMINUS
%%

Statment:E { printf(“Answer: %g \n”, $$); }


|Statment ‘\n’
;
E : E'+'E { $$ = $1 + $3; }
| E'-'E { $$=$1-$3; }
| E'*'E { $$=$1*$3; }
| E'/'E { $$=$1/$3; }
| NUM
;
%%

OUTPUT:
"cal2.y" 59L, 1186C written
[exam01@Cselab3 ~]$ lex cal2.l
[exam01@Cselab3 ~]$ yacc yaccal2.y
[exam01@Cselab3 ~]$ cc y.tab.c
[exam01@Cselab3 ~]$ ./a.out
Enter the expression:2+2
Answer:
AIM:
To write a C program to implement type checking
ALGORITHM:
Step1: Track the global scope type information (e.g. classes and their members)
Step2: Determine the type of expressions recursively, i.e. bottom-up, passing the resulting types upwards.
Step3: If type found correct, do the operation
Step4: Type mismatches, semantic error will be notified
PROGRAM :
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n,i,k,flag=0;
char vari[15],typ[15],b[15],c;
printf("Enter the number of variables:");
scanf(" %d",&n);
for(i=0;i<n;i++)
{
printf("Enter the variable[%d]:",i);
scanf(" %c",&vari[i]);
printf("Enter the variable-type[%d](float-f,int-i):",i);
scanf(" %c",&typ[i]);
if(typ[i]=='f')
flag=1;
}
printf("Enter the Expression(end with $):");
i=0;
getchar();
while((c=getchar())!='$')
{
b[i]=c;
i++; }
k=i;
for(i=0;i<k;i++)
{
if(b[i]=='/')
{
flag=1;
break; } }
for(i=0;i<n;i++)
{
if(b[0]==vari[i])
{
if(flag==1)
{
if(typ[i]=='f')
{ printf("\nthe datatype is correctly defined..!\n");
break; }
else
{ printf("Identifier %c must be a float type..!\n",vari[i]);
break; } }
else
{ printf("\nthe datatype is correctly defined..!\n");
break; } }
}
return 0;
}

OUTPUT:

. RESULT:
Thus the C program to implement type checking was executed and verified successfully
AIM:
To write a program for implementation of Code Optimization Technique.
ALGORITHM:
Step1: Generate the program for factorial program using for and do-while loop to specify optimization
technique.
Step2: In for loop variable initialization is activated first and the condition is checked next. If the condition
is true the corresponding statements are executed and specified increment / decrement operation is
performed.
Step3: The for loop operation is activated till the condition failure.
Step4: In do-while loop the variable is initialized and the statements are executed then the condition
checking and increment / decrement operation is performed.
Step5: When comparing both for and do-while loop for optimization dowhile is best because first the
statement execution is done then only the condition is checked. So, during the statement execution itself we
can find the inconvenience of the result and no need to wait for the specified condition result.
Step6: Finally when considering Code Optimization in loop do-while is best with respect to performance.
PROGRAM CODE:
#include<stdio.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;
printf("Enter the Number of Values:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("left: ");
scanf(" %c",&op[i].l);
printf("right: ");
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("\nAfter Dead Code Elimination\n");
for(k=0;k<z;k++)
{
printf("%c\t=",pr[k].l);
printf("%s\n",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\n",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';
}
}
}
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);
}
}
}
OUTPUT:

RESULT:
Thus the program for implementation of Code Optimization Technique was executed and verified
successfully.

You might also like