Practical CD Complete
Practical CD Complete
AND TECHNOLOGY
                               (DEGREE WING)
            Government Institute under Chandigarh (UT) Administration, Affiliated to
                                Panjab University, Chandigarh
                      Sector-26, Chandigarh. PIN-160019
                                  Semester: 6th
                              Compiler Design (Practical)
                             Subject Code: CS 654
ACKNOWLEDGEMENT
Perseverance, inspiration and motivation have played a great role in the success of any venture.
It would be incomplete to submit this practical file without acknowledging the people behind
this endeavour and without whose support I wouldn't have able to achieve this. I would like to
thank Dr. Gulshan Goyal for giving me an opportunity to work on such a fabulous project and
for their guidance and support in completing my project. Secondly, I would like to thank my
parents for their constant support which helped me finish my practical in limited time. It gives
me immense pleasure to express my gratitude to everyone who shared with me their precious
time and effort during the practical period
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 2
Compiler design Practical (CS-654)                                              C020328
Index
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 3
Compiler design Practical (CS-654)                                                    C020328
                                     Practical - 1
1.1. Aim
Write a program to generate a DFA and to show string processing corresponding to the DFA
generated.
1.2. Input
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 4
Compiler design Practical (CS-654)                                                    C020328
                          • 7.3.2.1. process=transition_b
                          • 7.3.2.2.print(process)
   ▪ 7.4. If (transition from last character of input string maps to final_state)
   ▪ 7.4.1. print(“string accepted”)
   ▪ 7.5. else
   ▪ 7.5.1. print(“string rejected”)
   1. Stop.
1.5. Flowchart
       #include <iostream>
       #include<cstring>
       using namespace std;
       int dfa[10][10];
       int col1,col2;//col1 for transitions of a nd col2 for transitions of b
       int states,length;//states calculates total no. of states
       int flaga,statea,flagb,stateb;
       char alpha1,alpha2;//input alphabets
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 6
Compiler design Practical (CS-654)                                             C020328
        break;
        case 2:
        cout<<"---DFA for SUFFIX---"<<endl;
        char suffix[10];
        cout<<"Enter the suffix string over alphabet {"<<alpha1<<","<<alpha2<<"}: ";
        cin>>suffix;
        length=strlen(suffix);
        states=length+1;
        for(i=0; i<length; i++)
        {
        col1= (suffix[i]==alpha1)? 0: 1;
        dfa[i][col1] = i+1;//next state
        col2 = (col1==0)? 1 : 0;//for second alphabet
        //flag shows missed one time atleast
        //state set as per the iteration going nd is repeated further
        if(col2 == 0 && flaga==0)
       {
        dfa[i][col2] = i;
        flaga = 1;
        statea = i;
        }
        else if(col2 == 0 && flaga==1)
        {
        dfa[i][col2] = statea;
        }
        if(col2== 1 && flagb==0)
        {
        dfa[i][col2] = i;
        flagb = 1;
        stateb = i;
        }
        else if(col2 == 1 && flagb==1)
        {
        dfa[i][col2] = stateb;
        }
        }
       if(flaga)
       dfa[length][0] = statea;
       else //case of aaa
       dfa[length][0] = length;
       if(flagb)
       dfa[length][1] = stateb;
       else//case of bbb
       dfa[length][1] = length;
        //handling exceptional cases for final states
        if(suffix[0]==alpha1 && suffix[1]==alpha1 && suffix[2]==alpha2)//aab
        dfa[3][0]=1;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 9
Compiler design Practical (CS-654)                                                        C020328
        dfa[length][0]=length;
        dfa[length][1]=length;
        print_table();
        string_process();
        flaga=0, flagb=0;
        statea=0,stateb=0;
        break;
        case 4:
        break;
        default:
        cout<<"Select a valid option !";
        }
        }while(choice!=4);
        return 0;
       }
1.7. Output:
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 11
Compiler design Practical (CS-654)                                             C020328
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 12
Compiler design Practical (CS-654)                                                      C020328
Q3: Write the regular expression for strings containing “abb” prefix over alphabet {a,
b}.
Ans: abb(a+b)*
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 13
Compiler design Practical (CS-654)                                                         C020328
                                       Practical-2
2.1. Aim
To write a program to convert NFA to DFA.
2.2. Input
Following is the input which is asked from the user that includes the details for designing the
NFA -
• Initial State of NFA
• Final State of NFA
• No. of transitions and states of NFA
• Initial state, final state & corresponding alphabet for that every transition state of NFA
2.4. Method
The method of converting NFA to its equivalent DFA is discussed below. In NFA, when a
specific input is given to the current state, the machine goes to multiple states. It can have zero,
one or more than one move on a given input symbol. On the other hand, in DFA, when a
specific input is given to the current state, the machine goes to only one state. DFA has only
one move on a given input symbol.
As we know that M = (Q, ∑, δ, q0, F) is an NFA which accepts the language L(M). So there
should be equivalent DFA denoted by M' = (Q', ∑', q0', δ', F') such that L(M) = L(M').
• The main objective of the program is to generate the transition table for a DFA for user
   input designed NFA. For this purpose, the user is initially asked to enter the initial state,
   final State of NFA, no. of transitions and states of NFA. Then the user enters the initial
   state, final state & corresponding alphabet for that every transition state for which the NFA
   has to be generated.
• Functions        such     as    bootstrapDFA(),      createDFA(),     initDFA(),       initNFA(),
   showTableNFA(NFA), showTableDFA(DFA), addTransition() and inputTransition() are
   used to implement the conversion process from NFA to DFA.
• Here showTableNFA(NFA) and showTableDFA(DFA) are used to display the transition
   table of NFA and DFA respectively.
• Then the transition table of NFA is shown on the basis of the user input.
• Thereafter, the NFA is successfully converted into DFA and transition table of DFA is
   displayed.
2.5. Algorithm
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 14
Compiler design Practical (CS-654)                                                            C020328
   1. BEGIN
   2. Declare
                     a. struct Transition {
                      i. unsigned int input_state;
                      i. unsigned int output_states;
                     ii. int symbol;
                    iii. };
                       This structure is for storing information for designing NFA.
            b. final[10] – For storing the final states of NFA.
            c. total_states[1] – For storing the total no. of states of NFA.
            d. final_count[1] – For storing the total no. of final states of NFA.
            e. struct FA {
                        unsigned int starting_state;
                        unsigned int final_states;
                        vector<struct Transition> transition_table;
                        };
                This structure is for storing information for generating DFA.
   3.   Execute the function initNFA().
   4.   Enter the initial state, total no. of states, total no. of final states of NFA, final state, no.
        of transitions.
   5.   Then the user enters the initial state, final state & corresponding alphabet for that every
        transition state for which the NFA has to be generated.
   6.   Execute showTableNFA(NFA) – It displays the transition table of NFA.
            a. Perform switch(check){
                               1. case 'a':
                                      a. tab[ctr][0]=setToString((*j).output_states);
                                      b. break;
                               2. case 'b':
                                      a. tab[ctr][1]=setToString((*j).output_states);
                                      b. break;
            b. Perform bool check_final(int index)to check whether the state index present in
                the set of final states or not.
            c. Set check = false.
            d. Initialize k .
            e. while(final[k] && !check){
                          if(index == final[k]) then set check = true and increment k
                          Else return check;
                          }
            f. if(check_final(k)) then mark the initial state of the DFA by ->q0
            g. Else mark final state by DFA by *qn.
   7.   Display the transition table of NFA.
   8.   Execute createDFA() which implements the transition table of DFA table.
   9. Perform initDFA() to find out the combination of States for each possible input
      alphabet.
            a. Set DFA.final_states = 0.
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 15
Compiler design Practical (CS-654)                                                    C020328
2.6. Flowchart
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 16
Compiler design Practical (CS-654)                                                       C020328
q0, w) ∈ F. That is a string is accepted by a DFA if and only if the DFA starting at the initial
state ends in an accepting state after processing the string.
       #include<stdio.h>
       #include<conio.h>
       #include<stdlib.h>
       char str[100000];
       int nstates[1000][100], temp[100];
       int ntable[1000][100];
       void print1(int k, int n)
       {
       int i, f=0, in=-1;
       printf("\t[");
       for(i=0;i<n;i++)
       {
       if(nstates[k][i])
       {
       f++;
       if(in==-1)
       in=i;
       }
       }
       if(f==1)
       {
       printf("q%d",in);
       }
       else if(f>1)
       {
       printf("q%d", in);
       for(i=in+1;i<n;i++)
       {
       if(nstates[k][i])
       {
       printf("q%d", i);
       }
       }
       }
       printf("]\t");
       }
       int main()
       {
       int n, ip, i, j, initial, noFinal, q, in, k, fin, numOftrans, f, no, l;
       //variables
       char choice;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 17
Compiler design Practical (CS-654)                                                                    C020328
       for(i=0;i<ip;i++)
       {
       printf("\t %c |\t", symbols[i]);
       }
       printf("\n\t|-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -|\n");
       for(i=0;i<n;i++)
       {
       if(i==initial)
       {
       printf("\t q%d", i);
       }
       else
       {
       printf("\t q%d", i);
       }
       for(j=0;j<noFinal;j++)
       {
       if(final[j]==i)
       {
       break;
       }
       }
       if(j<noFinal)
       {
       printf("**\t");
       }
       else
       {
       printf( " ");
       }
       for(j=0;j<ip;j++)
       {
       printf("|\t{");
       if(table[i][j][0]!=-1)
       {
       printf("q%d", table[i][j][0]);
       for(k=1;table[i][j][k]!=-1;k++)
       {
       printf("q%d", table[i][j][k]);
       }
       }
       printf("}\t");
       }
       printf("\t|\n\t|-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -|\n");
       printf("\n");
       }
       printf("HELLO");
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 19
Compiler design Practical (CS-654)                                                                    C020328
       nstates[0][initial] = 1;
       no = 1;
       for(i=0;i<no;i++)
       {
       for(j=0;j<ip;j++)
       {
       for(k=0;k<n;k++)
       {
       temp[k] =0;
       }
       for(k=0;k<n;k++)
       {
       if(nstates[i][k])
       {
       for(l=0;table[k][j][l]!=-1;l++)
       {
       temp[table[k][j][l]] = 1;
       }
       }
       }
       for(k=0;k<no;k++)
       {
       f=1;
       for(l=0;l<n;l++)
       {
       if(temp[l]!=nstates[k][l])
       {
       f=0;
       break;
       }
       }
       if(f) break;
       }
       ntable[i][j] = k;
       if(k>=no)
       {
       for(l=0;l<n;l++)
       {
       nstates[k][l] = temp[l];
       }
       no++;
       }
       }
       }
       printf("\n\n-- -- -- -- -- -- -- -- -- -- -- TRANSITION TABLE-- -- -- -- -- -- -- -- -- -- -- -- -- ");
       printf("\n\n\t states |");
       for(i=0;i<ip;i++)
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 20
Compiler design Practical (CS-654)                                                                             C020328
       {
       printf("\t %c |\t", symbols[i]);
       }
       printf("\n\t|-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -|\n");
       for(i=0;i<no;i++)
       {
       if(i==0)
       {
       printf(" ");
       print1(0,n);
       }
       else
       {
       printf(" ");
       print1(i,n);
       }
       f=0;
       for(j=0;j<noFinal;j++)
       {
       for(k=0;k<n;k++)
       {
       if(nstates[i][k] && k==final[j])
       {
       f=1;
       break;
       }
       }
       if(f) break;
       }
       if(f)
       {
       printf("**");
       }
       printf("|");
       for(j=0;j<ip;j++)
       {
       print1(ntable[i][j], n);
       printf(" ");
       }
       printf("\n\t|-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -|");
       printf("\n");
       }
       return 0;
       }
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 21
Compiler design Practical (CS-654)                                             C020328
2.8. Output
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 22
Compiler design Practical (CS-654)                                             C020328
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 23
Compiler design Practical (CS-654)                                                         C020328
2.9. Discussion
Thus for any initial state, final state & corresponding alphabet for that every transition state the
user has entered, the NFA and its conversion into equivalent DFA can be successfully
implemented.
4. Predict the number of transitions required to automate the following language using
only 3 states:
L= {w | w ends with 00}
Ans. 3
5. The finite automata is called NFA when there exists____________ for a specific input
from current state to next state. Fill in the blank.
Ans. Multiple paths
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 24
Compiler design Practical (CS-654)                                                         C020328
                                      Practical - 3
3.1. Aim
Write a program to identify and count the single line and multiline comments in a program
taken either as input using file handling or given by the user.
3.2. Input
3.4. Method
The purpose of this program to accept an input code and print every multi-line and single-line
comments in the source code, as well as the total number of both types of comments. Program
comments are explanatory statements that one can include in the code. These comments help
anyone reading the source code. All programming languages allow for some form of
comments. In this program I have implemented this code for single line and multi-line
comments in C++ language.
As known , in C++ single line comment is written as // (double slash) and multi-line comment
as (/* …*/) , so this program find s the count of these only. The code can be given in two ways
either in user input form or from a text file. The program then scans the entire code for
comments. It does so by looking for the first forward slash (/), and if it finds another slash (/)
immediately after it, it counts it as a single-line remark and adds one to its count. It marks it as
a multi-line comment and increases its count by one if an asterisk (*) is discovered after a slash
(/) and then after some characters, if and only if an asterisk (*) followed by a slash (/) is found.
The output of the program is a table including all of the comments, as well as the kind of each
sort of remark and their count.
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 25
Compiler design Practical (CS-654)                                               C020328
3.5. Algorithm
   1. Start
   2. Main menu opens to choose from three options.
               a. Enter the code on console
               b. Using notepad
               c. Exit
   3. If invalid option is entered go to 2
   4. If option selected = c, then Exit
   5. If option selected = a, then go to 7
   6. If option selected = b, then go to 8
   7. User input of code on console as string and go to 10
   8. Open the text file mentioned in code
   9. Read the contents of opened file line by line and store it in a string.
   10. Convert string into char array.
   11. Finding the length of the input and assign it in variable len.
   12. Initialise single=0 and multi=0.
   13. Scan the code i.e. is in the char array.
   14. If the input character = /
         II.      Check next character
        III.      If next character=/, then go to 14.iii. else go to 14.v.
        IV.       Print single line comment.
         V.        Increment single.
        VI.       If current character=*, then go to 14.vi. else go to 15.
       VII.       Print multi line comment.
      VIII.       Increment multi.
   15. Repeat step 14 until the entire input array is scanned.
   16. Output the table showing type of comment and the corresponding comment.
   17. Print the count of single and multi-line comments in the code.
   18. End
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 26
Compiler design Practical (CS-654)                                             C020328
3.6. Flowchart
#include<iostream>
#include<stdlib.h>
#include<fstream>
#include<string.h>
#include<ctype.h>
#include<iomanip>
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 27
Compiler design Practical (CS-654)                                             C020328
break; }
case 3:
{
exit(0);
break; }
default:
cout<<"Enter valid option";
}
cout<<"\nS.No. |\tType of Comment\t\t|\tComment\n";
cout<<"________|_______________________________|_________________________";
while(x!=len)
{
if(inp[x]=='/')
{
x++;
if(inp[x]=='/')
{
x++;
i=0;
while(inp[x]!='\n')
{
check[i]=inp[x];
x++;
i++;
}
cout<<"\n "<<++num<<"\t|\t"<<"Single line Comment"<<"\t|\t";
single++;
for(int q=0; q<i; q++)
cout<<check[q];
}
if(inp[x]=='*')
{
cout<<"\n "<<++num<<"\t|\t"<<"Multi line Comment"<<"\t|\t";
multi++;
x++;
i=0;
while(inp[x]!='*')
{
if(inp[x]=='\n')
{
x++;
continue;
}
cout<<inp[x];
i++;
x++;
}
}
}
x++;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 29
Compiler design Practical (CS-654)                                             C020328
}
cout<<"\n\n";
cout<<"Number of Single line Comments: "<<single<<endl;
cout<<"Number of Multi line Comments: "<<multi<<endl<<endl<<endl;
fin.close();
goto start;
return 0;
}
3.8. Output
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 30
Compiler design Practical (CS-654)                                                      C020328
3.9. FAQS
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 31
Compiler design Practical (CS-654)                                                       C020328
                                     Practical - 4
