一个简单的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");
        }
    }
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值