先决条件 – 解析 |设置 2(自下而上或 Shift Reduce 解析器)
Shift Reduce 解析器尝试以与自底向上解析类似的方式构建解析,即解析树是从叶子(底部)到根(向上)构建的。一种更通用的 shift reduce 解析器是 LR 解析器。
这个解析器需要一些数据结构,即
- 用于存储输入字符串的输入缓冲区。
- 用于存储和访问生产规则的堆栈。
基本操作——
- Shift:这涉及将符号从输入缓冲区移动到堆栈上。
- 减少:如果句柄出现在堆栈顶部,则使用适当的产生式规则进行减少,即产生式规则的 RHS 弹出堆栈,并将产生式规则的 LHS 压入堆栈。
- 接受:如果堆栈中只存在起始符号并且输入缓冲区为空,则解析操作称为接受。当得到accept动作时,就表示解析成功。
- 错误:这是解析器既不能执行移位动作也不能减少动作甚至不接受动作的情况。
示例 1 –考虑语法
S –> S + S
S –> S * S
S –> id
对输入字符串“id + id + id”执行 Shift Reduce 解析。
示例 2 –考虑语法
E –> 2E2
E –> 3E3
E –> 4
对输入字符串“32423”执行 Shift Reduce 解析。
示例 3 – 考虑语法
S –> ( L ) |一种
L –> L , S |秒
对输入字符串“( a , ( a , a ) ) ”执行Shift Reduce解析。
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 |
以下是实现-
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';
//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 + 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';
//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; 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