Compilation principle experiment: bottom-up syntax analysis - write the syntax analysis program of PL/0 language according to the grammar specification of PL/0 language

Posted by dezkit on Mon, 17 Jan 2022 04:50:49 +0100

**

Task description

**
1. Experimental purpose
The PL/0 grammar specification is given, and the syntax analysis program of PL/0 language is required.
By designing, compiling and debugging a typical bottom-up grammar analysis program, we can realize the grammar check and structure analysis of the word sequence provided by the lexical analysis program, and further master the common grammar analysis methods.
Select the most representative syntax analysis methods, such as operator priority analysis and LR analysis; Or investigate the function and working principle of YACC, an automatic parser generation tool, and use YACC to generate a bottom-up parser.
2. Experimental preparation
Install C language, or C + +, or Visual C + +
3. Experimental contents
The PL/0 language grammar has been given to construct a parser for the expression part.
BNF of the analysis object arithmetic expression is defined as follows:
< expression >: = [+ | -] < item > {< addition operator > < item >}
< item >: = < factor > {< mu lt iplication operator > < factor >}
< factor >: = < identifier > | < unsigned integer > | '(' < expression > ')
< addition operator >: =+|-
< mu lt iplication operator:: =*|/
< relational operator >: = |#|< = |> >=
4. Experimental requirements
Take the output result of Experiment 1 "lexical analysis" as the input of the expression parser for syntax analysis. For expressions with correct syntax, report "correct syntax"; For expressions with syntax errors, report "syntax errors" and indicate the cause of the error.
The parser is designed as an independent process.
The operator first analysis method or LR analysis method is used to realize syntax analysis; Or investigate the function and working principle of YACC, an automatic parser generation tool, and use YACC to generate a bottom-up parser.
5. Input and output
Input:
PL/0 expression, with the output form of Experiment 1 as the input. For example, for PL/0 expression, (a+15) b uses the following form as input:
  (lparen,()
  (ident,a)
  (plus,+)
  (number,15)
  (rparen,))
  (times,)
  (ident,b)
Output:
For expressions with correct syntax, report "correct syntax";
For expressions with syntax errors, report "syntax errors" and indicate the cause of the error.

Concrete implementation

design idea

Extended Bakos normal form
< expression >: = [+ | -] < item > {< addition operator > < item >}
< item >: = < factor > {< mu lt iplication operator > < factor >}
< factor >: = < identifier > | < unsigned integer > | '(' < expression > ')
< addition operator >: =+|-
< mu lt iplication operator:: =|/
Ordinary Bakos paradigm
For convenience:
Expression E, item X, factor Y, identifier b, unsigned integer z, addition operator A, multiplication operator C
    E->AX|X|EAX
    X->Y|XCY
    Y->b|z|(E)
    A->+|-
    C->|/
Itemset & DFA identifying live prefix

Among them, I1, I3, I10 and I18 have reduction move in conflict.

