• 算符优先分析法


    (1)输入一个文法根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否为算符优先文法

    (2)输入一个句子进行分析

     

    1、根据文法求FIRSTVT集和LASTVT

    给定一个上下文无关文法,根据算法设计一个程序,求文法中每个非终结符的FirstVT 集和LastVT 集。

    可参考算法描述如下:

    /* FirstVT 集的算法*/

    PROCEDURE insert(P,a);

    IF not F[P,a] then

    begin

    F[P,a] = true; //(P,a)进栈

    end;

    Procedure FirstVT;

    Begin

    for 对每个非终结符 P和终结符 a do

    F[P,a] = false

    for 对每个形如 P        a…或 PQa…的产生式 do

    Insert(P,a)

    while stack 非空

    begin

    栈顶项出栈,记为(Q,a)

    for 对每条形如 PQ…的产生式 do

    insert(P,a)

    end;

    end.

    同理,可构造计算LASTVT的算法。

    2、构造算符优先分析表

    依据文法和求出的相应FirstVT LastVT 集生成算符优先分析表。

    参考算法描述如下:

    for 每个形如 P->X1X2Xn的产生式 do

    for i =1 to n-1 do

    begin

    if XiXi+1都是终结符 then

    Xi = Xi+1

    if i<= n-2, XiXi+2 是终结符, Xi+1 为非终结符 then

    Xi = Xi+2

    if Xi为终结符, Xi+1为非终结符 then

    for FirstVT 中的每个元素 a do

    Xi < a ;

    if Xi为非终结符, Xi+1为终结符 then

    for LastVT 中的每个元素 a do

    a > Xi+1 ;

    end

    3、构造控制程序

        参考 算法描述如下:

    stack S;

    k = 1; //符号栈S的使用深度

    S[k] = '#'

    REPEAT

    把下一个输入符号读进a中;

    If S[k] VT then j = k else j = k-1;

    While S[j] > a do

    Begin

    Repeat

    Q = S[j];

    if S[j-1] VT then j = j-1 else j = j-2

    until S[j] < Q;

    S[j+1]…S[k]归约为某个N,并输出归约为哪个符号;

    K = j+1;

    S[k] = N;

    end of while

    if S[j] < a or S[j] = a then

    begin k = k+1; S[k] = a end

    else error //调用出错诊察程序

    until a = '#'

    4、对给定的表达式,给出准确与否的分析过程

    5、给出表达式的计算结果。

    源程序

    #include<iostream>

    #include<fstream>

    #include<stdio.h>

    #include<stdlib.h>

    #include<string.h>

    using namespace std;

    char str1[50][50]; //存放优先表

    struct csc{ //用结构体数组来存放产生式

        char Left; //存放产生式的左部

        char Right[100]; //存放产生式的右部

    }G[100];

    struct db{

        char VN; //用于存放 FIRSTVT(P) 和 LASTVT(P) 的非终结符

        char VtoT[100]; //用于存放 FIRSTVT(P) 和 LASTVT(P) 的终结符

    }firstvt[100], lastvt[100];

    int Capital(char ch) // 判断是否是非终结符,默认大写字母为非终结符,其他为终结符

    {

        if (ch >= 'A'&&ch <= 'Z')

            return 1;

        else

            return 0;

    }

    void Issfwf(csc G[], int length) //判断文法是否为算符文法

    {

        int i, j;

        int flag = 0;

        for (i = 0; i<length; i++)

        {

            for (j = 0; j<strlen(G[i].Right) - 1; j++)

            if (Capital(G[i].Right[j]) == 1 && Capital(G[i].Right[j + 1]) == 1)

            {

                flag = 1;

                break;

            }

        }

        if (flag == 1)

        {

            cout << " 该文法不是算符文法 !" << endl;

            return;

        }

        else

            cout << " 该文法是算符文法 !" << endl;

    }

    void Clean(db VNT[], int length1) //去掉集合中重复部分

    {

        char str1[20];

        char str2[20][100];

        int i, j, k, t;

        int length;

        int flag;

        for (i = 0; i<length1; i++)

        {

            str1[i] = VNT[i].VN;

            strcpy_s(str2[i], VNT[i].VtoT);

        }

        for (i = 0; i<length1; i++)

            memset(VNT[i].VtoT, 0, sizeof(VNT[i].VtoT));

        for (i = 0; i<length1; i++)

        {

            t = 0;

            length = strlen(str2[i]);

            for (j = 0; j<length; j++)

            {

                flag = 1;

                for (k = 0; k<t; k++)

                if (VNT[i].VtoT[k] == str2[i][j])

                    flag = 0;

                if (flag == 1)

                    VNT[i].VtoT[t++] = str2[i][j];

            }

            length = strlen(VNT[i].VtoT);

        }

    }

    void FIRSTVT(csc G[], db firstvt[], int length) //求各非终结符的 FIRSTVT 集合

    {

        int flag = 0, length1 = 0;

        int i, j, k;

        for (i = 0; i<100; i++)

            memset(firstvt[i].VtoT, 0, sizeof(firstvt[i].VtoT));

        while (flag<length)

        {

            j = 0;

            firstvt[length1].VN = G[flag].Left;

            while (firstvt[length1].VN == G[flag].Left)

            {

                if (Capital(G[flag].Right[0]) == 0) //P->a...则将 a加入 firstvt(P) 中

                    firstvt[length1].VtoT[j++]=G[flag].Right[0];

                else if (Capital(G[flag].Right[0]) == 1 && Capital(G[flag].Right[1]) == 0) //P->Qa...则将 a加入 firstvt(P) 中

                firstvt[length1].VtoT[j++] = G[flag].Right[1];

                flag++;

            }

            length1++;

        } for (i = length - 1; i >= 0; i--) //P->Q...,则将 Q 中的终结符加入 P 中

        if (Capital(G[i].Right[0]) == 1 && G[i].Left != G[i].Right[0])

        {

            for (j = 0; j<length1; j++)

            if (firstvt[j].VN == G[i].Right[0])

                break;

            for (k = 0; k<length1; k++)

            if (firstvt[k].VN == G[i].Left)

                break;

            strcat_s(firstvt[k].VtoT, firstvt[j].VtoT);

        }

        Clean(firstvt, length1);

        for (i = 0; i<length1; i++) //集合输出

        {

            cout << "FIRSTVT(";

            cout << firstvt[i].VN << ")" << "=" << "{";

            cout << firstvt[i].VtoT[0];

            for (j = 1; j<strlen(firstvt[i].VtoT); j++)

                cout << "," << firstvt[i].VtoT[j];

            cout << "}" << endl;

        }

    }

    void LASTVT(csc G[], db lastvt[], int length) //求各非终结符的 FIRSTVT 集合

    {

        int flag = 0, length1 = 0;

        int i, j, k, t;

        for (i = 0; i<100; i++)

            memset(lastvt[i].VtoT, 0, sizeof(lastvt[i].VtoT));

        while (flag<length)

        {

            j = 0;

            lastvt[length1].VN = G[flag].Left;

            while (lastvt[length1].VN == G[flag].Left)

            {

                t = strlen(G[flag].Right) - 1; if (Capital(G[flag].Right[t]) == 0) //P->...a 则将 a加入 lastvt(P)中

                    lastvt[length1].VtoT[j++] = G[flag].Right[t];

                else if (Capital(G[flag].Right[t]) == 1 && Capital(G[flag].Right[t - 1]) == 0) //P->...aQ 则将 a 加入 lastvt(P)中

                    lastvt[length1].VtoT[j++]=G[flag].Right[t-1];

                    flag++;

            }

            length1++;

        }

        for (i = length - 1; i >= 0; i--) //P->...Q,则将 Q 中的终结符加入 P 中

        {

            t = strlen(G[flag].Right) - 1;

        if (Capital(G[i].Right[t]) == 1 && G[i].Left != G[i].Right[t])

        {

            for (j = 0; j<length1; j++)

            if (lastvt[j].VN == G[i].Right[t])

                break;

            for (k = 0; k<length1; k++)

            if (lastvt[k].VN == G[i].Left)

                break;

            strcat_s(lastvt[k].VtoT, lastvt[j].VtoT);

        }

    }

    Clean(lastvt, length1);

    for (i = 0; i<length1; i++) //集合输出

    {

        cout << "LASTVT(";

        cout << lastvt[i].VN << ")" << "=" << "{";

        cout << lastvt[i].VtoT[0];

        for (j = 1; j<strlen(lastvt[i].VtoT); j++)

            cout << "," << lastvt[i].VtoT[j];

        cout << "}" << endl;

    }

    }

    void StructureTable(csc G[], db firstvt[], db lastvt[], int length) //返回非终结符个数

    {

        char str[50]; //存放终结符

        int i,j,k,flag,i1,i2,length1;

        int t = 0;

        for (i = 0; i<50; i++)

            memset(str1[i], 0, sizeof(str1[i]));

        memset(str, 0, sizeof(str));

        for (i = 0; i<length; i++) //求所有非终结符

        {

            j = strlen(G[i].Right);

            flag = 1;

            for (k = 0; k<j; k++)

            if (Capital(G[i].Right[k]) == 0)

            {

                for (i1 = 0; i1<t; i1++)

                if (G[i].Right[k] == str[i1])

                    flag = 0;

                if (flag == 1)

                    str[t++] = G[i].Right[k];

            }

        } for (i = 0; i<strlen(str); i++) // 与习惯保持一致,将 #置于最后一个

        if (str[i] == '#')

            break;

        swap(str[i], str[strlen(str) - 1]);

        for (i = 1; i <= strlen(str); i++)

        {

            str1[0][i] = str[i - 1];

            str1[i][0] = str[i - 1];

        }

        for (i = 0; i<length; i++)

        {

            length1 = strlen(G[i].Right);

            for (j = 0; j<length1 - 1; j++)

            {

                if (Capital(G[i].Right[j]) == 0 && Capital(G[i].Right[j + 1]) == 0)

                {

                    for (i1 = 0; i1 <= strlen(str); i1++)

                    for (i2 = 0; i2 <= strlen(str); i2++)

                    if (str1[0][i1] == G[i].Right[j] && str1[i2][0] == G[i].Right[j + 1])

                    {

                        if (str1[i1][i2] != 0)

                        {

                            cout << "该文法不是算符优先文法! " << endl;

                            return;

                        }

                        else

                            str1[i1][i2] = '=';

                    }

                }

                if (j<length1 - 2 && Capital(G[i].Right[j]) == 0 && Capital(G[i].Right[j + 2]) == 0 && Capital(G[i].

                    Right[j + 1]) == 1)

                {

                    for (i1 = 0; i1 <= strlen(str); i1++)

                    for (i2 = 0; i2 <= strlen(str); i2++)

                    if (str1[0][i1] == G[i].Right[j] && str1[i2][0] == G[i].Right[j + 2])

                    {

                        if (str1[i1][i2] != 0)

                        {

                            cout << "该文法不是算符优先文法! " << endl;

                            return;

                        }

                        else

                            str1[i1][i2] = '=';

                    }

                }

                if (Capital(G[i].Right[j]) == 0 && Capital(G[i].Right[j + 1]) == 1)

                {

                    for (i1 = 0; str1[0][i1] != G[i].Right[j]; i1++);

                    for (k = 0; firstvt[k].VN != G[i].Right[j + 1]; k++);

                    for (i2 = 0; i2 <= strlen(str); i2++)

                    for (t = 0; t<strlen(firstvt[k].VtoT); t++)

                    if (str1[i2][0] == firstvt[k].VtoT[t])

                    {

                        if (str1[i1][i2] != 0)

                        {

                            cout << "该文法不是算符优先文法! " << endl;

                            return;

                        }

                        else

                            str1[i1][i2] = '<';

                    }

                }

                if (Capital(G[i].Right[j]) == 1 && Capital(G[i].Right[j + 1]) == 0)

                {

                    for (t = 0; lastvt[t].VN != G[i].Right[j]; t++);

                    for (k = 0; k<strlen(lastvt[t].VtoT); k++)

                    for (i1 = 0; i1 <= strlen(str); i1++)

                    for (i2 = 0; i2 <= strlen(str); i2++)

                    if (str1[0][i1] == lastvt[t].VtoT[k] && str1[i2][0] == G[i].Right[j + 1])

                    {

                        if (str1[i1][i2] != 0)

                        {

                            cout << " 该文法不是算符优先文法! " << endl;

                            return;

                        }

                        else

                            str1[i1][i2] = '>';

                    }

                }

            }

        }

        for (i = 0; i <= strlen(str); i++)

        {

            for (j = 0; j <= strlen(str); j++)

                cout << str1[i][j] << " ";

            cout << endl;

        }

    }

    char GetRalation(char a, char b) //找到 a,b 对应的关系

    {

        int i, j;

        for (i = 0; str1[0][i] != a; i++);

        for (j = 0; str1[j][0] != b; j++);

        return str1[i][j];

    }

    void Judge(char *str, csc G[])

    {

        char Q;

        char a;

        char str2[100];

        char S[100];

        int flag = 0;

        int i = 0;

        int j, k;

        int s = 0, step = 1;

        int length; cout.width(5); // 输出表头

        cout.setf(ios::left); cout << "步骤 ";

        cout.width(15);

        cout.setf(ios::left); cout << "符号栈 ";

        cout.width(15);

        cout.setf(ios::left); cout << "输入串 ";

        cout.width(15);

        cout.setf(ios::left); cout << "动作 " << endl;

        memset(S, 0, sizeof(S));

        a = str[0];

        k = 1;

        S[k] = '#';

        while (a != '#')

        {

            a = str[flag++];

            if (Capital(S[k]) == 0)

                j = k;

            else

                j = k - 1;

            while (GetRalation(S[j], a) == '>')

            {

                Q = S[j];

                while (GetRalation(S[j], Q) != '<')

                {

                    Q = S[j];

                    if (Capital(S[j - 1]) == 0)

                        j = j - 1;

                    else

                        j = j - 2;

                }

                cout.width(5);

                cout.setf(ios::left);

                cout << step++;

                cout.width(15);

                cout << S + 1;

                cout.width(15);

                cout.setf(ios::left);

                cout << str + flag - 1;

                cout.width(15);

                cout.setf(ios::left); cout << " 规约 " << endl;

                for (i = j + 2; i <= k; i++)

                    S[i] = 0;

                k = j + 1;

                S[k] = 'N';

            }

            if (GetRalation(S[j], a) == '<' || GetRalation(S[j], a) == '=')

            {

                cout.width(5);

                cout.setf(ios::left);

                cout << step++;

                cout.width(15);

                cout << S + 1;

                cout.width(15);

                // cout.setf(ios::right);

                cout << str + flag - 1;

                if (a != '#')

                {

                    cout.width(15);

                    cout.setf(ios::left); cout << "移进 " << endl;

                }

                k = k + 1;

                S[k] = a;

            }

            else

            {

                cout << " 抱歉,输入的句子有误 " << endl; return;

            }

        } cout << "接受 " << endl; cout << "恭喜你!分析成功! " << endl;

    }

    void main()

    {

        char str3[100]; // 用于存放一个产生式子

        char str2[100]; // 用于存放待检测的字符串

        char filename[10];// 文件名

        int length=0; // 记录产生式个数

        int s = 0;

        cout << "请输入文件名: ";

        cin >> filename;

        memset(str1, 0, sizeof(str1)); //置空字符串

        ifstream fin1(filename);

        if (!fin1)

        {

            cout << "Cannot open the file. "; //未找到对应文件名的文件

            exit(1);

        }

        while (fin1)

        {

            fin1.getline(str3, 100); //读出一个产生式

            cout << str3 << endl; G[length].Left = str3[0]; //产生式的左部

            strcpy_s(G[length].Right, str3 + 3);

            length++;

        }

        length -= 1;

        Issfwf(G, length);

        cout << "各非终结符的 FIRSTVT 集合如下: " << endl;

        FIRSTVT(G, firstvt, length);

        cout << "各非终结符的 LASTVT 集合如下: " << endl;

        LASTVT(G, lastvt, length);

        cout << "构造分析表如下: " << endl;

        StructureTable(G, firstvt, lastvt, length);

        cout << "请任意输入一个输入串 (以#号键结束 ):" << endl;

        cin >> str2;

        Judge(str2, G);

    }

     

  • 相关阅读:
    JS学习笔记11_高级技巧
    【应用】wamp3.x.x设置,让外网能够访问本服务器
    数据建模(二)
    数据建模浅析(一)
    saltstack(四) saltstack的targeting、分组
    saltstack(三) grains、pillar的使用
    saltstack(二) master、minion常用配置选项
    dstat系统分析工具的使用
    PC蓝牙通信C#代码实现
    开源GIS-对比GeoServer和MapServer
  • 原文地址:https://www.cnblogs.com/aishanyishi/p/10305006.html
Copyright © 2020-2023  润新知