• 简单优先分析法演示系统——C/C++/Qt实现



    🔋 第二个 Qt、C/C++ 程序设计项目



    一、简单的效果演示

    在这里插入图片描述

      ● 说明:简单演示了一下整个系统。



    二、系统要求

    简单优先分析法,它是编译原理课程中所涉及的一种重要的语法分析方法:

    (1)系统能够分步演示说明简单优先关系矩阵的计算过程(例如 L 关系、 R 关系、L+关系、R+关系、小于、大于、等于关系的求解过程)。

    (2)系统能够演示利用简单优先关系矩阵分析符号串的过程。

    (3)界面美观。

    (4)对所采用的算法、程序结构和主要函数过程以及关键变量进行详细的说明。

    (5)提供关键程序的清单、源程序及可执行文件和相关的软件说明。



    三、系统设计

    在这里插入图片描述
    简单优先分析法演示系统的功能有如下 9 项:

    (1)支持系统运行时的状态参数配置,如文法表达式符号串的输入、分析符号串的输入、所有计算内容和输入框的清空。

    (2)能根据简单优先分析法的定义计算 L 关系、R 关系和等于关系,并利用 Warshall 算法实现 L+ 关系、R+ 关系的计算,最终计算出小于关系、大于关系和简单优先关系矩阵。

    (3)支持通过友好的界面展示文法表。

    (4)支持通过友好的界面展示 L 关系、R 关系、L+ 关系、R+ 关系、等于关系、小于关系、大于关系和简单优先关系矩阵。

    (5)利用堆栈算法思想来分析输入的符号串,判断通过该文法能否生成该符号串。

    (6)支持通过友好的界面展示分析过程。

    (7)若不能构造简单优先关系矩阵,系统会分析出具体是哪里的构造出了问题,并给予提示。

    (8)若不能通过该文法能否生成输入符号串,系统会分析出具体是哪一步出了问题,并给予提示。

    (9)系统另外还支持展示“带关系符号”的分析过程。



    四、框架搭建

    项目管理如下:

    在这里插入图片描述

    说明
      ① main.cpp 是启动程序的入口。
      ② mainwindow.cpp 是 “开始” 界面的源代码。
      ③ analysis.cpp 是简单优先分析系统的源代码 。

    头文件analysis.h 如下:
    在这里插入图片描述

    说明:该系统所有功能的触发,都是点击含有 pushButton 的函数而实现的。



    五、算法设计

    5.1 主要数据结构

    ● 该系统中未使用自己构造的结构体。主要使用了二维数组来存储关系和 Qt5.14.2 里面的 QVectorQMapQSetQString
      ① QVector 用于存储文法表达式的相关信息。
      ② QMap 用于存储每一个字符对应的数字,便于构造矩阵表。
      ③ QSet 用于实现对右部产生式进行判重的功能。
      ④ QString 用于输入输出、充当分析过程的“堆栈”。


    5.2 主要算法流程

    Warshall算法:为了有效地由布尔矩阵 B 来计算 B+,1962 年 Warshall 提出了一种算法(简称 Warshall 算法),该算法的文字描述过程如下,算法流程图如下图所示:
      ① 首先置矩阵 A = B A=B A=B
      ② 置 i = 1 i=1 i=1
      ③ 对 1 ≤ j ≤ n 1≤j≤n 1jn,若 A [ j , i ] = 1 A[j,i]=1 A[j,i]=1,对所有 k = 1 , 2 , … k=1,2,… k=1,2 n n n A [ j , k ] = A [ j , k ] + A [ I , k ] A[j,k]=A[j,k]+A[I,k] A[j,k]=A[j,k]+A[I,k]( + + +为布尔和) ;
      ④ 置 i = i + 1 i=i+1 i=i+1;
      ⑤ 如果 i ≤ n i≤n in,则转步骤③,否则停止,这样得到矩阵 A n × n A_{n×n} An×n,即 A n × n = B + A_{n×n}=B+ An×n=B+

    在这里插入图片描述

    简单优先分析算法:首先是在文法各种符号之间(终结符号和非终结符号)建立优先关系,在分析一个句型(指规范句型)时,从左到右依次扫视其中符号,利用符号之间优先关系找到句柄,再归约成某个非终结符。流程图如下图所示。

    在这里插入图片描述



    六、测试数据及其结果分析

    0. 开始界面如下:

    在这里插入图片描述


    1. 输入文法表达式并无误展示:

    在这里插入图片描述



    2. L关系展示:
    在这里插入图片描述



    3. R关系展示:

    在这里插入图片描述


    4. L+关系展示:
    在这里插入图片描述

    5. R+关系展示:

    在这里插入图片描述


    6. 等于关系展示:

    在这里插入图片描述


    7. 小于关系展示:

    在这里插入图片描述


    8. 大于关系展示:

    在这里插入图片描述


    9. 简单优先关系矩阵展示:

    在这里插入图片描述


    10. 不能构造简单优先关系矩阵的错误示例一展示(有相同右部):

    在这里插入图片描述


    11. 不能构造简单优先关系矩阵的错误示例二展示(关系发生重合):
    在这里插入图片描述


    12. 分析符号串时的错误示例一演示(没有产生式):

    在这里插入图片描述


    13. 分析符号串时的错误示例一演示(没有产生式):
    在这里插入图片描述


    14. 分析符号串时的错误示例二演示(没有关系):

    在这里插入图片描述


    15. 带关系符号串的分析:

    在这里插入图片描述



    七、完整代码

    项目文件源代码https://download.csdn.net/download/Wang_Dou_Dou_/86506201.

    部分核心代码:

    void Analysis::on_pushButton_14_clicked()   // 按下“L关系”按钮要做的事
    {
        // L={(U,S)|U::=S…}, S可以是终结符或非终结符
        for (int i = 0; i < v1.size(); i++)
        {
            for (int j = 0; j < v2[i].size(); j++)
            {
                int row = m[v1[i]];
                int col = m[v2[i][j][0].toLatin1()];
                L_table[row][col] = 1;   // 相应关系赋值为 1
                LP_table[row][col] = 1;  // 后续还要对该 L+ 关系做处理
            }
        }
    
        // 终端输出 L关系
        qDebug() << "L关系如下:";
        for (int i = 0; i < m.size() ;i++)
        {
            for (int j = 0; j < m.size() ;j++)
            {
                cout << L_table[i][j] << " ";
            }
            cout << endl;
        }
        cout << "---------------------" << endl;
    
        setTable_2(L_table, "L关系");
    }
    void Analysis::on_pushButton_15_clicked()   // 按下“R关系”按钮要做的事
    {
        // L={(U,S)|U::=…S}, S可以是终结符或非终结符
        for (int i = 0; i < v1.size(); i++)
        {
            for (int j = 0; j < v2[i].size(); j++)
            {
                int len = v2[i][j].length();
                int row = m[v1[i]];
                int col = m[v2[i][j][len-1].toLatin1()];
                R_table[row][col] = 1;      // 相应关系赋值为 1
                RP_table[row][col] = 1;     // 后续还要对该 R+ 关系做处理
            }
        }
    
        // 终端输出 R关系
        qDebug() << "R关系如下:";
        for (int i = 0; i < m.size() ;i++)
        {
            for (int j = 0; j < m.size() ;j++)
            {
                cout << R_table[i][j] << " ";
            }
            cout << endl;
        }
        cout << "---------------------" << endl;
        setTable_2(R_table, "R关系");
    }
    
    void Analysis::on_pushButton_17_clicked()   // 按下“等于关系”按钮要做的事
    {
        // = 关系构造, 若有 U → ...S_i S_j..., 则有 S_i = S_j
        for (int i = 0; i < v1.size(); i++)
        {
            for (int j = 0; j < v2[i].size(); j++)
            {
                // 窗口大小为 2
                int fp = 1;
                while (fp < v2[i][j].length())
                {
                    char row_c = v2[i][j][fp - 1].toLatin1();	// 为什么 u_int fp = 1; 就体现在这里
                    char col_c = v2[i][j][fp].toLatin1();
                    int row = m[row_c];
                    int col = m[col_c];
                    Q_table[row][col] = 1;	// 将 等于关系 置为 1
                    fp++;
                }
            }
        }
    
        // 终端输出 等于关系
        qDebug() << "等于关系如下:";
        for (int i = 0; i < m.size() ;i++)
        {
            for (int j = 0; j < m.size() ;j++)
            {
                cout << Q_table[i][j] << " ";
            }
            cout << endl;
        }
        cout << "---------------------" << endl;
        setTable_2(Q_table, "等于关系");
    }
    
    void Analysis::on_pushButton_18_clicked()   // 按下“L+关系”按钮要做的事
    {
        on_pushButton_14_clicked();   // 构造 L关系 的同时构造 L+关系
        // 计算 L+ 关系矩阵(先看列, 再看行)
        for (int j = 0; j < m.size(); j++)
        {
            for (int i = 0; i < m.size(); i++)
            {
                if (LP_table[j][i] == 1)
                {
                    for (int k = 1; k < m.size(); k++)
                    {
                        LP_table[j][k] = LP_table[j][k] || LP_table[i][k];	// 布尔加
                    }
                }
            }
        }
    
        // 终端输出 L+关系
        qDebug() << "L+关系如下:";
        for (int i = 0; i < m.size() ;i++)
        {
            for (int j = 0; j < m.size() ;j++)
            {
                cout << LP_table[i][j] << " ";
            }
            cout << endl;
        }
        cout << "---------------------" << endl;
        setTable_2(LP_table, "L+关系");
    }
    
    void Analysis::on_pushButton_19_clicked()   // 按下“R+关系”按钮要做的事
    {
        on_pushButton_15_clicked();   // 构造 R关系 的同时构造 R+关系
        // 计算 R+ 关系矩阵(先看列, 再看行)
        for (int j = 0; j < m.size(); j++)
        {
            for (int i = 0; i < m.size(); i++)
            {
                if (RP_table[j][i] == 1)
                {
                    for (int k = 1; k < m.size(); k++)
                    {
                        RP_table[j][k] = RP_table[j][k] || RP_table[i][k];	// 布尔加
                    }
                }
            }
        }
    
        // 终端输出 R+关系
        qDebug() << "R+关系如下:";
        for (int i = 0; i < m.size() ;i++)
        {
            for (int j = 0; j < m.size() ;j++)
            {
                cout << RP_table[i][j] << " ";
            }
            cout << endl;
        }
        cout << "---------------------" << endl;
        setTable_2(RP_table, "R+关系");
    }
    
    void Analysis::on_pushButton_16_clicked()   // 按下“小于关系”按钮要做的事
    {
        // “小于” = “等于” × “L+” (注意这是矩阵相乘)
        on_pushButton_17_clicked();   // 构造“等于关系”
        on_pushButton_18_clicked();   // 构造“L+关系”
    
    
        matrixMultiplication(Q_table, LP_table, XY_table, m.size());
    
        // 终端输出 小于关系
        qDebug() << "小于关系如下:";
        for (int i = 0; i < m.size() ;i++)
        {
            for (int j = 0; j < m.size() ;j++)
            {
                cout << XY_table[i][j] << " ";
            }
            cout << endl;
        }
        cout << "---------------------" << endl;
        setTable_2(XY_table, "小于关系");
    }
    
    void Analysis::on_pushButton_20_clicked()   // 按下“大于关系”按钮要做的事
    {
        // “大于” = “(R+)^T” × “等于” × “L*” (注意这是矩阵相乘)
        on_pushButton_18_clicked();   // 构造“L*关系”之前需要构造 L+ 关系
        for(int i = 0; i < m.size(); i++)
        {
            for (int j = 0; j < m.size(); j++)
            {
                LX_table[i][j] = LP_table[i][j];
                if (i == j)
                {
                    LX_table[i][i] = 1;
                }
            }
        }
        int res_table_1[100][100] = {{0}};
        int res_table_2[100][100] = {{0}};
        on_pushButton_19_clicked();   // 构造“R+关系”
        on_pushButton_17_clicked();   // 构造“等于关系”
        T(RP_table, res_table_1, m.size());
        matrixMultiplication(res_table_1, Q_table, res_table_2, m.size());
        matrixMultiplication(res_table_2, LX_table, DY_table, m.size());
    
        QMap<char, int>::iterator iter;
        // 此时还要将有非终结符号的列置零!!!
        for (int i = 0; i < v1.size(); i++)
            for (int j = 0; j < m.size(); j++)
                DY_table[j][m[v1[i]]] = 0;
    
        // 终端输出 大于关系
        qDebug() << "大于关系如下:";
        for (int i = 0; i < m.size() ;i++)
        {
            for (int j = 0; j < m.size() ;j++)
            {
                cout << DY_table[i][j] << " ";
            }
            cout << endl;
        }
        cout << "---------------------" << endl;
        setTable_2(DY_table, "大于关系");
    }
    
    void Analysis::matrixMultiplication(int m1[][100], int m2[][100], int result[][100], int n)   // 矩阵乘法
    {
        // qDebug() << "矩阵运算过程:";
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                for (int k = 0; k < n ; k++)
                {
                    result[i][j] |= m1[i][k] * m2[k][j];
                }
            }
        }
        return ;
    }
    
    void Analysis::T(int m[][100], int result[][100], int n)  // 矩阵的转置
    {
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n ; j++)
            {
                result[j][i] = m[i][j];
            }
        }
    }
    
    void Analysis::on_pushButton_21_clicked()   // 按下“优先关系矩阵”按钮要做的事
    {
        on_pushButton_17_clicked();    // “等于关系”
        on_pushButton_16_clicked();    // “小于关系”
        on_pushButton_20_clicked();    // “大于关系”
        int flag = 1;
        for (int i = 0 ; i < m.size(); i++)
        {
            for (int j = 0 ; j < m.size(); j++)
            {
                int tmp1 = 0, tmp2 = 0, tmp3 = 0;
                if (Q_table[i][j] == 1)     // =
                {
                    Res_Matrix[i][j] = 2;
                    tmp1++;
                }
                if (XY_table[i][j] == 1)    // <
                {
                    Res_Matrix[i][j] = 3;
                    tmp2++;
                }
                if (DY_table[i][j] == 1)    // >
                {
                    Res_Matrix[i][j] = 4;
                    tmp3++;
                }
                if (tmp1 + tmp2 + tmp3 == 0)
                    Res_Matrix[i][j] = -1;      // 这两个符号之间没有关系
                if (tmp1 + tmp2 + tmp3 > 1)     // 这两个符号之间有多重关系
                {
                    QChar X,Y;
                    X = QChar(m.key(i));
                    Y = QChar(m.key(j));
                    if (tmp1 == 0)  // 如果成立则说明 tmp2 + tmp3 = 2
                    {
                        QString str = "该文法中";
                        str = str + X + "和" + Y + "存在 > 和 < 的多重关系!不能构造简单优先关系矩阵!" ;
                        QMessageBox::information(this, "提示", str);
                    }
                    else if(tmp2 ==0)
                    {
                        QString str = "该文法中 ";
                        str = str + X + " 和 " + Y + " 存在 = 和 > 的多重关系!不能构造简单优先关系矩阵!" ;
                        QMessageBox::information(this, "提示", str);
                    }
                    else if (tmp3 == 0)
                    {
                        QString str = "该文法中 ";
                        str = str + X + " 和 " + Y + " 存在 = 和 < 的多重关系!不能构造简单优先关系矩阵!" ;
                        QMessageBox::information(this, "提示", str);
                    }
                    else
                    {
                        QString str = "该文法中 ";
                        str = str + X + " 和 " + Y + " 存在 = 、> 和 < 的多重关系!不能构造简单优先关系矩阵!" ;
                        QMessageBox::information(this, "提示", str);
                    }
                    qDebug() << "对于任意两个语法符号 X 和 Y ,至多成立一种优先关系;";
                    flag = 0;
                    open = 0;   // 如果 优先关系矩阵 都不能构造, 则无法分析符号串
                }
            }
        }
    
        if (flag == 1)
        {
            // 终端输出 优先关系矩阵
            qDebug() << "优先关系矩阵如下:";
            for (int i = 0; i < m.size() ;i++)
            {
                for (int j = 0; j < m.size() ;j++)
                {
                    cout << Res_Matrix[i][j] << " ";
                }
                cout << endl;
            }
            cout << "---------------------" << endl;
    
            setTable_2(Res_Matrix, "优先关系矩阵");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330


    八、参考附录

    [1] Qt 5.14.2 下载、安装、使用教程,Qt+vs2019开发环境搭建
    链接: https://www.bilibili.com/video/BV1r54y1G7m4.


    ⭐️ ⭐️

  • 相关阅读:
    如何通过编码器信号计算输送线/输送带线速度(飞剪、追剪算法基础)
    19-CSS弹性盒布局
    Python爬虫之BeautifulSoup4使用
    计算机系统(9)----- 进程控制
    SQL Server教程 - T-SQL-索引(INDEX)
    基于ATX的自动化测试管理软件:Q-Automation
    智能安防监控如何助力汽车4S店信息化精细化管理?最大程度做到降本增效?
    冰蝎逆向初探
    2022中国DevOps社区峰会 走进国产数据库的技术创新实践
    freeswitch的话单模块
  • 原文地址:https://blog.csdn.net/Wang_Dou_Dou_/article/details/126636951