实验四 LR(1)分析法

一、实验目的

       构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子,了解LR(K)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。

二、实验题目

1、对下列文法,用LR(1)分析法对任意输入的符号串进行分析: 

(0)E->S

(1)S->BB

(2)B->aB

(3)B->b

2、LR(1)分析表为:

(0)E->S

(1)S->BB

(2)B->aB

(3)B->b

状态

ACTION

GOTO

a

b

#

S

B

S0

S3

S4

1

2

S1

acc

S2

S6

S7

5

S3

S3

S4

8

S4

r3

r3

S5

r1

S6

S6

S7

9

S7

r3

S8

r2

r2

S9

r2

(1)若输入baba#,则输出为:

步骤      状态栈      符号栈       输入串       ACTION      GOTO

1             0              #              baba#              S4       

2             04            #b              aba#               r3             2

3             02            #B              aba#              S6

4             026           #Ba              ba#               S7

5             0267         #Bab               a#             error

(2)若输入bb#,则输出为:

步骤      状态栈      符号栈       输入串       ACTION     GOTO

1             0               #               bb#              S4       

2             04             #b               b#               r3             2

3             02             #B               b#               S7

4             027           #Bb               #                r3             5

5             025           #BB               #                r1             1

6             01             #S               #                acc

三、算法流程图

四、完整程序  

#include<stdio.h>
#include<string.h>
//ACTION表
char* action[10][3] = { "S3#","S4#",NULL,
              NULL,NULL,"acc",
              "S6#","S7#",NULL,
              "S3#","S4#",NULL,
              "r3#","r3#",NULL,
               NULL,NULL,"r1#",
              "S6#","S7#",NULL,
               NULL,NULL,"r3#",
              "r2#","r2#",NULL,
               NULL,NULL,"r2#" };

//GOTO表
int goto1[10][2] = { 1,2,
                     0,0,
                     0,5,
                     0,8,
                     0,0,
                     0,0,
                     0,9,
                     0,0,
                     0,0,
                     0,0};
char vt[3] = { 'a','b','#' };  /*存放终结符*/
char vn[2] = { 'S','B' };   /*存放非终结符*/
char* LR[4] = { "E->S#","S->BB#","B->aB#","B->b#" };  //从第四位开始存放产生式
/*输出状态栈、输出符号栈、输出输入串*/
int a[10];//状态表内容
char b[10], c[10], c1;
int top1, top2, top3, top, m, n;

int main() {
    int g, h, i, j, k, l, p, y, z, count;
    char x, copy[10], copy1[10];//copy1[]为产生式数组
    top1 = 0; top2 = 0; top3 = 0; top = 0;
    a[0] = 0;
    y = a[0];
    b[0] = '#';
    count = 0;
    z = 0;
    printf("input:\n");
    do {
        scanf_s("%c", &c1);
        c[top3] = c1;
        top3 = top3 + 1;
    } while (c1 != '#');
    printf("步骤\tS状态\t\tX符号\t\t输入串\t\tACTION\t\tGOTO\n");
    do
    {
        y = z; m = 0; n = 0;              /*y,z指向状态栈栈顶*/
        g = top; j = 0; k = 0;
        x = c[top];
        count++;	 printf("%d\t", count);
        while (m <= top1)                /*输出状态栈*/
        {
            printf("%d", a[m]);    m = m + 1;
        }	printf("\t\t");
        while (n <= top2)                  /*输出符号栈*/
        {
            printf("%c", b[n]);     n = n + 1;
        }	printf("\t\t");
        while (g <= top3)                 /*输出输入串*/
        {
            printf("%c", c[g]);   g = g + 1;
        }
        printf("\t\t");
        //查action表
        if (x == 'a')j = 0;
        if (x == 'b')j = 1;
        if (x == '#')j = 2;
        if (action[y][j] == NULL)
        {
            printf("error\n");
            return 0;
        }
        else
            strcpy(copy, action[y][j]);
        //处理移进
        if (copy[0] == 'S')
        {
            z = copy[1] - '0';
            top1 = top1 + 1;
            top2 = top2 + 1;
            a[top1] = z;
            b[top2] = x;
            top = top + 1;	i = 0;
            while (copy[i] != '#')
            {
                printf("%c", copy[i]); i++;
            }			printf("\n");
        }
        //处理归约
        if (copy[0] == 'r')
        {
            i = 0;
            while (copy[i] != '#')
            {
                printf("%c", copy[i]);	i++;
            }
            h = copy[1] - '0';
            strcpy(copy1, LR[h]);
            if (copy1[0] == 'S')k = 0;
            if (copy1[0] == 'B')k = 1;
            l = strlen(LR[h]) - 4;//得到产生式右部的长度
            top1 = top1 - l + 1;
            top2 = top2 - l + 1;
            y = a[top1 - 1];
            p = goto1[y][k];
            if (p == 0) {
                printf("error\n");
                return 0;
            }
            else
            {
                a[top1] = p;
                b[top2] = copy1[0];
                z = p;
                printf("\t\t");
                printf("%d\n", p);
            }
        }
    } while (action[y][j] != action[1][2]);
    printf("acc!\n");
    return 0;
}

五、运行结果截图

1、输入字符串abaa#错误,错误原因为输入串为空:

2、输入字符串babb#错误,出错原因为查表为空:

3、输入字符串bab#正确: 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值