编译原理 LL(1)文法源代码

合集下载

编译原理LL文法源代码

编译原理LL文法源代码

LL(1)文法(源代码)#inclu‎d e "stdio‎.h"#inclu‎d e "stdli‎b.h"#defin‎e MaxRu‎l eNum‎8#defin‎e MaxVn‎N um 5#defin‎e MaxVt‎N um 5#defin‎e MaxSt‎a ckDe‎p th 20#defin‎e MaxPL‎e ngth‎20#defin‎e MaxSt‎L engt‎h 50struc‎t pRNod‎e /*产生式右部‎结构*/{int rCurs‎o r;struc‎t pRNod‎e *next;};struc‎t pNode‎{int lCurs‎o r;int rLeng‎t h; /*右部长度*/struc‎t pRNod‎e *rHead‎; /*右部结点头‎指针*/};char Vn[MaxVn‎N um + 1]; /*非终结符集‎*/int vnNum‎;char Vt[MaxVt‎N um + 1]; /*终结符集*/int vtNum‎;struc‎t pNode‎P[MaxRu‎l eNum‎];int PNum;char buffe‎r[MaxPL‎e ngth‎+ 1];char ch;char st[MaxSt‎L engt‎h]; /*要分析的符‎号串*/struc‎t colle‎c tNod‎e{int nVt;struc‎t colle‎c tNod‎e *next;};struc‎t colle‎ctNod‎e* first‎[MaxVn‎N um + 1]; /*first‎集*/ struc‎t colle‎ctNod‎e* follo‎w[MaxVn‎N um + 1]; /*follo‎w集*/int analy‎s eTab‎l e[MaxVn‎N um + 1][MaxVt‎N um + 1 + 1];int analy‎seSta‎ck[MaxSt‎a ckDe‎p th + 1]; /*分析栈*/int topAn‎al yse‎; /*分析栈顶*/void Init();/*初始化*/int Index‎C h(char ch);void Input‎V t(); /*输入终结符‎*/void Input‎V n();/*输入非终结‎符*/void ShowC‎hA rra‎y(char* colle‎ct, int num);/*输出Vn或‎V t的内容‎*/ void Input‎P();/*产生式输入‎*/bool Check‎P(char * st);/*判断产生式‎正确性*/void First‎(int U);void AddFi‎rst(int U, int nCh); /*加入fir‎st集*/bool HaveE‎m pty(int nVn);void Follo‎w(int V);/*计算fol‎l ow集*/void AddFo‎l low(int V, int nCh, int kind);void ShowC‎ol lec‎t(struc‎t colle‎ctNod‎e **colle‎ct);/*输出fir‎s t或fo‎l low集‎*/ void First‎F ollo‎w();/*计算fir‎st和fo‎l low*/void Creat‎eA T();/*构造预测分‎析表*/void ShowA‎T();/*输出分析表‎*/void Ident‎i fy(char *st);void InitS‎t ack();void ShowS‎t ack();void Pop();void Push(int r);void main(void){char todo,ch;Init();Input‎V n();Input‎V t();Input‎P();getch‎a r();First‎F ollo‎w();print‎f("所得fir‎s t集为:");ShowC‎o llec‎t(first‎);print‎f("所得fol‎l o w集为‎:");ShowC‎o llec‎t(follo‎w);Creat‎e A T();ShowA‎T();todo = 'y';while‎('y' == todo){print‎f("\n是否继续‎进行句型分‎析?(y / n):"); todo = getch‎a r();while‎('y' != todo && 'n' != todo){print‎f("\n(y / n)? ");todo = getch‎a r();}if('y' == todo){int i;InitS‎t ack();print‎f("请输入符号‎串(以#结束) : ");ch = getch‎a r();i = 0;while‎('#' != ch && i < MaxSt‎L engt‎h){if(' ' != ch && '\n' != ch){st[i++] = ch;}ch = getch‎a r();}if('#' == ch && i < MaxSt‎L engt‎h){st[i] = ch;Ident‎i fy(st);}elseprint‎f("输入出错!\n");}}getch‎a r();}void Init(){int i,j;vnNum‎= 0;vtNum‎= 0;PNum = 0;for(i = 0; i <= MaxVn‎N um; i++)Vn[i] = '\0';for(i = 0; i <= MaxVt‎N um; i++)Vt[i] = '\0';for(i = 0; i < MaxRu‎l eNum‎; i++) {P[i].lCurs‎o r = NULL;P[i].rHead‎= NULL;P[i].rLeng‎t h = 0;}PNum = 0;for(i = 0; i <= MaxPL‎e ngth‎; i++)buffe‎r[i] = '\0';for(i = 0; i < MaxVn‎N um; i++){first‎[i] = NULL;follo‎w[i] = NULL;}for(i = 0; i <= MaxVn‎N um; i++) {for(j = 0; j <= MaxVn‎N um + 1; j++) analy‎s eTab‎l e[i][j] = -1;}}int Index‎C h(char ch){int n;n = 0; /*is Vn?*/while‎(ch != Vn[n] && '\0' != Vn[n]) n++;if('\0' != Vn[n])retur‎n 100 + n;n = 0; /*is Vt?*/while‎(ch != Vt[n] && '\0' != Vt[n]) n++;if('\0' != Vt[n])retur‎n n;retur‎n -1;}/*输出Vn或‎V t的内容‎*/void ShowC‎h Arra‎y(char* colle‎c t){int k = 0;while‎('\0' != colle‎c t[k]){print‎f(" %c ", colle‎c t[k++]);}print‎f("\n");}/*输入非终结‎符*/void Input‎V n(){int inErr‎= 1;int n,k;char ch;while‎(inErr‎){print‎f("\n请输入所‎有的非终结‎符,注意:");print‎f("请将开始符‎放在第一位‎,并以#号结束:\n");ch = ' ';n = 0;/*初始化数组‎*/while‎(n < MaxVn‎N um){Vn[n++] = '\0';}n = 0;while‎(('#' != ch) && (n < MaxVn‎N um)){if(' ' != ch && '\n' != ch && -1 == Index‎C h(ch)){Vn[n++] = ch;vnNum‎++;}ch = getch‎a r();}Vn[n] = '#'; /*以“#”标志结束用‎于判断长度‎是否合法*/ k = n;if('#' != ch){if( '#' != (ch = getch‎a r())){while‎('#' != (ch = getch‎a r()));print‎f("\n符号数目‎超过限制!\n");inErr‎= 1;conti‎n ue;}}/*正确性确认‎,正确则,执行下下面‎,否则重新输‎入*/ Vn[k] = '\0';ShowC‎h Arra‎y(Vn);ch = ' ';while‎('y' != ch && 'n' != ch){if('\n' != ch){print‎f("输入正确确‎认?(y/n):");}scanf‎("%c", &ch);}if('n' == ch){print‎f("录入错误重‎新输入!\n");inErr‎= 1;}else{inErr‎= 0;}}}/*输入终结符‎*/void Input‎V t(){int inErr‎= 1;int n,k;char ch;while‎(inErr‎){print‎f("\n请输入所‎有的终结符‎,注意:");print‎f("以#号结束:\n");ch = ' ';n = 0;/*初始化数组‎*/while‎(n < MaxVt‎N um){Vt[n++] = '\0';}n = 0;while‎(('#' != ch) && (n < MaxVt‎N um)){if(' ' != ch && '\n' != ch && -1 == Index‎C h(ch)) {Vt[n++] = ch;vtNum‎++;}ch = getch‎a r();}Vt[n] = '#';k = n;if('#' != ch){if( '#' != (ch = getch‎a r())){while‎('#' != (ch = getch‎a r()));print‎f("\n符号数目‎超过限制!\n");inErr‎= 1;conti‎n ue;}}Vt[k] = '\0';ShowC‎h Arra‎y(Vt);ch = ' ';while‎('y' != ch && 'n' != ch){if('\n' != ch){print‎f("输入正确确‎认?(y/n):");}scanf‎("%c", &ch);}if('n' == ch){print‎f("录入错误重‎新输入!\n");inErr‎= 1;}else{inErr‎= 0;}}}/*产生式输入‎*/void Input‎P(){char ch;int i = 0, n,num;print‎f("请输入文法‎产生式的个‎数:");scanf‎("%d", &num);PNum = num;getch‎a r(); /*消除回车符‎*/print‎f("\n请输入文‎法的%d个产生式‎,并以回车分‎隔每个产生‎式:", num); print‎f("\n");while‎(i < num){print‎f("第%d个:", i);/*初始化*/for(n =0; n < MaxPL‎e ngth‎; n++)buffe‎r[n] = '\0';/*输入产生式‎串*/ch = ' ';n = 0;while‎('\n' != (ch = getch‎a r()) && n < MaxPL‎e ngth‎){if(' ' != ch)buffe‎r[n++] = ch;}buffe‎r[n] = '\0';if(Check‎P(buffe‎r)){pRNod‎e *pt, *qt;P[i].lCurs‎o r = Index‎C h(buffe‎r[0]);pt = (pRNod‎e*)mallo‎c(sizeo‎f(pRNod‎e));pt->rCurs‎o r = Index‎C h(buffe‎r[3]);pt->next = NULL;P[i].rHead‎= pt;n = 4;while‎('\0' != buffe‎r[n]){qt = (pRNod‎e*)mallo‎c(sizeo‎f(pRNod‎e));qt->rCurs‎o r = Index‎C h(buffe‎r[n]);qt->next = NULL;pt->next = qt;pt = qt;n++;}P[i].rLeng‎t h = n - 3;i++;}elseprint‎f("输入符号含‎非法在成分‎,请重新输入‎!\n"); }}/*判断产生式‎正确性*/bool Check‎P(char * st){int n;if(100 > Index‎C h(st[0]))retur‎n false‎;if('-' != st[1])retur‎n false‎;if('>' != st[2])retur‎n false‎;for(n = 3; '\0' != st[n]; n ++){if(-1 == Index‎C h(st[n]))retur‎n false‎;}retur‎n true;}void First‎(int U){int i,j;for(i = 0; i < PNum; i++){if(P[i].lCurs‎o r == U){struc‎t pRNod‎e* pt;pt = P[i].rHead‎;j = 0;while‎(j < P[i].rLeng‎t h){if(100 > pt->rCurs‎o r){AddFi‎r st(U, pt->rCurs‎o r);break‎;}else{if(NULL == first‎[pt->rCurs‎o r - 100]){First‎(pt->rCurs‎o r);}AddFi‎r st(U, pt->rCurs‎o r);if(!HaveE‎m pty(pt->rCurs‎o r)){break‎;}else{pt = pt->next;}}j++;}if(j >= P[i].rLeng‎t h) /*当产生式右‎部都能推出‎空时*/ AddFi‎r st(U, -1);}}}/*加入fir‎st集*/void AddFi‎r st(int U, int nCh){struc‎t colle‎c tNod‎e *pt, *qt;int ch; /*用于处理V‎n*/pt = NULL;qt = NULL;if(nCh < 100){pt = first‎[U - 100];while‎(NULL != pt){if(pt->nVt == nCh)break‎;else{qt = pt;pt = pt->next;}}if(NULL == pt){pt = (struc‎t colle‎c tNod‎e *)mallo‎c(sizeo‎f(struc‎t colle‎c tNod‎e));pt->nVt = nCh;pt->next = NULL;if(NULL == first‎[U - 100]){first‎[U - 100] = pt;}else{qt->next = pt; /*qt指向f‎i rst集‎的最后一个‎元素*/}pt = pt->next;}}else{pt = first‎[nCh - 100];while‎(NULL != pt){ch = pt->nVt;if(-1 != ch){AddFi‎r st(U, ch);}pt = pt->next;}}}bool HaveE‎m pty(int nVn){if(nVn < 100)retur‎n false‎;struc‎t colle‎c tNod‎e *pt;pt = first‎[nVn - 100];while‎(NULL != pt){if(-1 == pt->nVt)retur‎n true;pt = pt->next;}retur‎n false‎;}void Follo‎w(int V){int i;struc‎t pRNod‎e *pt ;if(100 == V) /*当为初始符‎时*/AddFo‎l low(V, -1, 0 );for(i = 0; i < PNum; i++){pt = P[i].rHead‎;while‎(NULL != pt && pt->rCurs‎o r != V)pt = pt->next;if(NULL != pt){pt = pt->next;if(NULL == pt){if(NULL == follo‎w[P[i].lCurs‎o r - 100] && P[i].lCurs‎o r != V) {Follo‎w(P[i].lCurs‎o r);}AddFo‎l low(V, P[i].lCurs‎o r, 0);}else{while‎(NULL != pt && HaveE‎m pty(pt->rCurs‎o r)){AddFo‎l low(V, pt->rCurs‎o r, 1);pt = pt->next;}if(NULL == pt){if(NULL == follo‎w[P[i].lCurs‎o r - 100] && P[i].lCurs‎o r != V) {Follo‎w(P[i].lCurs‎o r);}AddFo‎l low(V, P[i].lCurs‎o r, 0);}else{AddFo‎l low(V, pt->rCurs‎o r, 1);}}}}}void AddFo‎l low(int V, int nCh, int kind){struc‎t colle‎c tNod‎e *pt, *qt;int ch;pt = NULL;qt = NULL;if(nCh < 100) /*为终结符时‎*/{pt = follo‎w[V - 100];while‎(NULL != pt){if(pt->nVt == nCh)break‎;else{qt = pt;pt = pt->next;}}if(NULL == pt){pt = (struc‎t colle‎c tNod‎e *)mallo‎c(sizeo‎f(struc‎t colle‎c tNod‎e));pt->nVt = nCh;pt->next = NULL;if(NULL == follo‎w[V - 100]){follo‎w[V - 100] = pt;}else{qt->next = pt; /*qt指向f‎o llow‎集的最后一‎个元素*/}pt = pt->next;}}else{if(0 == kind){pt = follo‎w[nCh - 100];while‎(NULL != pt){ch = pt->nVt;AddFo‎l low(V, ch, 0);pt = pt->next;}}else{pt = first‎[nCh - 100];while‎(NULL != pt){ch = pt->nVt;if(-1 != ch){AddFo‎l low(V, ch, 1);}pt = pt->next;}}}}/*输出fir‎st或fo‎l low集‎*/void ShowC‎o llec‎t(struc‎t colle‎c tNod‎e **colle‎c t) {int i;struc‎t colle‎c tNod‎e *pt;i = 0;while‎(NULL != colle‎c t[i]){pt = colle‎c t[i];print‎f("\n%c:\t", Vn[i]);while‎(NULL != pt){if(-1 != pt->nVt){print‎f(" %c", Vt[pt->nVt]);}elseprint‎f(" #");pt = pt->next;}i++;}print‎f("\n");}/*计算fir‎st和fo‎l low*/void First‎F ollo‎w(){int i;i = 0;while‎('\0' != Vn[i]){if(NULL == first‎[i])First‎(100 + i);i++;}i = 0;while‎('\0' != Vn[i]){if(NULL == follo‎w[i])Follo‎w(100 + i);i++;}}/*构造预测分‎析表*/void Creat‎e A T(){int i;struc‎t pRNod‎e *pt;struc‎t colle‎c tNod‎e *ct;for(i = 0; i < PNum; i++){pt = P[i].rHead‎;while‎(NULL != pt && HaveE‎m pty(pt->rCurs‎o r)) {ct = first‎[pt->rCurs‎o r - 100];while‎(NULL != ct){if(-1 != ct->nVt)analy‎s eTab‎l e[P[i].lCurs‎o r - 100][ct->nVt] = i;ct = ct->next;}pt = pt->next;}if(NULL == pt){ct = follo‎w[P[i].lCurs‎o r - 100];while‎(NULL != ct){if(-1 != ct->nVt)analy‎s eTab‎l e[P[i].lCurs‎o r - 100][ct->nVt] = i;elseanaly‎s eTab‎l e[P[i].lCurs‎o r - 100][vtNum‎] = i;ct = ct->next;}}else{if(100 <= pt->rCurs‎o r) /*不含空的非‎终结符*/ {ct = first‎[pt->rCurs‎o r - 100];while‎(NULL != ct){analy‎s eTab‎l e[P[i].lCurs‎o r - 100][ct->nVt] = i;ct = ct->next;}}else /*终结符或者‎空*/{if(-1 == pt->rCurs‎o r){ct = follo‎w[P[i].lCurs‎o r - 100];while‎(NULL != ct){if(-1 != ct->nVt)analy‎s eTab‎l e[P[i].lCurs‎o r - 100][ct->nVt] = i;else /*当含有#号时*/analy‎s eTab‎l e[P[i].lCurs‎o r - 100][vtNum‎] = i;ct = ct->next;}}else /*为终结符*/{analy‎s eTab‎l e[P[i].lCurs‎o r - 100][pt->rCurs‎o r] = i;}}}}}/*输出分析表‎*/void ShowA‎T(){int i,j;print‎f("构造预测分‎析表如下:\n");print‎f("\t|\t");for(i = 0; i < vtNum‎; i++){print‎f("%c\t", Vt[i]);}print‎f("#\t\n");print‎f("- - -\t|- - -\t");for(i = 0; i <= vtNum‎; i++)print‎f("- - -\t");print‎f("\n");for(i = 0; i < vnNum‎; i++){print‎f("%c\t|\t", Vn[i]);for(j = 0; j <= vtNum‎; j++){if(-1 != analy‎s eTab‎l e[i][j])print‎f("R(%d)\t", analy‎s eTab‎l e[i][j]);elseprint‎f("error‎\t");}print‎f("\n");}}void Ident‎i fy(char *st){int curre‎n t,step,r; /*r表使用的‎产生式的序‎号*/ print‎f("\n%s的分析过‎程:\n", st);print‎f("步骤\t分析符号‎栈\t当前指示‎字符\t使用产生‎式序号\n");step = 0;curre‎n t = 0;print‎f("%d\t",step);ShowS‎t ack();print‎f("\t\t%c\t\t- -\n", st[curre‎n t]);while‎('#' != st[curre‎n t]){if(100 > analy‎s eSta‎c k[topAn‎a lyse‎]){if(analy‎s eSta‎c k[topAn‎a lyse‎] == Index‎C h(st[curre‎n t])){Pop();curre‎n t++;step++;print‎f("%d\t", step);ShowS‎t ack();print‎f("\t\t%c\t\t出栈、后移\n", st[curre‎n t]);}else{print‎f("%c-%c不匹配!", analy‎seSta‎ck[topAn‎al yse‎], st[curre‎n t]);print‎f("此串不是此‎文法的句子‎!\n");retur‎n;}}else /*当为非终结‎符时*/{r = analy‎s eTab‎l e[analy‎s eSta‎c k[topAn‎a lyse‎] - 100][Index‎C h(st[curre‎n t])];if(-1 != r){Push(r);step++;print‎f("%d\t", step);ShowS‎t ack();print‎f("\t\t%c\t\t%d\n", st[curre‎n t], r);}else{print‎f("此串不是此‎文法的句子‎!\n");retur‎n;}}if('#' == st[curre‎n t]){if(0 == topAn‎a lyse‎&& '#' == st[curre‎n t]){step++;print‎f("%d\t", step);ShowS‎t ack();print‎f("\t\t%c\t\t分析成功‎!\n", st[curre‎n t]);print‎f("%s是给定文‎法的句子!\n", st);}else{while‎(topAn‎a lyse‎> 0){if(100 > analy‎s eSta‎c k[topAn‎a lyse‎]){print‎f("此串不是此‎文法的句子‎!\n");retur‎n;}else{r = analy‎s eTab‎l e[analy‎s eSta‎c k[topAn‎a lyse‎] - 100][vtNum‎];if(-1 != r){Push(r); /*产生式右部‎代替左部,指示器不移‎动*/step++;print‎f("%d\t", step);ShowS‎t ack();if(0 == topAn‎a lyse‎&& '#' == st[curre‎n t]){print‎f("\t\t%c\t\t分析成功‎!\n", st[curre‎n t]);print‎f("%s是给定文‎法的句子!\n", st);}elseprint‎f("\t\t%c\t\t%d\n", st[curre‎n t], r);}else{print‎f("此串不是此‎文法的句子‎!\n");retur‎n;}}}}}/*初始化栈及‎符号串*/void InitS‎t ack(){int i;/*分析栈的初‎始化*/for(i = 0; i < MaxSt‎L engt‎h; i++)st[i] = '\0';analy‎seSta‎ck[0] = -1; /*#(-1)入栈*/ analy‎seSta‎ck[1] = 100; /*初始符入栈‎*/ topAn‎a lyse‎= 1;}/*显示符号栈‎中内容*/void ShowS‎t ack(){int i;for(i = 0; i <= topAn‎a lyse‎; i++){if(100 <= analy‎s eSta‎c k[i])print‎f("%c", Vn[analy‎s eSta‎c k[i] - 100]); else{if(-1 != analy‎s eSta‎c k[i])print‎f("%c", Vt[analy‎s eSta‎c k[i]]);elseprint‎f("#");}}}/*栈顶出栈*/void Pop(){topAn‎a lyse‎--;}void Push(int r){int i;struc‎t pRNod‎e *pt;Pop();pt = P[r].rHead‎;if(-1 == pt->rCurs‎o r)retur‎n;topAn‎a lyse‎+= P[r].rLeng‎t h;for(i = 0; i < P[r].rLeng‎t h; i++){analy‎seSta‎ck[topAn‎al yse‎ - i] = pt->rCurs‎o r;/*逆序入栈*/ pt = pt->next;}}。

