编译原理实验(三)——LR(0)语法分析

编译原理实验(三)——LR(0)语法分析

实验要求

根据LR(0)分析法编写一个语法分析程序 直接输入根据已知文法构造的分析表M;对于输入的文法和符号串,所编制的语法分析程序应能正确判断此串是否为文法的句子,并要求输出分析过程。

参考程序

#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <iomanip>
using namespace std;

const int maxSize = 20; //输入规模的最大大小
const string errorstr = "你输入的语言该文法无法识别";
const int outWidth = 20; //设置输出字符串所占宽度

int terminatorNum;    //输入终结符的数量
int nonterminatorNum; //输入非终结符的数量
int stateNum;         //输入状态数
int num;              //输入产生式个数
int Goto[maxSize][maxSize];
char action[maxSize][maxSize];
int terAction[maxSize][maxSize];
string chang[maxSize];           //产生式
map<char, int> terminatorSet;    //输入终结符的集合,用map 映射表示在分析表的第几列
map<char, int> nonterminatorSet; //输入非终结符的集合,用map 映射表示在分析表的第几行
vector<char> signStack;          // 符合栈为了更好的输出栈中的内容,用vector数组模拟栈行为
vector<int> stateStack;          // LR0文法状态栈

void analysisProcess(string); //对输入的语言用LL1预测分析表进行分析
string intToString(int);      //将整数转化为字符串,并且大于9的数+()

int main()
{
    cout << "请输入产生式的个数:";
    cin >> num;
    cout << "请按顺序输入产生式:\n";
    for (int i = 1; i <= num; ++i)
        cin >> chang[i];
    cout << "请输入终结符的个数:";
    cin >> terminatorNum;
    char str;
    cout << "请依次按照分析表输入终结符(包含结束符#):" << endl;
    for (int i = 1; i <= terminatorNum; ++i)
    {
        cin >> str;
        terminatorSet[str] = i;
    }
    cout << "请输入非终结符的个数:";
    cin >> nonterminatorNum;
    cout << "请依次按照分析表输入终结符:" << endl;
    for (int i = 1; i <= nonterminatorNum; ++i)
    {
        cin >> str;
        nonterminatorSet[str] = i;
    }
    cout << "请输入最后一个状态数(从0开始):";
    cin >> stateNum;
    cout << "请依次输入非终结符goto表的内容,对于出错错误的请输入-1:\n";
    for (int i = 0; i <= stateNum; ++i)
    {
        for (int j = 1; j <= nonterminatorNum; ++j)
        {
            cin >> Goto[i][j];
        }
    }
    cout << "请依次输入终结符action的内容,对于出错错误的请输入-1:\n";
    cout << "输入格式按照 移进(S state) 规约(R state) 接受(A -1) 出错(E -1),state代表状态数\n";
    for (int i = 0; i <= stateNum; ++i)
    {
        for (int j = 1; j <= terminatorNum; ++j)
        {
            cin >> action[i][j] >> terAction[i][j];
        }
    }
    cout << "请输入要分析语言: ";
    string L;
    cin >> L;
    analysisProcess(L);
}