4.1. Aim
Write a program to construct a lexical analyser which scans the input code and produces the
lexemes and tokens as an output.
4.2. Input
In this program the user will type the required program and store it with .cpp extension. The
program will take the use the source code file to perform lexical analysis on it.
4.4. Method
In this experiment, a program is designed in C++ language that takes an input code and outputs.
In this practical, a lexical analyser has been implemented using C++. The primary task of the
lexical analyser is to convert the given input code into a stream of tokens. A token is nothing
but a small unit of the program which is basically made of series of characters. The tokens can
be keywords, identifiers, constant, operators, header files or punctuation symbols. The lexical
analyser does its work by scanning the whole program and splitting the whole program into
corresponding tokens. In this program, the user either inputs the code which has to be converted
into tokens via a text file or through the console. The program then scans the entire code and
stores it into a string array and then it scans character by character and matches it with the
initially specified operators, keywords or header files. Scanning the entire code, the given
program generates lexemes and classifies them into tokens. The defined token categories used
in the program are identifier, keyword, header files, operators, punctuation symbols and
constant. In C++, there are thirty four keywords.
4.5. Algorithm
2. Begin.
3. Select input method
            1. Using string
            2. Using file handling
4. Split string into tokens using delimiters
5. Select i token
           th
#include<iostream>
#include<stdlib.h>
#include<fstream>
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 33
Compiler design Practical (CS-654)                                             C020328
#include<string.h>
#include<ctype.h>
#include<iomanip>
using namespace std;
int num=0, len=0;
char inp[400];
void keyword(char check[60]){
 char valid_keyword[34][12] =
{"string","auto","break","case","char","const","continue","default",
 "do","double","else","enum","extern","float","for","goto",
 "if","elif","int","long","register","return","short","signed",
 "sizeof","static","struct","switch","typedef","union",
 "unsigned","void","while","main"};
 int i, key = 0;
 for(i=0;i<34;i++){
 if(strcmp(valid_keyword[i], check) == 0){
 key=1;
 break;
 }
 else
 key=0;
 }
 if(key==1)
 cout<<"\n "<<++num<<"\t|\t"<<check<<"\t\t|\t"<<"Keyword";
 if(key==0)
 cout<<"\n "<<++num<<"\t|\t"<<check<<"\t\t|\t"<<"Identifier";
 }
int main()
{
 start:
 num=0;
 len=0;
 char check[30], operators[] = "+-*/%=";
 string input, line,str;
 int choice,i,j=0,x=0;
 ifstream fin;
 cout<<"Choose the way you want to enter the code:"<<endl;
 cout<<"1. Enter the code on output screen"<<endl;;
 cout<<"2. Using notepad file"<<endl;
 cout<<"3. Exit"<<endl;
 cout<<"Enter your option: ";
 cin>>choice;
 switch(choice)
 {
 case 1:
 {
 cout<<"Enter input:\n";
 do
 {
 getline(cin,line);
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 34
Compiler design Practical (CS-654)                                             C020328
 input += line;
 }while(line != " ");
 len= input.length();
 for(int p=0;p<len;p++)
 inp[p]=input[p];
 break;
 }
 case 2:
 {
 fin.open("code.txt");
 if(!fin.is_open()){
 cout<<"\nError while opening the file\n";
 exit(0);
 }
 getline(fin, str);
while (fin){
input += str;
getline(fin, str);
}
len = input.length();
 for(int p=0;p<len;p++)
 inp[p]=input[p];
 break; }
 case 3:
 {
 exit(0);
 break; }
 default:
 cout<<"Enter valid option";
 }
 cout<<"\nS.No. |\tLexeme\t\t|\tToken\n";
 cout<<"________|_______________________|_________________________";
 while(x!=len){
 for(i = 0; i < 6; ++i){
 if(inp[x] == operators[i])
 cout<<"\n "<<++num<<"\t|\t"<<inp[x]<<"\t\t|\t"<<"Operator";
 }
 if(inp[x]==';')
 cout<<"\n "<<++num<<"\t|\t"<<inp[x]<<"\t\t|\t"<<"Punctuation Marks";
 if(inp[x]=='#'){
 cout<<"\n "<<++num<<"\t| ";
 while(inp[x]!='>'){
 cout<<inp[x];
 x++;
 }
 cout<<inp[x]<<"\t|\t"<<"Header file";
 }
 if(isdigit(inp[x])){
 cout<<"\n "<<++num<<"\t|\t";
 while(isdigit(inp[x])){
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 35
Compiler design Practical (CS-654)                                             C020328
 cout<<inp[x];
 x++;
 }
 cout<<inp[x]<<"\t\t|\t"<<"Constant";
 }
 if(isalnum(inp[x]) || inp[x]=='_'){
 check[j++] = inp[x];
 }
 if((inp[x]==' ' || inp[x]=='\n') && (j!=0)){
 check[j] = '\0';
 j=0;
 keyword(check);
 }
 x++;
 }
 cout<<"\n\n";
 fin.close();
 goto start;
 return 0;
}
4.8. Output:
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 36
Compiler design Practical (CS-654)                                             C020328
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 37
Compiler design Practical (CS-654)                                                          C020328
4.9. Discussion
This experiment teaches us how to design a lexical analyser for some hypothetical language
which tokenizes the input code given to it. The input can be a code through console window
or a file. Also various tokens for the hypothetical language are mentioned in the code of the
analyser. The program breaks each input line and matches it against the listed token, which
are: keywords, tokens, strings, constants, header files, separator. The output is a table
consisting of the lexeme and its token category.
2. What is a token?
Ans. It is a sequence of characters that can be treated as a unit in the grammar of the
programming languages.
4. The output of lexical analysis phase is further fed to which phase of compiler?
Ans. Syntax and semantic analyzer.
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 38
Compiler design Practical (CS-654)                                                        C020328
                                      Practical - 5
