实验 3 SLR(1),LR(1)等分析方法的程序实现-编译原理(湖工大)

【实验目的】

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

【实验内容】

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

【实验要求】

1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。

2、如果遇到错误的表达式,应输出错误提示信息。

3、程序输入/输出实例: 输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串

输出过程如下:  步骤     状态栈    符号栈    剩余输入串       动 作

                              1         0                 #         i+i*i#                 移进

【实验代码】

老师给的代码运行不了,在网上找的别人的代码

#include <iostream>
#include <stack>
#include <string>

using namespace std;

string action[12][6] = {"S5", "0", "0", "S4", "0", "0",
                        "0", "S6", "0", "0", "0", "acc",
                        "0", "r2", "S7", "0", "r2", "r2",
                        "0", "r4", "r4", "0", "r4", "r4",
                        "S5", "0", "0", "S4", "0", "0",
                        "0", "r6", "r6", "0", "r6", "r6",
                        "S5", "0", "0", "S4", "0", "0",
                        "S5", "0", "0", "S4", "0", "0",
                        "0", "S6", "0", "0", "S11", "0",
                        "0", "r1", "S7", "0", "r1", "r1",
                        "0", "r3", "r3", "0", "r3", "r3",
                        "0", "r5", "r5", "0", "r5", "r5"};
int gotoarr[12][3] = {1, 2, 3, //GOTO 表
                      0, 0, 0,
                      0, 0, 0,
                      0, 0, 0,
                      8, 2, 3,
                      0, 0, 0,
                      0, 9, 3,
                      0, 0, 10,
                      0, 0, 0,
                      0, 0, 0,
                      0, 0, 0,
                      0, 0, 0};
char vt[6] = {'i', '+', '*', '(', ')', '#'}; //存放终结符
char vn[3] = {'E', 'T', 'F'}; //存放非终结符
string Production[6] = {"E->E+T", "E->T", "T->T*F", "T->F", "F->(E)", "F->i"};//产生式集合
int com = 0;
int line = 1;//记录处理的步骤数
bool flag = false;
int StatusNumber = 1;//栈中状态数
string StackString = "#";//记录符号栈中内容
int Status[50] = {0};//记录状态栈
stack<char> Stack;//创建一个符号栈
stack<int> status;//创建一个状态栈
void Judge(int &i, int j, const char arr[], char ch, string s) {//判断输入串是否由文法终结符组成
    flag = false;
    for (int l = 0; l < j; l++) {
        if (ch == arr[l]) {
            flag = true;
            i = l;
            break;
        }
    }
    if (!flag) {
        cout << "\tError" << endl;
        com = s.size();
    }
}

void OutputStatus() {//输出状态集
    for (int i = 0; i < StatusNumber; i++)
        cout << Status[i];
}

void OutputString(string s) {//输出未处理的字符串
    for (int i = com; i < s.size(); i++)
        cout << s.at(i);
}

void Output(string s) {//输出步骤、 状态集、 符号集、 输入串
    cout << line << "\t";
    OutputStatus();
    cout << "\t" << StackString << "\t";
    OutputString(s);
    cout << "\t\t";
    line++;
}

void Shift(int i, string s) {//移进函数 S
    Output(s);
    cout << "ACTION[" << status.top() << "," << s.at(com) << "]=S" << i << ",状态" << i << "入栈" << endl;
    status.push(i);//将状态 i 压进状态
    Status[StatusNumber] = i;//Status 记录状态栈的内容
    Stack.push(s.at(com));//将当前面临的输入串符号压进符号栈
    StackString = StackString + s.at(com);//StackString 记录符号栈的内容
    com++;//当前面临的输入串字符往后移一位
    StatusNumber++;//状态数加一
}

void Goto(stack<int> st1, stack<char> st2, string s) {//GoTo 语句
    int j = -1;
    int ch1 = st1.top();
    char ch2 = st2.top();
    Judge(j, 3, vn, ch2, s);//求得 ch2 在非终结符表中的位置
    if (gotoarr[ch1][j] == 0) {
        cout << "\tError" << endl;
        com = s.size();
    } else {
        status.push(gotoarr[ch1][j]);//新状态进栈
        Status[StatusNumber] = gotoarr[ch1][j];
        StatusNumber++;
    }
}

void Reduction(int i, string s) {//归约函数 R
    Output(s);
    cout << "r" << i << ":" << Production[i - 1] << "归约, GoTo(";
    int N = Production[i - 1].length() - 3;
    for (int j = 0; j < N; j++) {//消除要归约的状态及符号
        status.pop();
        Stack.pop();
        StatusNumber--;
        StackString.erase(StackString.length() - 1);
    }
    cout << status.top() << "," << Production[i - 1].at(0) << ")=";
    Stack.push(Production[i - 1].at(0));//符号进栈
    StackString = StackString + Stack.top();
    Goto(status, Stack, s);
    cout << status.top() << "入栈" << endl;
    Status[StatusNumber] = status.top();
}

