Shift Reduce Parser in Compiler (original) (raw)

Last Updated : 24 Apr, 2026

Shift-reduce parsing is a popular bottom-up technique used in syntax analysis, where the goal is to create a parse tree for a given input based on grammar rules. The process works by reading a stream of tokens (the input), and then working backwards through the grammar rules to discover how the input can be generated.

  1. **Input Buffer: This stores the string or sequence of tokens that needs to be parsed.
  2. **Stack: The parser uses a stack to keep track of which symbols or parts of the parse it has already processed. As it processes the input, symbols are pushed onto and popped off the stack.
  3. **Parsing Table: Similar to a predictive parser, a parsing table helps the parser decide what action to take next.

Shift-reduce parsing works by processing the input left to right and gradually building up a parse tree by shifting tokens onto the stack and reducing them using grammar rules, until it reaches the start symbol of the grammar.

Four Main Operations of Shift Reduce Parser

  1. **Shift: Move the next input symbol onto the stack when no reduction is possible.
  2. **Reduce: Replace a sequence of symbols at the top of the stack with the left-hand side of a grammar rule.
  3. **Accept: Successfully complete parsing when the entire input is processed and the stack contains only the start symbol.
  4. **Error: Handle unexpected or invalid input when no shift or reduce action is possible.

Working

Shift-reduce parsers use a Deterministic Finite Automaton (DFA) to help recognize these handles. The DFA helps track what symbols are on the stack and decides when to shift or reduce by following a set of rules. Instead of directly analyzing the structure, the DFA helps the parser determine when reductions should occur based on the stack's contents.

The shift-reduce parser is a bottom-up parsing technique that breaks down a string into two parts: the undigested part and the semi-digested part. Here’s how it works:

  1. **Undigested Part: This part contains the remaining tokens that still need to be processed. It is the input that hasn’t been handled yet.
  2. **Semi-Digested Part: This part is on a stack. It's where tokens or parts of the string that have been processed are stored.

Parsing Process

At the beginning, the input string is entirely undigested, and the stack is empty.

The parser performs one of three actions at each step:

**Shift

**Reduce

**Error

**Example 1 - Consider the grammar
S --> S + S
S --> S * S
S --> id

Perform Shift Reduce parsing for input string "id + id + id".

**Example 2 - Consider the grammar
E --> 2E2
E --> 3E3
E --> 4
Perform Shift Reduce parsing for input string "32423".

**Example 3 - Consider the grammar
S --> ( L ) | a
L --> L , S | S
Perform Shift Reduce parsing for input string "( a, ( a, a ) ) ".

Stack Input Buffer Parsing Action
$ ( a , ( a , a ) ) $ Shift
$ ( a , ( a , a ) ) $ Shift
$ ( a , ( a , a ) ) $ Reduce S → a
$ ( S , ( a , a ) ) $ Reduce L → S
$ ( L , ( a , a ) ) $ Shift
$ ( L , ( a , a ) ) $ Shift
$ ( L , ( a , a ) ) $ Shift
$ ( L , ( a , a ) ) $ Reduce S → a
$ ( L , ( S , a ) ) $ Reduce L → S
$ ( L , ( L , a ) ) $ Shift
$ ( L , ( L , a ) ) $ Shift
$ ( L , ( L , a ) ) $ Reduce S → a
$ ( L, ( L, S ) ) $ Reduce L →L, S
$ ( L, ( L ) ) $ Shift
$ ( L, ( L ) ) $ Reduce S → (L)
$ ( L, S ) $ Reduce L → L, S
$ ( L ) $ Shift
$ ( L ) $ Reduce S → (L)
$ S $ Accept

Program to Simulate Shift-Reduce Parsing

Following is the implementation-