Solve the FOLLOW set of all non terminators
  Follow(S`)={#}
  Follow(E)={#,),+,-}
  Follow(X)={),+,-,#,,/}
  Follow(Y)={),+,-,#,,/}
  Follow(A)={b,z,(}
  Follow©={b,z,(}
The conflicts of I1, I3, I10 and I18 can be resolved, so the grammar is SLR(1) grammar.

Analysis table
  (0)S`->E
  (1)E->AX
  (2)E->X
  (3)E->EAX
  (4)X->Y
  (5)X->XCY
  (6)Y->b
  (7)Y->z
  (8)Y->(E)
  (9)A->+
  (10)A->-
  (11)C->*
  (12)C->
 

Algorithm flow

The main function is equivalent to the general control program, analysis_ The action function corresponds to the action table, analysis_ The goto function corresponds to the goto table.

code

#include <iostream>
#include <string>
#include<stack>
#include<vector>
using namespace std;
int flag=0; //Record analysis status
int p=-1;//The pointer acts as the subscript of the currently scanned word
stack <int> State;  //State stack
stack <string> in;  //Symbol stack
int error=0;//Error handling when set to 1, an error will be reported to end the analysis
//For the analyzed words, s1 is the code and s2 is the word symbol
struct strs
{
    string s1,s2;
};

strs analystr;//Currently analyzed words

//Scan next word
void Advance(strs *S)
{
    p++;
    analystr = S[p];
}
//Corresponding to the goto table, after reduction, determine which State should enter the State according to the current State and symbol
void Analy_goto()
{
    int state=State.top(); //Get the current stack top state
    string si=in.top(); //The top symbol of the current symbol stack
    char sii=si[0];  //String - > char conversion
    switch(state)
    {
    //According to goto table, press in the code of status
    case 0:
        if(sii=='E') State.push(1);
        else if(sii=='X') State.push(3);
        else if(sii=='Y') State.push(6);
        else if(sii=='A') State.push(2);
        else error=1;
        break;
    case 1:
        if(sii=='A') State.push(17);
        else error=1;
        break;
    case 2:
        if(sii=='X') State.push(10);
        else if(sii=='Y') State.push(6);
        else error=1;
        break;
    case 3:
        if(sii=='C') State.push(11);
        else error=1;
        break;
    case 9:
        if(sii=='E') State.push(14);
        else if(sii=='X') State.push(3);
        else if(sii=='Y') State.push(6);
        else if(sii=='A') State.push(2);
        else error=1;
        break;
    case 10:
        if(sii=='C') State.push(11);
        else error=1;
        break;
    case 11:
        if(sii=='Y') State.push(15);
        else error=1;
        break;
    case 14:
        if(sii=='A') State.push(17);
        else error=1;
        break;
    case 17:
        if(sii=='X') State.push(18);
        else if(sii=='Y') State.push(6);
        else error=1;
        break;
    case 18:
        if(sii=='C') State.push(11);
        else error=1;
        break;
    default:
        error=1;
        break;
    }
}
//Corresponding to the action table, move in or reduce according to the current top state of the stack and the input characters
void Analy_action(strs *S)
{
    int state=State.top();//Get the current stack top state
    switch(state)
    {
    //Select the operation code according to the action table. Only some examples are selected below
    case 0:
        if(analystr.s1=="ident")
        {
            //Move in operation
            State.push(7);//Push status 7 into the status stack
            in.push(analystr.s2);//Pushes the current symbol onto the symbol stack
            Advance(S);//Continue scanning forward
        }
        else if(analystr.s1=="number")
        {
            State.push(8);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="(")
        {
            State.push(9);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="+")
        {
            State.push(4);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="-")
        {
            State.push(5);
            in.push(analystr.s2);
            Advance(S);
        }
        else error=1;
        break;
    case 1:
        if(analystr.s2=="+")
        {
            State.push(4);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="-")
        {
            State.push(5);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s1=="#")
        {
            //Status 1 meets #, the scanning is completed, the matching is successful, and the analysis status is set to 1
            flag=1;
            p++;//Used to exit the while loop in the main function
        }
        else error=1;
        break;
    case 2:
        if(analystr.s1=="ident")
        {
            State.push(7);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s1=="number")
        {
            State.push(8);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="(")
        {
            State.push(9);
            in.push(analystr.s2);
            Advance(S);
        }
        else error=1;
        break;
    case 3:
        if(analystr.s2=="*")
        {
            State.push(12);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="/")
        {
            State.push(13);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="#" || analystr.s2=="+" || analystr.s2=="-" || analystr.s2==")")
        {
            //Reduction operation
            State.pop();//Reduce a few characters in the production formula, and the State stack and in stack pop several times
            in.pop();
            in.push("E");//Press reduced character
            Analy_goto();//Query goto table
        }
        else error=1;
        break;
    case 4:
        if(analystr.s1=="ident" || analystr.s1=="number" || analystr.s2=="(")
        {
            State.pop();
            in.pop();
            in.push("A");
            Analy_goto();
        }
        else error=1;
        break;
    case 5:
        if(analystr.s1=="ident" || analystr.s1=="number" || analystr.s2=="(")
        {
            State.pop();
            in.pop();
            in.push("A");
            Analy_goto();
        }
        else error=1;
        break;
    case 6:
        if(analystr.s2==")" || analystr.s2=="+" ||analystr.s2=="-" || analystr.s2=="*" || analystr.s2=="/" || analystr.s2=="#")
        {
            State.pop();
            in.pop();
            in.push("X");
            Analy_goto();
        }
        else error=1;
        break;
    case 7:
        if(analystr.s2==")" || analystr.s2=="+" ||analystr.s2=="-" || analystr.s2=="*" || analystr.s2=="/" || analystr.s2=="#")
        {
            State.pop();
            in.pop();
            in.push("Y");
            Analy_goto();
        }
        else error=1;

        break;
    case 8:
        if(analystr.s2==")" || analystr.s2=="+" ||analystr.s2=="-" || analystr.s2=="*" || analystr.s2=="/" || analystr.s2=="#")
        {
            State.pop();
            in.pop();
            in.push("Y");
            Analy_goto();
        }
        else error=1;
        break;
    case 9:
        if(analystr.s1=="ident")
        {
            State.push(7);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s1=="number")
        {
            State.push(8);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="(")
        {
            State.push(9);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="+")
        {
            State.push(4);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="-")
        {
            State.push(5);
            in.push(analystr.s2);
            Advance(S);
        }
        else error=1;
        break;
    case 10:
        if(analystr.s2=="*")
        {
            State.push(12);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="/")
        {
            State.push(13);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="#" || analystr.s2=="+" || analystr.s2=="-" || analystr.s2==")")
        {
            State.pop();State.pop();
            in.pop();in.pop();
            in.push("E");
            Analy_goto();
        }
        else error=1;
        break;
    case 11:
        if(analystr.s1=="ident")
        {
            State.push(7);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s1=="number")
        {
            State.push(8);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="(")
        {
            State.push(9);
            in.push(analystr.s2);
            Advance(S);
        }
        else error=1;
        break;
    case 12:
        if(analystr.s1=="ident" || analystr.s1=="number" || analystr.s2=="(")
        {
            State.pop();
            in.pop();
            in.push("C");
            Analy_goto();
        }
        else error=1;
        break;
    case 13:
        if(analystr.s1=="ident" || analystr.s1=="number" || analystr.s2=="(")
        {
            State.pop();
            in.pop();
            in.push("C");
            Analy_goto();
        }
        else error=1;
        break;
    case 14:
        if(analystr.s2==")")
        {
            State.push(16);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="+")
        {
            State.push(4);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="-")
        {
            State.push(5);
            in.push(analystr.s2);
            Advance(S);
        }
        else error=1;
        break;
    case 15:
        if(analystr.s2==")" || analystr.s2=="+" ||analystr.s2=="-" || analystr.s2=="*" || analystr.s2=="/" || analystr.s2=="#")
        {
            State.pop();State.pop();State.pop();
            in.pop();in.pop();in.pop();
            in.push("X");
            Analy_goto();
        }
        else error=1;
        break;
    case 16:
        if(analystr.s2==")" || analystr.s2=="+" ||analystr.s2=="-" || analystr.s2=="*" || analystr.s2=="/" || analystr.s2=="#")
        {
            State.pop();State.pop();State.pop();
            in.pop();in.pop();in.pop();
            in.push("Y");
            Analy_goto();
        }
        else error=1;
        break;
    case 17:
        if(analystr.s1=="ident")
        {
            State.push(7);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s1=="number")
        {
            State.push(8);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="(")
        {
            State.push(9);
            in.push(analystr.s2);
            Advance(S);
        }
        else error=1;
        break;
    case 18:
        if(analystr.s2=="*")
        {
            State.push(12);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="/")
        {
            State.push(13);
            in.push(analystr.s2);
            Advance(S);
        }
        else if(analystr.s2=="#" || analystr.s2=="+" || analystr.s2=="-" || analystr.s2==")")
        {
            State.pop();State.pop();State.pop();
            in.pop();in.pop();in.pop();
            in.push("E");
            Analy_goto();
        }
        else error=1;
        break;
    default:
        error=1;
        break;
    }
}
int main()
{
    string str,str1;
    int count=1;//Record the number of input words, plus#
    while(cin>>str1){
        str = str + str1 + ' ';
        count++;
    }//Save input word
/*Process the input words and store all words in the S array for easy scanning*/
    strs S[count];
    int len = str.size();
    int a=0,b=0,c=0;
    int j=0;
    for(int i=0;i<len;i++){
        if(str[i]=='(')
        {
            a=i+1;
            do
            {
                i++;
                if(str[i]==',') b=i;
            }while(!(str[i]==')' && str[i+1]==' '));
            c=i-1;
            S[j].s1=str.substr(a,b-a);
            S[j].s2=str.substr(b+1,c-b);
            j++;
        }
    }
    S[count-1].s1="#";//End with Terminator#
    S[count-1].s2="#";
/*         Start analysis           */
    int out=count; //Save the length of the string to be analyzed
    Advance(S);
    State.push(0);
    while(p<out && error==0)   //Exit loop after string scanning
    {
        Analy_action(S);
    }
    //Judgment analysis results
    if(flag==1) cout<<"Yes,it is correct."<<endl;
    else cout<<"No,it is wrong."<<endl;
    return 0;
}
                
    

result

Topics: C