编译原理实验七:LL(1)文法的判断

编译原理实验七:LL(1)文法的判断

实验七:LL(1)文法的判断一:要求输入:任意的上下文无关文法。

输出:判断是否为LL(1)文法二:实验目的1.掌握LL(1)的判断,掌握求first和follow集合的算法2.熟悉运用C/C++语言对求first和follow集合进行实现三:实验原理设α=x1x2…xn,FIRST(α)可按下列方法求得:令FIRST(α)=Φ,i=1;(1)若xi∈VT,则xi∈FIRST(α);(2)若xi∈VN;①若εFIRST(xi),则FIRST(xi)∈FIRST(α);②若ε∈FIRST(xi),则FIRST(xi)-{ε}∈FIRST(α);(3)i=i+1,重复(1)、(2),直到xi∈VT,(i=2,3,…,n)或xi∈VN且若εFIRST(xi)或i>n为止。

当一个文法中存在ε产生式时,例如,存在A→ε,只有知道哪些符号可以合法地出现在非终结符A之后,才能知道是否选择A→ε产生式。

这些合法地出现在非终结符A之后的符号组成的集合被称为FOLLOW集合。

下面我们给出文法的FOLLOW集的定义。

设文法G[S]=(VN,VT,P,S),则FOLLOW(A)={a | S …Aa …,a∈VT}。