5.1. Aim
Write a program to implement bottom-up parsing using:
                           A) shift-reduce parser
                           B) Operator precedence parser
5.2.1. Input
•   Set of production rules
•   String to be parsed
5.2.3. Method
Basically, a program is designed which can demonstrate the process of bottom-up parsing.
Bottom-up parsing starts from the leaf nodes of a tree and works in upward direction till it
reaches the root node.
Here, we start from a sentence and then apply production rules in reverse manner in order
to reach the start symbol. The input to the code will be a grammar and input string which
has to be parsed. The output will be the stack implementation of parsing of the input string.
For every step, the table consists of the current stack, current input and the action performed
correspondingly. And then the final step will determine as to whether or not the string is
accepted by the grammar or not and the same is displayed.
5.2.4. Algorithm
1. Start
2. Store the production rules of grammar in a construct.
3. Enter the input string to be checked.
4. Calculate its length and store first element in stack.
5. Do steps 6-12 until the length of stack !=1 && stacktop == input length.
6. Print the current stack elements and current input string.
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 39
Compiler design Practical (CS-654)                                             C020328
5.2.5. Flowchart
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 40
Compiler design Practical (CS-654)                                                    C020328
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
struct grammer{
char p[20];
char prod[20];
}g[10];
int main()
{
int i,stpos,j,k,l,m,o,p,f,r;
int np,tspos,cr;
cout<<"\n--------------------------------BOTTOM UP PARSING---------------------------------";
cout<<"\nEnter total no. of productions in your grammer: ";
cin>>np;
char sc,ts[10];
cout<<"\nEnter the set of productions:\n";
for(i=0;i<np;i++)
{
cin>>ts;
strncpy(g[i].p,ts,1);
strcpy(g[i].prod,&ts[3]);
}
char ip[10];
cout<<"\nEnter input string:";
 cin>>ip;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 41
Compiler design Practical (CS-654)                                             C020328
int lip=strlen(ip);
char stack[10];
stpos=0;
i=0;
//moving input
sc=ip[i];
stack[stpos]=sc;
i++;stpos++;
cout<<"\n\n|Stack|\t|Input|\t|Action|";
do
{
r=1;
while(r!=0)
{
cout<<"\n";
for(p=0;p<stpos;p++)
{
cout<<stack[p];
}
cout<<"\t";
for(p=i;p<lip;p++)
{
cout<<ip[p];
}
if(r==2)
{
cout<<"\tReduced";
}
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 42
Compiler design Practical (CS-654)                                             C020328
else
{
cout<<"\tShifted";
}
r=0;
//try reducing
for(k=0;k<stpos;k++)
{
f=0;
for(l=0;l<10;l++)
{
ts[l]='\0';
}
tspos=0;
for(l=k;l<stpos;l++) //removing first char
{
ts[tspos]=stack[l];
tspos++;
}
//now compare each possibility with production
for(m=0;m<np;m++)
{
cr = strcmp(ts,g[m].prod);
//if cr is zero then match is found
if(cr==0)
{
for(l=k;l<10;l++) //removing matched part from stack
{
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 43
Compiler design Practical (CS-654)                                             C020328
stack[l]='\0';
stpos--;
}
stpos=k;
//concatenate the string
strcat(stack,g[m].p);
stpos++;
r=2;
}
}
}
}
//moving input
sc=ip[i];
stack[stpos]=sc;
i++;stpos++;
}while(strlen(stack)!=1 && stpos!=lip);
if(strlen(stack)==1)
{
cout<<"\n \nString Accepted";
}
else
cout<<"\n \nString Rejected";
return 0;
}
5.2.7. Output:
1. Accepting a String:
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 44
Compiler design Practical (CS-654)                                             C020328
2. Rejecting a string
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 45
Compiler design Practical (CS-654)                                                      C020328
5.2.8. Discussion
In this program a bottom-up parser is designed in which takes a grammar’s production rules
as input and a corresponding string that we want to parse through the parser. As an output,
a table is generated which displays all the steps involved in the process of parsing like the
current stack elements, remaining input and the action being performed. After the complete
parsing, it displays whether the string can be accepted or not based on the stack size.
Q3. A grammar that produces more than one parse tree for some sentence is called?
Answer – Ambiguous grammar has more than one parse tree.
2. Grammar
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 46
Compiler design Practical (CS-654)                                                        C020328
2. Stack implementation
5.3.3. Method:
5.3.3.1. Bottom-up Parsing.
This parser compresses the non-terminals where it starts and moves backward to the starting
symbol of the parse tree using grammar productions to draw the input string's parse tree.
         •    In this technique, parsing starts from the leaf node of the parse tree to the start
              symbol of the parse tree in a bottom-up manner.
         •    Bottom-up parsing attempts to construct a parse tree by reducing input string and
              using Right Most Derivation.
         •    Bottom-up parsing starts with the input symbol and constructs the parse tree up
              to the start symbol using a production rule to reduce the string to get the starting
              symbol.
In operator, precedence parsing, the shift and reduce operations are done based on the priority
between the symbol at the top of the stack and the current input symbol.
Note:
    • Shift operation- This operation involves moving the current symbol from the input
       buffer onto the stack.
    • Reduce operation- When the parser knows the right hand of the handle is at the top of
       the stack, the reduce operation applies the applicable production rules, i.e., pops out
       the RHS of the production rule from the stack and pushes the LHS of the production
       rule onto the stack.
The operator precedence parser performs the operator precedence parsing using operator
grammar.
5.3.4. Algorithm
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 47
Compiler design Practical (CS-654)                                                           C020328
        1. Take a stack, put the $ symbol into it, and put the input string into the input buffer with
            the $ symbol at its end.
        2. Check whether the given grammar is operator grammar or not. If not, convert it to
            operator grammar.
        3. Draw the operator precedence relation table.
        4. From the operator precedence relations discussed above, we will draw a table
            containing the precedence relations of all the terminals present in our grammar.
        5. Parse the input string.
        6. Let “a” be the symbol at the top of the stack, and “b” be the current input symbol.
        7. If a ⋖ b or a ≐ b, perform the shift operation by pushing “b” onto the stack.
        8. Else if a ⋗ b, perform the reduce operation by popping the symbols out from the stack
            until the top of the stack symbol has lower precedence than the current input symbol.
        9. Repeat step 4. If the stack and the input buffer contain only the $ symbol, then accept
            the string; else, call an error-handling routine.
        10. If the string is accepted, generate the parse tree.
        5.3.5. Source code
#include<iostream>
#include<string>
#include<deque>
using namespace std;
int n,n1,n2;
int getPosition(string arr[], string q, int size)
{
    for(int i=0;i<size;i++)
    {
         if(q == arr[i])
           return i;
    }
    return -1;
}
int main()
{
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 48
Compiler design Practical (CS-654)                                             C020328
  string prods[10],leads[10],trails[10],nonterms[10],terms[10];
  char op_table[20][20] = {};
  cout<<"Enter the number of productions : ";
  cin>>n;
  cin.ignore();
  cout<<"Enter the productions"<<endl;
  for(int i=0;i<n;i++)
  {
      getline(cin,prods[i]);
  }
  cout<<"Enter the number of Terminals : ";
  cin>>n2;
  cin.ignore();
  cout<<"Enter the Terminals"<<endl;
  for(int i=0;i<n2;i++)
  {
      cin>>terms[i];
  }
  terms[n2] = "$";
  n2++;
  cout<<"Enter the number of Non-Terminals : ";
  cin>>n1;
  cin.ignore();
  for(int i=0;i<n1;i++)
  {
      cout<<"Enter Non-Terminal : ";
      getline(cin,nonterms[i]);
      cout<<"Enter Leads of "<<nonterms[i]<<" : ";
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 49
Compiler design Practical (CS-654)                                             C020328
       getline(cin,leads[i]);
       cout<<"Enter Trails of "<<nonterms[i]<<" : ";
       getline(cin,trails[i]);
  }
      cout<<"Enter the Rules (exit to stop)"<<endl;
  cout<<endl;
  for(int i=0;i<n2;i++)
  {
      cout<<terms[i]<<"\t";
      for(int j=0;j<n2;j++)
      {
          cout<<op_table[i][j]<<"\t";
      }
      cout<<endl;
  }
  //Parsing String
  char c;
  do{
  string ip;
  deque<string> op_stack;
  op_stack.push_back("$");
  cout<<"Enter the string to be parsed : ";
  getline(cin,ip);
  ip.push_back('$');
  cout<<"Stack\ti/p Buffer\tRelation\tAction"<<endl;
  while(true)
  {
      for(int i=0;i<op_stack.size();i++)
          cout<<op_stack[i];
      cout<<"\t";
      cout<<ip<<"\t";
      int row = getPosition(terms,op_stack.back(),n2);
      int column = getPosition(terms,ip.substr(0,1),n2);
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 52
Compiler design Practical (CS-654)                                             C020328
     if(op_table[row][column] == '<')
     {
         op_stack.push_back("<");
         op_stack.push_back(ip.substr(0,1));
         ip = ip.substr(1);
         cout<<"\t"<<"<\t\tPush";
     }
     else if(op_table[row][column] == '=')
     {
         op_stack.push_back("=");
         op_stack.push_back(ip.substr(0,1));
         ip = ip.substr(1);
         cout<<"\t"<<"=\t\tPush";
     }
     else if(op_table[row][column] == '>')
     {
         string last;
         do
         {
             op_stack.pop_back();
             last = op_stack.back();
             op_stack.pop_back();
         }while(last != "<");
         cout<<"\t"<<">\t\tPop";
     }
     else
     {
         if(ip[0] == '$' && op_stack.back() == "$")
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 53
Compiler design Practical (CS-654)                                             C020328
            {
                cout<<"\t\t\tAccept\nString Parsed."<<endl;
                break;
            }
            else
            {
                cout<<endl<<"String cannot be Parsed."<<endl;
                break;
            }
        }
        cout<<endl;
    }
    cout<<"Continue?(Y/N) ";
    cin>>c;
    cin.ignore();
    }while(c=='y' || c=='Y');
    return 0;
}
5.3.6. Output
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 54
Compiler design Practical (CS-654)                                             C020328
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 55
Compiler design Practical (CS-654)                                                             C020328
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 56
Compiler design Practical (CS-654)                                                      C020328
                                     Practical – 6
