PROGRAM 1: Design and implement a lexical analyzer for given language
using C and the lexical analyzer should ignore redundant spaces, tabs and
new lines.
To design and implement a lexical analyzer in C for a given language, you need to define the
language's tokens (keywords, identifiers, operators, etc.) and create a scanner that processes
the input and identifies those tokens. The lexical analyzer will also ignore redundant spaces,
tabs, and new lines.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
int isKeyword(char buffer[]){
char keywords[32][10] = {"main","auto","break","case","char","const","continue","default",
"do","double","else","enum","extern","float","for","goto","if","int","long","register","return",
"short","signed","sizeof","static","struct","switch","typedef","unsigned","void","printf",
"while"};
int i, flag = 0;
for(i = 0; i< 32; ++i){
if(strcmp(keywords[i], buffer) == 0){
flag = 1;
break;
}
}
return flag;
}
int main(){
char ch, buffer[15], operators[] = "+-*/%=";
FILE *fp;
int i,j=0;
fp = fopen("3lex_input.txt","r");
if(fp == NULL){
printf("error while opening the file\n");
exit(0);
}
while((ch = fgetc(fp)) != EOF){
for(i = 0; i< 6; ++i){
if(ch == operators[i])
printf("%c is operator\n", ch);
}
if(isalnum(ch)){
buffer[j++] = ch;
}
else if((ch == ' ' || ch == '\n') && (j != 0)){
buffer[j] = '\0';
j = 0;
if(isKeyword(buffer) == 1)
printf("%s is keyword\n", buffer);
else
printf("%s is identifier\n", buffer);
}
}
fclose(fp);
return 0;
}
Output:
PROGRAM 2: Implementation of Calculator using LEX and YACC.
To implement a calculator using LEX and YACC, we'll create a simple expression evaluator
that can handle arithmetic operations such as addition, subtraction, multiplication, division,
and parentheses for grouping.
Steps to Implement:
1. LEX: The lexical analyzer (lexer) will tokenize the input expression into tokens such
as numbers, operators, and parentheses.
2. YACC: The parser (using YACC) will build an abstract syntax tree (AST) or directly
evaluate the expression based on the tokens generated by the lexer.
LEX PART:
%{
#include<stdio.h> #include "[Link].h" extern intyylval;
%}
%%
[0-9]+ {
yylval=atoi(yytext);
return NUMBER; }
[\t] ;
[\n] return 0;
. return yytext[0];
%%
intyywrap()
{
return 1;
}
YACC PART:
%{ #include<stdio.h>
int flag=0;
%}
%token NUMBER
%left '+' '-'
%left '*' '/' '%'
%left '(' ')'
%%
Arithmetic Expression: E{ printf("\result=%d\n",$$); return 0;
};
E : E'+'E {$$=$1+$3;} | E'-'E {$$=$1-$3;} | E'*'E {$$=$1*$3;} | E'/'E {$$=$1/$3;} | E'%'E
{$$=$1%$3;} | '('E')' {$$=$2;} | NUMBER {$$=$1;};
%%
void main ()
{
printf ("\enter Any Arithmetic Expression which can have operations Addition, Subtraction,
Multiplication, division, Modulus and Round brackets:\n");
yyparse ();
if(flag==0)
printf("\nEntered arithmetic expression is Valid\n\n");
}
void yyerror()
{
printf("\nEntered arithmetic expression is Invalid\n\n");flag=1;
}
Output:
PROGRAM 3: Write program to find ε – closure of all states of any given
NFA with ε transition.
The ε-closure (epsilon-closure) of a state in a Non-deterministic Finite Automaton (NFA) is
the set of states that can be reached from the given state by traversing only ε (epsilon)
transitions. In other words, it includes the state itself and all states reachable through ε-
transitions.
#include<stdio.h>
#include<stdlib.h>
struct node
{
int st;
struct node *link;
};
void findclosure(int,int);
void insert_trantbl(int ,char, int);
int findalpha(char);
void print_e_closure(int);
static int set[20],nostate,noalpha,s,notransition,c,r,buffer[20];
char alphabet[20];
static int e_closure[20][20]={0};
struct node * transition[20][20]={NULL};
void main()
{
int i,j,k,m,t,n;
struct node *temp;
printf("Enter the number of alphabets?\n");
scanf("%d",&noalpha);
getchar();
// printf("NOTE:- [ use letter e as epsilon]\n");
// printf("NOTE:- [e must be last character ,if it is present]\n");
printf("\nEnter alphabets?\n");
for(i=0;i<noalpha;i++)
{
alphabet[i]=getchar();
getchar();
}
printf("\nEnter the number of states?\n");
scanf("%d",&nostate);
printf("\nEnter no of transition?\n");
scanf("%d",¬ransition);
// printf("NOTE:- [Transition is in the form->qno alphabet qno]\n",notransition);
// printf("NOTE:- [States number must be greater than zero]\n");
printf("\nEnter transition?\n");
for(i=0;i<notransition;i++)
{
scanf("%d %c%d",&r,&c,&s);
insert_trantbl(r,c,s);
}
printf("\n");
printf("e-closure of states : \n");
// printf("—————————–\n");
for(i=1;i<=nostate;i++)
{
c=0;
for(j=0;j<20;j++)
{
buffer[j]=0;
e_closure[i][j]=0;
}
findclosure(i,i);
printf("\ne-closure(q%d): ",i);
print_e_closure(i);
}
}
void findclosure(intx,intsta)
{
struct node *temp;
int i;
if(buffer[x])
return;
e_closure[sta][c++]=x;
buffer[x]=1;
if(alphabet[noalpha-1]=='e' && transition[x][noalpha-1]!=NULL)
{
temp=transition[x][noalpha-1];
while(temp!=NULL)
{
findclosure(temp->st,sta);
temp=temp->link;
}
}
}
void insert_trantbl(intr,charc,int s)
{
int j;
struct node *temp;
j=findalpha(c);
if(j==999)
{
printf("error\n");
exit(0);
}
temp=(struct node *)malloc(sizeof(struct node));
temp->st=s;
temp->link=transition[r][j];
transition[r][j]=temp;
}
int findalpha(char c)
{
int i;
for(i=0;i<noalpha;i++)
if(alphabet[i]==c)
return i;
return(999);
}
void print_e_closure(inti)
{
int j;
printf("{");
for(j=0;e_closure[i][j]!=0;j++)
printf("q%d,",e_closure[i][j]);
printf("}");
}
Output:
PROGRAM 4: Write a program to convert NFA to DFA.
To convert a Non-Deterministic Finite Automaton (NFA) to a Deterministic Finite
Automaton (DFA), we can use the subset construction algorithm. The core idea is to
represent each DFA state as a set of NFA states.
#include<stdio.h>
#include<string.h>
#include<math.h>
int ninputs;
int dfa[100][2][100] = {0};
int state[10000] = {0};
char ch[10], str[1000];
int go[10000][2] = {0};
int arr[10000] = {0};
int main()
{
int st, fin, in;
int f[10];
int i,j=3,s=0,final=0,flag=0,curr1,curr2,k,l;
int c;
printf("\nFollow the one based indexing\n");
printf("\nEnter the number of states::");
scanf("%d",&st);
printf("\nGive state numbers from 0 to %d",st-1);
for(i=0;i<st;i++)
state[(int)(pow(2,i))] = 1;
printf("\nEnter number of final states\t");
scanf("%d",&fin);
printf("\nEnter final states::");
for(i=0;i<fin;i++)
scanf("%d",&f[i]);
int p,q,r,rel;
printf("\nEnter the number of rules according to NFA::");
scanf("%d",&rel);
printf("\n\nDefine transition rule as \"initial state input symbol final state\"\n");
for(i=0; i<rel; i++)
{
scanf("%d%d%d",&p,&q,&r);
if (q==0)
dfa[p][0][r] = 1;
else
dfa[p][1][r] = 1;
}
printf("\nEnter initial state::");
scanf("%d",&in);
in = pow(2,in);
i=0;
printf("\nSolving according to DFA");
int x=0;
for(i=0;i<st;i++)
{
for(j=0;j<2;j++)
{
intstf=0;
for(k=0;k<st;k++)
{
if(dfa[i][j][k]==1)
stf = stf + pow(2,k);
}
go[(int)(pow(2,i))][j] = stf;
printf("%d-%d-->%d\n",(int)(pow(2,i)),j,stf);
if(state[stf]==0)
arr[x++] = stf;
state[stf] = 1;
}
}
for(i=0;i<x;i++)
{
printf("for %d ---- ",arr[x]);
for(j=0;j<2;j++)
{
int new=0;
for(k=0;k<st;k++)
{
if(arr[i] & (1<<k))
{
int h = pow(2,k);
if(new==0)
new = go[h][j];
new = new | (go[h][j]);
}
}
if(state[new]==0)
{
arr[x++] = new;
state[new] = 1;
}
}
}
printf("\nThe total number of distinct states are::\n");
printf("STATE 0 1\n");
for(i=0;i<10000;i++)
{
if(state[i]==1)
{
int y=0;
if(i==0)
printf("q0 ");
else
for(j=0;j<st;j++)
{
int x = 1<<j;
if(x&i)
{
printf("q%d ",j);
y = y+pow(2,j);
}
}
printf(" %d %d",go[y][0],go[y][1]);
printf("\n");
}
}
j=3;
while(j--)
{
printf("\nEnter string");
scanf("%s",str);
l = strlen(str);
curr1 = in;
flag = 0;
printf("\nString takes the following path-->\n");
printf("%d-",curr1);
for(i=0;i<l;i++)
{
curr1 = go[curr1][str[i]-'0'];
printf("%d-",curr1);
}
printf("\nFinal state - %d\n",curr1);
for(i=0;i<fin;i++)
{
if(curr1 & (1<<f[i]))
{
flag = 1;
break;
}
}
if(flag)
printf("\nString Accepted");
else
printf("\nString Rejected");
}
return 0;
}
Output:
PROGRAM 5: Write program to minimize any given DFA.
DFA minimization stands for converting a given DFA to its equivalent DFA with minimum
number of states. DFA minimization is also called as Optimization of DFA and uses
partitioning algorithm.
#include <stdio.h>
/* input format
row 1: input symbols
row 2: non-final states
row 3: final states
rows>3: transition table
*/
int table[10][10];
int matrix[10][10]={0};
int indexOf(char *array,charx,int max){
inti=0;
for(;i<max;i++){
if(array[i]==x)
return i;
}
return -1;
}
int movesToMarked(inti, int j, int l){
int k,x,y;
for(k=0;k<l;k++){
x=table[i][k]; // index of next state on kth input
y=table[j][k];
if(x!=-1 && y!=-1 && matrix[x][y]==1){
return 1;
}
}
return 0;
}
void printStates(char *states, int n, int f){ // prints new states
int i,j;
int store=0; //stores all encountered states
int bin, final;
for(i=0;i<n+f;i++){
bin=1<<i; //bitmask of state to add
if((store&bin)!=0)
continue;
final=(i>n)? 1 : 0; // is final state
store=store|bin;
printf("%c",states[i]);
for(j=i+1;j<n+f;j++){
if(matrix[j][i]==0){
bin=1<<j;
store=store|bin;
if(j>n) final=1;
printf("%c",states[j]);
}
}
if(final==1)
printf(" (f) ");
printf("\n");
}
}
int main(){
char language[10], ch;
int l = 0;
while (1){ //read input symbols till new line encountered
language[l++] = getchar();
if(getchar()=='\n')
break;
}
int n = 0, f = 0; // n: no of non-final states, f: no of final states
char states[10]; // array to store all states
while (1){
states[n++] = getchar(); //read input symbols till new line encountered
if(getchar()=='\n')
break;
}
char *finalstates;
finalstates = states + n; // address of first final state (not really required)
while (1){
finalstates[f++] = getchar();
if(getchar()=='\n')
break;
}
int i,j;
for (i = 0; i< n + f; i++){
for(j=0;j<l;j++){
scanf(" %c",&ch);
table[i][j]=indexOf(states,ch,n+f); // get transition table
}
}
for(i=0;i<n+f;i++){
matrix[i][i]=-1; // diagonal elements not required
}
for(i=n;i<n+f;i++){
for(j=0;j<n;j++){
matrix[i][j]=1;
matrix[j][i]=1; // makes matrix symmetric so (i,j)=(j,i) and order becomes irrelevent
}
}
int change=1;
while(change){
change=0;
for(i=0;i<n+f;i++){
for(j=0;j<n+f;j++){
if(matrix[i][j]==0){
if(movesToMarked(i,j,l)){ // mark i,j of i,j moves to a marked pair on some input
change=1;
matrix[i][j]=1;
matrix[j][i]=1;
}
}
}
}
}
printf(" "); // print matrix
for(i=0;i<n+f;i++){
printf("%c ",states[i]);
}
printf("\n");
for(i=0;i<n+f;i++){
printf("%c ",states[i]);
for(j=0;j<i;j++){
printf("%d ",matrix[i][j]);
}
printf("\n");
}
printStates(states,n,f); // print new states
return 0;
}
Output: