一个简单的SLR语法分析器

#include <stdio.h>
#include <string>
#include <stack>
#include <iostream>

using namespace std;

#define acc 0       // 接受状态
#define err 15  // 出错状态

int Action[12][6] = {
    { 5, err, err, 4, err, err },   // 0
    { err, 6, err, err, err, acc }, 
    { err, -2, 7, err, -2, -2 },    // 2 E->T.
    { err, -4, -4, err, -4, -4 },   // 3 T->F.
    { 5, err, err, 4, err, err },   // 4 
    { err, -6, -6, err, -6, -6 },   // 5 F->id.
    { 5, err, err, 4, err, err },   //
    { 5, err, err, 4, err, err },   //
    { err, 6, err, err, 11, err },  //
    { err, -1, 7, err, -1, -1 },    // 9 E->E+T.
    { err, -3, -3, err, -3, -3 },   // 10 T->T*F
    { err, -5, -5, err, -5, -5 }    // 11 F->(E).
};

int GoTo[12][3] = {
    { 1, 2, 3 },       // 0
    { err, err, err }, // 1
    { err, err, err }, // 2
    { err, err, err }, // 3
    { 8, 2, 3 },       // 4
    { err, err, err }, // 5
    { err, 9, 3 },     // 6
    { err, err, 10 },  // 7
    { err, err, err }, // 8
    { err, err, err }, // 9
    { err, err, err }, // 10
    { err, err, err }  // 11
};

string str = "@+*()#";  // 字母表集合
string nt = "ETF";      // 非终结符集合

// LookUp函数,状态转换
int lookup(char c, int state){
    int index = str.find_first_of(c);
    //printf("action:%d %c -> %d\n", state, c, Action[state][index]);
    return Action[state][index];
}

// GoTo函数
int go(char c, int state){
    int index = nt.find_first_of(c);
    //printf("goto:%d %c -> %d\n", state, c, GoTo[state][index]);
    return GoTo[state][index];
}

// 语法分析器
void parse(FILE *fp){
    int state = 0, temp = 1;
    char c;
    stack<int> ss;
    stack<char> sts;
    ss.push(state);
    fread(&c, sizeof(char), 1, fp);
    while (temp){
        //cin >> a;
        state = ss.top();
        temp = lookup(c, state);
        if (temp > 0){
            // 移入
            ss.push(temp);
            sts.push(c);
            // IP指向下一个符号
            fread(&c, sizeof(char), 1, fp);
        }else if (temp < 0){
            // 归约
            switch (-temp){
            case 1://E->E+T.
                printf("E->E+T.\n");
                ss.pop();
                ss.pop();
                ss.pop();
                sts.pop();
                sts.pop();
                sts.pop();
                // reduce
                sts.push('E');
                break;
            case 2://E->T.
                printf("E->T.\n");
                ss.pop();
                sts.pop();
                // reduce
                sts.push('E');
                break;
            case 3://T->T*F.
                printf("T->T*F.\n");
                ss.pop();
                ss.pop();
                ss.pop();
                sts.pop();
                sts.pop();
                sts.pop();
                // reduce
                sts.push('T');
                break;
            case 4://T->F.
                printf("T->F.\n");
                ss.pop();
                sts.pop();
                // reduce
                sts.push('T');
                break;
            case 5://F->(E).
                printf("F->(E).\n");
                ss.pop();
                ss.pop();
                ss.pop();
                sts.pop();
                sts.pop();
                sts.pop();
                // reduce
                sts.push('F');
                break;
            case 6://F->id.
                printf("F->id.\n");
                ss.pop();
                sts.pop();
                // reduce
                sts.push('F');
                break;
            default://ERR
                printf("error action.\n");
                break;
            }
            // 句型归约之后,需要查找GoTo表进行状态转换
            int r = go(sts.top(), ss.top());
            if (r != err){
                ss.push(r);
            }else {
                temp = 0;
                printf("error goto.\n");
            }
        }else{
            // 通过语法分析
            printf("pass.\n");
        }
    }
}
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
SLR(Simple LR)是一种比LR(0)更强的自底向上的语法分析方法,它的分析比LR(0)更大一些,但是比LR(1)小很多,因此在实际中应用得比较广泛。下面是使用SLR方法设计语法分析器的步骤: 1. 构造文法的SLR分析,包括状态、转移、规约等内容。具体步骤如下: - 对于每个非终结符A和终结符a,构造一个SLR分析中的项ACTION[s, a]或者GOTO[s, A]。其中s示状态,a示终结符,A示非终结符。 - 对于每个状态s,构造一个SLR分析中的项ACTION[s, a]或者GOTO[s, A]。其中a示终结符,A示非终结符。 - 对于每个状态s和每个终结符a,若存在一条形如“S → αaβ”的规约项,则将ACTION[s, a]设为“rj”,其中j示该规约项的编号。 - 对于每个状态s和每个非终结符A,若存在一条形如“S → αAβ”的转移项,则将GOTO[s, A]设为t,其中t示转移到的状态。 - 对于每个状态s,若存在一条形如“S → α”的规约项,则将ACTION[s, $]设为“acc”。 2. 利用SLR分析进行分析,具体步骤如下: - 初始化状态栈和符号栈,将起始状态和起始符号(通常为$)分别入栈。 - 从输入中读入一个符号a。 - 根据状态栈的栈顶状态s和输入符号a,查找SLR分析中的ACTION[s, a]项。 - 如果ACTION[s, a]为“shift t”,则将t压入状态栈,将a压入符号栈,继续读入下一个符号。 - 如果ACTION[s, a]为“rj”,则进行第j条规约操作,将规约项右侧的符号从符号栈中弹出,并将规约项左侧的非终结符A和GOTO[s, A]压入状态栈。 - 如果ACTION[s, a]为“acc”,则分析成功。 - 如果ACTION[s, a]为其他值(例如“error”),则分析失败。 总的来说,SLR方法是一种相对简单、易于理解和实现的语法分析方法,但是它的应用范围相对较窄,只能处理一些比较简单的文法。如果文法比较复杂,或者需要处理一些语法歧义的情况,可能需要使用更高级别的语法分析方法,例如LR或LL分析

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值