6.1. Aim
6.2. Input
   •   Set of non-terminals
   •   Set of terminals
   •   Set of production rules
6.4. Method
This practical aims at constructing an SLR parser. Simple LR parser is one of the three types
of bottom-up parsers. The first L in LR refers to scanning the tokens from left to right and R
defines the use of rightmost derivation in reverse. In this practical, I constructed an SLR
parser using C++ programming language. For this we first need to find the canonical item
sets for the entered context-free grammar.
Next in SLR parsing table has two parts i.e. one is ACTION and other is GoTO An Action
table that gives a grammar rule to apply, given the current state and the current terminal
symbol in the input stream; a Goto table that prescribes to which new state it should move.
After that decision is taken which action mong SHIFT REDUCE and ACCEPT has to be
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 57
Compiler design Practical (CS-654)                                                    C020328
taken based upon the canonical item sets formed. The program outputs the parsing table with
the corresponding actions taken.
6.5. Algorithm
1. Begin
2. Call get_prods function to get user input of set of terminals, non-terminals and
production rules.
6. Print I0.
11. Compute reduce table by computing follow of all terminals in left hand side of
productions in 10.
13. End
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 58
Compiler design Practical (CS-654)                                             C020328
6.6. Flowchart
 int prod_count;
 char prod[100][100]={{}};
};
void add_dots(struct state *I)//augumented grammar
{
 for(int i=0;i<I->prod_count;i++){
 for (int j=99;j>3;j--)
 I->prod[i][j] = I->prod[i][j-1];
 I->prod[i][3]='.';
 }
}
void augument(struct state *S,struct state *I){
 if(I->prod[0][0]=='S')
 strcpy(S->prod[0],"Z->.S");
 else{
 strcpy(S->prod[0],"S->.");
 S->prod[0][4]=I->prod[0][0];}
 S->prod_count++;
}
void get_prods(struct state *I)//user input
{
 cout<<"SLR PARSING TABLE"<<endl;
 cout<<endl<<"Directions: \n 1. Terminals must be single lettered. \n 2. Each production rule must
contain only 1 rule.\n 3. The format of the prodcution rule is: S->ABc"<<endl;
 cout<<endl<<"Enter total no. of productions: ";
 cin>>I->prod_count;
 cout<<endl<<"Enter no. of non terminals: ";
 cin>>no_nt;
 cout<<endl<<"Enter non terminals: ";
 for(int i=0;i<no_nt;i++)
 cin>>non_terminals[i];
 cout<<endl<<"Enter no. of terminals: ";
 cin>>no_t;
 cout<<endl<<"Enter terminals: ";
 for(int i=0;i<no_t;i++)
 cin>>terminals[i];
 cout<<endl<<"Enter the production rules: ";
 for(int i=0;i<I->prod_count;i++){
 cin>>I->prod[i];
 cout<<endl;
 }
}
bool is_non_terminal(char a){
 if (a >= 'A' && a <= 'Z')
 return true;
 else
 return false;
}
bool in_state(struct state *I,char *a){
 for(int i=0;i<I->prod_count;i++){
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 60
Compiler design Practical (CS-654)                                             C020328
 if(!strcmp(I->prod[i],a))
 return true;
 }
 return false;
}
char char_after_dot(char a[100]){
 char b;
 for(int i=0;i<strlen(a);i++)
 if(a[i]=='.'){
 b=a[i+1];
 return b;}
}
char* move_dot(char b[100],int len){
 char a[100]={};
 strcpy(a,b);
 for(int i=0;i<len;i++){
 if(a[i]=='.'){
 swap(a[i],a[i+1]);
 break;
 }
 }
 return &a[0];
}
bool same_state(struct state *I0,struct state *I){
 if (I0->prod_count != I->prod_count)
 return false;
 for (int i=0; i<I0->prod_count; i++)
 {
 int flag = 0;
 for (int j=0; j<I->prod_count; j++)
 if (strcmp(I0->prod[i], I->prod[j]) == 0)
 flag = 1;
 if (flag == 0)
 return false;
 }
 return true;
}
void closure(struct state *I,struct state *I0){
 char a={};
 for(int i=0;i<I0->prod_count;i++){
 a=char_after_dot(I0->prod[i]);
 if(is_non_terminal(a)){
 for(int j=0;j<I->prod_count;j++){
 if(I->prod[j][0]==a){
 if(!in_state(I0,I->prod[j])){
 strcpy(I0->prod[I0->prod_count],I->prod[j]);
 I0->prod_count++;
 }
 }
 }
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 61
Compiler design Practical (CS-654)                                             C020328
 }
 }
}
void goto_state(struct state *I,struct state *S,char a){
 int time=1;
 for(int i=0;i<I->prod_count;i++){
 if(char_after_dot(I->prod[i])==a){
 if(time==1){
 time++;
 }
 strcpy(S->prod[S->prod_count],move_dot(I->prod[i],strlen(I->prod[i])));
 S->prod_count++;
 }
}
}
void print_prods(struct state *I){
 for(int i=0;i<I->prod_count;i++)
 printf("%s\n",I->prod[i]);
 cout<<endl;
}
bool in_array(char a[20],char b){
 for(int i=0;i<strlen(a);i++)
 if(a[i]==b)
 return true;
 return false;
}
char* chars_after_dots(struct state *I){
 char a[20]={};
 for(int i=0;i<I->prod_count;i++){
 if(!in_array(a,char_after_dot(I->prod[i]))){
 a[strlen(a)]=char_after_dot(I->prod[i]);
 }
 }
 return &a[0];
}
void cleanup_prods(struct state * I){
 char a[100]={};
 for(int i=0;i<I->prod_count;i++)
 strcpy(I->prod[i],a);
 I->prod_count=0;
}
int return_index(char a){
 for(int i=0;i<no_t;i++)
 if(terminals[i]==a)
 return i;
 for(int i=0;i<no_nt;i++)
 if(non_terminals[i]==a)
 return no_t+i;
}
void print_shift_table(int state_count){
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 62
Compiler design Practical (CS-654)                                             C020328
 cout<<endl<<"SHIFT ACTIONS"<<endl<<endl;
 cout<<"\t";
 for(int i=0;i<no_t;i++)
 cout<<terminals[i]<<"\t";
 for(int i=0;i<no_nt;i++)
 cout<<non_terminals[i]<<"\t";
 cout<<endl;
 for(int i=0;i<state_count;i++){
 int arr[no_nt+no_t]={-1};
 for(int j=0;j<state_count;j++){
 if(goto_table[i][j]!='~'){
 arr[return_index(goto_table[i][j])]= j;
 }
 }
 cout<<"I"<<i<<"\t";
 for(int j=0;j<no_nt+no_t;j++){
 if(i==1&&j==no_t-1)
 cout<<"ACC"<<"\t";
 if(arr[j]==-1||arr[j]==0)
 cout<<"\t";
 else{
 if(j<no_t)
 cout<<"S"<<arr[j]<<"\t";
 else
 cout<<arr[j]<<"\t";
 }
 }
 cout<<"\n";
 }
}
int get_index(char c,char *a){
for(int i=0;i<strlen(a);i++)
 if(a[i]==c)
 return i;
}
void add_dot_at_end(struct state* I){
 for(int i=0;i<I->prod_count;i++){
 strcat(I->prod[i],".");
 }
}
void add_to_first(int n,char b){
 for(int i=0;i<strlen(first[n]);i++)
 if(first[n][i]==b)
 return;
 first[n][strlen(first[n])]=b;
}
void add_to_first(int m,int n){
 for(int i=0;i<strlen(first[n]);i++){
 int flag=0;
 for(int j=0;j<strlen(first[m]);j++){
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 63
Compiler design Practical (CS-654)                                             C020328
 if(first[n][i]==first[m][j])
 flag=1;
 }
 if(flag==0)
 add_to_first(m,first[n][i]);
 }
}
void add_to_follow(int n,char b){
 for(int i=0;i<strlen(follow[n]);i++)
 if(follow[n][i]==b)
 return;
 follow[n][strlen(follow[n])]=b;
}
void add_to_follow(int m,int n){
 for(int i=0;i<strlen(follow[n]);i++){
 int flag=0;
 for(int j=0;j<strlen(follow[m]);j++){
 if(follow[n][i]==follow[m][j])
 flag=1;
 }
 if(flag==0)
 add_to_follow(m,follow[n][i]);
 }
}
void add_to_follow_first(int m,int n){
 for(int i=0;i<strlen(first[n]);i++){
 int flag=0;
 for(int j=0;j<strlen(follow[m]);j++){
 if(first[n][i]==follow[m][j])
 flag=1;
 }
 if(flag==0)
 add_to_follow(m,first[n][i]);
 }
}
void find_first(struct state *I){
 for(int i=0;i<no_nt;i++){
 for(int j=0;j<I->prod_count;j++){
 if(I->prod[j][0]==non_terminals[i]){
 if(!is_non_terminal(I->prod[j][3])){
 add_to_first(i,I->prod[j][3]);
 }
 }
 }
 }
}
void find_follow(struct state *I){
 for(int i=0;i<no_nt;i++){
 for(int j=0;j<I->prod_count;j++){
 for(int k=3;k<strlen(I->prod[j]);k++){
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 64
Compiler design Practical (CS-654)                                             C020328
 if(I->prod[j][k]==non_terminals[i]){
 if(I->prod[j][k+1]!='\0'){
 if(!is_non_terminal(I->prod[j][k+1])){
 add_to_follow(i,I->prod[j][k+1]);
 }
 }
 }
 }
 }
 }
}
int get_index(int *arr,int n){
 for(int i=0;i<no_t;i++){
 if(arr[i]==n)
 return i;
 }
 return -1;
}
void print_reduce_table(int state_count,int *no_re,struct state *temp1){
 cout<<"REDUCE ACTIONS"<<endl<<endl;
 cout<<"\t";
 int arr[temp1->prod_count][no_t]={-1};
 for(int i=0;i<no_t;i++){
 cout<<terminals[i]<<"\t";
 }
 cout<<endl;
 for(int i=0;i<temp1->prod_count;i++){
 int n=no_re[i];
 for(int j=0;j<strlen(follow[return_index(temp1->prod[i][0])-no_t]);j++){
 for(int k=0;k<no_t;k++){
 if(follow[return_index(temp1->prod[i][0])-no_t][j]==terminals[k])
 arr[i][k]=i+1;
 }
 }
 cout<<"I"<<n<<"\t";
 for(int j=0;j<no_t;j++){
 if(arr[i][j]!=-1&&arr[i][j]!=0&&arr[i][j]<state_count)
 cout<<"R"<<arr[i][j]<<"\t";
 else
 cout<<"\t";
 }
 cout<<endl;
}
}
int main(){
 struct state init;
 struct state temp;struct state temp1;
 int state_count=1;
 get_prods(&init);
 temp=init;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 65
Compiler design Practical (CS-654)                                                      C020328
temp1=temp;
add_dots(&init);
for(int i=0;i<100;i++)
for(int j=0;j<100;j++)
goto_table[i][j]='~';
struct state I[50];
augument(&I[0],&init);
closure(&init,&I[0]);
cout<<"\nI0:\n";
print_prods(&I[0]);
char characters[20]={};
for(int i=0;i<state_count;i++){
char characters[20]={};
for(int z=0;z<I[i].prod_count;z++)
if(!in_array(characters,char_after_dot(I[i].prod[z])))
characters[strlen(characters)]=char_after_dot(I[i].prod[z]);
for(int j=0;j<strlen(characters);j++){
goto_state(&I[i],&I[state_count],characters[j]);
closure(&init,&I[state_count]);
int flag=0;
for(int k=0;k<state_count-1;k++){
if(same_state(&I[k],&I[state_count])){
cleanup_prods(&I[state_count]);flag=1;
cout<<"I"<<i<<" on reading the symbol "<<characters[j]<<" goes to I"<<k<<".\n";
goto_table[i][k]=characters[j];;
break;
}
}
if(flag==0){
state_count++;
cout<<"I"<<i<<" on reading the symbol "<<characters[j]<<" goes to I"<<state_count-1<<":\n";
goto_table[i][state_count-1]=characters[j];
print_prods(&I[state_count-1]);
}
}
}
int no_re[temp.prod_count]={-1};
terminals[no_t]='$';no_t++;
add_dot_at_end(&temp1);
for(int i=0;i<state_count;i++){
for(int j=0;j<I[i].prod_count;j++)
for(int k=0;k<temp1.prod_count;k++)
if(in_state(&I[i],temp1.prod[k]))
no_re[k]=i;
}
find_first(&temp);
for(int l=0;l<no_nt;l++){
for(int i=0;i<temp.prod_count;i++){
if(is_non_terminal(temp.prod[i][3])){
add_to_first(return_index(temp.prod[i][0])-
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 66
Compiler design Practical (CS-654)                                                    C020328
no_t,return_index(temp.prod[i][3])-no_t);
 }
 }}
 find_follow(&temp);
 add_to_follow(0,'$');
 for(int l=0;l<no_nt;l++){
 for(int i=0;i<temp.prod_count;i++){
 for(int k=3;k<strlen(temp.prod[i]);k++){
 if(temp.prod[i][k]==non_terminals[l]){
 if(is_non_terminal(temp.prod[i][k+1])){
 add_to_follow_first(l,return_index(temp.prod[i][k+1])-no_t);}
 if(temp.prod[i][k+1]=='\0')
 add_to_follow(l,return_index(temp.prod[i][0])-no_t);
 }
 }
 }
 }
 print_shift_table(state_count);
 cout<<endl<<endl;
 print_reduce_table(state_count,&no_re[0],&temp1);
cout<<"The above two tables combined generate the SLR Parsing Table \n";
 cout<<"*For error entries->cells where both shift and reduce actions are present";
}
6.8. Output:
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 67
Compiler design Practical (CS-654)                                             C020328
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 68
Compiler design Practical (CS-654)                                             C020328
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 69
Compiler design Practical (CS-654)                                                     C020328
6.9. Discussion
In this program we learnt one of the form of bottom up parsers. This is known as simple LR
parser. After learning the way of constructing SLR parser we implemented it in C++
programming language. For this we first need to find the canonical item sets for the entered
context free grammar. Next in SLR parsing table has two parts ie.e one is ACTION and other
is GoTO An Action table that gives a grammar rule to apply, given the current state and the
current terminal symbol in the input stream; a Goto table that prescribes to which new state it
should move. After that decision is taken which action mong SHIFT REDUCE and ACCEPT
has to be taken based upon the canonical itemsets formed. And finally the program outputs
the parsing table with the corresponding actions taken.
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 70
Compiler design Practical (CS-654)                                                   C020328
                                     Practical – 7