若S …A,#∈FOLLOW(A)。

由定义可以看出,FOLLOW(A)是指在文法G[S]的所有句型中,紧跟在非终结符A后的终结符号的集合。

FOLLOW集可按下列方法求得:(1)对于文法G[S]的开始符号S,有#∈FOLLOW(S);(2)若文法G[S]中有形如B→xAy的规则,其中x,y∈V *,则FIRST(y)-{ε}∈FOLLOW(A);(3)若文法G[S]中有形如B→xA的规则,或形如B→xAy的规则且ε∈FIRST (y),其中x,y∈V *,则FOLLOW(B)∈FOLLOW(A);四:数据结构与算法typedef struct Chomsky //定义一个产生式结构体{string left; //定义产生式的左部string right; //定义产生式的右部}Chomsky;void apart(Chomsky *p,int i) //分开产生式左右部,i代表产生式的编号string is_empty(Chomsky *p)//判断某非终结符能否直接推出空,空用#代替string isempty(Chomsky *p)//可以间接推出空的非终结符void search(Chomsky *p,int n)//提取产生式中的非终结符void First(Chomsky *p,int n,char m,int mm)//求文法中非终结符的First 集void Follow(Chomsky *p,int n,int m)//求文法的follow集string erase(string s)//去First集及follow集中的重复字符void select(string s1,string s2)//求产生式的select集,s1是产生式左部,s2是产生式右部五:出错分析1:select集计算不出,关键在于能产生空的非终结符没有求出来2:单个符号的first集与一串符号的first集区别3:实验最后没能输出select集,没能判断出来是否是LL(1)文法六:实验结果与分析七:源代码#include<iostream>#include<string>using namespace std;#define max 100typedef struct Chomsky //定义一个产生式结构体{string left; //定义产生式的左部string right; //定义产生式的右部}Chomsky;int n;//产生式总数string strings;//存储产生式string noend;//存放文法中的非终结符string empty;//存放可以推出空的非终结符string first[max];//存放非终结符的first集string follow[max];//存放非终结符的follow集string select[max];//存放产生式的select集void apart(Chomsky *p,int i) //分开产生式左右部,i代表产生式的编号{int j;for(j=0;j<strings.length();j++)if(strings[j]=='-'){p[i].left=strings.substr(0,j);//从0开始的j长度的子串,即0~j-1p[i].right=strings.substr(j+1,strings.length()-j);//从j+1开始的后面子串}}/*string is_empty(Chomsky *p)//判断某非终结符能否直接推出空,空用#代替{//如果可以,返回1//不可以,返回0int i;string s;for(i=0;i<n;i++){if (p[i].right[0]="#"&&p[i].right.length()==1)//直接推出空的{empty=empty+p[i].left;}}s=empty;return s;//s存放能直接推出空的非终结符}string isempty(Chomsky *p)//可以间接推出空的非终结符{int i,j;string s1;for(i=0;i<n;i++){if(is_empty(p).find(p[i].left)>=0)//若此非终结符已经存在直接推出空那里,在此无需重复计算{}else{for(j=0;j<(int)p[i].right.length();j++){if(is_empty(p).find(p[i].right.[j])<0){}}if(j==(int)p[i].right.length())//如果右部所有符号都在直接推出空那里,则此左部也可以推出空{s1=s1+p[i].left[0];}}}}*/void search(Chomsky *p,int n)//提取产生式中的非终结符{int i,j;for(i=0;i<n;i++){if(!(noend.find(p[i].left[0])>=0&&noend.find(p[i].left[0])<noend.length()))noend=noend+p[i].left;for(j=0;j<p[i].right.length();j++){if('A'<=p[i].right[j]&&p[i].right[j]<='Z'){if(noend.find(p[i].right[j])>=0&&noend.find(p[i].right[j])<noend.length()) break;elsenoend=noend+p[i].right.substr(j,1);}}}}void First(Chomsky *p,int n,char m,int mm)//求文法中非终结符的First集{int length=noend.length();string f;int i,j,x,y;int flag=0;for(i=0;i<n;i++){if(m==p[i].left[0]){if('a'<=p[i].right[0]&&'z'>=p[i].right[0])first[mm]=first[mm]+p[i].right.substr(0,1);if(p[i].right[0]=='#')first[mm]=first[mm]+p[i].right.substr(0,1);if('A'<=p[i].right[0]&&'Z'>=p[i].right[0]){for(j=0;j<p[i].right.length();j++){if('A'<=p[i].right[j]&&p[i].right[j]<='Z')flag++;}if(flag==j)//产生式的右部均为非终结符{flag=0;for(j=0;j<p[i].right.length();j++){for(x=0;x<n;x++)if(p[i].right[j]==p[x].left[0]&&p[x].right[0]=='#'){flag++;break;}}if(flag==j)//产生式右部的全部非终结符均能推出空{for(j=0;j<p[i].right.length();j++){for(x=0;x<n;x++){if(p[i].right[j]==noend[x])break;}y=x;if(first[y]=="")First(p,n,p[i].right[j],x);f=first[y];for(x=0;x<f.length();x++){if(f[x]=='#'){if(x==f.length()-1)f=f.substr(0,x);else f=f.substr(0,x)+f.substr(x+1);}}first[mm]=first[mm]+f;}first[mm]=first[mm]+"#";}else{for(j=0;j<p[i].right.length();j++){for(x=0;x<n;x++){if(p[i].right[j]==noend[x])break;}y=x;if(first[y]=="")First(p,n,p[i].right[j],x);f=first[y];for(x=0;x<f.length();x++){if(f[x]=='#'){if(x==f.length()-1)f=f.substr(0,x);else f=f.substr(0,x)+f.substr(x+1);}}first[mm]=first[mm]+f;}}}}}}}void Follow(Chomsky *p,int n,int m)//求文法的follow集{int i,j,x,y,k;string fo;for(i=0;i<n;i++){for(j=0;j<p[i].right.length();j++){if(noend[m]==p[i].right[j]){if(j<p[i].right.length()-1&&'a'<=p[i].right[j+1]&&p[i].right[j+1]<='z') follow[m]=follow[m]+p[i].right.substr(j+1,1);if(j<p[i].right.length()-1&&'A'<=p[i].right[j+1]&&p[i].right[j+1]<='Z') {for(y=0;y<noend.length();y++){if(noend[y]==p[i].right[j+1])break;}fo=first[y];for(x=0;x<first[y].length();x++){if(0<=first[y].find('#')&&first[y].find('#')<first[y].length())fo=first[y].substr(0,first[m].find('#'))+first[y].substr(first[y].find('#')+1);}follow[m]=follow[m]+fo;for(x=0;x<n;x++){if(p[i].right[j+1]==p[x].left[0]&&p[x].right[0]=='#')break;}if(x!=n)//非终结符后面的部分可以推出空{for(y=0;y<n;y++){if(p[i].left[0]==noend[y])break;}k=y;if(follow[k]=="")Follow(p,n,y);follow[m]=follow[m]+follow[k];}}if(j==p[i].right.length()-1){for(y=0;y<n;y++){if(p[i].left[0]==noend[y])break;}k=y;if(follow[k]=="")Follow(p,n,y);follow[m]=follow[m]+follow[k];}}}}}string erase(string s)//去First集及follow集中的重复字符{int i,j;for(i=0;i<s.length();i++){for(j=0;j<s.length();j++){if(i!=j&&s[i]==s[j])s=s.substr(0,j)+s.substr(j+1);}}return s;}/*void select(string s1,string s2)//求产生式的select集,s1是产生式左部,s2是产生式右部{if()//即s2可以推出空#{cout<<s1<<"->"<<s2<<"="<<first(s2)<<endl;}else//即s2不可以推出空#{cout<<s1<<"->"<<s2<<"="<<first(s2)-"#"+<<follow(s1)<<endl;}}*/void main(){cout<<"....................编译原理实验七:LL(1)文法的判断...................."<<endl;int i,j,m;char f;//存放文法开始符号cout<<"请输入文法产生式个数N以及各产生式(空用#代替,左右部的为-):"<<endl; cin>>n;Chomsky *p=new Chomsky[n]; // 初始化产生式数组for(i=0;i<n;i++){strings.erase();//清除cin>>strings;apart(p,i);}cout<<"请输入该文法的开始符号:"<<endl;cin>>f;search(p,n);//提取产生式中的非终结符//empty=is_empty(p)+isempty(p);//可以推出空的所有非终结符for(m=0;m<noend.length();m++){if(first[m]=="")First(p,n,noend[m],m);}cout<<"该文法非终结符的first集:"<<endl;for(i=0;i<noend.length();i++){first[i]=erase(first[i]);cout<<noend[i]<<":"<<first[i]<<endl;}for(m=0;m<noend.length();m++){if(noend[m]==f)follow[m]=follow[m]+"#";if(follow[m]=="")Follow(p,n,m);}cout<<"该文法非终结符的follow集:"<<endl;for(i=0;i<noend.length();i++){follow[i]=erase(follow[i]);cout<<noend[i]<<":"<<follow[i]<<endl;}cout<<"该文法的各产生式的select集:"<<endl;for(i=0;i<n;i++){select[i]=erase(select[i]);cout<<p[i].left<<"->"<<p[i].right<<":"<<select[i]<<endl; }system("pause");}11 / 11。

编译原理--LL(1)文法 算法代码

编译原理--LL(1)文法 算法代码

