Design and implementation of operator priority analysis algorithm (including code)

Posted by fuji on Mon, 29 Nov 2021 03:42:11 +0100

Design and implementation of operator priority analysis algorithm

Write in the front: my compilation principle is not very good and I don't listen to lectures, so my idea of writing code is relatively simple. Simple thinking means that the code is very cumbersome. Please cross if you mind. If you have any advice, please leave a message in the comment area.

1, Experimental purpose

  1. According to the operator priority analysis method, the expression is parsed so that it can judge whether an expression is correct.
  2. Through the implementation of operator first analysis method, deepen the understanding of bottom-up syntax analysis method.

2, Experimental content

  1. Input grammar. It can be the grammar of the following arithmetic expression (you can change it as needed):
    E→E+T|E-T|T
    T→T*F|T/F|F
    F→(E)|i

  2. Analyze the given expression and output the judgment of whether the expression is correct or not.
    Example of program input / output:
    Input: 1 + 2;
    Output: correct
    Input: (1 + 2) / 3 + 4 - (5 + 6 / 7);
    Output: correct
    Input: ((1-2) / 3 + 4
    Output: error
    Input: 1 + 2-3 + (* 4 / 5)
    Output: error

  3. Find FIRSTVT set and LASTVT set according to grammar
    Given a context free grammar, a program is designed according to the algorithm to find the FirstVT set and LastVT set of each non terminator in the grammar.
    Find the three rules of Firstvt:
    If you want to find the Firstvt of A, it appears in the candidate of A:
    A - > a..., that is, start with the terminator, and a enters Firstvt
    A - > b.., that is, it starts with a non terminator, and the Firstvt of B enters the Firstvt of A
    A - > ba..., that is, start with a non terminator and immediately follow the terminator, then a enters Firstvt
    Find the three rules of Lastvt:
    If you want to find Lastvt of A, the candidate of A appears:
    A - >... A, that is, it ends with a terminator, and a enters Lastvt
    A - >... B, that is, it ends with a non terminator. The Lastvt of B enters the Lastvt of A
    A - >... aB, that is, it ends with a non terminator first, followed by a terminator, then a enters Lastvt
    According to the above method of finding firstvt and lastvt, we calculate the example I give, and the final result is as follows.

  4. Construction operator priority analysis table
    Let me first outline the construction method:
    First, in the production on the right, find each terminator.
    If it is a single terminator, ignore it.
    First find the form of... aB... Which represents a < FIRSTVT (b).
    Find a in the left column of the operator priority analysis table, and then mark < < on the position of the corresponding element of each firstvt(B) to the right.
    Find the form of... Ba... Which means a > LASTVT (b).
    Find a in the upper row of the operator priority analysis table, and then mark down the position of the element of each lastvt(B).
    If there are... ab... Or... aCb... Cases, mark =, at the position of row a and column b.
    Let me talk about it with examples:
    First, construct the table:

+-*/()i#
+
-
*
/
(
)
i
#

Then let's look at the first line of grammar:
E->E+T|E-T|T
The first non terminator is +.
In fact, E+T represents LASTVT (E) < + < FIRSTVT (T).
Every time we watch <, then >.
+< FIRSTVT (T), i.e. + < *, /, (I).
< is from left to right, so it is necessary to mark < < at the four positions (+, *) (+, /) (+, () (+, i).
Namely:

+-*/()i#
+<<<<
-
*
/
(
)
i
#

Then look at >.
+>LASTVT (E), i.e. + > +, -, *, /,), i.
< from top to bottom, so mark > > in the six positions (+, +) (-, +) (*, +) (/, +) (), +) (i, +).
Namely:

+-*/()i#
+><<<<
->
*>
/>
(
)>
i>
#

First two lines of grammar:
E->E+T|E-T|T
T->T*F|T/F|F
The +, -, *, / are the same as what I said above.
The following table is available:

