• 算符优先分析法


    【实验目的】 

    掌握算符优先分析法的原理,利用算符优先分析法将赋值语句进行语法分析。 

    【实验内容】 

    (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…或 P→Qa…的产生式 do

    Insert(P,a)

    while stack  非空

    begin

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

    for  对每条形如 P→Q…的产生式 do

             insert(P,a)

    end;

    end.

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

    2、构造算符优先分析表

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

    参考算法描述如下:

    for  每个形如 P->X1X2…Xn的产生式  do

      for i =1 to n-1 do

      begin

            if Xi和Xi+1都是终结符 then  

               Xi   =   Xi+1

            if i<= n-2, Xi和Xi+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、给出表达式的计算结果。

    【实验结果】 

    图为参考,要求包含firstvt和lastvt集,算符优先表或优先函数表及句子分析过程。

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

  • 相关阅读:
    【redis】redis的 key的命名规则
    【redis】存入redis的值,如果为null是否默认不被存入
    【java】StringBuilder的三种清除方法对比
    【java】hash一致性算法的实现区别【标题暂定】
    【java】Java中十六进制转换 Integer.toHexString()到底做了什么?什么时候会用到它?为什么要用它?byte为什么要&0xff?为什么要和0xff做与运算?
    【java】TreeMap/HashMap的循环迭代中 keySet和entrySet和forEach方式 + map的几种迭代方式
    【java】Map、Set、List不同数据结构的各种不同循环迭代的效率对比,使用场景
    【java】安全加密MessageDigest的功能及用法【hash一致性算法】
    hbase分布式集群搭建
    hadoop分布式集群搭建
  • 原文地址:https://www.cnblogs.com/mxk123456/p/14208219.html
Copyright © 2020-2023  润新知