/* LL(1)文法<古城童话>$为空字; 输入0,表示结束测试案例:案例1.(编译原理P76的LL(1)文法,E'改成了A,T'改成了B);E->TA A->+TA|$ T->FB B->*FB|$ F->(E)|i 0案例2. (First和Follow有非空交集)S->Ab A->a|B|$ B->b|$ 0*/#include <iostream>#include <string>using namespace std;const int MAX=100;int FirstNum=0,FollowNum=0; // First集合Follow集的数目string SaveStr[MAX]; //预存输入的字符串string TerStr="#"; //保存终结字符串int FlagError1=0; //左递归错误标志struct Assemble{int FlagLast,FlagFirst; //首尾标志int Position ; //字符串的位置char Data;Assemble *Next;};Assemble *First[MAX]; //定义Fist集Assemble *Follow[MAX]; //定义Follow集int IsNonterminal(char Cur) //判断是否为非终结符{if(Cur<='Z'&&Cur>='A')return 1;return 0;}int IsTerminal(char Cur) //判断是否为终结符{if(IsNonterminal(Cur)||Cur=='|')return 0;return 1 ;}int Exist(Assemble* L,char Cur,int Flag) //L的集合里面是否有Cur字符{ //Flag为1表示First,为0表示Followif(!L) return 0;Assemble *P;for(P=L->Next;P;P=P->Next)if(P->Data==Cur)return Flag ? P->Position:1 ;return 0;}int IsEmptyStr(char Cur) //字符串里面是否有${for(int i=0;i<FirstNum;i++)if(SaveStr[i][0]==Cur){ if(SaveStr[i].find('$')==-1)return 0;return 1;}}void HideSame(Assemble* &L) //消除相同的字符{Assemble *P,*Pa;for(P=L->Next;P->Next;P=P->Next)for(Pa=P->Next;Pa;Pa=Pa->Next)if(P->Data==Pa->Data) Pa->Data=3;}Assemble* FindAddFirst(char Cur) //查找要添加的First集{for(int i=FirstNum-1;i>=0;i--)if(First[i]->Data==Cur) return First[i];return NULL;}Assemble* FindAddFollow(char Cur) //查找要添加的Follow集{for(int i=0;i<FollowNum;i++)if(Follow[i]->Data==Cur) return Follow[i];return NULL;}void CreatFirst(Assemble* &L,string Str) //创建Firs集{Assemble *P=L,*Pa;int FlagLeft=0,Pos=3,j,i;L->FlagLast=0;for(i=3;Str[i];i++){int FlagGo=1,FlagLa=1;char Ch=L->Data;if(Ch==Str[3]||Str[i-1]=='|'&&Str[i]==Ch) FlagError1=1; //含有左递归while(i<Str.length()&&Str[i]!='|'){if(IsNonterminal(Str[i]))FlagGo=(IsEmptyStr(Str[i])? 1:0);Pa=new Assemble;Pa->Data=Str[i];Pa->Position=Pos;P->Next=Pa;P=Pa;if(!FlagGo||IsTerminal(Str[i])){ FlagLa=0; break; }i++;}if(!FlagLa)while(Str[i]&&Str[i]!='|')i++;else { L->FlagLast=1; }Pos=i+1;}P->Next=NULL;}void CreatFollow(string Str) //创建Follow集{int i,j,Num;for(i=3;Str[i];i++){Num=-1;if(IsNonterminal(Str[i])){ for(j=0;j<FollowNum;j++)if(Follow[j]->Data==Str[i]){ Num=j; break; }if(Num<0){Follow[FollowNum]= new Assemble;Follow[FollowNum]->Data=Str[i];Follow[FollowNum]->Next=NULL;Num=FollowNum++;}int FlagGo=0,FlagLa=0;Assemble *Pa,*Pb,*P=Follow[Num];for(j=i+1;Str[j]&&Str[j]!='|';j++){Pa=new Assemble;Pa->FlagLast=0;for(;P->Next;P=P->Next);FlagGo=Exist(FindAddFirst(Str[j]),'$',1)? 1:0;Pa->Data=Str[j];P->Next=Pa;Pa->Next=NULL;if(!FlagGo){ FlagLa=1; break; } //是否继续添加}if(!FlagLa) //非终结符位于末尾{for(;P->Next;P=P->Next);Pb=new Assemble;Pb->FlagLast=1;Pb->Data=Str[0];Pb->Next=P->Next;P->Next=Pb;}}}}void InitFollow(int Num) //初始化Follow集{for(int i=0;i<Num;i++){if(!i){Follow[FollowNum]=new Assemble;Follow[FollowNum]->Data=SaveStr[0][0];Follow[FollowNum]->Next=new Assemble;Follow[FollowNum]->Next->Data='#';Follow[FollowNum++]->Next->Next=NULL;}CreatFollow(SaveStr[i]);}}//增添Follow集,Num=1,增添First集,Num=0,增添Follow集void AddFollow(Assemble* &L, Assemble* Head,int Num){Assemble *Pa,*Pb,*Pc;for(Pc=Head->Next;Pc;Pc=Pc->Next){ for(Pa=L->Next;Pa;Pa=Pa->Next)if(Pa->Data==Pc->Data)break;if(!Pa){if(Pc->Data=='$'&&Num) continue;Pb=new Assemble;Pb->Data=Pc->Data;Pb->Next=L->Next;L->Next=Pb;}}}void GetFollow(Assemble* &L) //得到Follow集{Assemble *P,*Head;for(P=L->Next;P;P=P->Next)if(IsNonterminal(P->Data)){if(P->FlagLast) //位于末尾,增添Follow集{Head=FindAddFollow(P->Data);AddFollow(L,Head,0);}else //不位于末尾,增添First集{Head=FindAddFirst(P->Data);AddFollow(L,Head,1);}}}int GetFirst(Assemble* &L) //得到First集{Assemble *P,*Pa,*Pb,*Pc,*Head;for(P=L->Next;P;P=P->Next)if(IsNonterminal(P->Data)){Head=FindAddFirst(P->Data);if(!Head)return 0;for(Pc=Head->Next;Pc;Pc=Pc->Next)if(Pc->Data=='$'&&!L->FlagLast)continue;Pb=new Assemble;Pb->Data=Pc->Data;Pb->Position=P->Position;Pb->Next=L->Next;L->Next=Pb;}}}void KeepTerStr(string Str) //保存终结符{for(int i=3;Str[i];i++)if(IsTerminal(Str[i])&&Str[i]!='$'){if(TerStr.find(Str[i])==-1)TerStr+=Str[i];}}void ShowLL1(Assemble *L,int num)//输出LL(1)文法{Assemble *P=L,*Head;int i,npos;string Str=SaveStr[num];cout<<First[num]->Data<<"\t";for(i=0;TerStr[i];i++){if(npos=Exist(L,TerStr[i],1)){cout<<First[num]->Data<<"->";if(npos==1)npos=3;while(Str[npos]!='|'&&npos<Str.length()){cout<<Str[npos];npos++;}}else if(Exist(L,'$',0)){Head=FindAddFollow(First[num]->Data);if(Exist(Head,TerStr[i],0))cout<<First[num]->Data<<"->"<<"$";cout<<"____";}else cout<<"____";cout<<"\t ";}cout<<"\n\n";}int IsError2()//测试是否有左因子{string AddStr,Str;for(int i=0;i<FirstNum;i++){AddStr="";Str=SaveStr[i];for(int j=0;Str[j];j++)if(j==3||Str[j-1]=='|'){if(AddStr.find(Str[j])!=-1) return 1;AddStr+=Str[j];}}return 0;}Assemble* IsError3(char &Ch) //测试First和Follow是否有非交集{Assemble *P,*Pa,*Head;for(int i=0;i<FirstNum;i++){for(P=First[i]->Next;P;P=P->Next){Head=FindAddFollow(First[i]->Data);if(P->Data!='$'&&IsTerminal(P->Data)&&P->Data!=3)for(Pa=Head->Next;Pa;Pa=Pa->Next)if(Pa->Data==P->Data){ Ch=First[i]->Data; return P; }}}return NULL;}int ShowForm() //显示LL(1)文法的终结符{Assemble *P;char Cur;if(FlagError1){ cout<<"\n文法中含有左递归...!\n"; return 1; }if(IsError2()){ cout<<"\n文法中含有左因子...!\n"; return 1; }if(P=IsError3(Cur)){ printf("\n文法中First(%c)和Follow(%c)有非空交集%c...!\n",Cur,Cur,P->Data);return 1;}cout<<"\nLL(1)分析表:\n\n";for(int i=0;TerStr[i];i++)cout<<"\t "<<TerStr[i];cout<<endl;for(int i=0;i<FirstNum;i++)ShowLL1(First[i],i);}void GetFistrFollow(int Num){int i,j;FirstNum=Num;for(i=0;i<Num;i++){First[i]=new Assemble;First[i]->Data=SaveStr[i][0];CreatFirst(First[i],SaveStr[i]); //创建First集}for(j=0,i=FirstNum-1;i>=0;i--,j++) //得到First集{GetFirst(First[i]);GetFirst(First[j]);}InitFollow(Num); //初始化Follow集for(i=0;i<FollowNum;i++)GetFollow(Follow[i]); //得到Follow集}int main(){int i,j,Num=0;cout<<"请输入文法产生式(以输入0结束):\n";while(cin>>SaveStr[Num]&&SaveStr[Num][0]!='0') {KeepTerStr(SaveStr[Num]);Num++;}GetFistrFollow(Num); //获得First集合Follw集ShowForm(); //输出LL(1)文法表system("pause");}。

编译原理实验报告3-LL(1)文法构造

编译原理实验报告3-LL(1)文法构造

实验3 LL(1)文法构造一、实验目的熟悉LL(1)文法的分析条件,了解LL(1)文法的构造方法。

二、实验内容1、编制一个能够将一个非LL(1)文法转换为LL(1)文法;2、消除左递归;3、消除回溯。

三、实验要求1、将一个可转换非LL(1)文法转换为LL(1)文法,要经过两个阶段,1)消除文法左递归,2)提取左因子,消除回溯。

2、提取文法左因子算法:1)对文法G的所有非终结符进行排序2)按上述顺序对每一个非终结符Pi依次执行:for( j=1; j< i-1;j++)将Pj代入Pi的产生式(若可代入的话);消除关于Pi的直接左递归:Pi -> Piα|β ,其中β不以Pi开头,则修改产生式为:Pi —> βPi′Pi′—>αPi′|ε3)化简上述所得文法。

3、提取左因子的算法:A—>δβ1|δβ2|…|δβn|γ1|γ2|…|γm(其中,每个γ不以δ开头) 那么,可以把这些产生式改写成A —>δA′|γ1| γ2…|γmA′—>β1|β2|…|βn4、利用上述算法,实现构造一个LL(1)文法:1)从文本文件g.txt中读入文法,利用实验1的结果,存入实验1设计的数据结构;2)设计函数remove_left_recursion()和remove_left_gene()实现消除左递归和提取左因子算法,分别对文法进行操作,消除文法中的左递归和提出左因子;3)整理得到的新文法;4)在一个新的文本文件newg.txt输出文法,文法输出按照一个非终结符号一行,开始符号引出的产生式写在第一行,同一个非终结符号的候选式用“|”分隔的方式输出。

四、实验环境PC微机DOS操作系统或Windows操作系统Turbo C程序集成环境或VisualC++ 程序集成环境五、实验步骤1、学习LL(1)文法的分析条件;2、学习构造LL(1)文法的算法;3、结合实验1给出的数据结构,编程实现构造LL(1)文法的算法;4、结合实验1编程和调试实现对一个具体文法运用上述算法,构造它的LL(1)文法形式;5、把实验结果写入一个新建立的文本文件。

编译原理-LL(1)文法源代码(实验三)

编译原理-LL(1)文法源代码(实验三)

一、实验目的及要求1.掌握LL(1)分析法的基本原理;2.掌握LL(1)分析表的构造方法;3.用LL(1)分析法分析高级语言表达式。

4、了解LL(1)分析器的工作过程。

文法:无二义性的算术表达式的文法(1)把词法分析作为语法分析的子程序实现(5分)(2)独立的语法分析程序(4分)(3)对表达式文法消除左递归、构造LL(1)分析表(4)LL(1)分析表可以直接输入(4分),也可以用程序实现(5分)(5)给一个表达式,给出分析过程(分析栈、输入串、所用规则)(4分)(6)生成一个棵语法树(5分)用二叉树的形式表示出来二、实验内容及原理1、实验原理(1)、LL(1)文法的定义LL(1)分析法属于确定的自顶向下分析方法。

LL(1)的含义是:第一个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将使用最左推导,1表明只需向右看一个符号便可决定如何推导,即选择哪个产生式(规则)进行推导。

LL(1)文法的判别需要依次计算FIRST集、FOLLOW集和SELLECT集,然后判断是否为LL(1)文法,最后再进行句子分析。

需要预测分析器对所给句型进行识别。

即在LL(1)分析法中,每当在符号栈的栈顶出现非终极符时,要预测用哪个产生式的右部去替换该非终极符;当出现终结符时,判断其与剩余输入串的第一个字符是否匹配,如果匹配,则继续分析,否则报错。

LL(1)分析方法要求文法满足如下条件:对于任一非终极符A的两个不同产生式A→α,A→β,都要满足下面条件:SELECT(A→α)∩SELECT(A→β)=∅(2)、预测分析表构造LL(1)分析表的作用是对当前非终极符和输入符号确定应该选择用哪个产生式进行推导。