7.1. Aim
7.2. Input
   •   Set of non-terminals
   •   Set of terminals
   •   Set of production rules
   •   The augmented grammar of the original grammar with all the canonical collection of
       LR(1) items and then the CLR parsing table.
7.4. Method
This program implements a CLR parser. CLR stand for canonical LR parser. It is also called
LR(1) parser. A CLR parser is similar to LR(0) parser, the only difference being that items of
an itemset contains a follow as well. CLR parser generates more number of states as compared
to SLR parser. CLR parser works in the following way :
a) Make augmented grammar
 b) Create itemsets
c) Generate CLR parsing table
In our program, production rules(such that only one rule is present), terminals and non-
terminals are set of inputs given by user. Output is the parsing table with SHIFT, REDUCE,
ERROR and ACCEPT actions, and it shows the stack implementation with the result that
whether string is accepted by parser or not.
7.5. Algorithm
3. The next step is to write the augmented grammar of the given grammar.
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 71
Compiler design Practical (CS-654)                                                     C020328
4. Now find the collection of LR(1) items using the closure and the goto.
5. To find the first item set find the closure of the first production rule of the augmented
grammar.
7. Check the dot symbol in each production rule and apply goto to the next symbol after it.
8. There is also a look ahead symbol which have to be taken cared of after the comma.
9. The rules which are derived from any other rule, there look ahead symbol depends on the
previous rule
and is calculated with the help of FIRST(c,terminal) where c can be a terminal or a non terminal
in the rule
A.Bc,terminal.
11. If the itemset formed has the dot after all the symbols ,then that itemset is reduced. Else
follow the same
13. Now construct the CLR parsing table which consists of the shift and the reduce operations.
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 72
Compiler design Practical (CS-654)                                                         C020328
6.6. Flowchart
void calc_first(int k)
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 73
Compiler design Practical (CS-654)                                             C020328
{
    int j, flag = 0, len, l, m, i;
    if (hash1[k])
       return;
    hash1[k] = 1;
    for (i = 0; i < no_of_prod; i++)
    {
       if (prod[i][0] == non_term[k])
       {
           flag = 0;
           len = strlen(prod[i]);
           for (j = 3; j < len; j++)
           {
              if (!flag)
              {
                 if (prod[i][j] >= 'A' && prod[i][j] <= 'Z')
                 {
                     for (l = 0; l < non_term_len; l++)
                     {
                        if (non_term[l] == prod[i][j])
                           break;
                     }
                     flag = 1;
                     if (hash1[l])
                     {
                        for (m = 0; m < term_len; m++)
                        {
                           if (first[l][m])
                           {
                              first[k][m] = 1;
                              if (term[m] == '^')
                                  flag = 0;
                           }
                        }
                     }
                     else
                     {
                        calc_first(l);
                        for (m = 0; m < term_len; m++)
                        {
                           if (first[l][m])
                           {
                              first[k][m] = 1;
                              if (term[m] == '^')
                                  flag = 0;
                           }
                        }
                     }
                 }
                 else if (prod[i][j] != '|')
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 74
Compiler design Practical (CS-654)                                             C020328
               {
                   for (l = 0; l < term_len; l++)
                   {
                      if (term[l] == prod[i][j])
                         break;
                   }
                   first[k][l] = 1;
                   flag = 1;
                }
             }
             else
             {
                if (prod[i][j] == '|')
                   flag = 0;
             }
         }
     }
  }
}
void print(int in)
{
  int i, j, len, k, l, prnt;
  printf("I%d:\n", in);
  for (i = 0; i < 10; i++)
  {
     prnt = 0;
     for (k = 0; k < term_len; k++)
     {
         if (canonical[in][no_of_prod - 1][i][k])
         {
             if (!prnt)
             {
                len = strlen(prod[no_of_prod - 1]);
                for (j = 0; j <= len; j++)
                {
                   if (j == i)
                      printf(".");
                   printf("%c", prod[no_of_prod - 1][j]);
                }
                printf(",%c", term[k]);
                prnt = 1;
             }
             else
                printf("|%c", term[k]);
         }
     }
     if (prnt)
         puts("");
  }
  for (l = 0; l < no_of_prod - 1; l++)
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 75
Compiler design Practical (CS-654)                                             C020328
  {
      for (i = 0; i < 10; i++)
      {
         prnt = 0;
         for (k = 0; k < term_len; k++)
         {
            if (canonical[in][l][i][k])
            {
               if (!prnt)
               {
                  len = strlen(prod[l]);
                  for (j = 0; j <= len; j++)
                  {
                     if (j == i)
                        printf(".");
                     printf("%c", prod[l][j]);
                  }
                  printf(",%c", term[k]);
                  prnt = 1;
               }
               else
                  printf("|%c", term[k]);
            }
         }
        if (prnt)
            puts("");
      }
  }
}
void Frst(char *str, int *arr)
{
  int j, flag = 0, len, l, m, i, k;
  len = strlen(str);
  for (j = 0; j < len; j++)
  {
     if (!flag)
     {
         if (str[j] >= 'A' && str[j] <= 'Z')
         {
            for (l = 0; l < non_term_len; l++)
            {
               if (non_term[l] == str[j])
                   break;
            }
            flag = 1;
            for (m = 0; m < term_len; m++)
            {
               if (first[l][m])
               {
                   arr[m] = 1;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 76
Compiler design Practical (CS-654)                                             C020328
                   if (term[m] == '^')
                      flag = 0;
               }
           }
        }
        else if (str[j] != '|')
        {
           for (l = 0; l < term_len; l++)
           {
              if (term[l] == str[j])
                 break;
           }
           arr[l] = 1;
           flag = 1;
        }
      }
      else
         break;
  }
}
void closure(int arr[][10][10])
{
  int i, j, flag = 1, k, l, m, arr1[10], n;
  char c, str[100];
  while (flag)
  {
     flag = 0;
     for (i = 0; i < no_of_prod; i++)
     {
         for (k = 0; k < 10; k++)
         {
            for (n = 0; n < 10; n++)
            {
               if (arr[i][k][n])
               {
                  c = prod[i][k];
                  for (j = 0; j < no_of_prod; j++)
                  {
                     if (prod[j][0] == c)
                     {
                        for (m = 0; m < 10; m++)
                           arr1[m] = 0;
                        for (m = k + 1; prod[i][m] != '\0'; m++)
                        {
                           str[m - k - 1] = prod[i][m];
                        }
                        str[m - k - 1] = term[n];
                        str[m - k] = '\0';
                        Frst(str, arr1);
                        for (m = 0; m < term_len; m++)
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 77
Compiler design Practical (CS-654)                                             C020328
                             {
                                 if (arr1[m] && !arr[j][3][m])
                                 {
                                    flag = 1;
                                    arr[j][3][m] = 1;
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
   }
}
int Goto(int in, int sym, int nt)
{
   int j, ans = 0, arr[100][10][10] = {0}, flg = 0, k, l, len, i, m;
   char c;
   for (i = 0; i < no_of_prod; i++)
   {
      for (j = 0; j < 10; j++)
      {
          for (k = 0; k < term_len; k++)
          {
             if (canonical[in][i][j][k])
             {
                if (nt)
                {
                   if (prod[i][j] == non_term[sym])
                   {
                      arr[i][j + 1][k] = 1;
                      flg = 1;
                   }
                }
                else if (prod[i][j] == term[sym])
                {
                   arr[i][j + 1][k] = 1;
                   flg = 1;
                }
             }
          }
      }
   }
   if (!flg)
      return 0;
   closure(arr);
   for (j = 0; j < can_len; j++)
   {
      flg = 0;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 78
Compiler design Practical (CS-654)                                             C020328
  {
      scanf("%s", &prod[i]);
      len = strlen(prod[i]);
      for (j = 0; j < len; j++)
      {
         if (prod[i][j] >= 'A' && prod[i][j] <= 'Z')
         {
            for (k = 0; k < non_term_len; k++)
            {
               if (non_term[k] == prod[i][j])
                  break;
            }
            if (k == non_term_len)
            {
               non_term[non_term_len] = prod[i][j];
               non_term_len++;
            }
         }
         else if (prod[i][j] != '-' && prod[i][j] != '>' && prod[i][j] != '|')
         {
            for (k = 0; k < term_len; k++)
            {
               if (term[k] == prod[i][j])
                  break;
            }
            if (k == term_len)
            {
               term[term_len] = prod[i][j];
               term_len++;
            }
         }
      }
  }
  printf("\nNon terminals are:\n");
  printf("%c", non_term[0]);
  for (i = 1; i < non_term_len; i++)
  {
     printf(",%c", non_term[i]);
  }
  puts("");
  printf("\nTerminals are:\n");
  printf("%c", term[0]);
  for (i = 1; i < term_len; i++)
  {
     printf(",%c", term[i]);
  }
  puts("");
  printf("\nFirst\n");
  for (i = 0; i < non_term_len; i++)
  {
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 81
Compiler design Practical (CS-654)                                                   C020328
    calc_first(i);
    printf("%c = { ", non_term[i]);
    for (j = 0; j < term_len; j++)
    {
       if (first[i][j])
           break;
    }
    if (j < term_len)
    {
       printf("%c", term[j]);
       j++;
       for (; j < term_len; j++)
       {
          if (first[i][j])
              printf(" ,%c", term[j]);
       }
    }
    printf(" }\n");
  }
  term[term_len] = '$';
  term_len++;
  for (i = 0; i < 100; i++)
  {
     for (j = 0; j < 100; j++)
     {
        sprintf(action[i][j], "\0");
        go_to[i][j] = -1;
     }
  }
  sprintf(prod[no_of_prod], "X->%c\0", prod[0][0]); // Added new initial symbol...
  no_of_prod++;
  puts("\nCanonical LR(1) collection of sets for grammar");
  canonical[0][no_of_prod - 1][3][term_len - 1] = 1;
  closure(canonical[0]);
  can_len++;
  puts("");
  print(0);
  flag = 1;
  while (flag)
  {
     flag = 0;
     for (i = 0; i < can_len; i++)
     {
        for (j = 0; j < non_term_len; j++)
        {
           if (Goto(i, j, 1))
           {
              printf("\nGOTO(I%d, %c) ", i, non_term[j]);
              print(can_len - 1);
              flag = 1;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 82
Compiler design Practical (CS-654)                                             C020328
          }
       }
       for (j = 0; j < term_len - 1; j++)
       {
         if (Goto(i, j, 0))
          {
             printf("\nGOTO(I%d, %c) ", i, term[j]);
             print(can_len - 1);
             flag = 1;
          }
       }
     }
  }
  if (clr)
  {
     printf("\nCLR Parsing Table\n\n");
     printf("State\t|\t\tAction");
     for (i = 0; i < term_len - 2; i++)
        printf("\t");
     printf("|\tGoTo\n");
     printf("------------------------------------------------\n\t|");
     for (i = 0; i < term_len; i++)
     {
        printf("%c\t", term[i]);
     }
     printf("|");
     for (i = 0; i < non_term_len; i++)
     {
        printf("%c\t", non_term[i]);
     }
     puts("\n------------------------------------------------");
     for (i = 0; i < can_len; i++)
     {
        printf("%d\t|", i);
        for (j = 0; j < term_len; j++)
        {
           printf("%s\t", action[i][j]);
        }
        printf("|");
        for (j = 0; j < non_term_len; j++)
        {
           if (go_to[i][j] != -1)
              printf("%d", go_to[i][j]);
           printf("\t");
        }
        puts("");
     }
     puts("\nThe Grammar is CLR(1)");
  }
  else
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 83
Compiler design Practical (CS-654)                                             C020328
    {
       puts("\nThe Grammar is not CLR(1)");
    }
    return 0;
}
7.8. Output:
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 84
Compiler design Practical (CS-654)                                                      C020328
Q4. Which is the most powerful parser among SLR, CLR and LALR?
Answer- CLR parser.
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 85
Compiler design Practical (CS-654)                                                       C020328
                                     Practical – 8
8.1. Aim
8.2. Input
The augmented grammar of the original grammar with all the canonical collection of LALR
(1) items and then the LALR parsing table.
8.4. Method
This program implements a LALR parser. LALR stand for lookahead LR parser. A LALR
parser is similar to CLR parser, we use the canonical collection of CLR parser, the only
difference being that if two states differ only in lookahead, then these two states are combined
together in LALR parser.
In our program, set of production rules(such that only one rule is present) is the input, Output
is the parsing table with SHIFT, REDUCE, ERROR and ACCEPT actions, and it shows the
stack implementation with the result that whether string is accepted by parser or not.
8.5. Algorithm
3. The next step is to write the augmented grammar of the given grammar.
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 86
Compiler design Practical (CS-654)                                                     C020328
4. Now find the collection of LR(1) items using the closure and the goto.
5. To find the first item set find the closure of the first production rule of the augmented
grammar.
7. Check the dot symbol in each production rule and apply goto to the next symbol after it.
8. There is also a look ahead symbol which have to be taken cared of after the comma.
9. The rules which are derived from any other rule, there look ahead symbol depends on the
previous rule
and is calculated with the help of FIRST(c,terminal) where c can be a terminal or a non terminal
in the rule
A.Bc,terminal.
10. Now find the closure of the next symbol after the dot.
12. If the itemset formed has the dot after all the symbols ,then that itemset is reduced. Else
follow the same
13. Now the itemsets which are common on the LHS side but different on the RHS side, make
them a single
itemset.
14. After performing the previous step, LR(1) items are converted into LALR(1) items.
15. Now construct the LALR parsing table which consists of the shift and the reduce operations.
-------------------------------------------------------------------------------------
Department of computer science and engineering                                          pg. 87
Compiler design Practical (CS-654)                                             C020328
8.6. Flowchart
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 88
Compiler design Practical (CS-654)                                                              C020328
struct action
{
   char row[6][5];
};
const struct action A[12] = {
   {"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"},
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 89
Compiler design Practical (CS-654)                                                C020328
       }
       else
       {
          if (temp[0] == 'r')
          {
             j = isstate(temp[1]);
             strcpy(temp, rl[j - 2].right);
             dl[0] = rl[j - 2].left;
             dl[1] = '\0';
             n = strlen(temp);
             for (k = 0; k < 2 * n; k++)
                pop(stack, &top);
             for (m = 0; dl[m] != '\0'; m++)
                push(stack, &top, dl[m]);
             l = top;
             y = stack[l - 1];
             isreduce(y, dl[0]);
             for (m = 0; temp[m] != '\0'; m++)
                push(stack, &top, temp[m]);
          }
       }
     }
     printt(stack, &top, inp, i);
  } while (inp[i] != '\0');
  if (strcmp(temp, "acc") == 0)
  {
     printf(" \n Input string is accepted\n ");
     printf(" \n Grammar is LALR(1)\n ");
  }
  else
     printf(" \n do not accept the input ");
  getch();
}
void push(char *s, int *sp, char item)
{
  if (*sp == 100)
     printf(" stack is full ");
  else
  {
     *sp = *sp + 1;
     s[*sp] = item;
  }
}
char stacktop(char *s)
{
  char i;
  i = s[top];
  return i;
}
void isproduct(char x, char p)
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 91
Compiler design Practical (CS-654)                                             C020328
{
    int k, l;
    k = ister(x);
    l = isstate(p);
    strcpy(temp, A[l - 1].row[k - 1]);
}
int ister(char x)
{
   int i;
   for (i = 0; i < 6; i++)
      if (x == ter[i])
          return i + 1;
   return 0;
}
int isnter(char x)
{
   int i;
   for (i = 0; i < 3; i++)
      if (x == nter[i])
          return i + 1;
   return 0;
}
int isstate(char p)
{
   int i;
   for (i = 0; i < 12; i++)
      if (p == states[i])
          return i + 1;
   return 0;
}
void error()
{
   printf(" error in the input ");
   exit(0);
}
void isreduce(char x, char p)
{
    int k, l;
    k = isstate(x);
    l = isnter(p);
    strcpy(temp, G[k - 1].r[l - 1]);
}
char pop(char *s, int *sp)
{
    char item;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 92
Compiler design Practical (CS-654)                                             C020328
    if (*sp == -1)
        printf(" stack is empty ");
    else
    {
        item = s[*sp];
        *sp = *sp - 1;
    }
    return item;
}
void printt(char *t, int *p, char inp[], int i)
{
    int r;
    printf("\n");
    for (r = 0; r <= *p; r++)
        rep(t, r);
    printf("\t\t\t");
    for (r = i; inp[r] != '\0'; r++)
        printf("%c", inp[r]);
}
void rep(char t[], int r)
{
    char c;
    c = t[r];
    switch (c)
    {
    case 'a':
        printf("0");
        break;
    case 'b':
        printf("1");
        break;
    case 'c':
        printf("2");
        break;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 93
Compiler design Practical (CS-654)                                             C020328
    case 'd':
        printf("3");
        break;
    case 'e':
        printf("4");
        break;
    case 'f':
        printf("5");
        break;
    case 'g':
        printf("6");
        break;
    case 'h':
        printf("7");
        break;
    case 'm':
        printf("8");
        break;
    case 'j':
        printf("9");
        break;
    case 'k':
        printf("10");
        break;
    case 'l':
        printf("11");
        break;
    default:
        printf("%c", t[r]);
        break;
    }
}
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 94
Compiler design Practical (CS-654)                                                      C020328
8.8. Output:
Q4. What are the two functions used in creating canonical collection of items in LR
parsers?
Answer- GOTO() and CLOSURE().
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 95
Compiler design Practical (CS-654)                                                    C020328
                                     Practical – 9
9.1. Aim
Write a program to implement top-down parser (LL(1)).
9.2. Input
Production rules of the grammar
String
9.4. Method
Bottom-up parsing begins at a tree's leaf nodes and moves up the tree until it reaches the root
node. Here, we begin with a sentence and use production rules backwards to get to the start
symbol.
             LR(1) – LR Parser:
                  o   Works on complete set of LR(1) Grammar
                  o   Generates large table and large number of states
                  o   Slow construction
9.5. Algorithm
                  1.Begin
                  2.Store the production rules of grammar.
                  3.Input the string to be parsed.
                  4.Calculate its length and store first element in stack.
                  5.Do steps 6-12 while the length of stack !=1 && stacktop == input
                    length.
                6. Print the current stack elements and current input string.
                7. According to the action print Reduced or Shifted.
                8. If reduce is possible then goto 9 else goto 5
                9. Pop first element from stack.
                10. Compare with each production rule and if matched goto 11 else goto 5
                11. Pop matched part from stack.
                12. Push LHS of that rule in stack.
                13. If length(stack) == 1 then goto 14 else goto 15
-------------------------------------------------------------------------------------
Department of computer science and engineering                                       pg. 96
Compiler design Practical (CS-654)                                             C020328
9.6. Flowchart
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 97
Compiler design Practical (CS-654)                                               C020328
int main()
    char ip[20];
    char r[20], st, an;
    int ir, ic, j = 0, k;
    char t[5][6][10] = {"$", "$", "TH", "$", "TH", "$",
if (TOS() == an)
        pop();
        display();
        display1(ip, j + 1);
        cout << "\tPOP\n";
        j++;
    }
an = ip[j];
st = TOS();
    if (st == 'E')
       ir = 0;
    else if (st == 'H')
       ir = 1;
    else if (st == 'T')
       ir = 2;
    else if (st == 'U')
       ir = 3;
    else if (st == 'F')
       ir = 4;
    else
    {
        error();
        break;
    }
    if (an == '+')
       ic = 0;
    else if (an == '*')
       ic = 1;
    else if (an == '(')
       ic = 2;
    else if (an == ')')
       ic = 3;
    else if ((an >= 'a' && an <= 'z') || (an >= 'A' && an <= 'Z'))
    {
       ic = 4;
       an = 'i';
    }
    else if (an == '$')
       ic = 5;
    strcpy(r, strrev(t[ir][ic]));
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 99
Compiler design Practical (CS-654)                                             C020328
        strrev(t[ir][ic]);
        pop();
        push(r);
        if (TOS() == 'e')
        {
            pop();
            display();
            display1(ip, j);
        else
        {
            display();
            display1(ip, j);
            cout << "\t" << st << "->" << t[ir][ic] << "\n";
        }
            error();
            break;
        }
    }
        if (top < 9)
           a[++top] = k[i];
    }
}
    return a[top];
}
    if (top >= 0)
       a[top--] = '\0';
}
    int l;
    cout << "\t";
    for (l = m; p[l] != '\0'; l++)
       cout << p[l];
}
char *stack()
{
  return a;
}
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 101
Compiler design Practical (CS-654)                                             C020328
9.8. Output:
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 102
Compiler design Practical (CS-654)                                                          C020328
Answer- A top-down parser is a parsing technique that begins with the most general syntactic
category of the input and uses a recursive approach to generate the input by applying production
rules. The parser endeavors to create a parse tree of the input by comparing it with a grammar
in a top-to-bottom fashion.
Answer- LL parsing is a variety of top-down parsing that examines the input from left to right
and produces a leftmost derivation of the input. It is denoted as LL since it scans the input from
left to right and generates a leftmost derivation of the input.
Answer- Top-down parsing starts with the broadest syntactic category and applies production
rules repeatedly to generate the input, while bottom-up parsing begins with the input tokens
and seeks to reach the highest-level syntactic category via reduction rules. Typically, top-down
parsing is utilized for LL grammars, whereas bottom-up parsing is more suitable for LR
grammars.
Answer- When a parser cannot determine its next step and is faced with uncertainty, it may
take a particular course of action. In such a scenario, the parser cannot shift, reduce or accept.
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 103
Compiler design Practical (CS-654)                                                       C020328
                                     Practical – 10
