📜  编译器中的Shift Reduce解析器

📅  最后修改于: 2021-06-28 07:33:13             🧑  作者: Mango

前提条件–解析|设置2(自下而上或Shift减少解析器)
Shift Reduce解析器尝试以与自底向上解析相同的方式来构建解析,即,解析树是从叶子(底部)到根(上)构建的。移位减少解析器的一种更通用的形式是LR解析器。
该解析器需要一些数据结构,即

  • 用于存储输入字符串的输入缓冲区。
  • 用于存储和访问生产规则的堆栈。

基本操作–

  • 移位:这涉及将符号从输入缓冲区移到堆栈上。
  • 减少:如果手柄出现在堆栈顶部,则通过使用适当的生产规则进行减少,即从堆栈中弹出生产规则的RHS并将生产规则的LHS推入堆栈。
  • 接受:如果堆栈中仅存在开始符号且输入缓冲区为空,则解析操作称为接受。当获得接受动作时,意味着成功解析。
  • 错误:在这种情况下,解析器既不能执行shift操作也不能执行reduce操作,甚至无法接受操作。

示例1 –考虑语法
S –> S + S
S –> S * S
S –> id
对输入字符串“ id + id + id”执行Shift Reduce解析。

示例2 –考虑语法
E –> 2E2
E –> 3E3
E –> 4
对输入字符串“ 32423”执行Shift Reduce解析。

以下是C-中的实现

C++
// Including Libraries 
#include 
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() 
{ 
    // Coping 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'; 
                
            //pinting 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 + 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 Lables (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 Shubhamsingh10


C
//Including Libraries
#include
#include
#include
  
//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()
{
    // Coping 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';
              
            //pinting 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; z3E3
        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 Lables (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


输出

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

stack      input      action
$    32423$    SHIFT
$3     2423$    SHIFT
$32      423$    SHIFT
$324       23$    REDUCE TO E -> 4
$32E       23$    SHIFT
$32E2        3$    REDUCE TO E -> 2E2
$3E        3$    SHIFT
$3E3         $    REDUCE TO E -> 3E3
$E         $    Accept