**
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; }