10.1. Aim
Write a program to implement intermediate code Generator using postfix, three address code and
its syntax tree.
10.2. Input
Infix expression
            1. Postfix expression
            2. 3 address code
            3. Syntax tree
10.4. Method
A sort of intermediate code called three address code is simple to create and may be quickly
translated into machine code. To represent an expression, it uses a maximum of three addresses
and one operator, and the value computed at each instruction is saved in a temporary variable
created by the compiler. The order of three address codes' operations is determined by the
compiler.
A syntax tree's nodes can all be executed as data that has numerous fields. One field of the
operator node identifies the operator, and the remaining field contains a pointer to the operands'
nodes. The operator is often referred to as the node's label. The nodes of the syntax tree for
expressions with binary operators are created using the following functions. A pointer to the
most recent node formed is the result of each function.
10.5. Algorithm
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 104
Compiler design Practical (CS-654)                                                           C020328
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 105
Compiler design Practical (CS-654)                                                             C020328
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 106
Compiler design Practical (CS-654)                                                        C020328
10.6. Flowchart
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 107
Compiler design Practical (CS-654)                                             C020328
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 108
Compiler design Practical (CS-654)                                             C020328
struct Node
{
   char data;
   Node *left;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 109
Compiler design Practical (CS-654)                                             C020328
     Node *right;
     Node(char data) : data(data), left(NULL), right(NULL) {}
};
bool isOperator(char c)
{
  if (c == '+' || c == '-' || c == '*' || c == '/')
     return true;
  return false;
}
struct exp
{
   int pos;
   char op;
} k[15];
struct Stack
{
   int top;
   unsigned capacity;
   int *array;
};
     if (!stack)
        return NULL;
     stack->top = -1;
     stack->capacity = capacity;
     stack->array = (int *)malloc(stack->capacity * sizeof(int));
     return stack;
}
int isEmpty(struct Stack *stack)
{
   return stack->top == -1;
}
char peek(struct Stack *stack)
{
   return stack->array[stack->top];
}
char pop(struct Stack *stack)
{
   if (!isEmpty(stack))
      return stack->array[stack->top--];
   return '$';
}
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 110
Compiler design Practical (CS-654)                                             C020328
    case '*':
    case '/':
      return 2;
    case '^':
      return 3;
    case '=':
       return 4;
    }
    return -1;
}
            nodes.pop();
            nodes.push(node);
          }
          operators.push(c);
        }
        else if (c == '(')
        {
           operators.push(c);
        }
        else if (c == ')')
        {
           while (operators.top() != '(')
           {
              Node *node = new Node(operators.top());
              operators.pop();
              node->right = nodes.top();
              nodes.pop();
              node->left = nodes.top();
              nodes.pop();
              nodes.push(node);
           }
           operators.pop();
        }
        else if (isalpha(c))
        {
           Node *node = new Node(c);
           nodes.push(node);
        }
    }
    while (!operators.empty())
    {
       Node *node = new Node(operators.top());
       operators.pop();
       node->right = nodes.top();
       nodes.pop();
       node->left = nodes.top();
       nodes.pop();
       nodes.push(node);
    }
    Node *node = new Node(str[0]);
    node->left = new Node(str[1]);
    node->right = nodes.top();
    nodes.pop();
    nodes.push(node);
    return nodes.top();
}
    if (root != NULL)
    {
       cout << indent;
       if (last)
       {
          cout << "!- ";
          indent += " ";
       }
       else
       {
          cout << "|-- ";
          indent += "| ";
       }
       cout << root->data << endl;
       printTree(root->left, indent, false);
       printTree(root->right, indent, true);
    }
}
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 113
Compiler design Practical (CS-654)                                                    C020328
    while (!isEmpty(stack))
      exp[++k] = pop(stack);
    exp[++k] = '\0';
    printf("%s", exp);
}
int main()
{
   char process = 1;
   while (process)
   {
     int choice;
     printf("Enter the choice of intermediate code generation you want to perform:-
\n1.Postfix\n2.Three Address Code\n3.Syntax tree\n4. Exit\n");
     printf("User's Choice: ");
     scanf("%d", &choice);
    return 0;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 114
Compiler design Practical (CS-654)                                             C020328
void intermediateCode()
{
  strcpy(expr, str);
  printf("\tThe Intermediate code is:\n");
  scan();
}
void threeAddressCode(int i)
{
  a[0] = b[0] = '\0';
  if (!isdigit(expr[i + 2]) && !isdigit(expr[i - 2]))
  {
     a[0] = expr[i - 1];
     b[0] = expr[i + 1];
  }
  if (isdigit(expr[i + 2]))
  {
     a[0] = expr[i - 1];
     b[0] = 't';
     b[1] = expr[i + 2];
  }
  if (isdigit(expr[i - 2]))
  {
     b[0] = expr[i + 1];
     a[0] = 't';
     a[1] = expr[i - 2];
     b[1] = '\0';
  }
  if (isdigit(expr[i + 2]) && isdigit(expr[i - 2]))
  {
     a[0] = 't';
     b[0] = 't';
     a[1] = expr[i - 2];
     b[1] = expr[i + 2];
     sprintf(ch, "%d", c);
     expr[i + 2] = expr[i - 2] = ch[0];
  }
  if (expr[i] == '*')
     printf("\tt%d=%s*%s\n", c, a, b);
  if (expr[i] == '/')
     printf("\tt%d=%s/%s\n", c, a, b);
  if (expr[i] == '+')
     printf("\tt%d=%s+%s\n", c, a, b);
  if (expr[i] == '-')
     printf("\tt%d=%s-%s\n", c, a, b);
  if (expr[i] == '=')
     printf("\t%c=t%d", expr[i - 1], --c);
  sprintf(ch, "%d", c);
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 115
Compiler design Practical (CS-654)                                             C020328
    expr[i] = ch[0];
    c++;
    scan();
}
void scan()
{
  pi = 0;
  l = 0;
  for (int i = 0; i < strlen(expr); i++)
  {
     for (int m = 0; m < 5; m++)
        if (expr[i] == sw[m])
           if (pi <= p[m])
           {
              pi = p[m];
              l = 1;
              kp = i;
           }
  }
  if (l == 1)
     threeAddressCode(kp);
}
10.8. Output:
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 116
Compiler design Practical (CS-654)                                                     C020328
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 117
Compiler design Practical (CS-654)                                                      C020328
                                 Practical – 11 (a)
11.1. Aim
Write a program to implement minimum 5 optimizations
11.2. Input
From user
11.4. Method
Code optimisation, a programme transformation technique, is used in the synthesis phase to try
to optimise the intermediate code by making it use fewer resources (such as CPU, Memory),
which should lead to faster-running machine code. The following goals should be achieved by
the compiler optimisation process:
• The optimisation must be accurate and cannot in any way alter the program's intent.
11.5. Algorithm
                  1. Prompt the user to enter an expression to optimize.
                  2. Read the expression from the user and store it in a string variable.
                  3. Use a regular expression to tokenize the expression
                     into individual operands andoperators, and store them
                     in a vector.
                  4. Perform the following optimizations on the expression:
                         • Constant folding: if the expression contains any
                             sub-expressions that can be evaluated at compile
                             time, evaluate them and replace the sub-expression
                             withthe resulting value.
                         • Constant propagation: if the expression contains
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 118
Compiler design Practical (CS-654)                                                  C020328
11.6. Flowchart
                                        Figure 11.1
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 119
Compiler design Practical (CS-654)                                             C020328
main()
{
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 120
Compiler design Practical (CS-654)                                             C020328
    int a, i, k, j, n, z = 0, m, q;
    char * p, * l;
    char temp, t;
    char * tem;
    printf("enter 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++;
         }
     }
 }
 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);
 }
            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",a);
                      pr[i].r[a] = pr[m].l;
                    }
                }
            }
      }
    }
    for (i = 0; i < z; i++) {
      printf("%c\t=", pr[i].l);
      printf("%s\n", pr[i].r);
    }
    // duplicate production elimination
            {
                pr[i].l = '\0';
                strcpy(pr[i].r, '\0');
            }
        }
    }
 char basic[10][20],var[100][100],fstr[10],op;