void analysisProcess(string str)
{
    str += "#";
    cout << setw(outWidth) << setiosflags(ios::left) << "步骤";
    cout << setw(outWidth) << setiosflags(ios::left) << "状态栈";
    cout << setw(outWidth) << setiosflags(ios::left) << "符号栈";
    cout << setw(outWidth) << setiosflags(ios::left) << "产生式"
         << "输入串" << endl;
    signStack.clear();
    stateStack.clear(); //清空状态栈,符合栈
    signStack.push_back('#');
    stateStack.push_back(0);        //初始化符合栈,状态栈
    int i = 0, ip = 0;              //i代表进行到第几步 a是分析到输入语言字符串第几个
    int Sm;                         //当前状态栈栈顶状态
    int a = terminatorSet[str[ip]]; //当前剩余输入串的首字符在输入终结符表的位置
    cout << setw(outWidth) << setiosflags(ios::left) << (++i);
    cout << setw(outWidth) << setiosflags(ios::left) << "0";
    cout << setw(outWidth) << setiosflags(ios::left) << "#";
    cout << setw(outWidth) << setiosflags(ios::left) << " " << str << endl;
    string outStr;
    while (++i)
    {
        Sm = stateStack.back();
        if (action[Sm][a] == 'S')
        {
            /*
            移进:当前输入符号ai移进符号栈,将action表中指出的状态S进状态栈
            */
            //cout<<terAction[Sm][a];
            stateStack.push_back(terAction[Sm][a]);
            signStack.push_back(str[ip]);
            a = terminatorSet[str[++ip]];
            cout << setw(outWidth) << setiosflags(ios::left) << i;
            outStr = "";
            for (int t = 0; t < stateStack.size(); ++t)
                outStr += intToString(stateStack[t]);
            cout << setw(outWidth) << setiosflags(ios::left) << outStr;
            outStr = "";
            for (int t = 0; t < signStack.size(); ++t)
                outStr += signStack[t];
            cout << setw(outWidth) << setiosflags(ios::left) << outStr;
            cout << setw(outWidth) << setiosflags(ios::left) << " " << str.substr(ip) << endl;
        }
        else if (action[Sm][a] == 'R')
        {
            int j = terAction[Sm][a];
            int size = chang[j].size() - 3;
            if (chang[j][3] == '@')
                size = 0; //为空产生式
            for (int t = 0; t < size; ++t)
                stateStack.pop_back();
            for (int t = 0; t < size; ++t)
                signStack.pop_back();
            Sm = stateStack.back();
            char A = chang[j][0]; //规约符号
            signStack.push_back(A);
            stateStack.push_back(Goto[Sm][nonterminatorSet[A]]);
            cout << setw(outWidth) << setiosflags(ios::left) << i;
            outStr = "";
            for (int t = 0; t < stateStack.size(); ++t)
                outStr += intToString(stateStack[t]);
            cout << setw(outWidth) << setiosflags(ios::left) << outStr;
            outStr = "";
            for (int t = 0; t < signStack.size(); ++t)
                outStr += signStack[t];
            cout << setw(outWidth) << setiosflags(ios::left) << outStr;
            cout << setw(outWidth) << setiosflags(ios::left) << chang[j] << str.substr(ip) << endl;
        }
        else if (action[Sm][a] == 'A')
        {
            cout << "该文法识别该语言" << endl;
            return;
        }
        else
        {
            cout << errorstr << endl;
            return;
        }
    }
}

string intToString(int num)
{
    int j = num;
    if (j == 0)
        return "0";
    string str = "";
    while (j)
    {
        str += char(j % 10 + '0');
        j /= 10;
    }
    str.reserve();
    if (num > 9)
        str = "(" + str + ")";
    return str;
}

实验结果

程序输入说明

输入的终结符与终结符都为单个字符
空( ε \varepsilon ε)用@表示
参考文法:
在这里插入图片描述
分析表:
在这里插入图片描述
输入数据案例

4
S->aAcBe
A->b
A->Ab
B->d

6
a c e b d #

3 
S A B

9
1 -1 -1
-1 -1 -1
-1 3 -1
-1 -1 -1
-1 -1 -1
-1 -1 7
-1 -1 -1
-1 -1 -1
-1 -1 -1
-1 -1 -1

S  2 E -1 E -1	E -1	E -1	E -1
E -1	E -1	E -1	E -1	E -1	A -1
E -1	E -1	E -1	S 4	E -1	E -1
E -1	S 5	E -1	S 6	E -1	E -1
R 2	R 2	R 2	R 2	R 2	R 2
E -1	E -1	E -1	E -1	S 8	E -1
R 3	R 3	R 3	R 3	R 3	R 3
E -1	E -1	S 9	E -1	E -1	E -1
R 4	R 4	R 4	R 4	R 4	R 4
R 1	R 1	R 1	R 1	R 1	R 1

abbcde
截图

在这里插入图片描述
在这里插入图片描述

  • 17
    点赞
  • 141
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值