+-*/()i#
+>><<<<
->><<<<
*>>>><<
/>>>><<
(
)>>>>
i>>>>
#

Finally, let's look at the last Grammar:
F->(E)|i
i is just a terminator. There is no size relationship. Don't look at it.
And (E) is (< FIRSTVT (E); LASTVT (E) <).
And (E) if... aBc... Is satisfied, the position of column (row, column) shall be marked with =.
The following table is available:

+-*/()i#
+>><<<><
->><<<><
*>>>><><
/>>>><><
(<<<<<=<
)>>>>>
i>>>>>
#

Finally, if you want to consider #.
We consider it #E#.
Namely: # < FIRSTVT (E); LASTVT (E) < #.
Final table available:

+-*/()i#
+>><<<><>
->><<<><>
*>>>><><>
/>>>><><>
(<<<<<=<
)>>>>>>
i>>>>>>
#<<<<<<=

This is the operator precedence grammar we require.

  1. For a given expression, the analysis process of whether it is accurate or not is given, and the calculation results of the expression are given.
    In fact, we can just look at the grammar directly during the specification (if the grammar is relatively simple), but I'll talk about how to specify according to the operator priority analysis table.
    In a word: find out whether the corresponding position of the rightmost terminator of the stack and the leftmost terminator of the input string is <, > or =. < move in, > specify, = move in first and then specify. If the corresponding position in the table is a space, it means that the expression is wrong.
    For example: # (i+i)/i+i-(i+i/i)#
stepStackInput stringaction
0#(i+i)/i+i-(i+i/i)#get set
1#(i+i)/i+i-(i+i/i)#Look up the table, (#, () = <, move in
2#(i+i)/i+i-(i+i/i)#Look up the table, (, i) = <, move in
3#(N+i)/i+i-(i+i/i)#Look up the table, (i, +) = >, protocol (N can be replaced with other capital letters)
4#(N+i)/i+i-(i+i/i)#(, +) = <, move in
5#(N+i)/i+i-(i+i/i)#(+, i) = <, move in
6#(N+N)/i+i-(i+i/i)#(i,) = >, protocol
7#(N)/i+i-(i+i/i)#(+,) = >, protocol
8#(N)/i+i-(i+i/i)#(,) = =, move in first
9#N/i+i-(i+i/i)#Post protocol
10#N#Well, I'm lazy and don't want to write. Anyway, <, >, = there are all three situations. Draw inferences from one instance

3, Experimental code

