CD - Yash Final
CD - Yash Final
5thKM Stone Delhi, Meerut Road, Near Raj Nagar Extension Road, Ghaziabad, UP-201003
Approved by AICTE, N. Delhi &Affiliated to Dr. A.P.J. Abdul Kalam Technical University, Lucknow
NBA Accredited Program (B. Tech- ECE, IT) & B. Pharma
EXPERIMENT - 1
Aim: Design and implement a lexical analyzer for given language using C and the lexical analyzer
should ignore redundant spaces, tabs and new lines.
Description:
Lexical analysis or scanning is the process where the stream of characters making up the source
program is read from left-to-right and grouped into tokens. Tokens are sequences of characters with a
collective meaning. There are usually only a small number of tokens for a programming language:
constants (integer, double, char, string, etc.), operators (arithmetic, relational, logical), punctuation,
and reserved words.
PROGRAM CODE:
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<string.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(“static”, str)==0 ||
strcmp(“switch”,str)==0 || strcmp(“case”,str)==0) printf(“\n %s is a key word”, str);
else
printf(“\n %s is an identifier”,str);
}
main()
{
FILE *f1,*f2,*f3;
char c,str[10],st1[10];
int num[100], lineno=0, tokenvalue=0,i=0.j=0,k=0;
printf(“\nEnter te c ptogram”);
f1=fopen(“input”, “w”);
while((c=getchar())!=EOF)
putc(c,f1);
fclose(f1);
f1=fopen(“input”,”r”);
f2=fopen(“identifier”,”w”);
f3=fopen(“specialchar”,”w”);
while((c=getc(f1))!=EOF)
{
if(isdigit(c))
{
str[k++]=c;
else
{
str[k]='\0';
keyword(str);
k=0;
}
}
INPUT:
Enter Program $ for termination:
{
int a[3],t1,t2;
t1=2; a[0]=1; a[1]=2; a[t1]=3;
t2=-(a[2]+t1*6)/(a[2]-t1);
if t2>5 then
print(t2);
else {
int t3;
t3=99;
t2=-25;
print(-t1+t2*t3); /* this is a comment on 2 lines */
} endif
}
OUTPUT:
Variables :a[3]t1 t2 t3
Operator : – + * / >
Constants : 2 1 3 6 5 99 -25
Keywords : int if then else endif
Special Symbols : , ; ( ) { }
Comments : this is a comment on 2 lines
EXPERIMENT - 2
Aim: To write a c program for implementing a lexical analyzer using LEX tool
ALGORITHM:
Step1: 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.
Step2: 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.
Step3: 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.
Step4: Each pattern may have a corresponding action, that is, a fragment of C source code to execute
when the pattern is matched.
Step5: 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.
Step6: In user subroutine section, main routine calls yylex(). yywrap() is used to get more input.
Step7: 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.
PROGRAM CODE:
//Implementation of Lexical Analyzer using Lex tool
%{
int COMMENT=0;
%}
identifier [a-zA-Z][a-zA-Z0-9]*
%%
#.* {printf("\n%s is a preprocessor directive",yytext);
}
int |
INPUT:
//var.c
#include<stdio.h>
#include<conio.h>
void main()
{
int a,b,c;
a=1;
b=2;
c=a+b;
printf("Sum:%d",c);
}
OUTPUT:
EXPERIMENT - 3
Aim: Generate YACC specification for a few syntactic categories:
a) Program to recognize a valid arithmetic expression that uses operator +, –, * and/.
b) Program to recognize a valid variable which starts with a letter followed by any number of letters or
digits.
c) Implementation of Calculator using LEX and YACC.
d) Convert the BNF rules into YACC form and write code to generate abstract syntax tree
Description:
A parser generators program that takes as input a specification of a syntax, and produces as
output a procedure for recognizing that language. Historically, they are also called compiler-
compilers.
YACC (yet another compiler-compiler) is an LALR(1)(Look Ahead, Left-to-right, Rightmost
derivation producer with 1 look ahead token) parser generator. YACC was originally designed
for being complemented by Lex.
Program name:arith_id.l
%{
/* This LEX program returns the tokens for the expression */
#include “y.tab.h”
%}
%%
“=” {printf(“\n Operator is EQUAL”);
}
“+”
{
printf(“\n Operator is PLUS”);
}
“-“
{
printf(“\n Operator is MINUS”);
}
“/”
{printf(“\n Operator isDIVISION”);
}
“*”
{
[a-z A-Z]*[0-9]*
{
printf(“\n Identifier is %s”,yytext);
return ID;
}
return yytext[0];
\n return 0;
%%
int yywrap()
{
return 1;
%{
#include
/* This YACC program is for recognising the Expression*/
%}
%token ID INT FLOAT DOUBLE
%%
D;TL
;
L:L,ID
|ID;
%%
extern FILE *yyin;
main()
{
do
{
yyparse();
}while(!feof(yyin));
}
yyerror(char*s)
{
}
Output:
2 * 2 + 5 /4
Answer = 5.25
mem = cos 45
sin 45/mem
Answer = 1
ln 10
Answer = 2.
EXPERIMENT - 4
Aim: Write program to find ε – closure of all states of any given NFA with ε transition.
Description:
A nondeterministic finite automaton (NFA), or nondeterministic finite state machine, does not
need to obey these restrictions. In particular, every DFA is also an NFA.
Using the subset construction algorithm, each NFA can be translated to an equivalent DFA, i.e. a
DFA recognizing the same formal language. Like DFAs, NFAs only recognize regular languages.
Sometimes the term NFA is used in a narrower sense, meaning an automaton that properly
violates an above restriction i.e. that is not a DFA.
ALGORITHM:
Step1: Start the Program.
Step2: Enter the regular expression R over alphabet E.
Step3: Decompose the regular expression R into its primitive components Step4: For each
component construct finite automata.
Step5: To construct components for the basic regular expression way that corresponding to that
way compound regular expression.
Step6: Stop the Program
PROGRAM :
#include<stdio.h>
#include<string.h>
char result[20][20],copy[3],states[20][20];
void add_state(char a[3],int i){
strcpy(result[i],a);
}
void display(int n){
int k=0;
printf("nnn Epsilon closure of %s = { ",copy);
while(k < n){
printf(" %s",result[k]);
for( k=0;k<n;k++){
i=0;
strcpy(state,states[k]);
strcpy(copy,state);
add_state(state,i++);
while(1){
end = fscanf(INPUT,"%s%s%s",state1,input,state2);
if (end == EOF ){
break;
}
if( strcmp(state,state1) == 0 ){
if( strcmp(input,"e") == 0 ) {
add_state(state2,i++);
strcpy(state, state2);
}
}
}
display(i);
rewind(INPUT);
}
return 0;
}
INPUT& OUTPUT:
q0 0 q0
q0 1 q1
q0 e q1
q1 1 q2
Compiler Design Lab (BCS-602) (CSE, VI SEM)
Raj Kumar Goel Institute of Technology, Ghaziabad
EXPERIMENT - 5
Aim: Write program to convert NFA with ε transition to NFA without ε transition.
PROGRAM CODE:
#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 findfinalstate(void);
void unionclosure(int);
void print_e_closure(int);
static int set[20],nostate,noalpha,s,notransition,nofinal,start,finalstate[20],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("Enter the number of states?\n");
scanf("%d",&nostate);
printf("Enter the start state?\n");
scanf("%d",&start);
printf("Enter the number of final states?\n");
scanf("%d",&nofinal);
printf("Enter the final states?\n");
for(i=0;i<nofinal;i++)
Compiler Design Lab (BCS-602) (CSE, VI SEM)
Raj Kumar Goel Institute of Technology, Ghaziabad
EXPERIMENT - 6
Description:
Step1: q0=2^0=1 , q1=2^1=2, q2=2^2=4
Step2: Similarly union od states will be represented as:
q0q1=2^0+2^1=3, q1q2=2^1+2^2=6, q0q1q2=2^0+2^1+2^2=7
Step3: Do no give any condition for “phi”…….
That case is not handled…….(Coz I M LAZY:P)
Step4: Follow zero based indexing everywhere
Step5: Program assumes that if “Number of states are=n” then they are numbered as q0,q1,q2,..q(n-1)
Step6: If you find any bug, message me and forgive me for the error.
Program :
#include<string.h>
#include<stdio.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[];
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++)
{
for(i=0;i<fin; i++)
{
if(curr1 & (1<<f[i]))
{
flag = 1;
break;
}
}
if(flag)
printf("\n String Accepted");
else
printf("\n String Rejected");
}
return 0;
}
EXPERIMENT - 7
ALGORITHM:
Suppose there is a DFA D < Q, Σ, q0, δ, F > which recognizes a language L. Then the
minimized DFA D < Q’, Σ, q0, δ’, F’ > can be constructed for language L as:
Step 1: We will divide Q (set of states) into two sets. One set will contain all final states and
other set will contain non-final states. This partition is called P0.
Step 2: Initialize k = 1
Step 3: Find Pk by partitioning the different sets of Pk-1. In each set of Pk-1, we will take all
possible pair of states. If two states of a set are distinguishable, we will split the sets into
different sets in Pk.
Step 5: All states of one set are merged into one. No. of states in minimized DFA will be
equal to no. of sets in Pk.
PROGRAM :
#include <stdlib.h>
#include <string.h>
#include<stdio.h>
int **transition Map; // 2D array which is used to store state transitions. Transition Map[i][j]
is the state
reached when state i is given symbol j
int **partition Transition Map; // same as transition Map, except row indices represent
partition numbers,
not state numbers
int start State; // The starting state. This is used as the root for DFS to eliminate unreachable
states
long int reachable; // A bitset to represent states that are reachable
long int allStates; // A bitset to represent all states in the FSM
long int finalStates; // A bitset to represent final states in the FSM
long int nonFinalStates; // A bitset to represent non-final states in the FSM
long int *P; // array of partitions. Each partition is a bitset of states
void dfs(int v)
{
reachable |= (1 << v);
// Try exploring all paths..
for(int i=0; i<26; i++)
Compiler Design Lab (BCS-602) (CSE, VI SEM)
Raj Kumar Goel Institute of Technology, Ghaziabad
INPUT:
0
25
0 a1
1b2
0b3
3 a4
4b5
OUTPUT:
3
0
1b0
2 a1
3 a1
3b2
EXPERIMENT - 8
Aim: Implementation of shift reduce parsing algorithm.
Description:
Shift-reduce parsing attempts to construct a parse tree for an input string beginning at the
leaves and working up towards the root. In other words, it is a process of “reducing” (opposite
of deriving a symbol using a production rule) a string w to the start symbol of a grammar.
ALGORITHM:
STEP1: Initial State: the stack consists of the single state, s0; ip points to the first character in
w.
STEP 2: For top-of-stack symbol, s, and next input symbol, a case action of T[s,a]
STEP 3: shift x: (x is a STATE number) push a, then x on the top of the stack and advance ip
to point to the next input symbol.
STEP 4: reduce y: (y is a PRODUCTION number) Assume that the production is of the form
A ==> beta pop 2 * |beta| symbols of the stack.
STEP 5: At this point the top of the stack should be a state number, say s’. push A, then goto
of T[s’,A] (a state number) on the top of the stack.
PROGRAM CODE:
#include<stdio.h>
#include<conio.h>
#include<string.h>
int k=0,z=0,i=0,j=0,c=0;
char a[16],ac[20],stk[15],act[10];
void check();
void main()
{
clrscr();
puts("GRAMMAR is E->E+E \n E->E*E \n E->(E) \n E->id");
puts("enter input string ");
gets(a);
c=strlen(a);
strcpy(act,"SHIFT->");
puts("stack \t input \t action");
for(k=0,i=0; j<c; k++,i++,j++)
EXPERIMENT - 9
Aim: Write program to find Simulate First and Follow of any given grammar.
Description:
First and Follow sets are needed so that the parser can properly apply the needed
production rule at the correct position.
PROGRAM CODE:
// C program to calculate the First and
// Follow sets of a given grammar
#include<stdio.h>
#include<ctype.h>
#include<string.h>
// Functions to calculate Follow
void followfirst(char, int, int);
void follow(char c);
// Function to calculate First
void findfirst(char, int, int);
int count, n = 0;
// Stores the final result
// of the First Sets
char calc_first[10][100];
// Stores the final result
// of the Follow Sets
char calc_follow[10][100];
int m = 0;
// Stores the production rules
char production[10][10];
char f[10], first[10];
int k;
char ck;
int e;
int main(int argc, char **argv)
{
int jm = 0;
int km = 0;
int i, choice;
char c, ch;
count = 8;
// The Inputgrammar
strcpy(production[3], "T=FY");
strcpy(production[4], "Y=*FY");
strcpy(production[5], "Y=#");
strcpy(production[6], "F=(E)");
strcpy(production[7], "F=i");
int kay;
char done[count];
int ptr = -1;
// Initializing the calc_first array
for(k = 0; k < count; k++) {
for(kay = 0; kay < 100; kay++) {
calc_first[k][kay] = '!';
}
}
int point1 = 0, point2, xxx;
for(k = 0; k < count; k++)
{
c = production[k][0];
point2 = 0;
xxx = 0;
// Checking if First of c has
// already been calculated
for(kay = 0; kay <= ptr; kay++)
if(c == done[kay])
xxx = 1;
if (xxx == 1)
continue;
// Function call
findfirst(c, 0, 0);
ptr += 1;
// Adding c to the calculated list
done[ptr] = c;
printf("\n First(%c) = { ", c);
calc_first[point1][point2++] = c;
// Printing the First Sets of the grammar
for(i = 0 + jm; i < n; i++) {
int lark = 0, chk = 0;
for(lark = 0; lark < point2; lark++) {
if (first[i] == calc_first[point1][lark])
{
chk = 1;
break;
}
}
if(chk == 0)
{
EXPERIMENT - 10
Description:
Recursive descent is a top-down parsing technique that constructs the parse tree from the top
and the input is read from left to right. It uses procedures for every terminal and non-terminal
entity. This parsing technique recursively parses the input to make a parse tree, which may or
may not require back-tracking. But the grammar associated with it (if not left factored) cannot
avoid back- tracking. A form of recursive-descent parsing that does not require any back-
tracking is known as predictive parsing.
ALGORITHM:
Step1:start.
Step2:DeclaretheprototypefunctionsE(),EP(),T(),TP(),F()Step3:
Readthestringtobe parsed.
Step 4: Check the productions
Step 5: Compare the terminals and Non-terminals Step
6: Read the parse string
Step 7: stop the production
PROGRAM CODE:
#include "stdio.h"
#include "conio.h"
char input[100];
char prod[100][100];
int pos=-1,l,st=-1;
char id,num;
voidE();
voidT();
voidF();
void advance();
scanf("%s",input);
l=strlen(input);
input[l]='$';
advance();
E();
if(pos==l)
{
printf("String Accepted\n");
for(i=0;i<=st;i++)
{
printf("%s\n",prod[i]);
}
}
else
{
printf("String rejected\n");
}
getch();
return 0;
}
INPUT:
E->TE’
E’-> +TE’ | -TE’ | null
T-> FT’
T’-> *FT’| /FT’ | null
F-> id/ (E)/ num
OUTPUT:
EXPERIMENT - 11
Aim: - Write a C program to implement operator precedence parsing
Description:
An operator precedence grammar is a context-free grammar that has the property (among
others) that no production has either an empty right-hand side or two adjacent nonterminals in
its right- hand side. These properties allow precedence relations to be defined between the
terminals of the grammar. A parser that exploits these relations is considerably simpler than
more general-purpose parsers such as LALR parsers. Operator-precedence parsers can be
constructed for a large class of context-free grammars.
ALGORITHM:
Step 1: Push # onto stack
Step 2: Read first input symbol and push it onto stack Step 3: Do
Obtain OP relation between the top terminal symbol on the stack and the next input symbol If
the OP relation is < or =
i. Pop top of the stack into handle, include non-terminal symbol if appropriate.
ii. Obtain the relation between the top terminal symbol on the stack and the left
most terminal symbol in the handle.
PROGRAM:
#include<stdio.h>
#include<conio.h>
void main(){
/*OPERATOR PRECEDENCE PARSER*/
char stack[20],ip[20],opt[10][10][1],ter[10];
int i,j,k,n,top=0,col,row;
clrscr();
for(i=0;i<10;i++)
for(i=0;i<n;i++)
{
printf("\t%c",ter[i]);
}
printf("\n");
for(i=0;i<n;i++){printf("\n%c",ter[i]);
for(j=0;j<n;j++){printf("\t%c",opt[i][j][0]);}}
stack[top]='$';
printf("\nEnter the input string:");
scanf("%s",ip);
$ i*i Shift i
$<i *i Reduce
$ *i Shift *
$<* i Shift i
$<*<i String is not accepted
EXPERIMENT - 12
Aim: Write a program to perform loop unrolling.
Description:
Loop unrolling is a loop transformation technique that helps to optimize the execution time of a
program. We basically remove or reduce iterations. Loop unrolling increases the program’s speed by
eliminating loop control instruction and loop test instructions.
PREEXPERIMENT
Q1. Define loop unrolling.
Q2. Give example of loop unrolling.
ALGORITHM:
Step1: Start Step2: Declare n
Step3: Enter n value
Step4: Loop rolling display countbit1 or move to next step 5 Step5: Loop unrolling display
countbit2
Step6: End
PROGRAM:
Program 1:
int main(void)
{
for (int i=0; i<5; i++)
printf("Hello\n"); //print hello 5 times
return 0;
}
Program 2:
Output:
Hello
Hello
Hello
Hello
Hello
Illustration:
Program 2 is more efficient than program 1 because in program 1 there is a need to check the value of
i and increment the value of i every time round the loop. So small loops like this or loops where there
is fixed number of iterations are involved can be unrolled completely to reduce the loop overhead.
EXPERIMENT - 13
Aim: Write a Program to implement Code Optimization Techniques (eg. Constant
propagation etc)
Description:
The algorithm we shall present basically tries to find for every statement in the program a
mapping between variables, and values of N T ∪⊥ { , } . If a variable is mapped to a constant
number, that number is the variables value in that statement on every execution. If a variable
is mapped to T (top), its value in the statement is not known to be constant, and in the variable
is mapped to ⊥ (bottom), its value is not initialized on every execution, or the statement is
unreachable. The algorithm for assigning the mappings to the statements is an iterative
algorithm that traverses the control flow graph of the algorithm, and updates each mapping
according to the mapping of the previous statement, and the functionality of the statement.
The traversal is iterative, because non- trivial programs have circles in their control flow
graphs, and it ends when a “fixed-point” is reached – i.e., further iterations don’t change the
mappings.
ALGORITHM:
Step1: Start
Step2: Create an input file which contains three address code
Step3: Open the file in read mode
Step4:If the file pointer returns NULL, exit the program else goto 5
Step5: Scan the input symbol from left to right.
Common sub-expression elimination.
Step6: Store the first expression in a string.
Step7: Compare the string with the other expressions in the file.
Step8: If there is a match, remove the expression from the input file.
Step9: Perform the step 5 to 8 for all the input symbols in the file.
Dead Code Elimination
Step10: Scan the input symbol from the file from left to right.
Step11: Get the operand before the operator from the three address code.
Step12: Check whether the operand is used in any other expression in the three
address code.
Step13: If the operand is not used, then eliminate the complete expression from the three
address code else goto 14.
Step14: Perform step 11-13 for all the operands in the three address code till end of
file is reached.
Step15: Stop.
PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<string.h>
struct op{
char 1;
op[10], pr[10];
voidmain()
{
int a,i,k,j,n,z=0,m,q;
char *p, *l;
char temp,t;
char *temp;
clrscr();
printf(“Enter the no. of values”);
scanf(“%d”, &n);
for(i=0;i<n;i++)
{
printf(“\tleft\t”);
op[i].l=getche();
printf(“\tright:\t”);
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++;
printf(“\n after dead code elimination\n”);
for(k=0;k<z;k++)
{
printf(“%c\t=”,pr[k].l);
printf(“%s\n”,pr[k].r);
}
// sub expression elimination
for(m=0;m<z; m++)
{
tem=pr[m].r;
for(j=m+1;j<z;j++)
{
Compiler Design Lab (BCS-602) (CSE, VI SEM)
Raj Kumar Goel Institute of Technology, Ghaziabad
OUTPUT:
lefta right 9
leftb rightc+d
lefte rightc+d
leftf rightb+e
leftr right f
intermediate code
a=9
b=c+d
e=c+d
f=b+e
r=f
EXPERIMENT - 14
Description:
Three address code is a type of intermediate code which is easy to generate and can be easily
converted to machine code. It makes use of at most three addresses and one operator to
represent an expression and the value computed at each instruction is stored in temporary
variable generated by compiler. The compiler decides the order of operation given by three
address code.
Program:
#include<stdio.h>
#include<conio.h>
#include<string.h>
inti=1,j=0,no=0,tmpch=90;
char str[100],left[15],right[15];
void findopr();
void explore();
void fleft(int);
void fright(int);
structexp{
int pos;
charop;
}
k[15];
void main()
{
clrscr();
printf("\t\tINTERMEDIATE CODE GENERATION\n\n");
printf("Enter the Expression :");
scanf("%s",str);
printf("The intermediate code:\t\tExpression\n");
findopr();
explore();
getch();
}
void findopr()
{
for(i=0;str[i]!='\0';i++)
if(str[i]==':')
{
k[j].pos=i;
k[j++].op=':';
}
for(i=0;str[i]!='\0';i++)
if(str[i]=='/')
{
k[j].pos=i;
for(i=0;str[i]!='\0';i++)
if(str[i]=='*')
{
k[j].pos=i;
k[j++].op='*';
}
for(i=0;str[i]!='\0';i++)
if(str[i]=='+')
{
k[j].pos=i;
k[j++].op='+';
}
for(i=0;str[i]!='\0';i++)
if(str[i]=='-')
{
k[j].pos=i;
k[j++].op='-';
}
}
voidexplore()
{
i=1;
while(k[i].op!='\0')
{
fleft(k[i].pos);
fright(k[i].pos);
str[k[i].pos]=tmpch--;
printf("\t%c := %s%c%s\t\t",str[k[i].pos],left,k[i].op,right);
for(j=0;j <strlen(str);j++)
if(str[j]!='$')
printf("%c",str[j]);
printf("\n");
i++;
}
fright(-1);
if(no==0)
{
fleft(strlen(str));
printf("\t%s := %s",right,left);
getch();
exit(0);
}
printf("\t%s := %c",right,str[k[--i].pos]);
getch();
}
void fleft(int x)
{
int w=0,flag=0;
x--;
while(x!= -1&&str[x]!='+'&&str[x]!='*'&&str[x]!='='&&str[x]!='\0'&&str[x]!='-
'&&str[x]!='/'&&str[x]!=':')
{
if(str[x]!='$'&& flag==0)
{
left[w++]=str[x];
left[w]='\0';
str[x]='$';
flag=1;
Output
EXPERIMENT - 15
Aim: Implement the back end of the compiler which takes the three address code and
produces the 8086 assembly language instructions that can be assembled and run using an 8086
assembler. The target assembly instructions can be simple move, add, sub, jumpetc.
ALGORITHM:
PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
char icode[10][30], str[20],opr[10];
int i=10;
clrscr();
printf(“\n Enter the set of intermediate code(terminated by exit):\n”);
do
{
scanf(“%s”, icode[i]);
}while(strcmp(icode[i++],”exit”)!=0);
printf(“\n target code generation”);
printf(“\n************************”);
i=0;
do{
strcpy(str,icode[i]);
switch(str[3]){
case‘+’:
strcpy(opr,”ADD”);
break;
case ‘-‘:
strcpy(opr,”SUB”);
break;
case ‘*’:
strcpy(opr, “MUL”);
break;
}
printf(“\n\tMov %c,R%d”, str[2], i);
printf(“\n\t%s%c,R%d”, opr, str[4], i);
printf(“\n\tMov R%d,%c”, i, str[0]);
}while(strcmp(icode[++i],”exit”)!=0);
getch();
}
OUTPUT:
EXPERIMENT - 16
Aim: Write a C program for constructing of LL (1) parsing.
Description:
An LL parser is a top-down parser for a subset of context-free languages. It parses the input
from Left to right, performing Left most derivation of the sentence. An LL parser is called an
LL(k) parser if it uses k tokens of look-ahead when parsing a sentence. If such a parser exists
for a certain grammar and it can parse sentences of this grammar without backtracking then it
is called an LL(k) grammar. LL(k) grammars can generate more languages the higher the
number k of look ahead tokens.
ALGORITHM:
Step1:IfA→αisaproductionchoice,andthereisaderivationα⇒∗ aβ,whereaisa token,
then we add A → α to the table entry M[A,a].
Step 2: If A → α is a production choice, and there are derivations α ⇒∗ ε
andS$⇒∗ βAaγ,where S is the start symbol and a is a token(or$),the new add A
→ α to the table entry M[A, a]
PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<string.h>
char s[20],stack[20];
void main()
{
char m[5][6][3]={"tb"," "," ","tb"," "," "," ","+tb"," "," ","n","n","fc"," "," ","fc"," "," ","
","n","*fc"," a ","n","n","i"," "," ","(e)"," "," "};
int size[5][6]={2,0,0,2,0,0,0,3,0,0,1,1,2,0,0,2,0,0,0,1,3,0,1,1,1,0,0,3,0,0};
int i,j,k,n,str1,str2;
clrscr();
printf("\n Enter the input string: ");
scanf("%s",s);
strcat(s,"$");
n=strlen(s);
stack[0]='$';
stack[1]='e';
i=1;
j=0;
printf("\nStack Input\n");
$bcf i$
$bci i$
$bc $
$b $
$ $
sucess
Description:
An LALR parser or Look-Ahead LR parser is a simplified version of a canonical LR parser,
to parse (separate and analyze) a text according to a set of production rules specified by a
formal grammar for a computer language. ("LR" means left-to-right, right most derivation.)
ALGORITHM:
STEP1:Represent by its CLOSURE ,those item sthat are either the initial item[S’
do not have the . a t the left end of the RHS
STEP2:Compute shift,reduce,and goto actions for the state derived from Iidirectlyfrom
CLOSURE(Ii)
PROGRAM:
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
void push(char *,int *,char);
char stacktop(char *);
void isproduct(char,char);
int ister(char);
int isnter(char);
intisstate(char);
voiderror();
void isreduce(char,char);
char pop(char *,int *);
void printt(char *,int *,char [],int);
void rep(char [],int);
struct action
{
char row[6][5]; };
{"sf","emp","emp","se","emp","emp"},
{"emp","sg","emp","emp","emp","acc"},
{"emp","rc","sh","emp","rc","rc"},
{"emp","re","re","emp","re","re"},
{"sf","emp","emp","se","emp","emp"},
{"emp","rg","rg","emp","rg","rg"},
{"sf","emp","emp","se","emp","emp"},
{"sf","emp","emp","se","emp","emp"},
{"emp","sg","emp","emp","sl","emp"},
{"emp","rb","sh","emp","rb","rb"},
{"emp","rb","rd","emp","rd","rd"},
{"emp","rf","rf","emp","rf","rf"}
};
struct gotol
{
char r[3][4];
};
const struct gotol G[12]={
{"b","c","d"},
{"emp","emp","emp"},
{"emp","emp","emp"},
{"emp","emp","emp"},
{"i","c","d"},
{"emp","emp","emp"},
{"emp","j","d"},
{"emp","emp","k"},
{"emp","emp","emp"},
{"emp","emp","emp"},
};
char ter[6]={'i','+','*',')','(','$'};
char nter[3]={'E','T','F'};
char states[12]={'a','b','c','d','e','f','g','h','m','j','k','l'};
char stack[100];
int top=-1;
char temp[10];
structgrammar
{
char left; charright[5]; };