int reg,vc,flag=0;
    printf("optimized code");
    k=0;
    for (i = 0; i < z; i++)
{
        if (pr[i].l != '\0') {
           basic[i][k]=pr[i].l;
           k++;
           basic[i][k]=pr[i].r[0];
           basic[i][k]=pr[i].r[1];
           k++;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 122
Compiler design Practical (CS-654)                                             C020328
     printf("%c=", pr[i].l);
     printf("%s\n", pr[i].r);
    } }
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 123
Compiler design Practical (CS-654)                                                          C020328
11.8. Output:
Figure 11.2
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 124
Compiler design Practical (CS-654)                                                    C020328
                                 Practical – 11 (b)
11.1. Aim
Write a program to implement code generation
11.2. Input
Three-address code
11.4. Method
The process of code generation can be thought of as the culmination of compilation. The
optimisation method can be applied to the code through post code generation, although that
can be considered as a component of the code generation step itself. The code that the compiler
produces is an object code for a certain low-level programming language, like assembly. We've
seen how lower-level object code is produced by converting source code written in a higher-
level language into a lower-level language. Lower-level object code must contain the following
minimal characteristics:
11.5. Algorithm
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 125
Compiler design Practical (CS-654)                                             C020328
11.6. Flowchart
int main() {
// Open output file for writing
ofstream outFile("output.txt");
return 0;
}
11.8. Output:
Figure 11(b).2
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 127
Compiler design Practical (CS-654)                                                    C020328
Answer-The stages of code generation typically include lexical analysis, syntax analysis,
semantic analysis, intermediate code generation, optimization, and code generation.
Answer- The central processing unit (CPU) of a computer executes machine code, a low-level
programming language. It is made up of binary instructions that are tailored to a given CPU
architecture.
                                     Practical – 12