void Analyse(string s) {//具体分析函数
    Stack.push('#');//初始化
    status.push(0);
    s = s + "#";
    int t = -1;//记录 ch 在数组 vt 的位置
    while (com < s.size()) {
        int i = status.top();
        char ch = s.at(com);
        Judge(t, 6, vt, ch, s);
        if (flag) {
            if (action[i][t] != "acc" && action[i][t] != "0") {
                if (action[i][t].at(0) == 'S') {
                    action[i][t].erase(0, 1); //删除 action[i][t]的首字母 S
                    Shift(atoi(action[i][t].c_str()), s);//atoi(action[i][t].c_str()), 将action[i][t]转换为整型
                    action[i][t].insert(0, "S");//将 S 添加回 action[i][t]
                } else if (action[i][t].at(0) == 'r') {
                    action[i][t].erase(0, 1);//删除 action[i][t]的首字母 r
                    Reduction(atoi(action[i][t].c_str()), s);//atoi(action[i][t].c_str()), 将action[i][t]转换为整型
                    action[i][t].insert(0, "r");//将 r 添加回 action[i][t]
                }
            } else if (action[i][t] == "0") {
                cout << "\tError" << endl;
                break;
            } else if (action[i][t] == "acc") {
                Output(s);
                cout << "acc" << "\t 分析成功" << endl;
                break;
            }
        } else if (!flag)
            break;
    }
}

int main() {
    string s;
    cout << "输入的文法" << endl;
    for (int j = 0; j < 6; j++)
        cout << Production[j] << endl;
    cout << "VT:" << endl;
    for (int i = 0; i < 6; i++)
        cout << vt[i] << " ";
    cout << endl;
    for (int i = 0; i < 3; i++)
        cout << vn[i] << " ";
    cout << endl;
    cout << "****************************LR(1)****************************" << endl;
    char T;
    cout << "Enter String" << endl;
    cin >> s;
    cout << "**************************Analyzer***************************" << endl;
    cout << "Step" << "\t" << "StateStack" << "\t" << "SymbolStack" << "\t" << "RemainingString" << "\t" << "Info"
         << endl;
    Analyse(s);
    com = 0;
    line = 1;
    StackString = "#";
    StatusNumber = 1;
    while (!Stack.empty())
        Stack.pop();
    while (!status.empty())
        status.pop();
    return 0;
}

运行出来的结果如下图所示:(参考编译原理教程第四版P77表3.14)

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SLR(1)是一种语法分析器,用于解析上下文无关文法。下面是一个简单的SLR(1)实验: 1. 首先,需要定义上下文无关文法。例如,考虑以下文法: ``` S -> E E -> E + T | T T -> T * F | F F -> ( E ) | id ``` 2. 接下来,需要构造文法的SLR(1)分析表。这个表将会告诉分析器在哪里进行移进(shift)和规约(reduce)操作。可以通过以下步骤构造分析表: a. 计算每个非终结符的FIRST集和FOLLOW集。 b. 对于每个产生式,找出它的FOLLOW集,并将它添加到该产生式的FOLLOW集中。 c. 对于每个非终结符A和每个终结符a,找出A可以推导出的所有产生式,并将它们添加到分析表中的[A, a]项中。如果这些产生式是形如A -> α的,那么将移进项Sj添加到[A, a]项中,其中j是在项Sj中第一个符号是a的那个状态。 d. 对于每个非终结符A和每个终结符a,找出A的FOLLOW集中的所有符号,并将它们添加到分析表中的[A, a]项中。如果A是文法的开始符号,那么将接受项acc添加到[A, $]项中。 3. 最后,使用分析表进行语法分析。首先,将输入符号串转换为一个词法单元序列。接下来,使用一个栈来跟踪分析过程。将栈初始化为只包含状态0。然后,重复以下步骤: a. 从输入中读取下一个符号。 b. 在分析表中查找当前状态和下一个符号的项。 c. 如果该项是移进项,将下一个符号压入栈中,并转移到新状态。如果该项是规约项,将产生式右侧的符号弹出栈,并使用产生式左侧的符号替换它们。然后,再次在分析表中查找当前状态和新符号的项,并将新项推入栈中。 d. 如果分析表中没有与当前状态和下一个符号匹配的项,则报告语法错误。 e. 如果下一个符号是结束符号$,并且栈中只剩下一个状态,那么分析成功。 以上是一个简单的SLR(1)实验的步骤。在实际应用中,可能需要更复杂的文法和更复杂的分析表构造算法

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值