算符优先分析法

(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.\n"; //未找到对应文件名的文件

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

}

 

posted @ 2019-01-22 17:31  夏延  阅读(2158)  评论(0编辑  收藏  举报