12.1. Aim
A software program designed to compute the Leading and Trailing sets of Non-Terminals.
12.2. Input
12.4. Method
In the Leading method, the set of FIRST terminals that can be deduced from the non-terminal
symbol A is represented as LEADING(A) = a | A => ya0, where y is either an empty string or
a single non-terminal symbol. This set can be computed using a 2D array of booleans, where
LIA,a is true if the terminal symbol an is a member of the LEADING(A) set; otherwise, it is
false. Furthermore, a collection of pairs between non-terminal symbols and terminal symbols
is used to discover new pairs according to rule (b).
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 129
Compiler design Practical (CS-654)                                                       C020328
In the Trailing method, a non-terminal symbol A can be used to deduce the final or last terminal
symbol in a string, referred to as "TRAILING(A)". The set of terminal symbols that can be
used as the final character in a string deriving from a non-terminal symbol is represented by
TRAILING(A), where TRAILING(A) = a | A => yas, and y can be either an empty symbol or
a single non-terminal symbol. Similar to the Leading method, TRAILING(A) can be computed
by applying production-specific derivations to find the first terminal symbol from the right side
of a production.
Both Leading and Trailing methods can only be used with an operator precedence grammar to
produce an operator-precedence parser. An operator precedence grammar is a specific instance
of an operator grammar, in which no production rule has two consecutive non-terminal
symbols. When a non-terminal symbol is passed as an input, the Leading and Trailing functions
return a group of terminals that could represent the beginning or last terminal symbol in a string
produced from the non-terminal. Another way to think of the Leading set is the set of terminal
symbols that are "visible" from the beginning of a production rule. The term "transparent"
refers to non-terminal symbols, while a terminal symbol may be seen by gazing through a
leading non-terminal symbol or through a leading non-terminal symbol.
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 130
Compiler design Practical (CS-654)                                             C020328
12.6. Flowchart
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 131
Compiler design Practical (CS-654)                                                C020328
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <set>
if (islower(production[0])) {
leading_set.insert(production.substr(0, 1));
else if (isupper(production[0])) {
set<string> new_leading_set;
leading_set.insert(new_leading_set.begin(), new_leading_set.end());
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 132
Compiler design Practical (CS-654)                                                          C020328
if (islower(production.back()))
trailing_set.insert(production.substr(production.size() - 1, 1));
else if (isupper(production.back()))
set<string> new_trailing_set;
trailing_set.insert(new_trailing_set.begin(), new_trailing_set.end());
int main() {
int num_productions;
cout << "Enter the productions in the form A -> B | C | D, one per line:\n";
string production_str;
getline(cin, production_str);
getline(cin, production_str);
size_t pipe_pos = 0;
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 133
Compiler design Practical (CS-654)                                             C020328
productions[non_terminal].push_back(rhs.substr(0, pipe_pos));
productions[non_terminal].push_back(rhs);
cout << "Enter the non-terminal to find the leading and trailing of: ";
string target_non_terminal;
set<string> leading_set;
set<string> trailing_set;
find_leading(target_non_terminal, leading_set);
find_trailing(target_non_terminal, trailing_set);
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 134
Compiler design Practical (CS-654)                                                  C020328
return 0;
12.8. Output:
12.9. Discussion:
Creating an operator precedence table is an important step in building a parser for a
programming language. The table serves as a guide for the parser to correctly interpret the
grammar rules and generate the appropriate output. Without an operator precedence table, the
parser may misinterpret the input string and produce incorrect results.
To determine the LEADING() and TRAILING() functions, one needs to analyze the grammar
rules carefully and identify the terminals that can appear at the beginning and end of each
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 135
Compiler design Practical (CS-654)                                                      C020328
production. These functions play a crucial role in constructing the operator precedence table as
they help in establishing the order of evaluation of operators.
The process of constructing an operator precedence table involves assigning a precedence level
to each operator pair based on a comparison of their LEADING() and TRAILING() sets. The
precedence level determines the order in which the operators should be evaluated. Operators
with a higher precedence level are evaluated first, followed by operators with a lower
precedence level.
Once the operator precedence table is constructed, the parser can use it to determine the correct
order of evaluation of operators in the input string. This ensures that the output generated by
the parser is correct and meets the requirements of the programming language.
-------------------------------------------------------------------------------------
Department of computer science and engineering                                  pg. 136