它的行对应文法的非终极符,列对应终极符,表中的值有两种:一是产生式的右部的字符串,一是null。

若用M表示LL(1)分析表,则M可表示如下:M: VN×VT→P∪{Error}M(A, t) = A→α,当t∈select(A→α) ,否则M(A, t) = Error其中P表示所有产生式的集合。

编译原理之LL(1)GFG

编译原理之LL(1)GFG

LL(1)GFG文法#include "stdio.h"#include "string.h"#include "stdlib.h"#define STR_MAX 80 //串的最大长度#define MAX_NUM 100 //符号的最大个数#define MAX 32767 //文件中符号的最大个数struct PRO{ //产生式类型char left;char right[STR_MAX];char firstR[MAX_NUM];char followL[MAX_NUM];char select[MAX_NUM];};struct VNStru{char vn;int checked;int flag;char first[MAX_NUM];char follow[MAX_NUM];};char SOUR[STR_MAX]; //源文件名char OBJ[STR_MAX]; //目标文件名char ERR[STR_MAX]; //错误信息文件名FILE *INF; //源程序文件指针FILE *OUTF; //分析结果文件指针FILE *ERRF; //错误信息文件指针char GFG[MAX]; //存放上下文无关文法int GFGLen; //上下文无关文法长度VNStru VN[MAX_NUM]; //非终结符数组int VN_CNT; //非终结符个数char VT[MAX_NUM]; //终结符数组int VT_CNT; //终结符个数char S0; //开始符号PRO P[MAX_NUM]; //产生式数组int P_CNT; //产生式个数char VN_EMPTY[MAX_NUM]; //可空非终结符char VN_NotEMPTY[MAX_NUM]; //不可空非终结符bool isIN(char ch,char arr[]); //判别符号ch是否在arr数组中int isVN(char ch); //判别符号ch是否在VN数组中,存在则返回下标,否则返回-1int isVT(char ch); //判别符号ch是否在VT数组中,存在则返回下标,否则返回-1void getGFG(); //从源文件取得GFG文法串void getVN_VT_S_P(); //从GFG文法提取VN,VT,S,P bool isEMPTY(char a[]); //判别集合是否为空void Eflag_VN(); //判别所有非终结符的可空性bool isE_ch(char ch); //判别一个文法符号是否可以推到为空bool isE_str(char a[]); //判别一个文法串a是否可以推到为空void subE(char a[],char b[]); //集合a去掉空元素@,存入b void MIX(char a[],char b[],char c[]); //求a,b的交集cvoid UNION(char a[],char b[],char c[]); //求a,b的并集cvoid substr(char str[],char substr[],int begin,int end); //求子串void FIRST_ch(char ch,char s[]); //求文法符号ch的FIRST集s void FIRST_str(char str[],char s[]); //求文法符号串str的FIRST集s void FOLLOW(char ch,char s[]); //求VN符号ch的FOLLOW集s void SELECT(PRO p,char s[]); //求产生式p的SELECT集s bool LL1(); //判别P数组中产生式组成的文法是否为LL(1)文法//判别符号ch是否在arr数组中bool isIN(char ch,char arr[]){int len=strlen(arr);for(int i=0;i<len;i++){if(ch==arr[i]) return true;}return false;}//判别符号ch是否在VN数组中,存在则返回下标,否则返回-1 int isVN(char ch){for(int i=0;i<VN_CNT;i++){if(ch==VN[i].vn) return i;}return -1;}//判别符号ch是否在VT数组中,存在则返回下标,否则返回-1 int isVT(char ch){for(int i=0;i<VT_CNT;i++){if(ch==VT[i]) return i;}return -1;}//从源文件取得GFG文法串void getGFG(){GFGLen=0;char ch;while(!feof(INF)){ch=fgetc(INF);if(ch!=' ')GFG[GFGLen++]=ch;}GFG[GFGLen]='\0';printf("The GFG is :\n"); //将文法输出到屏幕puts(GFG);fprintf(OUTF,"The GFG is :\n");fputs(GFG,OUTF); //将文法输出到文件}//从GFG文法提取VN,VT,S,Pvoid getVN_VT_S_P(){VN_CNT=0;VT_CNT=0;P_CNT=0;int newPF=0; //是否进入新产生式的标志int rightLen=0;char prech,ch,nextch;for(int i=0;i<GFGLen;i++){if(i!=0) prech=GFG[i-1]; //取文法文件中的前一个符号ch=GFG[i]; //取文法文件中的当前符号nextch=GFG[i+1]; //取文法文件中的下一个符号if(nextch=='~'){ //下一个符号是~,代表箭头if(isVN(ch)==-1){ //当前符号不是已经识别到的VN VN[VN_CNT].vn=ch; //加入VNVN[VN_CNT].checked=0; //并初始化VN记录VN[VN_CNT].flag=0;strcpy(VN[VN_CNT].first,"");strcpy(VN[VN_CNT].follow,"");VN_CNT++;}P[P_CNT].left=ch; //记入新产生式的左部if(P_CNT==0)S0=ch; //第一条产生式的左部是开始符号i++; //跳过~}if(prech=='~'||prech=='|'){newPF=1; //进入新的产生式rightLen=0;}if(newPF==1){P[P_CNT].right[rightLen++]=ch;}if(nextch=='\n'||nextch=='|'){newPF=0; //一条产生式结束strcpy(P[P_CNT].firstR,""); //初始化产生式记录strcpy(P[P_CNT].followL,"");strcpy(P[P_CNT].select,"");P_CNT++; //产生式个数加1P[P_CNT].left=P[P_CNT-1].left;i++; //跳过回车和|}}P_CNT++;ch=GFG[j];if(ch!='~'&&ch!='|'&&ch!='@'&&ch!='\n'&&isVN(ch)==-1&&is VT(ch)==-1)VT[VT_CNT++]=ch;}VT[VT_CNT]='\0';//输出VNprintf("\nVN:\t");fprintf(OUTF,"\nVN:\t");for(int x=0;x<VN_CNT;x++){printf("%c",VN[x].vn);fprintf(OUTF,"%c",VN[x].vn);}//输出VTprintf("\nVT:\t%s\n",VT);fprintf(OUTF,"\nVT:\t%s\n",VT);//输出Sprintf("S0:\t%c\n",S0);fprintf(OUTF,"S0:%c\n",S0);//输出Pfor(int k=0;k<P_CNT;k++){printf("P[%d]:\t%c-->%s\n",k,P[k].left,P[k].right);fprintf(OUTF,"P[%d]:\t%c-->%s\n",k,P[k].left,P[k].right);}}//判别集合是否为空bool isEMPTY(char a[]){if(strlen(a)==0) return true;else return false;}//判别所有非终结符的可空性void Eflag_VN(){int E_VN_cnt=0,NE_VN_cnt=0;//可空和不可空的VN个数初始均为0 int pNUM=0,cur_rightLen; //PNUM记录当前被考察的VN 的产生式个数pNUM=0;for(int i=0;i<P_CNT;i++){//在所有产生式中查找当前VN 的所有产生式if(VN[v].vn==P[i].left&&VN[v].checked==0){pNUM++;cur_rightLen=strlen(P[i].right);for(int j=0;j<cur_rightLen;j++)if(P[i].right[j]=='@'){VN[v].flag+=0;VN_EMPTY[E_VN_cnt++]=VN[v].vn;//将VN 加入到可空数组VN[v].checked=1;break;}else{if(isVT(P[i].right[j])!=-1){VN[v].flag+=1;break;}}}}if(VN[v].checked==0&&pNUM==VN[v].flag){VN[v].checked=1;VN_NotEMPTY[NE_VN_cnt++]=VN[v].vn; //将VN加入到不可空数组}}int f;while(E_VN_cnt+NE_VN_cnt!=VN_CNT){ //仍有未确定可空或不可空的VNfor(int k=0;k<VN_CNT;k++){if(VN[k].checked==0){ //循环所有未检查的VNpNUM=0;for(int n=0;n<P_CNT;n++){f=0;if(VN[k].vn==P[n].left){pNUM++;cur_rightLen=strlen(P[n].right);for(int m=0;m<cur_rightLen;m++)if(isIN(P[n].right[m],VN_EMPTY))f+=0;else if(isIN(P[n].right[m],VN_NotEMPTY))f+=1;else f=-1;if(f==0){VN[k].flag+=0;VN[k].checked=1;VN_EMPTY[E_VN_cnt++]=VN[k].vn;//可空break;}else if(f>0) VN[k].flag+=1;}}if(VN[k].checked==0&&pNUM==VN[k].flag){VN[k].checked=1;VN_NotEMPTY[NE_VN_cnt++]=VN[k].vn; //不可空}}}}VN_EMPTY[E_VN_cnt]='\0';VN_NotEMPTY[NE_VN_cnt]='\0';//输出VN_EMPTY和VN_NotEMPTYprintf("\nEMPTY_VN:\t%s\n",VN_EMPTY);printf("NOT_EMPTY_VN:\t%s\n\n",VN_NotEMPTY);fprintf(OUTF,"\nEMPTY_VN:\t%s\n",VN_EMPTY);fprintf(OUTF,"NOT_EMPTY_VN:\t%s\n\n",VN_NotEMPTY);}//判别一个文法符号是否可以推到为空bool isE_ch(char ch){if(isIN(ch,VT))return false;else if(ch=='@')return true;else if(isIN(ch,VN_EMPTY))return true;else return false;}//判别一个文法符号串是否可以推到为空bool isE_str(char a[]){int alen=strlen(a);bool f=true;for(int i=0;i<alen;i++){f&=isE_ch(a[i]);}return f;}//集合去掉空元素@void subE(char a[],char b[]){int alen=strlen(a);int j=0;for(int i=0;i<=alen;i++)if(a[i]!='@')b[j++]=a[i];}//求交集void MIX(char a[],char b[],char c[]){ int alen,blen,clen;alen=strlen(a);blen=strlen(b);clen=0;for(int i=0;i<alen;i++)for(int j=0;j<blen;j++){if(a[i]==b[j]){c[clen++]=a[i];break;}}c[clen]='\0';}//求并集void UNION(char a[],char b[],char c[]){ int alen,blen,clen;alen=strlen(a);blen=strlen(b);clen=0;for(int i=0;i<alen;i++)c[clen++]=a[i];for(int j=0;j<blen;j++){for(int k=0;k<alen;k++)if(b[j]==a[k])break;if(k==alen)c[clen++]=b[j];}c[clen]='\0';}//求文法符号的FIRST集/*1. 若X∈VT,则FIRST(X)={X};2. 若X∈VN,且有X→a…,a∈VT,则a∈ FIRST(X)。

编译原理LL(1)语法分析器java版完整源代码

编译原理LL(1)语法分析器java版完整源代码

