编译原理 LL(1)文法源代码
编译原理LL文法源代码
LL(1)文法(源代码)#includ e "stdio.h"#includ e "stdlib.h"#define MaxRul eNum8#define MaxVnN um 5#define MaxVtN um 5#define MaxSta ckDep th 20#define MaxPLe ngth20#define MaxStL ength 50struct pRNode /*产生式右部结构*/{int rCurso r;struct pRNode *next;};struct pNode{int lCurso r;int rLengt h; /*右部长度*/struct pRNode *rHead; /*右部结点头指针*/};char Vn[MaxVnN um + 1]; /*非终结符集*/int vnNum;char Vt[MaxVtN um + 1]; /*终结符集*/int vtNum;struct pNodeP[MaxRul eNum];int PNum;char buffer[MaxPLe ngth+ 1];char ch;char st[MaxStL ength]; /*要分析的符号串*/struct collec tNode{int nVt;struct collec tNode *next;};struct collectNode* first[MaxVnN um + 1]; /*first集*/ struct collectNode* follow[MaxVnN um + 1]; /*follow集*/int analys eTabl e[MaxVnN um + 1][MaxVtN um + 1 + 1];int analyseStack[MaxSta ckDep th + 1]; /*分析栈*/int topAnal yse; /*分析栈顶*/void Init();/*初始化*/int IndexC h(char ch);void InputV t(); /*输入终结符*/void InputV n();/*输入非终结符*/void ShowChA rray(char* collect, int num);/*输出Vn或V t的内容*/ void InputP();/*产生式输入*/bool CheckP(char * st);/*判断产生式正确性*/void First(int U);void AddFirst(int U, int nCh); /*加入first集*/bool HaveEm pty(int nVn);void Follow(int V);/*计算foll ow集*/void AddFol low(int V, int nCh, int kind);void ShowCol lect(struct collectNode **collect);/*输出firs t或fol low集*/ void FirstF ollow();/*计算first和fol low*/void CreateA T();/*构造预测分析表*/void ShowAT();/*输出分析表*/void Identi fy(char *st);void InitSt ack();void ShowSt ack();void Pop();void Push(int r);void main(void){char todo,ch;Init();InputV n();InputV t();InputP();getcha r();FirstF ollow();printf("所得firs t集为:");ShowCo llect(first);printf("所得foll o w集为:");ShowCo llect(follow);Create A T();ShowAT();todo = 'y';while('y' == todo){printf("\n是否继续进行句型分析?(y / n):"); todo = getcha r();while('y' != todo && 'n' != todo){printf("\n(y / n)? ");todo = getcha r();}if('y' == todo){int i;InitSt ack();printf("请输入符号串(以#结束) : ");ch = getcha r();i = 0;while('#' != ch && i < MaxStL ength){if(' ' != ch && '\n' != ch){st[i++] = ch;}ch = getcha r();}if('#' == ch && i < MaxStL ength){st[i] = ch;Identi fy(st);}elseprintf("输入出错!\n");}}getcha r();}void Init(){int i,j;vnNum= 0;vtNum= 0;PNum = 0;for(i = 0; i <= MaxVnN um; i++)Vn[i] = '\0';for(i = 0; i <= MaxVtN um; i++)Vt[i] = '\0';for(i = 0; i < MaxRul eNum; i++) {P[i].lCurso r = NULL;P[i].rHead= NULL;P[i].rLengt h = 0;}PNum = 0;for(i = 0; i <= MaxPLe ngth; i++)buffer[i] = '\0';for(i = 0; i < MaxVnN um; i++){first[i] = NULL;follow[i] = NULL;}for(i = 0; i <= MaxVnN um; i++) {for(j = 0; j <= MaxVnN um + 1; j++) analys eTabl e[i][j] = -1;}}int IndexC h(char ch){int n;n = 0; /*is Vn?*/while(ch != Vn[n] && '\0' != Vn[n]) n++;if('\0' != Vn[n])return 100 + n;n = 0; /*is Vt?*/while(ch != Vt[n] && '\0' != Vt[n]) n++;if('\0' != Vt[n])return n;return -1;}/*输出Vn或V t的内容*/void ShowCh Array(char* collec t){int k = 0;while('\0' != collec t[k]){printf(" %c ", collec t[k++]);}printf("\n");}/*输入非终结符*/void InputV n(){int inErr= 1;int n,k;char ch;while(inErr){printf("\n请输入所有的非终结符,注意:");printf("请将开始符放在第一位,并以#号结束:\n");ch = ' ';n = 0;/*初始化数组*/while(n < MaxVnN um){Vn[n++] = '\0';}n = 0;while(('#' != ch) && (n < MaxVnN um)){if(' ' != ch && '\n' != ch && -1 == IndexC h(ch)){Vn[n++] = ch;vnNum++;}ch = getcha r();}Vn[n] = '#'; /*以“#”标志结束用于判断长度是否合法*/ k = n;if('#' != ch){if( '#' != (ch = getcha r())){while('#' != (ch = getcha r()));printf("\n符号数目超过限制!\n");inErr= 1;contin ue;}}/*正确性确认,正确则,执行下下面,否则重新输入*/ Vn[k] = '\0';ShowCh Array(Vn);ch = ' ';while('y' != ch && 'n' != ch){if('\n' != ch){printf("输入正确确认?(y/n):");}scanf("%c", &ch);}if('n' == ch){printf("录入错误重新输入!\n");inErr= 1;}else{inErr= 0;}}}/*输入终结符*/void InputV t(){int inErr= 1;int n,k;char ch;while(inErr){printf("\n请输入所有的终结符,注意:");printf("以#号结束:\n");ch = ' ';n = 0;/*初始化数组*/while(n < MaxVtN um){Vt[n++] = '\0';}n = 0;while(('#' != ch) && (n < MaxVtN um)){if(' ' != ch && '\n' != ch && -1 == IndexC h(ch)) {Vt[n++] = ch;vtNum++;}ch = getcha r();}Vt[n] = '#';k = n;if('#' != ch){if( '#' != (ch = getcha r())){while('#' != (ch = getcha r()));printf("\n符号数目超过限制!\n");inErr= 1;contin ue;}}Vt[k] = '\0';ShowCh Array(Vt);ch = ' ';while('y' != ch && 'n' != ch){if('\n' != ch){printf("输入正确确认?(y/n):");}scanf("%c", &ch);}if('n' == ch){printf("录入错误重新输入!\n");inErr= 1;}else{inErr= 0;}}}/*产生式输入*/void InputP(){char ch;int i = 0, n,num;printf("请输入文法产生式的个数:");scanf("%d", &num);PNum = num;getcha r(); /*消除回车符*/printf("\n请输入文法的%d个产生式,并以回车分隔每个产生式:", num); printf("\n");while(i < num){printf("第%d个:", i);/*初始化*/for(n =0; n < MaxPLe ngth; n++)buffer[n] = '\0';/*输入产生式串*/ch = ' ';n = 0;while('\n' != (ch = getcha r()) && n < MaxPLe ngth){if(' ' != ch)buffer[n++] = ch;}buffer[n] = '\0';if(CheckP(buffer)){pRNode *pt, *qt;P[i].lCurso r = IndexC h(buffer[0]);pt = (pRNode*)malloc(sizeof(pRNode));pt->rCurso r = IndexC h(buffer[3]);pt->next = NULL;P[i].rHead= pt;n = 4;while('\0' != buffer[n]){qt = (pRNode*)malloc(sizeof(pRNode));qt->rCurso r = IndexC h(buffer[n]);qt->next = NULL;pt->next = qt;pt = qt;n++;}P[i].rLengt h = n - 3;i++;}elseprintf("输入符号含非法在成分,请重新输入!\n"); }}/*判断产生式正确性*/bool CheckP(char * st){int n;if(100 > IndexC h(st[0]))return false;if('-' != st[1])return false;if('>' != st[2])return false;for(n = 3; '\0' != st[n]; n ++){if(-1 == IndexC h(st[n]))return false;}return true;}void First(int U){int i,j;for(i = 0; i < PNum; i++){if(P[i].lCurso r == U){struct pRNode* pt;pt = P[i].rHead;j = 0;while(j < P[i].rLengt h){if(100 > pt->rCurso r){AddFir st(U, pt->rCurso r);break;}else{if(NULL == first[pt->rCurso r - 100]){First(pt->rCurso r);}AddFir st(U, pt->rCurso r);if(!HaveEm pty(pt->rCurso r)){break;}else{pt = pt->next;}}j++;}if(j >= P[i].rLengt h) /*当产生式右部都能推出空时*/ AddFir st(U, -1);}}}/*加入first集*/void AddFir st(int U, int nCh){struct collec tNode *pt, *qt;int ch; /*用于处理Vn*/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 = (struct collec tNode *)malloc(sizeof(struct collec tNode));pt->nVt = nCh;pt->next = NULL;if(NULL == first[U - 100]){first[U - 100] = pt;}else{qt->next = pt; /*qt指向fi rst集的最后一个元素*/}pt = pt->next;}}else{pt = first[nCh - 100];while(NULL != pt){ch = pt->nVt;if(-1 != ch){AddFir st(U, ch);}pt = pt->next;}}}bool HaveEm pty(int nVn){if(nVn < 100)return false;struct collec tNode *pt;pt = first[nVn - 100];while(NULL != pt){if(-1 == pt->nVt)return true;pt = pt->next;}return false;}void Follow(int V){int i;struct pRNode *pt ;if(100 == V) /*当为初始符时*/AddFol low(V, -1, 0 );for(i = 0; i < PNum; i++){pt = P[i].rHead;while(NULL != pt && pt->rCurso r != V)pt = pt->next;if(NULL != pt){pt = pt->next;if(NULL == pt){if(NULL == follow[P[i].lCurso r - 100] && P[i].lCurso r != V) {Follow(P[i].lCurso r);}AddFol low(V, P[i].lCurso r, 0);}else{while(NULL != pt && HaveEm pty(pt->rCurso r)){AddFol low(V, pt->rCurso r, 1);pt = pt->next;}if(NULL == pt){if(NULL == follow[P[i].lCurso r - 100] && P[i].lCurso r != V) {Follow(P[i].lCurso r);}AddFol low(V, P[i].lCurso r, 0);}else{AddFol low(V, pt->rCurso r, 1);}}}}}void AddFol low(int V, int nCh, int kind){struct collec tNode *pt, *qt;int ch;pt = NULL;qt = NULL;if(nCh < 100) /*为终结符时*/{pt = follow[V - 100];while(NULL != pt){if(pt->nVt == nCh)break;else{qt = pt;pt = pt->next;}}if(NULL == pt){pt = (struct collec tNode *)malloc(sizeof(struct collec tNode));pt->nVt = nCh;pt->next = NULL;if(NULL == follow[V - 100]){follow[V - 100] = pt;}else{qt->next = pt; /*qt指向fo llow集的最后一个元素*/}pt = pt->next;}}else{if(0 == kind){pt = follow[nCh - 100];while(NULL != pt){ch = pt->nVt;AddFol low(V, ch, 0);pt = pt->next;}}else{pt = first[nCh - 100];while(NULL != pt){ch = pt->nVt;if(-1 != ch){AddFol low(V, ch, 1);}pt = pt->next;}}}}/*输出first或fol low集*/void ShowCo llect(struct collec tNode **collec t) {int i;struct collec tNode *pt;i = 0;while(NULL != collec t[i]){pt = collec t[i];printf("\n%c:\t", Vn[i]);while(NULL != pt){if(-1 != pt->nVt){printf(" %c", Vt[pt->nVt]);}elseprintf(" #");pt = pt->next;}i++;}printf("\n");}/*计算first和fol low*/void FirstF ollow(){int i;i = 0;while('\0' != Vn[i]){if(NULL == first[i])First(100 + i);i++;}i = 0;while('\0' != Vn[i]){if(NULL == follow[i])Follow(100 + i);i++;}}/*构造预测分析表*/void Create A T(){int i;struct pRNode *pt;struct collec tNode *ct;for(i = 0; i < PNum; i++){pt = P[i].rHead;while(NULL != pt && HaveEm pty(pt->rCurso r)) {ct = first[pt->rCurso r - 100];while(NULL != ct){if(-1 != ct->nVt)analys eTabl e[P[i].lCurso r - 100][ct->nVt] = i;ct = ct->next;}pt = pt->next;}if(NULL == pt){ct = follow[P[i].lCurso r - 100];while(NULL != ct){if(-1 != ct->nVt)analys eTabl e[P[i].lCurso r - 100][ct->nVt] = i;elseanalys eTabl e[P[i].lCurso r - 100][vtNum] = i;ct = ct->next;}}else{if(100 <= pt->rCurso r) /*不含空的非终结符*/ {ct = first[pt->rCurso r - 100];while(NULL != ct){analys eTabl e[P[i].lCurso r - 100][ct->nVt] = i;ct = ct->next;}}else /*终结符或者空*/{if(-1 == pt->rCurso r){ct = follow[P[i].lCurso r - 100];while(NULL != ct){if(-1 != ct->nVt)analys eTabl e[P[i].lCurso r - 100][ct->nVt] = i;else /*当含有#号时*/analys eTabl e[P[i].lCurso r - 100][vtNum] = i;ct = ct->next;}}else /*为终结符*/{analys eTabl e[P[i].lCurso r - 100][pt->rCurso r] = i;}}}}}/*输出分析表*/void ShowAT(){int i,j;printf("构造预测分析表如下:\n");printf("\t|\t");for(i = 0; i < vtNum; i++){printf("%c\t", Vt[i]);}printf("#\t\n");printf("- - -\t|- - -\t");for(i = 0; i <= vtNum; i++)printf("- - -\t");printf("\n");for(i = 0; i < vnNum; i++){printf("%c\t|\t", Vn[i]);for(j = 0; j <= vtNum; j++){if(-1 != analys eTabl e[i][j])printf("R(%d)\t", analys eTabl e[i][j]);elseprintf("error\t");}printf("\n");}}void Identi fy(char *st){int curren t,step,r; /*r表使用的产生式的序号*/ printf("\n%s的分析过程:\n", st);printf("步骤\t分析符号栈\t当前指示字符\t使用产生式序号\n");step = 0;curren t = 0;printf("%d\t",step);ShowSt ack();printf("\t\t%c\t\t- -\n", st[curren t]);while('#' != st[curren t]){if(100 > analys eStac k[topAna lyse]){if(analys eStac k[topAna lyse] == IndexC h(st[curren t])){Pop();curren t++;step++;printf("%d\t", step);ShowSt ack();printf("\t\t%c\t\t出栈、后移\n", st[curren t]);}else{printf("%c-%c不匹配!", analyseStack[topAnal yse], st[curren t]);printf("此串不是此文法的句子!\n");return;}}else /*当为非终结符时*/{r = analys eTabl e[analys eStac k[topAna lyse] - 100][IndexC h(st[curren t])];if(-1 != r){Push(r);step++;printf("%d\t", step);ShowSt ack();printf("\t\t%c\t\t%d\n", st[curren t], r);}else{printf("此串不是此文法的句子!\n");return;}}if('#' == st[curren t]){if(0 == topAna lyse&& '#' == st[curren t]){step++;printf("%d\t", step);ShowSt ack();printf("\t\t%c\t\t分析成功!\n", st[curren t]);printf("%s是给定文法的句子!\n", st);}else{while(topAna lyse> 0){if(100 > analys eStac k[topAna lyse]){printf("此串不是此文法的句子!\n");return;}else{r = analys eTabl e[analys eStac k[topAna lyse] - 100][vtNum];if(-1 != r){Push(r); /*产生式右部代替左部,指示器不移动*/step++;printf("%d\t", step);ShowSt ack();if(0 == topAna lyse&& '#' == st[curren t]){printf("\t\t%c\t\t分析成功!\n", st[curren t]);printf("%s是给定文法的句子!\n", st);}elseprintf("\t\t%c\t\t%d\n", st[curren t], r);}else{printf("此串不是此文法的句子!\n");return;}}}}}/*初始化栈及符号串*/void InitSt ack(){int i;/*分析栈的初始化*/for(i = 0; i < MaxStL ength; i++)st[i] = '\0';analyseStack[0] = -1; /*#(-1)入栈*/ analyseStack[1] = 100; /*初始符入栈*/ topAna lyse= 1;}/*显示符号栈中内容*/void ShowSt ack(){int i;for(i = 0; i <= topAna lyse; i++){if(100 <= analys eStac k[i])printf("%c", Vn[analys eStac k[i] - 100]); else{if(-1 != analys eStac k[i])printf("%c", Vt[analys eStac k[i]]);elseprintf("#");}}}/*栈顶出栈*/void Pop(){topAna lyse--;}void Push(int r){int i;struct pRNode *pt;Pop();pt = P[r].rHead;if(-1 == pt->rCurso r)return;topAna lyse+= P[r].rLengt h;for(i = 0; i < P[r].rLengt h; i++){analyseStack[topAnal yse - i] = pt->rCurso r;/*逆序入栈*/ pt = pt->next;}}。
编译原理实验七: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)文法<古城童话>$为空字; 输入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)文法构造一、实验目的熟悉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)文法源代码(实验三)
一、实验目的及要求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文法#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版完整源代码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)⽂法 - 程序解析编译原理学习,语法分析程序设计(⼀)要求及功能已知 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。
编译原理词法分析器,ll1,lr0,python实现代码
计算机科学与通信工程学院编译原理实验报告题目: 1.词法分析器2. LL(1)分析器3. LR(0)分析器班级::学号:指导老师:2017年月目录一、实验题目 (1)二、实验目的和要求 (1)三、代码实现 (2)四、总结 (27)一、实验题目1.词法分析器分析一段程序代码,将代码中的单词符号分解出来,并对其进行检查,输出token表和error表2.LL(1)文法分析器分析给定文法。
求出文法的FIRST集,FOLLOW集,并构建分析表,对给定输入串进行分析。
3.LR(0)文法分析器分析给定文法。
用Ꜫ_CLOSURE方法构造文法的LR(0)项目集规族,根据状态转换函数GO构造出文法的DFA,并转换为分析表,对给定输入串进行分析。
二、实验目的和要求1.学会词法分析器的实现思路。
2.学会求解FIRST集, FOLLOW集,构造LL(1)分析表。
3.学会Ꜫ_CLOSURE方法,状态转换函数GO, 构造LR(0)分析表。
三、代码实现1.词法分析器program.txt 中存放要分析的文法:E->TRR->+TR|-TR|~T->FGG->*FG|/FG|~F->(E)|i代码:KEYWORD_LIST = ['while', 'if', 'else', 'switch', 'case']SEPARATOR_LIST = [';', ':', ',', '(', ')', '[', ']', '{', '}'] OPERATOR_LIST1 = ['+', '-', '*']OPERATOR_LIST2 = ['<=', '<', '==', '=', '>', '>=']CATEGORY_DICT = {# KEYWORD"while": {"while": ""},"if": {"if": ""},"else": {"else": ""},"switch": {"switch": ""},"case": {"case": ""},# OPERATOR"+": {"+": ""},"-": {"-": ""},"*": {"*": ""},"<=": {"relop": "LE"},"<": {"relop": "LT"},">=": {"relop": "GE"},">": {"relop": "GT"},"==": {"relop": "EQ"},"=": {"=": ""},# SEPARATOR";": {";": ""},":": {":": ""},",": {",": ""},"(": {"(": ""},")": {")": ""},"[": {"]": ""},"]": {"]": ""},"{": {"{": ""},"}": {"}": ""},}CONSTANTTABLE = []TOKENTABLE = []OPERATORTABLE = []KEYWORDTABLE = []SEPARATORTABLE = []UNDEFINEDTABLE = []# READ FILEdef read_file(path, method):temp_str = ""try:file = open(path, method)for line in file:line = line.replace('\n', " ") temp_str += linetemp_str = str(temp_str)except IOError as e:print(e)exit()finally:file.close()return temp_str.strip() + " "# GETBEdef getbe():global tokengetchar()token = ""return# GETCHARdef getchar():global characterglobal locationwhile all_string[location] == " ":location = location + 1character = all_string[location]return character# LINK TOKENdef concatenation():global tokenglobal charactertoken = token + character# IS NUMBERdef digit():if '0' <= character <= '9':return Truereturn False# IS ALPHABETdef letter():if 'A' <= character <= 'Z' or 'a' <= character <= 'z': return Truereturn False# IS IDENTIFIERdef reserve():if token in KEYWORD_LIST:return CATEGORY_DICT[token]else:return 0# RETRACTdef retract():global locationglobal character# location = location - 1character = ""return# MAIN FUNCTIONdef main():global tokenglobal characterglobal locations = getchar()getbe()if 'a' <= s <= 'z' or 'A' <= s <= 'Z':while letter() or digit():concatenation()location = location + 1character = all_string[location]retract()c = reserve()if c == 0:TOKENTABLE.append(token)print("这是标识符:{'", token, "':'", TOKENTABLE.index(token), "'}") else:KEYWORDTABLE.append(token)print("这是保留字:", CATEGORY_DICT[token])elif '0' <= s <= '9':while digit():concatenation()location = location + 1character = all_string[location]retract()CONSTANTTABLE.append(token)print("这是常数:{'", token, "':'", CONSTANTTABLE.index(token), "'}") elif s in OPERATOR_LIST1:location = location + 1OPERATORTABLE.append(s)print("这是单操作符:", CATEGORY_DICT[s])elif s in OPERATOR_LIST2:location = location + 1character = all_string[location]if character == '=':OPERATORTABLE.append(s + character)print("这是双操作符:", CATEGORY_DICT[s + character])else:retract()location = location + 1OPERATORTABLE.append(s)print("这是单操作符:", CATEGORY_DICT[s])elif s in SEPARATOR_LIST:location = location + 1SEPARATORTABLE.append(s)print("这是分隔符:", CATEGORY_DICT[s])else:location += 1UNDEFINEDTABLE.append(s)print("error:undefined identity :'", s, "'")if __name__ == '__main__':character = ""token = ""all_string = read_file("program.txt", "r") location = 0while location + 1 < len(all_string): main()print('KEYWORDTABLE:', KEYWORDTABLE)print('TOKENTABLE:', TOKENTABLE)print('CONSTANTTABLE:', CONSTANTTABLE)print('OPERATORTABLE:', OPERATORTABLE)print('SEPARATORTABLE:', SEPARATORTABLE) 运行结果:2.LL(1)分析器program.txt 中存放要分析的文法:E->TRR->+TR|-TR|~T->FGG->*FG|/FG|~F->(E)|i输入串:i+i*i代码:NonTermSet = set() # 非终结符集合TermSet = set() # 终结符集合First = {} # First集Follow = {} # Follow集GramaDict = {} # 处理过的产生式Code = [] # 读入的产生式AnalysisList = {} # 分析表StartSym = "" # 开始符号EndSym = '#' # 结束符号为“#“Epsilon = "~" # 由于没有epsilon符号用“~”代替# 构造First集def getFirst():global NonTermSet, TermSet, First, Follow, FirstAfor X in NonTermSet:First[X] = set() # 初始化非终结符First集为空for X in TermSet:First[X] = set(X) # 初始化终结符First集为自己Change = Truewhile Change: # 当First集没有更新则算法结束Change = Falsefor X in NonTermSet:for Y in GramaDict[X]:k = 0Continue = Truewhile Continue and k < len(Y):if not First[Y[k]] - set(Epsilon) <= First[X]: # 没有一样的就添加,并且改变标志if Epsilon not in First[Y[k]] and Y[k] in NonTermSet and k > 0: # Y1到Yi候选式都有~存在Continue = Falseelse:First[X] |= First[Y[k]] - set(Epsilon)Change = Trueif Epsilon not in First[Y[k]]:Continue = Falsek += 1if Continue: # X->~或者Y1到Yk均有~产生式First[X] |= set(Epsilon)# FirstA[Y] |= set(Epsilon)# 构造Follow集def getFollow():global NonTermSet, TermSet, First, Follow, StartSymfor A in NonTermSet:Follow[A] = set()Follow[StartSym].add(EndSym) # 将结束符号加入Follow[开始符号]中Change = Truewhile Change: # 当Follow集没有更新算法结束Change = Falsefor X in NonTermSet:for Y in GramaDict[X]:for i in range(len(Y)):if Y[i] in TermSet:continueFlag = Truefor j in range(i + 1, len(Y)): # continueif not First[Y[j]] - set(Epsilon) <= Follow[Y[i]]:Follow[Y[i]] |= First[Y[j]] - set(Epsilon) # 步骤2 FIRST(β)/~ 加入到FOLLOW(B)中。
编译原理中LL(1)文法的源代码汇总
一. 实验目的1.掌握LL(1分析法的基本原理2.掌握LL(1分析表的构造方法3.掌握LL(1驱动程序的构造方法二. 实验内容及要求根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对预测分析LL(1)分析法的理解。
例:对下列文法,用LL(1)分析法对任意输入的符号串进行分析:(1)E->TG(2)G->+TG|—TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E(8)F->i输出的格式如下:(1LL(1)分析程序,编制人:姓名,学号,班级(2输入一以#结束的符号串(包括+—*/()i#:在此位置输入符号串(3输出过程如下:步骤分析栈剩余输入串所用产生式1 E i+i*i# E->TG(4输入符号串为非法符号串(或者为合法符号串备注:(1在“所用产生式”一列中如果对应有推导则写出所用产生式;如果为匹配终结符则写明匹配的终结符;如分析异常出错则写为“分析出错”;若成功结束则写为“分析成功”。
(2 在此位置输入符号串为用户自行输入的符号串。
(3上述描述的输出过程只是其中一部分的。
注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符i,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);3.对学有余力的同学,测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以分号分割。
同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照;4.可采用的其它的文法。
三. 实验过程LL(1分析法的实验源程序代码如下:#include#include#include#includechar A[20];/*分析栈*/char B[20];/*剩余串*/char v1[20]={'i','+','*','(','','#'};/*终结符 */char v2[20]={'E','G','T','S','F'};/*非终结符 */int j=0,b=0,top=0,l;/*L为输入串长度 */typedef struct type/*产生式类型定义 */{char origin;/*大写字符 */char array[5];/*产生式右边字符 */int length;/*字符个数 */}type;type e,t,g,g1,s,s1,f,f1;/*结构体变量 */ type C[10][10];/*预测分析表 */void print(/*输出分析栈 */{int a;/*指针*/for(a=0;a<=top+1;a++printf("%c",A[a];printf("\t\t";}/*print*/void print1(/*输出剩余串*/{int j;for(j=0;j 输出对齐符 */printf(" ";for(j=b;j<=l;j++printf("%c",B[j];printf("\t\t\t";}/*print1*/void main({int m,n,k=0,flag=0,finish=0;char ch,x;type cha;/*用来接受C[m][n]*/ /*把文法产生式赋值结构体*/ e.origin='E';strcpy(e.array,"TG";e.length=2;t.origin='T';strcpy(t.array,"FS";t.length=2;g.origin='G';strcpy(g.array,"+TG";g.length=3;g1.origin='G';g1.array[0]='^';g1.length=1;s.origin='S';strcpy(s.array,"*FS";s.length=3;s1.origin='S';s1.array[0]='^';s1.length=1;f.origin='F';strcpy(f.array,"(E";f.length=3;f1.origin='F';f1.array[0]='i';f1.length=1;for(m=0;m<=4;m++/*初始化分析表*/for(n=0;n<=5;n++C[m][n].origin='N';/*全部赋为空*//*填充分析表*/C[0][0]=e;C[0][3]=e;C[1][1]=g;C[1][4]=g1;C[1][5]=g1;C[2][0]=t;C[2][3]=t;C[3][1]=s1;C[3][2]=s;C[3][4]=C[3][5]=s1;C[4][0]=f1;C[4][3]=f;printf("提示:本程序只能对由'i','+','*','(',''构成的以'#'结束的字符串进行分析,\n"; printf("请输入要分析的字符串:";do/*读入分析串*/{scanf("%c",&ch;if ((ch!='i' &&(ch!='+' &&(ch!='*'&&(ch!='('&&(ch!=''&&(ch!='#'{printf("输入串中有非法字符\n";exit(1;}B[j]=ch;j++;}while(ch!='#';l=j;/*分析串长度*/ch=B[0];/*当前分析字符*/A[top]='#'; A[++top]='E';/*'#','E'进栈*/printf("步骤\t\t分析栈 \t\t剩余字符 \t\t所用产生式 \n"; do{x=A[top--];/*x为当前栈顶字符*/printf("%d",k++;printf("\t\t";for(j=0;j<=5;j++/*判断是否为终结符*/if(x==v1[j]{flag=1;break;}if(flag==1/*如果是终结符*/{if(x=='#'{finish=1;/*结束标记*/printf("acc!\n";/*接受 */getchar(;getchar(;exit(1;}/*if*/if(x==ch{print(;print1(;printf("%c匹配\n",ch;ch=B[++b];/*下一个输入字符*/flag=0;/*恢复标记*/}/*if*/else/*出错处理*/{print(;print1(;printf("%c出错\n",ch;/*输出出错终结符*/ exit(1;}/*else*/}/*if*/else/*非终结符处理*/{for(j=0;j<=4;j++if(x==v2[j]{m=j;/*行号*/break;}for(j=0;j<=5;j++if(ch==v1[j]{n=j;/*列号*/break;}cha=C[m][n];if(cha.origin!='N'/*判断是否为空*/{print(;print1(;printf("%c->",cha.origin;/*输出产生式*/for(j=0;jprintf("%c",cha.array[j];printf("\n";for(j=(cha.length-1;j>=0;j--/*产生式逆序入栈*/ A[++top]=cha.array[j];if(A[top]=='^'/*为空则不进栈*/top--;}/*if*/else/*出错处理*/{print(;print1(;printf("%c出错\n",x;/*输出出错非终结符*/exit(1;}/*else*/}/*else*/}while(finish==0;}/*main*/程序的运行结果如下:四. 实验心得经过这个实验的练习,通过对程序的分析,让我进一步了解LL(1)算法的思想以及它的进一步程序实现,让我对它的了解从简单的理论上升到程序实现的级别,有理论上升到实际,让我更清楚它的用途。
c语言文法产生式ll(1)
c语言文法产生式ll(1)
在C语言中,文法产生式是用来描述语言结构的规则,而LL(1)表示一种文法分析算法,它是一种自顶向下的语法分析算法,主要用于编译
器的语法分析部分。
在LL(1)算法中,每个文法产生式对应一个语法规则,其中L表示左部,R表示右部,数字1表示每个文法产生式只有一个非终结符。
LL(1)算
法通过预测分析表来选择下一个产生式进行匹配,以确定语法分析的
下一步操作。
下面是一个简单的C语言文法产生式的例子:
```c
E -> E + T | T
T -> T * F | F
F -> ( E ) | id
```
其中,E表示表达式,T表示项,F表示因子。
这个文法产生式描述了
表达式的加法、乘法和括号等操作符的优先级和结合性。
在LL(1)算法中,这个文法产生式可以被转换成如下预测分析表:
```c
E -> E + T | T
T -> T * F | F
F -> ( E ) | id
```
预测分析表中的每个格子表示一个文法产生式,其中第一列表示当前输入符号,后面的列表示对应的选择动作。
在预测分析表的构建过程中,需要对文法产生式进行规范化处理,消除左递归和回溯等不良属性,以保证算法的正确性和高效性。
简易c语言LL(1)文法
简易c语⾔LL(1)⽂法〈程序〉::〈声明〉|〈函数〉〈声明〉::(A|〈声明〉')〈函数声明〉A::〈头⽂件〉|〈宏定义〉〈声明〉'::〈声明〉|null〈头⽂件〉::〈头⽂件〉〈头⽂件〉'〈头⽂件〉'::〈头⽂件〉|null〈宏定义〉::#define B〈宏定义〉|nullB::〈字符串〉CC::〈字符串〉|〈数字〉〈字符串〉::〈变量名〉〈函数声明〉::〈返回值类型〉〈函数名〉(〈形参〉) ;〈函数声明〉|null〈形参〉::〈数据类型〉〈变量名〉|〈数据类型〉〈变量名〉〈,〉〈形参〉|void〈变量名〉::〈字母〉DD::〈字母〉|〈数字〉|〈_〉|D|null〈字母〉::F〈字母〉'F::a|b|...|y|z|(⼤写字母。
)〈字母〉'::〈字母〉|null〈数字〉::E〈数字〉'E::0|1|...|8|9〈数字〉'::〈数字〉|null〈返回值类型〉::int|float|char|void〈函数名〉::〈变量名〉〈函数〉::〈返回值类型〉〈函数名〉{〈函数主体〉}|函数名〉{〈函数主体〉}〈函数〉〈函数主体〉::〈变量的申请〉〈处理语句〉〈变量的申请〉::〈数据类型〉〈变量名〉;〈变量的申请〉'〈变量的申请〉'::〈变量的申请〉|null〈数据类型〉::int|float|char〈处理语句〉::F〈处理语句〉'F::〈赋值语句〉|〈判断语句〉|〈循环语句〉|〈函数调⽤〉〈处理语句〉'::〈处理语句〉|null〈赋值语句〉::〈变量名〉=GG::〈字母〉|〈数字〉|〈变量名〉|〈运算〉〈运算〉::〈变量名〉〈运算符〉〈数字〉|〈数字〉〈运算符〉〈数字〉〈运算符〉::+|-|*|/〈判断语句〉::if(〈条件〉){〈处理语句〉|null}HH::〈Else if〉else{〈处理语句〉|null}|null〈Else if〉::〈Else if〉'〈else if〉(〈条件〉){〈处理语句〉|null}|null〈Else if〉'::〈Else if〉|null〈条件〉::〈变量名〉〈判断运算符〉〈变量名〉|〈变量名〉〈判断运算符〉〈数字〉|〈数字〉〈判断运算符〉〈数字〉|〈数字〉〈判断运算符〉::=|>|<|>=|<=|!=〈循环语句〉::while(〈条件〉){〈处理语句〉}|do{〈处理语句〉}while(〈条件〉)|for(〈赋值语句〉;〈条件〉;〈运算〉){〈处理语句〉}〈函数调⽤〉::〈变量名〉=〈函数名〉(〈形参〉)|〈函数名〉(〈形参〉)。
编译原理实验 LL(1)分析
实验三语法分析---LL(1)分析器目录一. 实验的目的与思路 (2)(1)目的 (2)(2)思路 (2)二. 基本的功能 (3)三.总体设计 (4)四.详细设计 (5)五.源程序清单 (6)六.源代码 (6)....................................................................................................................................................一. 实验的目的与思路(1)目的1. 用程序的方法实现语法分析的LL(1)方法。
(2)思路本程序是采用的LL(1)方法进行的语法分析,而LL(1)的分析方法是属于自上而下的方法。
自上而下分析的基本思想是:对任意输入串,试图用一切可能的方法,从文法开始符号(根结点)出发,自上而下为输入串建立一棵语法树。
从推导的角度看,它是从文法的开始符号出发,反复使用各种产生式,寻找与输入串匹配的推导。
在输入之前必须要进行该文法是不是LL(1)文法的判断,然后再构造相应的LL(1)分析表来用预测分析方法进行语法分析,依据下面的文法及分析表来设计程序实现预测分析的分析过程。
1.文法G[E]:E --> E+T|TT --> T*F|FF --> (E) | i2.通过观察可知道该文法是一个左递归文法,要进行语法分析就必须消除左递归才能继续判断它是不是LL(1)文法,然后才能用预测分析方法进行语法分析。
3.消除左递归:E -->TMM --> +TM|uT --> FQQ --> *FQ|uF --> (E) | i4.在进行LL(1)文法的判断:(1.)各非终结符的FIRST集如下:FIRST(E)= FIRST(TM)= {(,i }FIRST(M)= { + }FIRST(T)= {(,i }FIRST(Q)= { * }FIRST(F)= { (,i }(2.)各非终结符的FOLLOW集如下:FOLLOW(E)= { ),# }FOLLOW(M)= { ),# }FOLLOW(T)= { + ,),# }FOLLOW(Q)= { + ,),# }FOLLOW(F)= { * ,+ ,),# }(3.)各产生式的SELECT集如下:SELECT(E→TM)={ ( ,i }SELECT(M→+TM)={+}SELECT(M→u)={ }, #}SELECT(T→FQ)={ ( ,i }SELECT(Q→*FQ)={ *}SELECT(Q→u)={ +,), # }SELECT(F→(E))={ ( )SELECT(F→i)={ i }因为:SELECT(M→+TM)∩SELECT(M→u)=ФSELECT(Q→*FQ)∩SELECT(Q→u)=ФSELECT(F→(E))∩SELECT(F→i)=Ф因此可以判断该文法是一个LL(1)文法可以构造预测分析表。
编译原理:FOR循环语句的翻译程序设计LL(1)法、输出四元式(附源代码)
学号:课程设计FOR循环语句的翻译程序设计题目(LL(1)法、输出四元式)学院计算机科学与技术专业计算机科学与技术班级计算机0901班姓名指导教师2012 年01 月03 日课程设计任务书学生姓名:专业班级:计算机0901班指导教师:工作单位:计算机科学与技术学院题目: FOR循环语句的翻译程序设计(LL(1)法、输出四元式)初始条件:理论:学完编译课程,掌握一种计算机高级语言的使用。
实践:计算机实验室提供计算机及软件环境。
如果自己有计算机可以在其上进行设计。
要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)(1)写出符合给定的语法分析方法的文法及属性文法。
(2)完成题目要求的中间代码四元式的描述。
(3)写出给定的语法分析方法的思想,完成语法分析和语义分析程序设计。
(4)编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。
(5)设计报告格式按附件要求书写。
课程设计报告书正文的内容应包括:1 系统描述(问题域描述);2 文法及属性文法的描述;3 语法分析方法描述及语法分析表设计;4 按给定的题目给出中间代码形式的描述及中间代码序列的结构设计;5 编译系统的概要设计;6 详细的算法描述(流程图或伪代码);7 软件的测试方法和测试结果;8 研制报告(研制过程,本设计的评价、特点、不足、收获与体会等);9 参考文献(按公开发表的规范书写)。
时间安排:设计安排一周:周1、周2:完成系统分析及设计。
周3、周4:完成程序调试及测试。
周5:撰写课程设计报告。
设计验收安排:设计周的星期五第1节课开始到实验室进行上机验收。
设计报告书收取时间:设计周的次周星期一上午10点。
指导教师签名: 2011年11月18日系主任(或责任教师)签名: 2011年11月18日FOR循环语句的翻译程序设计——LL(1)法、输出四元式1.系统描述1.1问题描述用LL(1)法设计、编制、调试一个FOR(表达式1;表达式2;表达式3)〈赋值语句〉的语法及语义分析程序,输出四元式。
LL(1)文法判断程序java代码
LL(1)文法判断程序java代码分为两个类import .ArrayList;import .HashMap;import .HashSet;import .Stack;public class LL_1 {public HashMap<Character, HashSet<Character>> firstSet = new HashMap<Character, HashSet<Character>>();public HashMap<String, HashSet<Character>> firstSetX = new HashMap<String, HashSet<Character>>();public Character S = 'E';public HashMap<Character, HashSet<Character>> followSet = new HashMap<Character, HashSet<Character>>();public HashSet<Character> VnSet = new HashSet<Character>();public HashSet<Character> VtSet = new HashSet<Character>();public HashMap<Character, ArrayList<String>> experssionSet = new HashMap<Character, ArrayList<String>>();public String[] inputExperssion = { "E->TK", "K->+TK", "K->ε", "T->FM", "M->*FM", "M->ε", "F->i", "F->(E)" };public String[][] table;public Stack<Character> analyzeStatck = new Stack<Character>();public String strInput = "i+i*i#";public String action = "";int index = 0;public void Init() {for (String e : inputExperssion) {String[] str = e.split("->");char c = str[0].charAt(0);ArrayList<String> list = experssionSet.containsKey(c) ? experssionSet.get(c) : new ArrayList<String>();list.add(str[1]);experssionSet.put(c, list);}for (Character c : VnSet)getFirst(c);for (Character c : VnSet) {ArrayList<String> l = experssionSet.get(c);for (String s : l)getFirst(s);}getFollow(S);for (Character c : VnSet) {getFollow(c);}}public void getNvNt() {for (String e : inputExperssion) {String[] str = e.split("->");VnSet.add(str[0].charAt(0));}for (String e : inputExperssion) {String[] str = e.split("->");String right = str[1];for (int i = 0; i < (); i++)if (right.charAt(i)))VtSet.add((i));}}public void getFirst(Character c) {ArrayList<String> list = experssionSet.get(c);HashSet<Character> set = firstSet.containsKey(c) ? firstSet.get(c) : new HashSet<Character>();// c为终结符直接添加if (VtSet.contains(c)) {set.add(c);firstSet.put(c, set);return;}// c为非终结符处理其每条产生式for (String s : list) {// c 推出空串直接添加if (s == Character.toString('ε')) {set.add('ε');}// X -> Y1Y2Y3… 情况else {// 从左往右扫描生成式右部int i = 0;while (i < ()) {char tn = (i);// 先处理防止未初始化getFirst(tn);HashSet<Character> tvSet = firstSet.get(tn);// 将其first集参加左部for (Character tmp : tvSet)set.add(tmp);// 假设包含空串处理下一个符号if (tvSet.contains('ε'))i++;// 否那么退出处理下一个产生式elsebreak;}}}firstSet.put(c, set);}public void getFirst(String s) {HashSet<Character> set = (firstSetX.containsKey(s)) ? firstSetX.get(s) : new HashSet<Character>();// 从左往右扫描该式int i = 0;while (i < ()) {char tn = (i);HashSet<Character> tvSet = firstSet.get(tn);// 将其非空first集参加左部for (Character tmp : tvSet)if (tmp != 'ε')set.add(tmp);// 假设包含空串处理下一个符号if (tvSet.contains('ε'))i++;// 否那么完毕elsebreak;// 到了尾部即所有符号的first集都包含空串把空串参加if (i == ()) {set.add('ε');}}firstSetX.put(s, set);}public void getFollow(char c) {ArrayList<String> list = experssionSet.get(c);HashSet<Character> setA = followSet.containsKey(c) ? followSet.get(c) : new HashSet<Character>();// 假如是开场符添加#if (c == S) {setA.add('#');}// 查找输入的所有产生式,确定c的后跟终结符for (Character ch : VnSet) {ArrayList<String> l = experssionSet.get(ch);for (String s : l)for (int i = 0; i < (); i++)if ((i) == c && i + 1 < s.length() && VtSet.contains(s.charAt(i + 1)))setA.add(s.charAt(i + 1));}followSet.put(c, setA);// 处理c的每一条产生式for (String s : list) {int i = () - 1;while (i >= 0) {char tn = (i);// 只处理非终结符if (VnSet.contains(tn)) {// 都按A->αBβ 形式处理// 假设β不存在followA 参加followB// 假设β存在,把β的非空first集参加followB// 假设β存在且first(β)包含空串followA 参加followB// 假设β存在if (() - i - 1 > 0) {String right = (i + 1);// 非空first集参加followBHashSet<Character> setF = null;if (() == 1 && firstSet.containsKey(right.charAt(0)))setF = firstSet.get((0));else {if (right)) {HashSet<Character> set = new HashSet<Character>();firstSetX.put(right, set);}setF = firstSetX.get(right);}HashSet<Character> setX = followSet.containsKey(tn) ? followSet.get(tn): new HashSet<Character>();for (Character var : setF)if (var != 'ε')setX.add(var);followSet.put(tn, setX);// 假设first(β)包含空串followA 参加followBif (setF.contains('ε')) {if (tn != c) {HashSet<Character> setB = followSet.containsKey(tn) ? followSet.get(tn): new HashSet<Character>();for (Character var : setA)setB.add(var);followSet.put(tn, setB);}}}// 假设β不存在followA 参加followBelse {// A和B一样不添加if (tn != c) {HashSet<Character> setB = followSet.containsKey(tn) ? followSet.get(tn): new HashSet<Character>();for (Character var : setA)setB.add(var);followSet.put(tn, setB);}}i--;}// 假如是终结符往前看如A->aaaBCDaaaa 此时β为CDaaaaelsei--;}}}public void createTable() {Object[] VtArray = VtSet.toArray();Object[] VnArray = VnSet.toArray();// 预测分析表初始化table = new String[VnArray.length + 1][VtArray.length + 1];table[0][0] = "Vn/Vt";// 初始化首行首列for (int i = 0; i < VtArray.length; i++)table[0][i + 1] = (VtArray[i].toString().charAt(0) == 'ε') ? "#" : VtArray[i].toString();for (int i = 0; i < VnArray.length; i++)table[i + 1][0] = VnArray[i] + "";// 全部置errorfor (int i = 0; i < VnArray.length; i++)for (int j = 0; j < VtArray.length; j++)table[i + 1][j + 1] = "error";// 插入生成式for (char A : VnSet) {ArrayList<String> l = experssionSet.get(A);for (String s : l) {HashSet<Character> set = firstSetX.get(s);for (char a : set)insert(A, a, s);if (('ε')) {HashSet<Character> setFollow = followSet.get(A);if (setFollow.contains('#'))insert(A, '#', s);for (char b : setFollow)insert(A, b, s);}}}}public void analyzeLL() {System.out.println(" Stack Input Action");analyzeStatck.push('#');analyzeStatck.push('E');displayLL();char X = analyzeStatck.peek();while (X != '#') {char a = strInput.charAt(index);if (X == a) {action = "匹配" + analyzeStatck.peek();analyzeStatck.pop();index++;} else if (VtSet.contains(X))return;else if (find(X, a).equals("error"))return;else if (find(X, a).equals("ε")) {analyzeStatck.pop();action = X + "->ε";} else {String str = find(X, a);if (str != "") {action = X + "->" + str;analyzeStatck.pop();int len = ();for (int i = len - 1; i >= 0; i--)analyzeStatck.push((i));} else {System.out.println("error at '" + strInput.charAt(index) + " in " + index);return;}}X = analyzeStatck.peek();displayLL();}System.out.println("Successful,为LL(1)文法");}public String find(char X, char a) {for (int i = 0; i < VnSet.size() + 1; i++) {if (table[i][0].charAt(0) == X)for (int j = 0; j < VtSet.size() + 1; j++) {if (table[0][j].charAt(0) == a)return table[i][j];}}return "";}public void insert(char X, char a, String s) {if (a == 'ε')a = '#';for (int i = 0; i < VnSet.size() + 1; i++) {if (table[i][0].charAt(0) == X)for (int j = 0; j < VtSet.size() + 1; j++) {if (table[0][j].charAt(0) == a) {table[i][j] = s;return;}}}}public void displayLL() {Stack<Character> s = analyzeStatck;System.out.printf("%23s", s);System.out.printf("%13s", strInput.substring(index));System.out.printf("%10s", action);System.out.println();}}public class Test {public static void main(String[] args) {LL_1 l = new LL_1();l.getNvNt();l.Init();l.createTable();l.analyzeLL();}}。
LL(1)文法源代码【精选】
//******************************************************************* *******************************//LL(1)分析法//编译环境:g++//语言:C++//******************************************************************* *******************************#include <iostream>#include <string>#include <stdlib.h>#include <fstream>using namespace std;//****************************************************************** ********************************class Grammar{ public:Grammar();Grammar(const Grammar&);//复制构造函数Grammar& operator =(const Grammar&);//赋值函数friend ostream& operator<<(ostream& output,const Grammar& rs)//输出文法 {output<<"结终符:"<<rs.zhong<<endl;output<<"非结终符:"<<rs.fei<<endl;output<<"文法内容(共"<<rs.number<<"条):"<<endl;int i=0;while(i<rs.number)//显示文法内容 {output<<rs.content[i++]<<endl;}output<<"**************************************************** *************"<<endl;output<<"非终结符\t\tFIRST集合\t\tFOLLOW集合"<<endl;for(unsigned int j=0;j<rs.fei.size();j++)cout<<rs.fei[j]<<"\t\t\t"<<rs.first[j]<<"\t\t\t"<<rs.foll ow[j]<<endl;output<<"**************************************************** *************"<<endl;output<<"预测分析表:"<<endl<<"\t";for(unsigned int j=0;j<rs.zhong.size();j++)output<<rs.zhong[j]<<"\t";//显示终结符output<<"#"<<endl;for(unsigned int j=0;j<rs.fei.size();j++){output<<rs.fei[j]<<"\t";//显示非终结符 //开始显示内容 for(unsigned int k=0;k<=rs.zhong.size();k++)cout<<rs.table[j][k]<<"\t";output<<endl;}return output;}friend istream& operator>>(istream& input,Grammar& rs)//输入文法 {unsigned int j=0;//cout<<"请输入文法:"<<endl; //cout<<"(请按文法次序输入,使用推导符\"->\",每一句一行,最后一行请以'#'开头,'ε'使用'^'表示!每一行一条文法句。
编译原理中LL(1)文法的源代码
编译原理中LL(1)⽂法的源代码好好好好⼀.实验⽬的1.掌握LL(1)分析法的基本原理2.掌握LL(1)分析表的构造⽅法3.掌握LL(1)驱动程序的构造⽅法⼆.实验内容及要求根据某⼀⽂法编制调试LL(1)分析程序,以便对任意输⼊的符号串进⾏分析。
本次实验的⽬的主要是加深对预测分析LL(1)分析法的理解。
例:对下列⽂法,⽤LL(1)分析法对任意输⼊的符号串进⾏分析:(1)E->TG(2)G->+TG|—TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E)(8)F->i输出的格式如下:(1)LL(1(2)输⼊⼀以#结束的符号串((3)输出过程如下:步骤分析栈剩余输⼊串所⽤产⽣式1 E i+i*i# E->TG(或者为合法符号串)备注:(1)在“所⽤产⽣式”⼀列中如果对应有推导则写出所⽤产⽣式;如果为匹配终结符则写明匹配的终结符;如分析异常出错则写为“分析出错”;若成功结束则写为“分析成功”。
(3)上述描述的输出过程只是其中⼀部分的。
注意:1.表达式中允许使⽤运算符(+-*/)、分割符(括号)、字符i,结束符#;2.如果遇到错误的表达式,应输出错误提⽰信息(该信息越详细越好);3.对学有余⼒的同学,测试⽤的表达式事先放在⽂本⽂件中,⼀⾏存放⼀个表达式,同时以分号分割。
同时将预期的输出结果写在另⼀个⽂本⽂件中,以便和输出进⾏对照;4.可采⽤的其它的⽂法。
三.实验过程LL(1)分析法的实验源程序代码如下:#include#include#include#includechar A[20];/*分析栈*/char B[20];/*剩余串*/char v1[20]={'i','+','*','(',')','#'};/*终结符 */ char v2[20]={'E','G','T','S','F'};/*⾮终结符 */ int j=0,b=0,top=0,l;/*L为输⼊串长度 */typedef struct type/*产⽣式类型定义 */{char origin;/*⼤写字符 */char array[5];/*产⽣式右边字符 */int length;/*字符个数 */}type;type e,t,g,g1,s,s1,f,f1;/*结构体变量 */type C[10][10];/*预测分析表 */void print()/*输出分析栈 */{int a;/*指针*/for(a=0;a<=top+1;a++)printf("%c",A[a]);printf("\t\t");}/*print*/void print1()/*输出剩余串*/{int j;for(j=0;jprintf(" ");for(j=b;j<=l;j++)printf("%c",B[j]);printf("\t\t\t");}/*print1*/void main(){int m,n,k=0,flag=0,finish=0;char ch,x;type cha;/*⽤来接受C[m][n]*//*把⽂法产⽣式赋值结构体*/e.origin='E';strcpy(e.array,"TG");e.length=2;t.origin='T';strcpy(t.array,"FS");t.length=2;g.origin='G';strcpy(g.array,"+TG");g.length=3;g1.origin='G';g1.array[0]='^';g1.length=1;s.origin='S';strcpy(s.array,"*FS");s.length=3;s1.origin='S';s1.array[0]='^';s1.length=1;f.origin='F';strcpy(f.array,"(E)");f.length=3;f1.origin='F';f1.array[0]='i';f1.length=1;for(m=0;m<=4;m++)/*初始化分析表*/ for(n=0;n<=5;n++)C[m][n].origin='N';/*全部赋为空*//*填充分析表*/C[0][0]=e;C[0][3]=e;C[1][1]=g;C[1][4]=g1;C[1][5]=g1;C[2][0]=t;C[2][3]=t;C[3][1]=s1;C[3][2]=s;C[3][4]=C[3][5]=s1;C[4][0]=f1;C[4][3]=f;printf("提⽰:本程序只能对由'i','+','*','(',')'构成的以'#'结束的字符串进⾏分析,\n"); printf("请输⼊要分析的字符串:");do/*读⼊分析串*/{scanf("%c",&ch);if ((ch!='i') &&(ch!='+') &&(ch!='*')&&(ch!='(')&&(ch!=')')&&(ch!='#')) {printf("输⼊串中有⾮法字符\n");exit(1);}B[j]=ch;j++;}while(ch!='#');l=j;/*分析串长度*/ch=B[0];/*当前分析字符*/A[top]='#'; A[++top]='E';/*'#','E'进栈*/printf("步骤\t\t分析栈 \t\t剩余字符 \t\t所⽤产⽣式 \n"); do{x=A[top--];/*x为当前栈顶字符*/printf("%d",k++);printf("\t\t");for(j=0;j<=5;j++)/*判断是否为终结符*/if(x==v1[j]){flag=1;break;}if(flag==1)/*如果是终结符*/{if(x=='#'){finish=1;/*结束标记*/printf("acc!\n");/*接受 */getchar();getchar();exit(1);}/*if*/if(x==ch){print();print1();printf("%c匹配\n",ch);ch=B[++b];/*下⼀个输⼊字符*/flag=0;/*恢复标记*/}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",ch);/*输出出错终结符*/ exit(1);}/*else*/}/*if*/else/*⾮终结符处理*/{for(j=0;j<=4;j++)if(x==v2[j]){m=j;/*⾏号*/break;}for(j=0;j<=5;j++)if(ch==v1[j]){n=j;/*列号*/break;}cha=C[m][n];if(cha.origin!='N')/*判断是否为空*/{print();print1();printf("%c->",cha.origin);/*输出产⽣式*/for(j=0;jprintf("%c",cha.array[j]);printf("\n");for(j=(cha.length-1);j>=0;j--)/*产⽣式逆序⼊栈*/A[++top]=cha.array[j];if(A[top]=='^')/*为空则不进栈*/top--;}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",x);/*输出出错⾮终结符*/exit(1);}/*else*/}/*else*/}while(finish==0);}/*main*/程序的运⾏结果如下:四.实验⼼得经过这个实验的练习,通过对程序的分析,让我进⼀步了解LL(1)算法的思想以及它的进⼀步程序实现,让我对它的了解从简单的理论上升到程序实现的级别,有理论上升到实际,让我更清楚它的⽤途。
编译原理c语言ll1代码
/********************************************/#include<stdlib.h>#include<stdio.h>#include<string.h>/*******************************************/int count=0; /*分解的产生式的个数*/int number; /*所有终结符和非终结符的总数*/char start; /*开始符号*/char termin[50]; /*终结符号*/char non_ter[50]; /*非终结符号*/char v[50]; /*所有符号*/char left[50]; /*左部*/char right[50][50]; /*右部*/char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/char first1[50][50]; /*所有单个符号的FIRST集合*/char select[50][50]; /*各单个产生式的SELECT集合*/char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/ char empty[20]; /*记录可直接推出^的符号*/char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/ int validity=1; /*表示输入文法是否有效*/int ll=1; /*表示输入文法是否为LL(1)文法*/int M[20][20]; /*分析表*/char choose; /*用户输入时使用*/char empt[20]; /*求_emp()时使用*/char fo[20]; /*求FOLLOW集合时使用*//*******************************************判断一个字符是否在指定字符串中********************************************/int in(char c,char *p){int i;if(strlen(p)==0)return(0);for(i=0;;i++){if(p[i]==c)return(1); /*若在,返回*/if(i==strlen(p))return(0); /*若不在,返回*/ }}/*******************************************得到一个不是非终结符的符号********************************************/char c(){char c='A';while(in(c,non_ter)==1)c++;return(c);}/*******************************************分解含有左递归的产生式********************************************/void recur(char *point){ /*完整的产生式在point[]中*/ int j,m=0,n=3,k;char temp[20],ch;ch=c(); /*得到一个非终结符*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;j<=strlen(point)-1;j++){if(point[n]==point[0]){ /*如果‘|’后的首符号和左部相同*/ for(j=n+1;j<=strlen(point)-1;j++){while(point[j]!='|'&&point[j]!='\0')temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|'){n=j+1;break;}}}else{ /*如果‘|’后的首符号和左部不同*/ left[count]=ch;right[count][0]='^';right[count][1]='\0';count++;for(j=n;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';printf(" count=%d ",count);m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;}}}/*******************************************分解不含有左递归的产生式********************************************/void non_re(char *point){int m=0,j;char temp[20];for(j=3;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;}/*******************************************读入一个文法********************************************/char grammer(char *t,char *n,char *left,char right[50][50]) {char vn[50],vt[50];char s;char p[50][50];int i,j,k;printf("\n请输入文法的非终结符号串:");scanf("%s",vn);getchar();i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf("请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("请输入文法的开始符号:");scanf("%c",&s);getchar();printf("请输入文法产生式的条数:");scanf("%d",&i);getchar();for(j=1;j<=i;j++){printf("请输入文法的第%d条(共%d条)产生式:",j,i);scanf("%s",p[j-1]);getchar();}for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){ printf("\ninput error!");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/ if(p[k][3]==p[k][0])recur(p[k]);elsenon_re(p[k]);}return(s);}/*******************************************将单个符号或符号串并入另一符号串********************************************/void merge(char *d,char *s,int type){ /*d是目标符号串,s是源串,type=,源串中的‘^ ’一并并入目串;type=,源串中的‘^ ’不并入目串*/int i,j;for(i=0;i<=strlen(s)-1;i++){if(type==2&&s[i]=='^');else{for(j=0;;j++){if(j<strlen(d)&&s[i]==d[j])break;if(j==strlen(d)){d[j]=s[i];d[j+1]='\0';break;}}}}}/*******************************************求所有能直接推出^的符号********************************************/void emp(char c){ /*即求所有由‘^ ’推出的符号*/ char temp[10];int i;for(i=0;i<=count-1;i++){if(right[i][0]==c&&strlen(right[i])==1){temp[0]=left[i];temp[1]='\0';merge(empty,temp,1);emp(left[i]);}}}/*******************************************求某一符号能否推出‘^ ’********************************************/int_emp(char c){ /*若能推出,返回;否则,返回*/ int i,j,k,result=1,mark=0;char temp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1)return(1);for(i=0;;i++){if(i==count)return(0);if(left[i]==c) /*找一个左部为c的产生式*/ {j=strlen(right[i]); /*j为右部的长度*/if(j==1&&in(right[i][0],empty)==1)return(1);else if(j==1&&in(right[i][0],termin)==1)return(0);else{for(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1)mark=1;if(mark==1)continue;else{for(k=0;k<=j-1;k++){result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);}}}if(result==0&&i<count)continue;else if(result==1&&i<count)return(1);}}}/*******************************************判断读入的文法是否正确********************************************/int judge(){int i,j;for(i=0;i<=count-1;i++){if(in(left[i],non_ter)==0){ /*若左部不在非终结符中,报错*/printf("\nerror1!");validity=0;return(0);}for(j=0;j<=strlen(right[i])-1;j++){if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='^') { /*若右部某一符号不在非终结符、终结符中且不为‘^ ’,报错*/printf("\nerror2!");validity=0;return(0);}}}return(1);}/*******************************************求单个符号的FIRST********************************************/void first2(int i){ /*i为符号在所有输入符号中的序号*/ char c,temp[20];int j,k,m;c=v[i];char ch='^';emp(ch);if(in(c,termin)==1) /*若为终结符*/{first1[i][0]=c;first1[i][1]='\0';}else if(in(c,non_ter)==1) /*若为非终结符*/{for(j=0;j<=count-1;j++){if(left[j]==c){if(in(right[j][0],termin)==1||right[j][0]=='^'){temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);}else if(in(right[j][0],non_ter)==1){if(right[j][0]==c)continue;for(k=0;;k++)if(v[k]==right[j][0])break;if(f[k]=='0'){first2(k);f[k]='1';}merge(first1[i],first1[k],2);for(k=0;k<=strlen(right[j])-1;k++){empt[0]='\0';if(_emp(right[j][k])==1&&k<strlen(right[j])-1){for(m=0;;m++)if(v[m]==right[j][k+1])break;if(f[m]=='0'){first2(m);f[m]='1';}merge(first1[i],first1[m],2);}else if(_emp(right[j][k])==1&&k==strlen(right[j])-1) {temp[0]='^';temp[1]='\0';merge(first1[i],temp,1);}elsebreak;}}}}}f[i]='1';}/*******************************************求各产生式右部的FIRST********************************************/void FIRST(int i,char *p){int length;int j,k,m;char temp[20];length=strlen(p);if(length==1) /*如果右部为单个符号*/ {if(p[0]=='^'){if(i>=0){first[i][0]='^';first[i][1]='\0';}else{TEMP[0]='^';TEMP[1]='\0';}}else{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0){memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';}else{memcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';}}}else/*如果右部为符号串*/ {for(j=0;;j++)if(v[j]==p[0])break;if(i>=0)merge(first[i],first1[j],2);elsemerge(TEMP,first1[j],2);for(k=0;k<=length-1;k++){empt[0]='\0';if(_emp(p[k])==1&&k<length-1){for(m=0;;m++)if(v[m]==right[i][k+1])break;if(i>=0)merge(first[i],first1[m],2);elsemerge(TEMP,first1[m],2);}else if(_emp(p[k])==1&&k==length-1){temp[0]='^';temp[1]='\0';if(i>=0)merge(first[i],temp,1);elsemerge(TEMP,temp,1);}else if(_emp(p[k])==0)break;}}}/*******************************************求各产生式左部的FOLLOW********************************************/void FOLLOW(int i){int j,k,m,n,result=1;char c,temp[20];c=non_ter[i]; /*c为待求的非终结符*/temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若为开始符号*/temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);}for(j=0;j<=count-1;j++){if(in(c,right[j])==1) /*找一个右部含有c的产生式*/{for(k=0;;k++)if(right[j][k]==c)break; /*k为c在该产生式右部的序号*/for(m=0;;m++)if(v[m]==left[j])break; /*m为产生式左部非终结符在所有符号中的序号*/if(k==strlen(right[j])-1){ /*如果c在产生式右部的最后*/if(in(v[m],fo)==1){merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}else{ /*如果c不在产生式右部的最后*/ for(n=k+1;n<=strlen(right[j])-1;n++){empt[0]='\0';result*=_emp(right[j][n]);}if(result==1){ /*如果右部c后面的符号串能推出^*/ if(in(v[m],fo)==1){ /*避免循环递归*/merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}for(n=k+1;n<=strlen(right[j])-1;n++)temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);}}}F[i]='1';}/*******************************************判断读入文法是否为一个LL(1)文法********************************************/int ll1(){int i,j,length,result=1;char temp[50];for(j=0;j<=49;j++){ /*初始化*/first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';}for(j=0;j<=strlen(v)-1;j++)first2(j); /*求单个符号的FIRST集合*/ printf("\nfirst1:");for(j=0;j<=strlen(v)-1;j++)printf("%c:%s ",v[j],first1[j]);printf("\nempty:%s",empty);printf("\n:::\n_emp:");for(j=0;j<=strlen(v)-1;j++)printf("%d ",_emp(v[j]));for(i=0;i<=count-1;i++)FIRST(i,right[i]); /*求FIRST*/printf("\n");for(j=0;j<=strlen(non_ter)-1;j++){ /*求FOLLOW*/ if(fo[j]==0){fo[0]='\0';FOLLOW(j);}}printf("\nfirst:");for(i=0;i<=count-1;i++)printf("%s ",first[i]);printf("\nfollow:");for(i=0;i<=strlen(non_ter)-1;i++)printf("%s ",follow[i]);for(i=0;i<=count-1;i++){ /*求每一产生式的SELECT集合*/ memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;j<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==1&&right[i][0]=='^')result=1;if(result==1){for(j=0;;j++)if(v[j]==left[i])break;merge(select[i],follow[j],1);}}printf("\nselect:");for(i=0;i<=count-1;i++)printf("%s ",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=1;i<=count-1;i++){ /*判断输入文法是否为LL(1)文法*/ length=strlen(temp);if(left[i]==left[i-1]){merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i]))return(0);}else{temp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';}}return(1);}/*******************************************构造分析表M********************************************/void MM(){int i,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++)M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*将#加入终结符数组*/termin[i+1]='\0';for(i=0;i<=count-1;i++){for(m=0;;m++)if(non_ter[m]==left[i])break; /*m为产生式左部非终结符的序号*/ for(j=0;j<=strlen(select[i])-1;j++){if(in(select[i][j],termin)==1){for(k=0;;k++)if(termin[k]==select[i][j])break; /*k为产生式右部终结符的序号*/ M[m][k]=i;}}}}/*******************************************总控算法********************************************/void syntax(){int i,j,k,m,n,p,q;char ch;char S[50],str[50];printf("请输入该文法的句型:");scanf("%s",str);getchar();i=strlen(str);str[i]='#';str[i+1]='\0';S[0]='#';S[1]=start;S[2]='\0';j=0;ch=str[j];while(1){if(in(S[strlen(S)-1],termin)==1){if(S[strlen(S)-1]!=ch){printf("\n该符号串不是文法的句型!");return;}else if(S[strlen(S)-1]=='#'){printf("\n该符号串是文法的句型.");return;}else{S[strlen(S)-1]='\0';j++;ch=str[j];}}else{for(i=0;;i++)if(non_ter[i]==S[strlen(S)-1])break;for(k=0;;k++){if(termin[k]==ch)break;if(k==strlen(termin)){printf("\n词法错误!");return;}}if(M[i][k]==-1){printf("\n语法错误!");return;}else{m=M[i][k];if(right[m][0]=='^')S[strlen(S)-1]='\0';else{p=strlen(S)-1;q=p;for(n=strlen(right[m])-1;n>=0;n--)S[p++]=right[m][n];S[q+strlen(right[m])]='\0';}}}printf("\nS:%s str:",S);for(p=j;p<=strlen(str)-1;p++)printf("%c",str[p]);printf(" ");}}/*******************************************一个用户调用函数********************************************/void menu(){syntax();printf("\n是否继续?(y or n):");scanf("%c",&choose);getchar();while(choose=='y'){menu();}}/*******************************************主函数********************************************/void main(){int i,j;start=grammer(termin,non_ter,left,right); /*读入一个文法*/printf("count=%d",count);printf("\nstart:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\nv:%s",v);printf("\nnon_ter:%s",non_ter);printf("\ntermin:%s",termin);printf("\nright:");for(i=0;i<=count-1;i++)printf("%s ",right[i]);printf("\nleft:");for(i=0;i<=count-1;i++)printf("%c ",left[i]);if(validity==1)validity=judge();printf("\nvalidity=%d",validity);if(validity==1){printf("\n文法有效");ll=ll1();printf("\nll=%d",ll);if(ll==0)printf("\n该文法不是一个LL1文法!");else{MM();printf("\n");for(i=0;i<=19;i++)for(j=0;j<=19;j++)if(M[i][j]>=0)printf("M[%d][%d]=%d ",i,j,M[i][j]);printf("\n");menu();}}}。
LL1文法的实现
printf("%d\t", k++); for (j = 0; j < ROW; j++){ //判断是否为终结符 if (x == TerSymbol[j]){ flag = 1; break; } } if (flag == 1){ //如果是终结符 if (x == '#'){ print(); print1(); finish = 1; //结束标记 printf("Accept!\n"); getchar(); exit(1); } if (x == ch){ print(); print1(); printf("%c matching\n", ch); ch = SpareStack[++b]; //下一个输入字符 flag = 0; //恢复标记 } else{//出错处理 print(); print1(); printf("%c Error!\n", ch);//输出出错终结符 exit(1); } } else{//非终结符处理 for (j = 0; j < LINE; j++){ if (x == NTerSymbol[j]){ m = j; break; } } for (j = 0; j < ROW; j++){ if (ch == TerSymbol[j]){ n = j; break; } }
PreTable[0][5] = e;
PreTable[1][7] = d2; PreTable[2][5] = t; PreTable[3][2] = c2;
PreTable[3][7] = c2;
printf("Please Enter A String to analyze:"); do{ //读入分析串,放入剩余栈中 scanf("%c", &ch); if (ch!='i' && ch!='+' && ch!='-' && ch!='*' && ch!='/' && ch!='(' && ch!=')' && ch!='#'){ printf("Input characters are illegal!\n"); exit(1); } SpareStack[j] = ch; j++; } while (ch!='#'); l = j;//分析串长度 ch = SpareStack[0];//当前分析字符 AnalStack[top]= '#'; AnalStack[++top] = 'E';//'#','E'进栈 printf("\nStep\tAnalysis stack\tRemaining string\tProduction\n"); do{ x = AnalStack[top--]; //为当前栈顶字符
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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)