编译原理:lr(k)语法分析实验

一、实验目的

运用LR(K)语法分析的基本原理实现对于句子的语法分析

二、实验要求

1、输入的文法须是LR(0)文法。
2、该文法的LR(0)分析表由用户输入,请自行设计相应的数据结构。

三、实验内容

1、输入一个LR(0)文法及其对应的LR(0)分析表
2、输入一个字符串,运用LR(K)分析算法判断它是否为该文法的一个句子。

四、数据结构设计

1.用数组来保存输入的产生式和goto,action

在这里插入图片描述

2.依次用map和vector来保存一下信息
(1)输入终结符的集合,用map 映射表示在分析表的第几列
(2)输入非终结符的集合,用map 映射表示在分析表的第几行
(3)符合栈为了更好的输出栈中的内容,用vector数组模拟栈行为vector stateStack;
(4)LR0文法状态栈
在这里插入图片描述

3.关键函数analysisprocess

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

五、算法流程

在这里插入图片描述

六、实验结果

1.输入文法和分析表的信息

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

2.输入要分析的串
在这里插入图片描述

输入示例:

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

七、实验代码

#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;
}


  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值