编译原理LL(1)语法分析器java版完整源代码public class Accept2 {public static StringBuffer stack=new StringBuffer("#E");public static StringBuffer stack2=new StringBuffer("i+i*#");public static void main(String arts[]){//stack2.deleteCharAt(0);System.out.print(accept(stack,stack2));}public static boolean accept(StringBuffer stack,StringBuffer stack2){//判断识别与否boolean result=true;outer:while (true) {System.out.format("%-9s",stack+"");System.out.format("%9s",stack2+"\n");char c1 = stack.charAt(stack.length() - 1);char c2 = stack2.charAt(0);if(c1=='#'&&c2=='#')return true;switch (c1) {case'E':if(!E(c2)) {result=false;break outer;}break;case'P': //P代表E’if(!P(c2)) {result=false;break outer;}break;case'T':if(!T(c2)) {result=false;break outer;}break;case'Q': //Q代表T’if(!Q(c2)) {result=false;break outer;}break;case'F':if(!F(c2)) {result=false;break outer;}break;default: {//终结符的时候if(c2==c1){//System.out.println();}else{return false;}}}if(result=false)break outer;}return result;}public static boolean E(char c) {//语法分析⼦程序 E boolean result=true;if(c=='i') {stack.deleteCharAt(stack.length()-1);stack.append("PT");}else if(c=='('){stack.deleteCharAt(stack.length()-1);stack.append("PT");else{System.err.println("E 推导时错误!不能匹配!"); result=false;}return result;}public static boolean P(char c){//语法分析⼦程序 P boolean result=true;if(c=='+') {stack.deleteCharAt(stack.length()-1);stack.append("PT+");}else if(c==')') {//stack.append("");System.out.println("P->/");}else if(c=='#') {stack.deleteCharAt(stack.length()-1);//stack.append("");System.out.println("P->/");else{System.err.println("P 推导时错误!不能匹配!");result=false;}return result;}public static boolean T(char c) {//语法分析⼦程序 Tboolean result=true;if(c=='i') {stack.deleteCharAt(stack.length()-1);stack.append("QF");}else if(c=='(') {stack.deleteCharAt(stack.length()-1);stack.append("QF");}else{result=false;System.err.println("T 推导时错误!不能匹配!");}return result;public static boolean Q(char c){//语法分析⼦程序 Q boolean result=true; if(c=='+') {stack.deleteCharAt(stack.length()-1);//stack.append("");System.out.println("Q->/");}stack.deleteCharAt(stack.length()-1);stack.append("QF*");}else if(c==')') {stack.deleteCharAt(stack.length()-1);//stack.append("");System.out.println("Q->/");}else if(c=='#') {stack.deleteCharAt(stack.length()-1);//stack.append("");System.out.println("Q->/");}else{result=false;System.err.println("Q 推导时错误!不能匹配!"); }return result;}public static boolean F(char c) {//语法分析⼦程序 F boolean result=true;if(c=='i') {stack.deleteCharAt(stack.length()-1);stack.append("i");}else if(c=='(') {stack.deleteCharAt(stack.length()-1);stack.append(")E(");}else{result=false;System.err.println("F 推导时错误!不能匹配!"); }return result;/* public static StringBuffer changeOrder(String s){//左右交换顺序StringBuffer sb=new StringBuffer();for(int i=0;isb.append(s.charAt(s.length()-1-i));}return sb;}*/}#E i+i*i+i##PT i+i*i+i##PQF i+i*i+i##PQi i+i*i+i##PQ +i*i+i#Q->/#P +i*i+i##PT+ +i*i+i##PT i*i+i##PQF i*i+i##PQi i*i+i##PQ *i+i##PQF* *i+i##PQF i+i##PQi i+i##PQ +i#Q->/#P +i##PT+ +i##PT i##PQF i##PQi i##PQ #Q->/#P #P->/True#E i+i*##PT i+i*##PQF i+i*##PQi i+i*##PQ +i*#Q->/#P +i*##PT+ +i*##PT i*##PQF i*##PQi i*##PQ *##PQF* *##PQF #falseF 推导时错误!不能匹配!。

Java实现《编译原理》简单-语法分析功能-LL(1)文法-程序解析

Java实现《编译原理》简单-语法分析功能-LL(1)文法-程序解析

Java实现《编译原理》简单-语法分析功能-LL(1)⽂法-程序解析Java 实现《编译原理》简单-语法分析功能-LL(1)⽂法 - 程序解析编译原理学习,语法分析程序设计(⼀)要求及功能已知 LL(1) ⽂法为:G'[E]: E→TE'E'→+TE'|εT→FT'T'→*FT'|εF→(E)|i为了⽅便处理,⽤:M 代替 E',N 代表 T';并展开相同同⼀⾮终结符的产⽣式;不影响含义,可⾃⾏再优化即有:G[E]: E→TMM→+TMM→εT→FNN→*FNN→εF→(E)F→i根据⽂法建⽴ LL(1) 分析表,并对输⼊串 i+i*i 进⾏语法分析,判断其是否是合法的句⼦(⼆)整体与执⾏结果所需类:执⾏结果:(三)程序源代码(1)Grammar.java ⽂件:package com.java997.analyzer.grammar; import java.io.File;import java.io.FileWriter;import java.io.Serializable;import java.io.Writer;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.Set;import java.util.TreeMap;import java.util.TreeSet;/*** LL(1)⽂法* 1.获取 First 集* 2.获取 Follow 集* 3.获取 SELECT 集** @author XiaoPengwei* @since 2019-06-18*/public class Grammar implements Serializable {private static final long serialVersionUID = 1L;public Grammar() {super();gsArray = new ArrayList<String>();nvSet = new TreeSet<Character>();ntSet = new TreeSet<Character>();firstMap = new HashMap<Character, TreeSet<Character>>();followMap = new HashMap<Character, TreeSet<Character>>();selectMap = new TreeMap<Character, HashMap<String, TreeSet<Character>>>(); }private String[][] analyzeTable;/*** Select集合*/private TreeMap<Character, HashMap<String, TreeSet<Character>>> selectMap;/*** LL(1)⽂法产⽣集合*/private ArrayList<String> gsArray;/*** 表达式集合*/private HashMap<Character, ArrayList<String>> expressionMap;/*** 开始符*/private Character s;/*** Vn⾮终结符集合*/private TreeSet<Character> nvSet;/*** Vt终结符集合*/private TreeSet<Character> ntSet;/*** First集合*/private HashMap<Character, TreeSet<Character>> firstMap;/*** Follow集合*/private HashMap<Character, TreeSet<Character>> followMap;public String[][] getAnalyzeTable() {return analyzeTable;}public void setAnalyzeTable(String[][] analyzeTable) {this.analyzeTable = analyzeTable;public TreeMap<Character, HashMap<String, TreeSet<Character>>> getSelectMap() {return selectMap;}public void setSelectMap(TreeMap<Character, HashMap<String, TreeSet<Character>>> selectMap) { this.selectMap = selectMap;}public HashMap<Character, TreeSet<Character>> getFirstMap() {return firstMap;}public void setFirstMap(HashMap<Character, TreeSet<Character>> firstMap) {this.firstMap = firstMap;}public HashMap<Character, TreeSet<Character>> getFollowMap() {return followMap;}public void setFollowMap(HashMap<Character, TreeSet<Character>> followMap) {this.followMap = followMap;}public HashMap<Character, ArrayList<String>> getExpressionMap() {return expressionMap;}public void setExpressionMap(HashMap<Character, ArrayList<String>> expressionMap) {this.expressionMap = expressionMap;}public ArrayList<String> getGsArray() {return gsArray;}public void setGsArray(ArrayList<String> gsArray) {this.gsArray = gsArray;}public Character getS() {return s;}public void setS(Character s) {this.s = s;}public TreeSet<Character> getNvSet() {return nvSet;}public void setNvSet(TreeSet<Character> nvSet) {this.nvSet = nvSet;}public TreeSet<Character> getNtSet() {return ntSet;}public void setNtSet(TreeSet<Character> ntSet) {this.ntSet = ntSet;}/*** 获取⾮终结符集与终结符集*/public void getNvNt() {for (String gsItem : gsArray) {String[] nvNtItem = gsItem.split("->");String charItemStr = nvNtItem[0];char charItem = charItemStr.charAt(0);// nv在左边nvSet.add(charItem);}for (String gsItem : gsArray) {String[] nvNtItem = gsItem.split("->");// nt在右边String nvItemStr = nvNtItem[1];// 遍历每⼀个字for (int i = 0; i < nvItemStr.length(); i++) {char charItem = nvItemStr.charAt(i);if (!nvSet.contains(charItem)) {ntSet.add(charItem);}}}}/*** 初始化表达式集合*/public void initExpressionMaps() {expressionMap = new HashMap<Character, ArrayList<String>>(); for (String gsItem : gsArray) {String[] nvNtItem = gsItem.split("->");String charItemStr = nvNtItem[0];String charItemRightStr = nvNtItem[1];char charItem = charItemStr.charAt(0);if (!expressionMap.containsKey(charItem)) {ArrayList<String> expArr = new ArrayList<String>();expArr.add(charItemRightStr);expressionMap.put(charItem, expArr);} else {ArrayList<String> expArr = expressionMap.get(charItem);expArr.add(charItemRightStr);expressionMap.put(charItem, expArr);}}}/*** 获取 First 集*/public void getFirst() {// 遍历所有Nv,求出它们的First集合Iterator<Character> iterator = nvSet.iterator();while (iterator.hasNext()) {Character charItem = iterator.next();ArrayList<String> arrayList = expressionMap.get(charItem);for (String itemStr : arrayList) {boolean shouldBreak = false;// Y1Y2Y3...Ykfor (int i = 0; i < itemStr.length(); i++) {char itemitemChar = itemStr.charAt(i);TreeSet<Character> itemSet = firstMap.get(charItem);if (null == itemSet) {itemSet = new TreeSet<Character>();}shouldBreak = calcFirst(itemSet, charItem, itemitemChar); if (shouldBreak) {break;}}}}}/*** 计算 First 函数** @param itemSet* @param charItem* @param itemitemChar* @return boolean*/private boolean calcFirst(TreeSet<Character> itemSet, Character charItem, char itemitemChar) {// 将它的每⼀位和Nt判断下// 是终结符或空串,就停⽌,并将它加到FirstMap中if (itemitemChar == 'ε' || ntSet.contains(itemitemChar)) {itemSet.add(itemitemChar);firstMap.put(charItem, itemSet);// break;return true;} else if (nvSet.contains(itemitemChar)) {// 这⼀位是⼀个⾮终结符ArrayList<String> arrayList = expressionMap.get(itemitemChar);for (int i = 0; i < arrayList.size(); i++) {String string = arrayList.get(i);char tempChar = string.charAt(0);calcFirst(itemSet, charItem, tempChar);}}return true;}/*** 获取 Follow 集合*/public void getFollow() {for (Character tempKey : nvSet) {TreeSet<Character> tempSet = new TreeSet<Character>();followMap.put(tempKey, tempSet);}// 遍历所有Nv,求出它们的First集合Iterator<Character> iterator = nvSet.descendingIterator();while (iterator.hasNext()) {Character charItem = iterator.next();System.out.println("charItem:" + charItem);Set<Character> keySet = expressionMap.keySet();for (Character keyCharItem : keySet) {ArrayList<String> charItemArray = expressionMap.get(keyCharItem);for (String itemCharStr : charItemArray) {System.out.println(keyCharItem + "->" + itemCharStr);TreeSet<Character> itemSet = followMap.get(charItem);calcFollow(charItem, charItem, keyCharItem, itemCharStr, itemSet);}}}}/*** 计算 Follow 集** @param putCharItem 正在查询item* @param charItem 待找item* @param keyCharItem 节点名* @param itemCharStr 符号集* @param itemSet 结果集合*/private void calcFollow(Character putCharItem, Character charItem, Character keyCharItem, String itemCharStr, TreeSet<Character> itemSet) {// (1)A是S(开始符),加⼊#if (charItem.equals(s)) {itemSet.add('#');System.out.println("---------------find S:" + charItem + " ={#}+Follow(E)");followMap.put(putCharItem, itemSet);}// (2)Ab,=First(b)-ε,直接添加终结符if (TextUtil.containsAb(ntSet, itemCharStr, charItem)) {Character alastChar = TextUtil.getAlastChar(itemCharStr, charItem);System.out.println("---------------find Ab:" + itemCharStr + " " + charItem + " =" + alastChar);itemSet.add(alastChar);followMap.put(putCharItem, itemSet);// return;}// (2).2AB,=First(B)-ε,=First(B)-ε,添加first集合if (TextUtil.containsAB(nvSet, itemCharStr, charItem)) {Character alastChar = TextUtil.getAlastChar(itemCharStr, charItem);System.out.println("---------------find AB:" + itemCharStr + " " + charItem + " =First(" + alastChar + ")");TreeSet<Character> treeSet = firstMap.get(alastChar);itemSet.addAll(treeSet);if (treeSet.contains('ε')) {itemSet.add('#');}itemSet.remove('ε');followMap.put(putCharItem, itemSet);if (TextUtil.containsbAbIsNull(nvSet, itemCharStr, charItem, expressionMap)) {char tempChar = TextUtil.getAlastChar(itemCharStr, charItem);System.out.println("tempChar:" + tempChar + " key" + keyCharItem);if (!keyCharItem.equals(charItem)) {System.out.println("---------------find tempChar bA: " + "tempChar:" + tempChar + keyCharItem+ " " + itemCharStr + " " + charItem + " =Follow(" + keyCharItem + ")");Set<Character> keySet = expressionMap.keySet();for (Character keyCharItems : keySet) {ArrayList<String> charItemArray = expressionMap.get(keyCharItems);for (String itemCharStrs : charItemArray) {calcFollow(putCharItem, keyCharItem, keyCharItems, itemCharStrs, itemSet);}}}}}// (3)B->aA,=Follow(B),添加followBif (TextUtil.containsbA(nvSet, itemCharStr, charItem, expressionMap)) {if (!keyCharItem.equals(charItem)) {System.out.println("---------------find bA: " + keyCharItem + " " + itemCharStr + " " + charItem+ " =Follow(" + keyCharItem + ")");Set<Character> keySet = expressionMap.keySet();for (Character keyCharItems : keySet) {ArrayList<String> charItemArray = expressionMap.get(keyCharItems);for (String itemCharStrs : charItemArray) {calcFollow(putCharItem, keyCharItem, keyCharItems, itemCharStrs, itemSet);}}}}}/*** 获取 Select 集合*/public void getSelect() {// 遍历每⼀个表达式// HashMap<Character, HashMap<String, TreeSet<Character>>>Set<Character> keySet = expressionMap.keySet();for (Character selectKey : keySet) {ArrayList<String> arrayList = expressionMap.get(selectKey);// 每⼀个表达式HashMap<String, TreeSet<Character>> selectItemMap = new HashMap<String, TreeSet<Character>>(); for (String selectExp : arrayList) {/*** 存放select结果的集合*/TreeSet<Character> selectSet = new TreeSet<Character>();// set⾥存放的数据分3种情况,由selectExp决定// 1.A->ε,=follow(A)if (TextUtil.isEmptyStart(selectExp)) {selectSet = followMap.get(selectKey);selectSet.remove('ε');selectItemMap.put(selectExp, selectSet);}// 2.Nt开始,=Nt// <br>终结符开始if (TextUtil.isNtStart(ntSet, selectExp)) {selectSet.add(selectExp.charAt(0));selectSet.remove('ε');selectItemMap.put(selectExp, selectSet);}// 3.Nv开始,=first(Nv)if (TextUtil.isNvStart(nvSet, selectExp)) {selectSet = firstMap.get(selectKey);selectSet.remove('ε');selectItemMap.put(selectExp, selectSet);}selectMap.put(selectKey, selectItemMap);}}}/*** ⽣成预测分析表*/public void genAnalyzeTable() throws Exception {Object[] ntArray = ntSet.toArray();Object[] nvArray = nvSet.toArray();// 预测分析表初始化analyzeTable = new String[nvArray.length + 1][ntArray.length + 1];System.out.println("====================\n预测分析表\n====================");File outputFile = new File("D:\\template\\analyzer\\src\\main\\java\\com\\java997\\analyzer\\grammar\\analyzeTable.txt"); try (Writer writer = new FileWriter(outputFile)) {writer.write("====================\n预测分析表\n====================\n");// 输出⼀个占位符System.out.print("表" + "\t");writer.write("表" + "\t");analyzeTable[0][0] = "Nv/Nt";// 初始化⾸⾏for (int i = 0; i < ntArray.length; i++) {if (ntArray[i].equals('ε')) {ntArray[i] = '#';}writer.write(ntArray[i] + "\t\t");System.out.print(ntArray[i] + "\t\t");analyzeTable[0][i + 1] = ntArray[i] + "";}System.out.println("");writer.write("\n");for (int i = 0; i < nvArray.length; i++) {// ⾸列初始化writer.write(nvArray[i] + "\t");System.out.print(nvArray[i] + "\t");analyzeTable[i + 1][0] = nvArray[i] + "";for (int j = 0; j < ntArray.length; j++) {String findUseExp = TextUtil.findUseExp(selectMap, Character.valueOf((Character) nvArray[i]),Character.valueOf((Character) ntArray[j]));if (null == findUseExp) {writer.write("空\t\t");System.out.print("空\t\t");analyzeTable[i + 1][j + 1] = "";} else {writer.write(nvArray[i] + "->" + findUseExp + "\t");System.out.print(nvArray[i] + "->" + findUseExp + "\t");analyzeTable[i + 1][j + 1] = nvArray[i] + "->" + findUseExp; }}writer.write("\n");System.out.println();}} catch (Exception e) {e.printStackTrace();}}}(2)Analyzer.javapackage com.java997.analyzer.grammar;import java.util.ArrayList;import java.util.Stack;/*** <p>* 主程序句⼦分析器** @author XiaoPengwei* @since 2019-06-18*/public class Analyzer {public Analyzer() {super();analyzeStatck = new Stack<Character>();// 结束符进栈analyzeStatck.push('#');}private ArrayList<AnalyzeProduce> analyzeProduces;/*** LL(1)⽂法*/private Grammar ll1Grammar;public Grammar getLl1Grammar() {return ll1Grammar;}public void setLl1Grammar(Grammar ll1Grammar) {this.ll1Grammar = ll1Grammar;}/*** 开始符*/private Character startChar;/*** 分析栈*/private Stack<Character> analyzeStatck;/*** 剩余输⼊串*/private String str;/*** 推导所⽤产⽣或匹配*/private String useExp;public ArrayList<AnalyzeProduce> getAnalyzeProduces() {return analyzeProduces;}public void setAnalyzeProduces(ArrayList<AnalyzeProduce> analyzeProduces) {this.analyzeProduces = analyzeProduces;}public Character getStartChar() {return startChar;}public void setStartChar(Character startChar) {this.startChar = startChar;}public Stack<Character> getAnalyzeStatck() {return analyzeStatck;}public void setAnalyzeStatck(Stack<Character> analyzeStatck) {this.analyzeStatck = analyzeStatck;}public String getStr() {return str;}public void setStr(String str) {this.str = str;}public String getUseExp() {return useExp;}public void setUseExp(String useExp) {eExp = useExp;}/*** 分析*/public void analyze() {analyzeProduces = new ArrayList<AnalyzeProduce>();// 开始符进栈analyzeStatck.push(startChar);System.out.println("====================\nLL(1)⽂法分析过程\n====================");System.out.println("开始符:" + startChar);System.out.println("序号\t\t符号栈\t\t\t输⼊串\t\t\t所⽤产⽣式");int index = 0;// 开始分析// while (analyzeStatck.peek() != '#' && str.charAt(0) != '#') {while (!analyzeStatck.empty()) {index++;if (analyzeStatck.peek() != str.charAt(0)) {// 到分析表中找到这个产⽣式String nowUseExpStr = TextUtil.findUseExp(ll1Grammar.getSelectMap(), analyzeStatck.peek(), str.charAt(0)); //打印表格注意, 制表符的个数if (analyzeStatck.size()==1){System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t\t\t\t" + str + "\t\t\t"+ analyzeStatck.peek() + "->" + nowUseExpStr);}else if (analyzeStatck.size()==2){System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t\t\t" + str + "\t\t\t"+ analyzeStatck.peek() + "->" + nowUseExpStr);}else if (analyzeStatck.size()==3){System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t\t" + str + "\t\t\t"+ analyzeStatck.peek() + "->" + nowUseExpStr);}else {System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t" + str + "\t\t\t"+ analyzeStatck.peek() + "->" + nowUseExpStr);}AnalyzeProduce produce = new AnalyzeProduce();produce.setIndex(index);produce.setAnalyzeStackStr(analyzeStatck.toString());produce.setStr(str);if (null == nowUseExpStr) {produce.setUseExpStr("⽆法匹配!");} else {produce.setUseExpStr(analyzeStatck.peek() + "->" + nowUseExpStr);}analyzeProduces.add(produce);// 将之前的分析栈中的栈顶出栈analyzeStatck.pop();// 将要⽤到的表达式⼊栈,反序⼊栈if (null != nowUseExpStr && nowUseExpStr.charAt(0) != 'ε') {for (int j = nowUseExpStr.length() - 1; j >= 0; j--) {char currentChar = nowUseExpStr.charAt(j);analyzeStatck.push(currentChar);}}continue;}// 如果可以匹配,分析栈出栈,串去掉⼀位if (analyzeStatck.peek() == str.charAt(0)) {if (analyzeStatck.size()==1){System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t\t\t\t" + str + "\t\t\t" + "“" + str.charAt(0) + "”匹配");}else if (analyzeStatck.size()==2){System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t\t\t" + str + "\t\t\t" + "“" + str.charAt(0) + "”匹配");}else if (analyzeStatck.size()==3){System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t\t" + str + "\t\t\t" + "“" + str.charAt(0) + "”匹配");}else {System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t" + str + "\t\t\t" + "“"+ str.charAt(0) + "”匹配");}AnalyzeProduce produce = new AnalyzeProduce();produce.setIndex(index);produce.setAnalyzeStackStr(analyzeStatck.toString());produce.setStr(str);produce.setUseExpStr("“" + str.charAt(0) + "”匹配");analyzeProduces.add(produce);analyzeStatck.pop();str = str.substring(1);continue;}}}}(3)AnalyzeProduce.javapackage com.java997.analyzer.grammar;import java.io.Serializable;/*** <p>* 分析过程 Bean** @author XiaoPengwei* @since 2019-06-18*/public class AnalyzeProduce implements Serializable {private static final long serialVersionUID = 10L;private Integer index;private String analyzeStackStr;private String str;private String useExpStr;public Integer getIndex() {return index;}public void setIndex(Integer index) {this.index = index;}public String getAnalyzeStackStr() {return analyzeStackStr;}public void setAnalyzeStackStr(String analyzeStackStr) { this.analyzeStackStr = analyzeStackStr;}public String getStr() {return str;}public void setStr(String str) {this.str = str;}public String getUseExpStr() {return useExpStr;}public void setUseExpStr(String useExpStr) {eExpStr = useExpStr;}}(4)Main.javapackage com.java997.analyzer.grammar;import java.util.ArrayList;import java.util.TreeSet;/*** <p>* 主程序** @author XiaoPengwei* @since 2019-06-18*/public class Main {public static void main(String[] args) throws Exception { // 第⼀步:获取 LL(1)⽂法ArrayList<String> gsArray = new ArrayList<String>(); Grammar grammar = new Grammar();//初始化 LL(1), 设定该⽂法的产⽣式initGs(gsArray);grammar.setGsArray(gsArray);grammar.getNvNt();grammar.initExpressionMaps();grammar.getFirst();// 设置开始符grammar.setS('E');grammar.getFollow();grammar.getSelect();//打印预测分析表, 并保存⽂件grammar.genAnalyzeTable();// 创建⼀个分析器Analyzer analyzer = new Analyzer();// 设定开始符号analyzer.setStartChar('E');analyzer.setLl1Grammar(grammar);// 待分析的字符串analyzer.setStr("i+i*i#");// 执⾏分析, 打印分析步骤, 保存⽂件analyzer.analyze();}/*** 获取⾮终结符集与终结符集** @param gsArray* @param nvSet* @param ntSet*/private static void getNvNt(ArrayList<String> gsArray, TreeSet<Character> nvSet, TreeSet<Character> ntSet) { for (String gsItem : gsArray) {String[] nvNtItem = gsItem.split("->");String charItemStr = nvNtItem[0];char charItem = charItemStr.charAt(0);// nv在左边nvSet.add(charItem);}for (String gsItem : gsArray) {String[] nvNtItem = gsItem.split("->");// nt在右边String nvItemStr = nvNtItem[1];// 遍历每⼀个字for (int i = 0; i < nvItemStr.length(); i++) {char charItem = nvItemStr.charAt(i);if (!nvSet.contains(charItem)) {ntSet.add(charItem);}}}}/*** 初始化 LL(1)⽂法, 设定产⽣式** @param gsArray*/private static void initGs(ArrayList<String> gsArray) {//E' = M//T' = NgsArray.add("E->TM");gsArray.add("M->+TF");gsArray.add("M->ε");gsArray.add("T->FN");gsArray.add("N->*FN");gsArray.add("N->ε");gsArray.add("F->(E)");gsArray.add("F->i");}}(5)TextUtil.javapackage com.java997.analyzer.grammar;import java.util.ArrayList;import java.util.HashMap;import java.util.Set;import java.util.TreeMap;import java.util.TreeSet;/*** <p>* 字符⼯具类** @author XiaoPengwei* @since 2019-06-18*/public class TextUtil {/*** (3)B->aA,=Follow(B)** @param nvSet* @param itemCharStr* @param a* @param expressionMap*/public static boolean containsbA(TreeSet<Character> nvSet, String itemCharStr, Character a,HashMap<Character, ArrayList<String>> expressionMap) {String aStr = a.toString();String lastStr = itemCharStr.substring(itemCharStr.length() - 1);return lastStr.equals(aStr);}/*** 形如 aBb,b=空** @param nvSet* @param itemCharStr* @param a* @param expressionMap*/public static boolean containsbAbIsNull(TreeSet<Character> nvSet, String itemCharStr, Character a, HashMap<Character, ArrayList<String>> expressionMap) {String aStr = a.toString();if (containsAB(nvSet, itemCharStr, a)) {Character alastChar = getAlastChar(itemCharStr, a);System.out.println("----------------+++++++++++++++++++--" + expressionMap.toString());ArrayList<String> arrayList = expressionMap.get(alastChar);if (arrayList.contains("ε")) {System.out.println(alastChar + " contains('ε')" + aStr);return true;}}return false;}/***是否包含这种的字符串<Br>* (2)Ab,=First(b)-ε,直接添加终结符** @param ntSet* @param itemCharStr* @param a* @return boolean*/public static boolean containsAb(TreeSet<Character> ntSet, String itemCharStr, Character a) {String aStr = a.toString();if (itemCharStr.contains(aStr)){int aIndex = itemCharStr.indexOf(aStr);String findStr;try {findStr = itemCharStr.substring(aIndex + 1, aIndex + 2);} catch (Exception e) {return false;}return ntSet.contains(findStr.charAt(0));} else {return false;}}/*** 是否包含这种的字符串<Br>* (2).2Ab,=First(b)-ε* @param nvSet* @param itemCharStr* @param a* @return boolean*/public static boolean containsAB(TreeSet<Character> nvSet, String itemCharStr, Character a) { String aStr = a.toString();if (itemCharStr.contains(aStr)) {int aIndex = itemCharStr.indexOf(aStr);String findStr;try {findStr = itemCharStr.substring(aIndex + 1, aIndex + 2);} catch (Exception e) {return false;}return nvSet.contains(findStr.charAt(0));} else {return false;}}/*** 获取 A 后的字符** @param itemCharStr* @param a*/public static Character getAlastChar(String itemCharStr, Character a) {String aStr = a.toString();if (itemCharStr.contains(aStr)) {int aIndex = itemCharStr.indexOf(aStr);String findStr = "";try {findStr = itemCharStr.substring(aIndex + 1, aIndex + 2);} catch (Exception e) {return null;}return findStr.charAt(0);}return null;}/*** 是否为ε开始的** @param selectExp*/public static boolean isEmptyStart(String selectExp) {char charAt = selectExp.charAt(0);return charAt == 'ε';}/*** 是否是终结符开始的** @param ntSet* @param selectExp*/public static boolean isNtStart(TreeSet<Character> ntSet, String selectExp) {char charAt = selectExp.charAt(0);return ntSet.contains(charAt);}/*** 是否是⾮终结符开始的** @param nvSet* @param selectExp* @return*/public static boolean isNvStart(TreeSet<Character> nvSet, String selectExp) {char charAt = selectExp.charAt(0);return nvSet.contains(charAt);}/*** 查找产⽣式** @param selectMap* @param peek 当前 Nv* @param charAt 当前字符* @return*/public static String findUseExp(TreeMap<Character, HashMap<String, TreeSet<Character>>> selectMap, Character peek, char charAt) {try {HashMap<String, TreeSet<Character>> hashMap = selectMap.get(peek);Set<String> keySet = hashMap.keySet();for (String useExp : keySet) {TreeSet<Character> treeSet = hashMap.get(useExp);if (treeSet.contains(charAt)) {return useExp;}}} catch (Exception e) {return null;}return null;}}执⾏ Main.java。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
}
/*判断产生式正确性*/
bool CheckP(char * st)
{
int n;
if(100 > IndexCh(st[0]))
return false;
if('-' != st[1])
return false;
if('>' != st[2])
return false;
for(n = 3; '\0' != st[n]; n ++)
{
qt = (pRNode*)malloc(sizeof(pRNode));
qt->rCursor = IndexCh(buffer[n]);
qt->next = NULL;
pt->next = qt;
pt = qt;
n++;
}
P[i].rLength = n - 3;
i++;
}
else
printf("输入符号含非法在成分,请重新输入!\n");
}
printf("\n");
}
/*输入非终结符*/
void InputVn()
{
int inErr = 1;
int n,k;
char ch;
while(inErr)
{
printf("\n请输入所有的非终结符,注意:");
printf("请将开始符放在第一位,并以#号结束:\n");
ch = ' ';
};
char Vn[MaxVnNum + 1]; /*非终结符集*/
int vnNum;
char Vt[MaxVtNum + 1]; /*终结符集*/
int vtNum;
struct pNode P[MaxRuleNum];
int PNum;
char buffer[MaxPLength + 1];
char ch;
for(i = 0; i <= MaxVtNum; i++)
Vt[i] = '\0';
for(i = 0; i < MaxRuleNum; i++)
{
P[i].lCursor = NULL;
P[i].rHead = NULL;
P[i].rLength = 0;
}
PNum = 0;
for(i = 0; i <= MaxPLength; i++)
void Identify(char *st);
void InitStack();
void ShowStack();
void Pop();
void Push(int r);
void main(void)
{
char todo,ch;
Init();
InputVn();
InputVt();
InputP();
buffer[i] = '\0';
for(i = 0; i < MaxVnNum; i++)
{
first[i] = NULL;
follow[i] = NULL;
}
for(i = 0; i <= MaxVnNum; i++)
{
for(j = 0; j <= MaxVnNum + 1; j++)
analyseTable[i][j] = -1;
{
st[i] = ch;
Identify(st);
}
else
printf("输入出错!\n");
}
}
getchar();
}
void Init()
{
int i,j;
vnNum = 0;
vtNum = 0;
PNum = 0;
for(i = 0; i <= MaxVnNum; i++)
Vn[i] = '\0';
{
printf("\n是否继续进行句型分析?(y / n):");
todo = getchar();
while('y' != todo && 'n' != todo)
{
printf("\n(y / n)? ");
todo = getchar();
}
if('y' == todo)
{
int i;
InitStack();
void First(int U);
void AddFirst(int U, int nCh); /*加入first集*/
bool HaveEmpty(int nVn);
void Follow(int V);/*计算follow集*/
void AddFollow(int V, int nCh, int kind);
int analyseTable[MaxVnNum + 1][MaxVtNum + 1 + 1];
int analyseStack[MaxStackDepth + 1]; /*分析栈*/
int topAnalyse; /*分析栈顶*/
void Init();/*初始化*/
int IndexCh(char ch);
}
scanf("%c", &ch);
}
if('n' == ch)
{
printf("录入错误重新输入!\n");
inErr = 1;
}
else
{
inErr = 0;
}
}
}
/*输入终结符*/
void InputVt()
{
int inErr = 1;
int n,k;
char ch;
while(inErr)
n++;
if('\0' != Vt[n])
return n;
return -1;
}
/*输出Vn或Vt的内容*/
void ShowChArray(char* collect)
{
int k = 0;
while('\0' != collect[k])
{
printf(" %c ", collect[k++]);
#define MaxStLength 50
struct pRNode /*产生式右部结构*/
{
int rCursor;
struct pRNode *next;
};
struct pNode
{
int lCursor;
int rLength; /*右部长度*/
struct pRNode *rHead; /*右部结点头指针*/
P[i].lCursor = IndexCh(buffer[0]);
pt = (pRNode*)malloc(sizeof(pRNode));
pt->rCursor = IndexCh(buffer[3]);
pt->next = NULL;
P[i].rHead = pt;
n = 4;
while('\0' != buffer[n])
n = 0;
/*初始化数组*/
while(n < MaxVnNum)
{
Vn[n++] = '\0';
}
n = 0;
while(('#' != ch) && (n < MaxVnNum))
{
if(' ' != ch && '\n' != ch && -1 == IndexCh(ch))
{
Vn[n++] = ch;
void InputVt(); /*输入终结符*/
void InputVn();/*输入非终结符*/
void ShowChArray(char* collect, int num);/*输出Vn或Vt的内容*/
void InputP();/*产生式输入*/
bool CheckP(char * st);/*判断产生式正确性*/
{
printf("\n请输入所有的终结符,注意:");
printf("以#号结束:\n");
ch = ' ';
n = 0;
/*初始化数组*/
while(n < MaxVtNum)
{
Vt[n++] = '\0';
}
n = 0;
while(('#' != ch) && (n < MaxVtNum))
{
if(' ' != ch && '\n' != ch && -1 == IndexCh(ch))
printf("请输入符号串(以#结束) : ");
ch = getchar();
i = 0;
while('#' != ch && i < MaxStLength)
相关文档
最新文档