C++ `

// Including Libraries #include <bits/stdc++.h> using namespace std;

// Global Variables int z = 0, i = 0, j = 0, c = 0;

// Modify array size to increase
// length of string to be parsed char a[16], ac[20], stk[15], act[10];

// This Function will check whether // the stack contain a production rule
// which is to be Reduce. // Rules can be E->2E2 , E->3E3 , E->4 void check() { // Copying string to be printed as action strcpy(ac,"REDUCE TO E -> ");

// c=length of input string 
for(z = 0; z < c; z++)  
{ 
    // checking for producing rule E->4 
    if(stk[z] == '4')  
    { 
        printf("%s4", ac); 
        stk[z] = 'E'; 
        stk[z + 1] = '\0'; 
          
        //printing action 
        printf("\n$%s\t%s$\t", stk, a);  
    } 
} 
      
for(z = 0; z < c - 2; z++) 
{ 
    // checking for another production 
    if(stk[z] == '2' && stk[z + 1] == 'E' &&  
                            stk[z + 2] == '2')  
    { 
        printf("%s2E2", ac); 
        stk[z] = 'E'; 
        stk[z + 1] = '\0'; 
        stk[z + 2] = '\0'; 
        printf("\n$%s\t%s$\t", stk, a); 
        i = i - 2; 
    } 
      
} 
      
for(z = 0; z < c - 2; z++) 
{ 
    //checking for E->3E3 
    if(stk[z] == '3' && stk[z + 1] == 'E' &&  
                            stk[z + 2] == '3')  
    { 
        printf("%s3E3", ac); 
        stk[z]='E'; 
        stk[z + 1]='\0'; 
        stk[z + 2]='\0'; 
        printf("\n$%s\t%s$\t", stk, a); 
        i = i - 2; 
    } 
} 
return ; // return to main 

}

// Driver Function int main() { printf("GRAMMAR is -\nE->2E2 \nE->3E3 \nE->4\n");

// a is input string 
strcpy(a,"32423");  
  
// strlen(a) will return the length of a to c 
c=strlen(a);  
  
// "SHIFT" is copied to act to be printed 
strcpy(act,"SHIFT");  
  
// This will print Labels (column name) 
printf("\nstack \t input \t action");  
  
// This will print the initial  
// values of stack and input 
printf("\n$\t%s$\t", a);  
  
// This will Run upto length of input string 
for(i = 0; j < c; i++, j++)  
{ 
    // Printing action 
    printf("%s", act);  
      
    // Pushing into stack 
    stk[i] = a[j];      
    stk[i + 1] = '\0'; 
      
    // Moving the pointer 
    a[j]=' '; 
      
    // Printing action 
    printf("\n$%s\t%s$\t", stk, a);  
      
    // Call check function ..which will  
    // check the stack whether its contain 
    // any production or not 
    check();  
} 
  
// Rechecking last time if contain 
// any valid production then it will 
// replace otherwise invalid 
check();  
  
// if top of the stack is E(starting symbol) 
// then it will accept the input 
if(stk[0] == 'E' && stk[1] == '\0')  
    printf("Accept\n"); 
else //else reject 
    printf("Reject\n"); 

}

C

//Including Libraries #include<stdio.h> #include<stdlib.h> #include<string.h>

//Global Variables int z = 0, i = 0, j = 0, c = 0;

// Modify array size to increase // length of string to be parsed char a[16], ac[20], stk[15], act[10];

// This Function will check whether // the stack contain a production rule // which is to be Reduce. // Rules can be E->2E2 , E->3E3 , E->4 void check() { // Copying string to be printed as action strcpy(ac,"REDUCE TO E -> ");

// c=length of input string
for(z = 0; z < strlen(stk); z++)
{
    //checking for producing rule E->4
    if(stk[z] == '4') 
    {
        printf("%s4", ac);
        stk[z] = 'E';
        stk[z + 1] = '\0';
        
        //printing action
        printf("\n$%s\t%s$\t", stk, a); 
    }
}
    
for(z = 0; z < c - 2; z++)
{
    //checking for another production
    if(stk[z] == '2' && stk[z + 1] == 'E' && 
                            stk[z + 2] == '2') 
    {
        printf("%s2E2", ac);
        stk[z] = 'E';
        stk[z + 1] = '\0';
        stk[z + 2] = '\0';
        printf("\n$%s\t%s$\t", stk, a);
        i = z;
    }
    
}
    
for(z=0; z<c-2; z++)
{
    //checking for E->3E3
    if(stk[z] == '3' && stk[z + 1] == 'E' && 
                            stk[z + 2] == '3') 
    {
        printf("%s3E3", ac);
        stk[z]='E';
        stk[z + 1]='\0';
        stk[z + 1]='\0';
        printf("\n$%s\t%s$\t", stk, a);
        i = i - 2;
    }
}
return ; //return to main

}

//Driver Function int main() { printf("GRAMMAR is -\nE->2E2 \nE->3E3 \nE->4\n");

// a is input string
strcpy(a,"32423"); 

// strlen(a) will return the length of a to c
c=strlen(a); 

// "SHIFT" is copied to act to be printed
strcpy(act,"SHIFT"); 

// This will print Labels (column name)
printf("\nstack \t input \t action"); 

// This will print the initial 
// values of stack and input
printf("\n$\t%s$\t", a); 

// This will Run upto length of input string
for(i = 0; j < c; i++, j++) 
{
    // Printing action
    printf("%s", act); 
    
    // Pushing into stack
    stk[i] = a[j];     
    stk[i + 1] = '\0';
    
    // Moving the pointer
    a[j]=' ';
    
    // Printing action
    printf("\n$%s\t%s$\t", stk, a); 
    
    // Call check function ..which will 
    // check the stack whether its contain
    // any production or not
    check(); 
}

// Rechecking last time if contain
// any valid production then it will
// replace otherwise invalid
check(); 

// if top of the stack is E(starting symbol)
// then it will accept the input
if(stk[0] == 'E' && stk[1] == '\0') 
    printf("Accept\n");
else //else reject
    printf("Reject\n");

} // This code is contributed by Ritesh Aggarwal

`

Output

GRAMMAR is - E->2E2 E->3E3 E->4

stack input action $ 32423$ SHIFT 324233 242332423 SHIFT 3242332 42332423 SHIFT 32423324 2332423 REDUCE TO E -> 4 32E2332E 2332E23 SHIFT 32E2332E2 332E23 REDUCE TO E -> 2E2 3E33E 33E3 SHIFT 3E33E3 3E3 REDUCE TO E -> 3E3 EE E Accept

Key Characteristics