1, first read into the Terminator, non-Terminator, and all production type.
2, pre-processing: initialization; GETPP () obtains the number of each non-terminator on the left of the production type,
Recorded in string getp[] (can be multiple).
3. Get the first set of all the symbols: DFS, starting from S DFS, encountering Terminator is a recursive exit, back-to-back time to save records on the entire path of VN first, (encountered with left recursion, continue, left recursive production without affecting the fisrt set)
4: Get Project Set family: an LR (1) project with a structure record, get_close (Project T): BFS to complete the closure of T. Getxmjizu (): BFS, with a chain-forward star record chart.
5. Get the Analysis table table[][]: Traverse for all sides of the graph, the state i->j has the right to the side of W, the Action (i,w) =j;go, the essence is the same. Next scan all items, for the attribution of the project, the imputation
6 Master Control Program: Two stacks: the status stack and the symbol stack, nothing more than move in, return to, accept save.
Test:
A b
H S B
H->s
B->ab
S->bb
B->b
End
I * () +
E T F
E->e+t
E->t
T->t*f
T->f
F-> (E)
F->i
End
A B c D
S A B
S->a
A->b|cad
B->abb|ab
End
#include <iostream> #include <string> #include <map> #include <vector> #include <stack># include<set> #include <cstring> #include <queue>using namespace Std;map<char,int>getnum;char GETCHAR[100]; Get the corresponding character vector<string>proce; generated int table[30][30]; Pre-measured analysis table -1int tb_s_r[30][30]; is to move the input or the statute item, -1,-2.int Num=0;int numvt=0; NUMVT is the Terminator collection, 0 is ' # ', numvt empty word void readin ()//read into VT,VN, number 1-num, read in all production {memset (table,-1,sizeof (tabl e)); getnum[' # ']=0; getchar[0]= ' # '; cout<< "Please enter Terminator set:" <<endl; char x; do {cin>>x; Getnum[x]=++num; Getchar[num]=x; }while (Cin.peek ()! = ' \ n '); Numvt=++num; getnum[' @ ']=numvt; Kong Zi getchar[num]= (' @ '); cout<< "Please enter non-terminator set:" <<endl; do {cin>>x; Getnum[x]=++num; Getchar[num]=x; }while (Cin.peek ()! = ' \ n '); cout<< "Input all production (empty word with ' @ '), end With ' End ':" <<endl; STring Pro; while (cin>>pro&&pro!= "end") {string ss; SS+=PRO[0]; for (int i=3;i<pro.size (); i++) {if (pro[i]== ' | ') {Proce.push_back (ss); Ss.clear (); ss+=pro[0]; } else {ss+=pro[i]; }} proce.push_back (ss); }}struct XIANGMU//a project {int nump; The resulting type number int id; . The position of string fst; Set};string getp[100]; Get a terminator on the left of the production set void Getpp () {for (int i=0;i<proce.size (); i++) {int temp=getnum[proce[i][0]]; Getp[temp]+=char (' 0 ' +i); }}string first[100]; First set of each symbol bool GOTFIRST[100]; has finished first collection void Dfsgetfirst (int nv,int nump)//current symbol, and corresponding production number {int temp=getnum[proce[nump][1]]; The first character of the production comes out gotfirst[nump]=1; Mark if (TEMP<=NUMVT) First[nv]+=char (' 0 ' +temp); is terminator else {for (int i=0;i<getp[temp].size (); i++)//All temp can be introduced to the symbol corresponding to the production {if (proce[nump][0]==proce[nump][1]) continue;//The production of left recursion does not affect the fisrt set Dfsgetfirst (temp,getp[temp][i]-' 0 '); } First[nv]+=first[temp]; The}}void Get_first () {for (int i=1;i<=numvt;i++)//Terminator first collection is its own when backtracking. {First[i]=char (' 0 ' +i); } for (int i=0;i<proce.size (); i++) {if (proce[i][0]==proce[i][1]) continue;///left recursive production without affecting the fisrt set if (Gotfirst[i]) continue; has been generated.
int temp=getnum[proce[i][0]]; Dfsgetfirst (Temp,i); }}vector<vector<xiangmu> >v; Project set family int e[100][3]; int Head[100];int nume=0; Chain forward star project set family diagram void Addegde (int from,int to,int W)//join Edge {e[nume][0]=to;e[nume][1]=head[from];head[from]=nume; E[nume++][2]=w;} void clear ()//initialization function {for (int i=0;i<100;i++) head[i]=-1; for (int i=0;i<30;i++) for (int j=0;j<30;j++) tb_s_r[i][j]=table[i][j]=-1; nume=0;} inline bool Xmeq (XIANGMU A,xiangmu b) {if (a.fst==b.fst&&a.id==b.id&&a.nump==b.nump) return 1; return 0;} BOOL Isin (XIANGMU a,vector<xiangmu> b)//xm A is in Xmji b{for (int i=0;i<b.size (); i++) {if (XM EQ (A,b[i])) return 1; } return 0;} Vector<xiangmu> hebing (Vector<xiangmu>a, vector<xiangmu>b)//merge project set, B to a{for (int i=0;i<b.siz E (); i++) {if (Isin (b[i],a)) continue; else A.push_back (B[i]); } return A; BOOL Xmjieq (vector<xiangmu> a,vector<xiangmu> B)//Two set of items are equal {if (A.size ()!=b.size ()) return 0; for (int i=0;i<a.size (); i++) {if (!isin (a[i],b)) return 0; } return 1;} int Xmji_isin_xmjizu (vector<xiangmu>a,vector<vector<xiangmu> >b)//Find item set, if any, then return number, one at a stroke {for (int i =0;i<b.size (); i++) {if (Xmjieq (A,b[i])) return i; } return-1;} Vector<xiangmu> get_close (Xiangmu t)//to project T as closure {vector<xiangmu> temp; Temp.push_back (t); Queue<xiangmu> Q; BFS Complete closure Q.push (t); while (!q.empty ()) {Xiangmu cur=q.front (); Q.pop (); if (Cur.id==proce[cur.nump].size ())//return to the continue; int tt=getnum[proce[cur.nump][cur.id]]; TT is tHM num of '. ' Zhihoudefuhao if (TT<=NUMVT) continue; If Terminator, you do not need to find the for (int i=0;i<getp[tt].size (); i++)//The corresponding production of the number {XIANGMU C; c.id=1; c.nump=getp[tt][i]-' 0 '; if (Proce[cur.nump].size ()-cur.id==1)//The LAST:A->BC. D,a/b c.fst+=cur.fst; Else//not the last:a->b.cfb,a/b {int tttnum=getnum[proce[cur.nump][cur.id +1]]; C.fst+=first[tttnum]; } if (!isin (c,temp))//row weight, the new project is added. {Q.push (c); Temp.push_back (c); }}} return temp;} void Get_xiangmujizu ()//Get project set family {vector<xiangmu>temp; Xiangmu T; t.nump=0;t.id=1;t.fst+= ' 0 '; Initial set of items: 0 temp=get_close (t); Queue<vector<xiangmu> >q; BFs method obtained Q.push (temp); V.push_back (temp); First in while (!q.empty ()) {vector<xiangmu> cur=q.front (); Q.pop (); for (int i=1;i<=num;i++)//All symbols {if (I==NUMVT) continue; ‘#‘ Vector<xiangmu> temp; for (int j=0;j<cur.size (); j + +)//All items in the project set {if (Cur[j].id==proce[cur[j].nump].size ()) C Ontinue; is the statute item. Can no longer read into int tt=getnum[proce[cur[j].nump][cur[j].id]]; if (tt==i)//can read in sign I {XIANGMU tempt; TEMPT.FST=CUR[J].FST; tempt.id=cur[j].id+1; Tempt.nump=cur[j].nump; Temp=hebing (Temp,get_close (tempt)); }} if (Temp.size () ==0) continue; The symbol cannot be read in. int Numcur=xmji_isin_xmjizu (CUR,V); Current node designator int Tttnum=xmji_isin_xmjizu (TEMP,V); New Target label if (TTTNUM==-1)//New project set {V.push_back (TEM p); Q.push (temp); Addegde (Numcur,v.size () -1,i); Join Edge, the right is read into the characterID} else//old project set {add Egde (Numcur,tttnum,i); }}}}void Print_xmjizu ()//print project set family {for (int i=0;i<v.size (); i++) {cout<< "project set "<<i<<": "<<endl; for (int j=0;j<v[i].size (); j + +) {cout<<proce[v[i][j].nump]<< "" <<v[i][j].id<< " "<<v[i][j].fst<<endl; } cout<<endl; } for (int i=0;i<v.size (), i++) {for (int j=head[i];j!=-1;j=e[j][1]) {cout<< "" < ;<getchar[e[j][2]]<<endl; cout<<i<< "--->" <<e[j][0]<<endl; }}}bool get_table ()//Get Analysis table table[i][j]=w: status I-->j, read in symbol W.
{for (int i=0;i<v.size (); i++)//Traverse graph {for (int j=head[i];j!=-1;j=e[j][1]) {i F (Table[i][e[j][2]]!=-1) return 0; Multiple entrances. Error. TABLE[I][E[J][2]]=E[J][0]; Tb_s_r[i][e[j][2]]=-1; Move closer-1.
}} for (int i=0;i<v.size (); i++)//Traverse all items {for (int j=0;j<v[i].size (); j + +) { if (V[i][j].id==proce[v[i][j].nump].size ())//attribution {for (int k=0;k<v[i][j].fst.siz E (); k++) {if (table[i][(V[I][J].FST) [k]-' 0 ']!=-1) return 0; Multiple entrances, error. if ((V[I][J].FST) [k]== ' 0 ' &&v[i][j].nump==0) table[i][(V[I][J].FST) [k]-' 0 ']=-3; Acceptable state. else {table[i][(v[i][j].fst) [k]-' 0 ']=v[i][j].nump; tb_s_r[i][(V[I][J].FST) [k]-' 0 ']=-2; Return to the State}}}}} 1; void Print_table () {cout<< "LR (1) Analysis table:" <<endl; cout<< "status" << "Actoin" <<endl; for (int j=0;j<=num;j++) {if (J==NUMVT) continue; Cout<< "" <<getchar[j]; } cout<<endl; for (int i=0;i<v.size (); i++) {cout<<i<< ""; for (int j=0;j<=num;j++) {if (J==NUMVT) continue; if (table[i][j]==-3) cout<< "ACC" << ""; Accept else if (table[i][j]==-1) cout<< ""; Empty else if (tb_s_r[i][j]==-1) cout<< "s" <<table[i][j]<< ""; Move near else if (tb_s_r[i][j]==-2) cout<< "R" <<table[i][j]<< ""; Attribution} cout<<endl; }}string word;void print_now_state (int count,stack<int>state,stack<int>wd,int i) {cout<<count< < ' t ' << ' t '; stack<int>temp; while (!state.empty ()) {Temp.push (State.top ()); State.pop (); } while (!temp.empty ()) {cout<<temp.top (); Temp.pop (); } cout<< ' \ t ' << ' \ t '; while (!wd.empty ()) {Temp.push (Wd.top ()); Wd.pop (); } while (!temp.empty ()) {cout<<getchar[temp.top ()]; Temp.pop (); } cout<< ' \ t ' << ' \ t '; for (int j=i;j<word.size (); j + +) cout<<word[j]; cout<< ' \ t ' << ' t ';} Parsing process for bool analyze () {cout<< "<<word<<": "<<endl; cout<< "Step \t\t" << "status Stack \t\t" << "symbol stack \t\t" << "input string \t\t" << "Action description" <<endl; stack<int>state; Two stacks: state stack and symbol stack stack<int>wd; int count=0; State.push (0); Initialize Wd.push (0); ' # ' for (int i=0;;) I, {int cur=state.top () reading into the text; if (table[cur][getnum[word[i]]]==-1)//blank, report error return 0; if (table[cur][getnum[word[i]]]==-3)//Accept State {print_now_state (count++,state,wd,i); cout<< "Congratulations. acc! " <<endl; return 1; } if (Tb_s_r[cur][getnum[word[i]]]==-1)//Move Input { Print_now_state (Count++,state,wd,i); int Newstate=table[cur][getnum[word[i]]; cout<< "action[" <<cur<< "," <<getnum[word[i]]<< "]=" <<newstate; cout<< ", status" <<newstate<< "into the stack" <<endl; Wd.push (Getnum[word[i]); State.push (newstate); i++; } else if (tb_s_r[cur][getnum[word[i]]]==-2)//Attribution {print_now_state (count++,state,wd,i); int Numpro=table[cur][getnum[word[i]]; The resulting formula is normalized to about int len=proce[numpro].size ()-1; for (int ii=0;ii<len;ii++)//Stack {wd.pop (); State.pop (); } wd.push (Getnum[proce[numpro][0]]); New into int cur=state.top (); cout<< "with" <<proce[numpro][0]<< ","; for (int ii=1;ii<=len;ii++) cout<<proce[numpro][ii]; Cout<< "for Attribution," << "goto[" <<cur<< "," <<getnum[word[i]]<< "]=" <<table[cur][ Getnum[proce[numpro][0]]; cout<< "into the stack" <<endl; State.push (Table[cur][getnum[proce[numpro][0]]); }} return 1;} int main () {clear (); Readin (); GETPP (); Get_first (); Get_xiangmujizu (); if (!get_table ()) {cout<< "This grammar has multiple entries when generating an analytic table, non-LR (1) Grammar!
"<<endl; return 0; }//Print_xmjizu (); Print_table (); cout<< "Please input word:" <<endl; cin>>word; word+= ' # '; if (!analyze ()) cout<< "error!" <<endl; Else return 0;}
LR (1) Grammar analyzer//c++ implementation