//owner:junfuxiaotong
//date:2021/11/28
#include<bits/stdc++.h>
#include<cstdlib>
using namespace std;
#define N 100
#define true 1
#define false -1
char wenfa[N][N];
char VN[N],VT[N];
char firstvt[N][N],lastvt[N][N],table[N][N];
int vnvt(int n)//Get vn vt
{
    int flag=true;
    for(int i=0;i<n;i++)
    {
        if((wenfa[i][0]>='A'&&wenfa[i][0]<='Z')&&wenfa[i][1]=='-'&&wenfa[i][2]=='>')
        {
            VN[i]=wenfa[i][0];
        }
        else
        {
            flag=false;
            break;
        }
    }
    if(flag==false)
    {
        return flag;
    }
    else
    {
        int k=0;
        int l=0;
        for(int i=0;i<n;i++)
        {
            for(int j=3;wenfa[i][j]!='\0';j++)
            {
                if((wenfa[i][j]<'A'||wenfa[i][j]>'Z')&&wenfa[i][j]!='|')
                {
                    for(l=0;l<k;l++)
                    {
                        if(wenfa[i][j]==VT[l])
                        {
                            break;
                        }
                    }
                    if(l==k)
                    {
                        VT[k]=wenfa[i][j];
                        k++;
                    }
                }
            }
        }
        return flag;
    }
}
void getfirstvt(int n)
{
    // int point=0; / / used to point to the first two symbols of each production
    for(int i=0;i<n;i++)//First, find out whether the first two symbols of each production are terminators, and add them to the corresponding firstvt set.
    {
        int flag=true;
        for(int j=3;;)
        {
            for(int k=0;k<strlen(VT);k++)
            {
                if(wenfa[i][j]==VT[k])
                {
                    int mark=true;//Used to check whether the terminator already exists in the firstvt set.
                    for(int l=0;l<strlen(firstvt[i]);l++)
                    {
                        if(wenfa[i][j]==firstvt[i][l])
                        {
                            mark=false;
                            break;
                        }
                    }
                    if(mark==true)//If it does not exist, it is added to the firstvt set
                    {
                        int length=strlen(firstvt[i]);
                        firstvt[i][length]=wenfa[i][j];
                    }
                }
                if(wenfa[i][j+1]==VT[k])
                {
                    int mark=true;
                    for(int l=0;l<strlen(firstvt[i]);l++)
                    {
                        if(wenfa[i][j+1]==firstvt[i][l])
                        {
                            mark=false;
                            break;
                        }
                    }
                    if(mark==true)
                    {
                        int length=strlen(firstvt[i]);
                        firstvt[i][length]=wenfa[i][j+1];
                    }
                }
            }
            while(wenfa[i][j]!='|')
            {
                if(wenfa[i][j]=='\0')
                {
                    flag=false;
                    break;
                }
                j++;
            }
            j++;
            if(flag==false)
            {
                break;
            }
        }
    }
    //The following code loops to see which first VT sets of non terminators can be added to the first VT sets of other non terminators until the length of each non terminator does not change.
    int *origin=new int[n];//Used to record the length of the array before traversal to see if there is any change.
    while(1)
    {
        int sign=true;//Used to identify whether firstvt changes before and after traversal.
        for(int i=0;i<n;i++)
        {
            if(origin[i]!=strlen(firstvt[i]))
            {
                sign=false;//Change in length
                origin[i]=strlen(firstvt[i]);
            }
        }
        if(sign==true)
        {
            break;
        }
        for(int i=0;i<n;i++)
        {
            for(int j=3;;)
            {
                for(int k=0;k<n;k++)
                {
                    if(k==i)
                    {
                        continue;
                    }
                    else if(wenfa[i][j]==wenfa[k][0])
                    {
                        for(int l=0;l<strlen(firstvt[k]);l++)
                        {
                            int flag=true;//It is used to identify whether a terminator is already in the firstvt set. true means that it is not in it.
                            for(int m=0;m<strlen(firstvt[i]);m++)
                            {
                                if(firstvt[k][l]==firstvt[i][m])
                                {
                                    flag=false;
                                    break;
                                }
                            }
                            if(flag==false)
                            {
                                continue;
                            }
                            else
                            {
                                int length=strlen(firstvt[i]);
                                firstvt[i][length]=firstvt[k][l];
                            }
                        }
                    }
                }
                int flag=true;
                while(wenfa[i][j]!='|')
                {
                    if(wenfa[i][j]=='\0')
                    {
                        flag=false;
                        break;
                    }
                    j++;
                }
                if(flag==false)
                {
                    break;
                }
                j++;
            }
        }
    }
}
void getlastvt(int n)//Get the lastvt set. The subscript of this function starts with abc... And I don't know why
{
    for(int a=0;a<n;a++)
    {
        for(int b=0;;)
        {
            int sign=true;//It is used to identify whether it has reached the end of a sentence division
            while(wenfa[a][b]!='|')
            {
                if(wenfa[a][b]=='\0')
                {
                    sign=false;
                    break;
                }
                b++;
            }
            for(int c=0;c<strlen(VT);c++)
            {
                if(wenfa[a][b-1]==VT[c])
                {
                    int flag=true;
                    for(int e=0;e<strlen(lastvt[a]);e++)
                    {
                        if(wenfa[a][b-1]==lastvt[a][e])
                        {
                            flag=false;
                            break;
                        }
                    }
                    if(flag==true)
                    {
                        int length=strlen(lastvt[a]);
                        lastvt[a][length]=VT[c];
                    }
                }
                if(wenfa[a][b-2]==VT[c])
                {
                    int flag=true;
                    for(int e=0;e<strlen(lastvt[a]);e++)
                    {
                        if(wenfa[a][b-2]==lastvt[a][e])
                        {
                            flag=false;
                            break;
                        }
                    }
                    if(flag==true)
                    {
                        int length=strlen(lastvt[a]);
                        lastvt[a][length]=VT[c];
                    }
                }
            }
            if(sign==false)
            {
                break;
            }
            b++;//B + + is set here because wenfa[a][b] = = '|', so the previous while loop cannot scan the forward subscript, so skip the subscript first.
        }
    }
    //The code below is as like as two peas of getfirstvt, but just changing all firstvt to lastvt.
    int *origin=new int[n];//Used to record the length of the array before traversal to see if there is any change.
    while(1)
    {
        int sign=true;//Used to identify whether lastvt changes before and after traversal.
        for(int i=0;i<n;i++)
        {
            if(origin[i]!=strlen(lastvt[i]))
            {
                sign=false;//Change in length
                origin[i]=strlen(lastvt[i]);
            }
        }
        if(sign==true)
        {
            break;
        }
        for(int i=0;i<n;i++)
        {
            for(int j=3;;)
            {
                for(int k=0;k<n;k++)
                {
                    if(k==i)
                    {
                        continue;
                    }
                    else if(wenfa[i][j]==wenfa[k][0])
                    {
                        for(int l=0;l<strlen(lastvt[k]);l++)
                        {
                            int flag=true;//It is used to identify whether a terminator is already in the lastvt set. true means that it is not in it.
                            for(int m=0;m<strlen(lastvt[i]);m++)
                            {
                                if(lastvt[k][l]==lastvt[i][m])
                                {
                                    flag=false;
                                    break;
                                }
                            }
                            if(flag==false)
                            {
                                continue;
                            }
                            else
                            {
                                int length=strlen(lastvt[i]);
                                lastvt[i][length]=lastvt[k][l];
                            }
                        }
                    }
                }
                int flag=true;
                while(wenfa[i][j]!='|')
                {
                    if(wenfa[i][j]=='\0')
                    {
                        flag=false;
                        break;
                    }
                    j++;
                }
                if(flag==false)
                {
                    break;
                }
                j++;
            }
        }
    }
}
void gettable(int n)
{
    char data[N];//Used to save each production
    for(int i=0;i<n;i++)//<
    {
        int dt=0;
        // int flag=true;
        for(int j=3;;)
        {
            if(wenfa[i][j]=='|'||wenfa[i][j]=='\0')
            {
                if(strlen(data)!=1)
                {
                    for(int k=0;k<strlen(data);k++)
                    {
                        if(data[k]<'A'||data[k]>'Z')
                        {
                            if(data[k+1]!='\0'&&data[k+1]>='A'&&data[k+1]<='Z')
                            {
                                int x;
                                int yk;
                                for(int l=0;l<strlen(VT);l++)
                                {
                                    if(data[k]==VT[l])
                                    {
                                        x=l;
                                        break;
                                    }
                                }
                                for(int l=0;l<strlen(VN);l++)
                                {
                                    if(data[k+1]==VN[l])
                                    {
                                        yk=l;
                                        break;
                                    }
                                }
                                for(int l=0;l<strlen(firstvt[yk]);l++)
                                {
                                    for(int m=0;m<strlen(VT);m++)
                                    {
                                        if(firstvt[yk][l]==VT[m])
                                        {
                                            if(table[x][m]=='\0')
                                            {
                                                table[x][m]='<';
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                if(wenfa[i][j]=='\0')
                {
                    break;
                }
                j++;
                memset(data,'\0',sizeof(data));
                dt=0;
            }
            else
            {
                data[dt]=wenfa[i][j];
                j++;
                dt++;
            }
        }
    }
    for(int i=0;i<n;i++)//>Actually, it's almost the same as the < above
    {
        int dt=0;
        // int flag=true;
        for(int j=3;;)
        {
            if(wenfa[i][j]=='|'||wenfa[i][j]=='\0')
            {
                if(strlen(data)!=1)
                {
                    for(int k=0;k<strlen(data);k++)
                    {
                        if(data[k]<'A'||data[k]>'Z')
                        {
                            if(k>=1&&data[k-1]>='A'&&data[k-1]<='Z')
                            {
                                int y;
                                int xk;
                                for(int l=0;l<strlen(VT);l++)
                                {
                                    if(data[k]==VT[l])
                                    {
                                        y=l;
                                        break;
                                    }
                                }
                                for(int l=0;l<strlen(VN);l++)
                                {
                                    if(data[k-1]==VN[l])
                                    {
                                        xk=l;
                                        break;
                                    }
                                }
                                for(int l=0;l<strlen(lastvt[xk]);l++)
                                {
                                    for(int m=0;m<strlen(VT);m++)
                                    {
                                        if(lastvt[xk][l]==VT[m])
                                        {
                                            if(table[m][y]=='\0')
                                            {
                                                table[m][y]='>';
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                if(wenfa[i][j]=='\0')
                {
                    break;
                }
                j++;
                memset(data,'\0',sizeof(data));
                dt=0;
            }
            else
            {
                data[dt]=wenfa[i][j];
                j++;
                dt++;
            }
        }
    }
    for(int i=0;i<n;i++)//=
    {
        int dt=0;
        // int flag=true;
        for(int j=3;;)
        {
            if(wenfa[i][j]=='|'||wenfa[i][j]=='\0')
            {
                if(strlen(data)!=1)
                {
                    for(int k=0;k<strlen(data);k++)
                    {
                        if(data[k]<'A'||data[k]>'Z')
                        {
                            if(data[k+1]!='\0'&&(data[k+1]<'A'||data[k+1]>'Z'))
                            {
                                int x,y;
                                for(int l=0;l<strlen(VT);l++)
                                {
                                    if(data[k]==VT[l])
                                    {
                                        x=l;
                                    }
                                    if(data[k+1]==VT[l])
                                    {
                                        y=l;
                                    }
                                }
                                if(table[x][y]=='\0')
                                {
                                    table[x][y]='=';
                                }
                            }
                            if(data[k+2]!='\0'&&(data[k+2]<'A'||data[k+2]>'Z'))
                            {
                                int x,y;
                                for(int l=0;l<strlen(VT);l++)
                                {
                                    if(data[k]==VT[l])
                                    {
                                        x=l;
                                    }
                                    if(data[k+2]==VT[l])
                                    {
                                        y=l;
                                    }
                                }
                                if(table[x][y]=='\0')
                                {
                                    table[x][y]='=';
                                }
                            }
                        }
                    }
                }
                if(wenfa[i][j]=='\0')
                {
                    break;
                }
                j++;
                memset(data,'\0',sizeof(data));
                dt=0;
            }
            else
            {
                data[dt]=wenfa[i][j];
                j++;
                dt++;
            }
        }
    }
    int jinghao=strlen(VT);
    table[jinghao][jinghao]='=';
    for(int i=0;i<strlen(VT);i++)
    {
        for(int j=0;j<strlen(firstvt[0]);j++)
        {
            if(VT[i]==firstvt[0][j])
            {
                table[jinghao][i]='<';
                break;
            }
        }
    }
    for(int i=0;i<strlen(VT);i++)
    {
        for(int j=0;j<strlen(lastvt[0]);j++)
        {
            if(VT[i]==lastvt[0][j])
            {
                table[i][jinghao]='>';
                break;
            }
        }
    }
}
void fenxi(char *sentence)
{
    char in[N];
    in[0]='#';
    char out[N];
    for(int i=0;i<strlen(sentence);i++)
    {
        out[i]=sentence[i];
    }
    out[strlen(sentence)]='#';
    int step=0;
    int lin=1;
    int lout=strlen(sentence)+1;
    cout<<step<<'\t';
    for(int i=0;i<lin;i++)
    {
        cout<<in[i];
    }
    cout<<'\t';
    for(int i=0;i<lout;i++)
    {
        cout<<out[i];
    }
    cout<<'\t'<<"get set"<<endl;
    int flag=true;
    while(true)
    {
        int i=lin-1;
        while(in[i]=='N')
        {
            i--;
        }
        int j=0;
        int x,y;
        for(int k=0;k<strlen(VT);k++)
        {
            if(in[i]==VT[k])
            {
                x=k;
            }
            if(out[0]==VT[k])
            {
                y=k;
            }
        }
        if((in[i]>='a'&&in[i]<='z')||(in[i]>='0'&&in[i]<='9'))
        {
            for(int k=0;k<strlen(VT);k++)
            {
                if('i'==VT[k])
                {
                    x=k;
                }
            }
        }
        if((out[0]>='a'&&out[0]<='z')||(out[0]>='0'&&out[0]<='9'))
        {
            for(int k=0;k<strlen(VT);k++)
            {
                if('i'==VT[k])
                {
                    y=k;
                }
            }
        }
        if(in[i]=='#')
        {
            x=strlen(VT);
        }
        if(out[0]=='#')
        {
            y=strlen(VT);
        }
        if(x==y&&y==strlen(VT))
        {
            break;
        }
        if(table[x][y]=='<')
        {
            in[lin]=out[0];
            lin++;
            lout--;
            for(int l=0;l<lout;l++)
            {
                out[l]=out[l+1];
            }
            step++;
            cout<<step<<'\t';
            for(int l=0;l<lin;l++)
            {
                cout<<in[l];
            }
            cout<<'\t';
            for(int l=0;l<lout;l++)
            {
                cout<<out[l];
            }
            cout<<'\t'<<"Move in"<<endl;
        }
        else if(table[x][y]=='=')
        {
            step++;
            cout<<step<<'\t';
            for(int l=0;l<lin;l++)
            {
                cout<<in[l];
            }
            cout<<out[0]<<'\t';
            for(int l=1;l<lout;l++)
            {
                cout<<out[l];
            }
            cout<<'\t'<<"Move in"<<endl;
            in[i]='N';
            int lin1=lin;
            for(int k=i+1;k<lin1;k++)
            {
                in[k]='\0';
                lin--;
            }
            lout--;
            for(int k=0;k<lout;k++)
            {
                out[k]=out[k+1];
            }
            step++;
            cout<<step<<'\t';
            for(int l=0;l<lin;l++)
            {
                cout<<in[l];
            }
            cout<<'\t';
            for(int l=1;l<lout;l++)
            {
                cout<<out[l];
            }
            cout<<'\t'<<"Statute"<<endl;
        }
        else if(table[x][y]=='>')
        {
            while(true)
            {
                if(in[i-1]=='N')
                {
                    i--;
                }
                else
                {
                    break;
                }
            }
            in[i]='N';
            int lin1=lin;
            for(int k=i+1;k<lin1;k++)
            {
                in[k]='\0';
                lin--;
            }
            step++;
            cout<<step<<'\t';
            for(int k=0;k<lin;k++)
            {
                cout<<in[k];
            }
            cout<<'\t';
            for(int k=0;k<lout;k++)
            {
                cout<<out[k];
            }
            cout<<'\t'<<"Statute"<<endl;
        }
        else
        {
            flag=false;
            break;
        }
    }
    if(flag==true)
    {
        cout<<"Congratulations, your sentence is OK."<<endl;
    }
    else if(flag==false)
    {
        cout<<"There is no corresponding relationship between these two non terminators in the operator priority analysis table. Matching failed."<<endl;
    }
}
int main()
{
    cout<<"Please use English input method to input grammar, enter#On behalf of the end. In addition: This program has no error detection function for the right part of grammar. "<<endl;
    int n;
    while(1)
    {
        int i=0;
        do
        {
            cin>>wenfa[i];
            i++;
        } while (wenfa[i-1][0]!='#');
        n=i-1;//Grammar quantity
        // for(i=0;i<n;i++)
        // {
        //     cout<<wenfa[i]<<endl;
        // }
        if(vnvt(n)==false)
        {
            cout<<"The left part of the grammar you entered may be wrong. Please check it and re-enter it."<<endl;
        }
        else
        {
            break;
        }
    }
    getfirstvt(n);
    getlastvt(n);
    gettable(n);
    cout<<"---------------------------------------------------"<<endl<<"Non terminators are: VN={";
    for(int i=0;i<strlen(VN);i++)
    {
        cout<<VN[i];
        if(i!=strlen(VN)-1)
        {
            cout<<',';
        }
    }
    cout<<'}'<<endl<<"Terminators are: VT={";
    for(int i=0;i<strlen(VT);i++)
    {
        cout<<VT[i];
        if(i!=strlen(VT)-1)
        {
            cout<<',';
        }
    }
    cout<<'}'<<endl<<"---------------------------------------------------"<<endl;
    for(int i=0;i<strlen(VN);i++)
    {
        cout<<"FIRSTVT("<<VN[i]<<")={";
        for(int j=0;j<strlen(firstvt[i]);j++)
        {
            cout<<firstvt[i][j];
            if(j!=strlen(firstvt[i])-1)
            {
                cout<<',';
            }
        }
        cout<<'}'<<endl;
    }
    cout<<endl;
    for(int i=0;i<strlen(VN);i++)
    {
        cout<<"LASTVT("<<VN[i]<<")={";
        for(int j=0;j<strlen(lastvt[i]);j++)
        {
            cout<<lastvt[i][j];
            if(j!=strlen(lastvt[i])-1)
            {
                cout<<',';
            }
        }
        cout<<'}'<<endl;
    }
    cout<<"---------------------------------------------------"<<endl<<"The operator priority analysis table is as follows:"<<endl<<'\t';
    for(int i=0;i<strlen(VT);i++)
    {
        cout<<VT[i]<<'\t';
    }
    cout<<'#'<<endl;
    for(int i=0;i<strlen(VT)+1;i++)
    {
        if(i==strlen(VT))
        {
            cout<<'#'<<'\t';
        }
        else
        {
            cout<<VT[i]<<'\t';
        }
        
        for(int j=0;j<strlen(VT)+1;j++)
        {
            cout<<table[i][j]<<'\t';
        }
        cout<<endl;
    }
    char sentence[N];
    while(true)
    {
        cout<<"Please enter the sentence you want to recognize#It means that there is no sentence to be recognized: "< < endl;
        cin>>sentence;
        if(sentence[0]=='#')
        {
            break;
        }
        cout<<"step"<<'\t'<<"Stack"<<'\t'<<"Input string"<<'\t'<<"action"<<endl;
        fenxi(sentence);
    }
    system("pause");
    return 0;
}

The operation results are as follows:

The results of several examples are as follows: to illustrate, my code treats all numbers and lowercase letters as i.
eg1: 1+2

eg2: (1 + 2) / 3 + 4 - (5 + 6 / 7) (in fact, this is the example i gave. i replaced it with i for simplicity)

eg3: ((1-2) / 3 + 4 (example of error)

Finally, just enter # to end the run.
OK, bye and have a nice life.

Topics: C++ Algorithm