编最近上的编译原理课呢做实验,输入一个文法,然后判断是不是LL1文法,根据清华大学张素琴老师主编的《编译原理》第二版80页的算法,写了短程序:
- //compile.c
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- #define length 100
- typedef struct {
- char T[length];
- char first[length][length];
- int len;
- } ter,*Ter;
- typedef struct {
- char N[length];
- char first[length][length];
- char follow[length][length];
- char p_emp[length];
- char n_emp[length];
- int len;
- }*NTer,nter;
- //define Produce data
- typedef struct {
- char front;
- char back[length];
- }*Pro,prox;
- typedef struct {
- Pro pro[length];
- char string_first[length][length];
- char select[length][length];
- int len;
- }*Prod,prodx;
- //define G
- typedef struct {
- Ter t_symbol;
- NTer n_symbol;
- Prod produce;
- char start_symbol;
- }*G,grame;
- int belong_Arr(char x,char arr[])
- {
- int i=0;
- while(arr[i]!='\0') {
- if(arr[i]==x)
- return 1;
- i++;
- }
- return 0;
- }
- int join(char a[],char b[],int a_len,int b_len)
- {
- int i;
- for(i=0; i<b_len; i++)
- if((!belong_Arr(b[i],a))&&(b[i]!='&')) {
- a[a_len]=b[i];
- a_len++;
- }
- return a_len;
- }
- int join_arr(char a[],char b[])
- {
- int i,len;
- len=0;
- while(a[len]!='\0')
- len++;
- i=0;
- while(b[i]!='\0') {
- if((!belong_Arr(b[i],a))&&(b[i]!='&')) {
- a[len]=b[i];
- len++;
- }
- i++;
- }
- return len;
- }
- int belong_N(char x,NTer n)
- {
- int i=0;
- for(; i<n->len; i++) {
- if(x==n->N[i])
- return 1;
- }
- return 0;
- }
- int belong_T(char x,Ter t)
- {
- int i=0;
- for(; i<t->len; i++) {
- if(x==t->T[i])
- return 1;
- }
- return 0;
- }
- typedef struct {
- char syb;
- int tag;
- }*elm,el;
- typedef struct {
- elm elms[length];
- int len;
- }*x_table,x_tab;
- void find_null(Prod pr,NTer n,Ter t)
- {
- int i=0;
- int j=0;
- int k=0;
- int m,a;
- int b;
- int q;
- int loop=1;
- int flag[n->len];
- char temp;
- //作为标记,辨别产生世是否删除
- int tags[pr->len];
- x_table tab=(x_table)malloc(sizeof(x_tab));
- Prod p=(Prod)malloc(sizeof(prodx));
- p->len=pr->len;
- for(i=0; i<pr->len; i++) {
- p->pro[i]=(Pro)malloc(sizeof(prox));
- p->pro[i]->front=pr->pro[i]->front;
- strcpy(p->pro[i]->back,pr->pro[i]->back);
- }
- for(i=0; i<p->len; i++) {
- tags[i]=1;
- }
- for(i=0; i<n->len; i++) {
- tab->elms[i]=(elm)malloc(sizeof(el));
- tab->elms[i]->syb=n->N[i];
- tab->elms[i]->tag=0;
- }
- tab->len=n->len;
- for(i=0; i<p->len; i++) {
- j=0;
- while((temp=p->pro[i]->back[j++])!='#') {
- if(belong_T(temp,t)) {
- tags[i]=0;
- break;
- }
- }
- }
- //确定以某一非终结符为左部的产生是的个数;判断以某一非终结符为左部的所有产生是都被删除,则将此非终结符标记否 即为 2 此为 步骤2_1
- for(i=0; i<tab->len; i++) {
- k=0;
- m=0;
- for(j=0; j<p->len; j++) {
- if(tab->elms[i]->syb==p->pro[j]->front) {
- k++;
- if(tags[j]==0)
- m++;
- }
- }
- if(k==0)
- continue;
- else if(k==m) {
- tab->elms[i]->tag=2;
- }
- }
- //判断 右部 是不是 yi bu xiu 是则 标记 1 , 此为步骤 2_2
- for(i=0; i<p->len; i++) {
- if(p->pro[i]->back[0]=='#') {
- tags[i]=0;
- for(j=0; j<tab->len; j++) {
- if(tab->elms[j]->syb==p->pro[i]->front) {
- tab->elms[j]->tag=1;
- }
- }
- }
- }
- k=0,j=0;
- for(i=0; i<tab->len; i++) {
- if(tab->elms[i]->tag==1) {
- n->p_emp[k]=tab->elms[i]->syb;
- k++;
- } else if(tab->elms[i]->tag==2) {
- n->n_emp[j]=tab->elms[i]->syb;
- j++;
- }
- }
- n->p_emp[k]='\0';
- n->n_emp[j]='\0';
- printf("==============================================\n");
- printf("==============================================\n");
- printf("U---------Unknown\n");
- printf("Y---------Can produce empty set\n");
- printf("N---------Can't produce empty set\n");
- printf("The first time scaning\n");
- for(i=0; i<tab->len; i++)
- printf("%c ",tab->elms[i]->syb);
- printf("\n");
- for(i=0; i<tab->len; i++) {
- if(tab->elms[i]->tag==0)
- printf("U ");
- else if(tab->elms[i]->tag==1)
- printf("Y ");
- else
- printf("N ");
- }
- printf("\n");
- m=0,j=0,k=0;
- //步骤3_1
- while(loop==1) {
- loop=0;
- for(j=0; j<tab->len; j++) {
- flag[j]=tab->elms[j]->tag;
- }
- for(i=0; i<p->len; i++) {
- if(tags[i]==1) {
- k=0;
- while(p->pro[i]->back[k]!='#') {
- if(belong_N(p->pro[i]->back[k],n)) {
- for(j=0; j<tab->len; j++) {
- if(tab->elms[j]->syb==p->pro[i]->back[k]) {
- if(tab->elms[j]->tag==1) {
- m=k;
- while('\0'!=p->pro[i]->back[m]) {
- p->pro[i]->back[m]=p->pro[i]->back[m+1];
- //printf("%c\n",p->pro[i]->back[m]);
- m++;
- }
- k=k-1;
- if('#'==p->pro[i]->back[0]) {
- for(b=0; b<tab->len; b++) {
- if(tab->elms[b]->syb==p->pro[i]->front) {
- tab->elms[b]->tag=1;
- q=b;
- }
- }
- for(b=0; b<p->len; b++) {
- if(p->pro[b]->front==tab->elms[q]->syb) {
- tags[b]=0;
- }
- }
- }
- }
- else if(tab->elms[j]->tag==2) {
- tags[i]=0;
- b=0;
- for(a=0; a<p->len; a++) {
- if((p->pro[a]->front==p->pro[i]->front)&&(tags[a]==1)) {
- tags[a]=0;
- }
- }
- for(a=0; a<p->len; a++) {
- if((p->pro[a]->front==p->pro[i]->front)&&(tags[a]==1)) {
- b++;
- }
- }
- if(b==0) {
- for(a=0; a<tab->len; a++) {
- if((tab->elms[a]->syb==p->pro[i]->front)&&(tab->elms[a]->tag==0)) {
- tab->elms[a]->tag=2;
- }
- }
- }
- }
- }
- }
- }
- k++;
- }
- }
- }
- for(i=0; i<tab->len; i++) {
- if(tab->elms[i]->tag!=flag[i]) {
- loop=1;
- break;
- }
- }
- }
- printf("The second time scaning\n");
- for(i=0; i<tab->len; i++)
- printf("%c ",tab->elms[i]->syb);
- printf("\n");
- for(i=0; i<tab->len; i++) {
- if(tab->elms[i]->tag==0)
- printf("U ");
- else if(tab->elms[i]->tag==1)
- printf("Y ");
- else
- printf("N ");
- }
- k=0,j=0,m;
- for(i=0; i<tab->len; i++) {
- if(tab->elms[i]->tag==1) {
- //n_pro_e[k]=tab->elms[i]->syb;
- n->p_emp[k]=tab->elms[i]->syb;
- k++;
- } else if(tab->elms[i]->tag==2) {
- //npro_e[j]=tab->elms[i]->syb;
- n->n_emp[j]=tab->elms[i]->syb;
- j++;
- }
- }
- n->p_emp[k]='\0';
- n->n_emp[j]='\0';
- return ;
- }
- void get_first_set(Prod p,NTer n,Ter t)
- {
- int i,j,k,temp;
- int flag,a,b;
- int m;
- int tags[n->len];
- //int lock[n->len];
- int loop=1;
- int judge[n->len];
- printf("\n==============================================\n");
- printf("\nBeging finding first set\n");
- //X is included in Vt,F(X)={X};
- for(i=0; i<t->len; i++) {
- t->first[i][0]=t->T[i];
- }
- printf("The terminal symnol's First Set\n");
- for(i=0; i<t->len; i++)
- printf("First(%c)={%c}\n",t->T[i],t->first[i][0]);
- printf("\n");
- for(i=0; i<n->len; i++)
- tags[i]=0;
-
- for(i=0; i<p->len; i++) {
- //X->a..... a is included in first[X]
- if(belong_T(p->pro[i]->back[0],t)) {
- for(j=0; j<n->len; j++) {
- if(p->pro[i]->front==n->N[j]) {
- temp=tags[j]++;
- n->first[j][temp]=p->pro[i]->back[0];
- //lock[j]=0;
- break;
- }
- }
- }
- //X-># & is included in First[X]
- else if(p->pro[i]->back[0]=='#') {
- for(j=0; j<n->len; j++) {
- if(p->pro[i]->front==n->N[j]) {
- temp=tags[j]++;
- n->first[j][temp]='&';
- // lock[j]=0;
- break;
- }
- }
- }
- }
- while(loop==1) {
- loop=0;
- for(i=0; i<n->len; i++)
- judge[i]=tags[i];
- for(i=0; i<p->len; i++) {
- //flag=0;
- if(p->pro[i]->back[0]=='#')
- continue;
- if(belong_T(p->pro[i]->back[0],t))
- continue;
- for(a=0; a<n->len; a++)
- if(n->N[a]==p->pro[i]->front)
- break;
- j=0;
- while('#'!=p->pro[i]->back[j]) {
- if(belong_Arr(p->pro[i]->back[j],n->p_emp)) {
- for(b=0; b<n->len; b++)
- if(n->N[b]==p->pro[i]->back[j])
- break;
- tags[a]=join(n->first[a],n->first[b],tags[a],tags[b]);
- j++;
- } else if(belong_Arr(p->pro[i]->back[j],n->n_emp)) {
- for(b=0; b<n->len; b++)
- if(n->N[b]==p->pro[i]->back[j])
- break;
- tags[a]=join(n->first[a],n->first[b],tags[a],tags[b]);
- break;
- } else if(belong_T(p->pro[i]->back[j],t)) {
- if(!belong_Arr(p->pro[i]->back[j],n->first[a])) {
- n->first[a][tags[a]++]=p->pro[i]->back[j];
- }
- break;
- }
- }
- if(p->pro[i]->back[j]=='#')
- if(!belong_Arr('&',n->first[a]))
- n->first[a][tags[a]++]='&';
- }
- for(i=0; i<n->len; i++)
- if(judge[i]!=tags[i]) {
- loop=1;
- break;
- }
- }
- printf("The not_terminal symbol's First Set\n");
- for(m=0; m<n->len; m++) {
- printf("First(%c)={",n->N[m]);
- //printf("%d ",tags[i]);
- for(j=0; j<tags[m]; j++)
- printf("%c ",n->first[m][j]);
- printf("}\n");
- }
- printf("\n");
- printf("\n");
- for(i=0; i<p->len; i++) {
- if(p->pro[i]->back[0]=='#') {
- p->string_first[i][0]='&';
- }
- else if(!belong_Arr(p->pro[i]->back[0],n->p_emp))
- if(belong_T(p->pro[i]->back[0],t)) {
- for(j=0; j<t->len; j++)
- if(p->pro[i]->back[0]==t->T[j])
- break;
- join_arr(p->string_first[i],t->first[j]);
- } else {
- for(j=0; j<n->len; j++)
- if(p->pro[i]->back[0]==n->N[j])
- break;
- join_arr(p->string_first[i],n->first[j]);
- }
- else {
- j=0;
- while(p->pro[i]->back[j]!='#') {
- if(belong_Arr(p->pro[i]->back[j],n->p_emp)) {
- for(k=0; k<n->len; k++)
- if(n->N[k]==p->pro[i]->back[j])
- break;
- temp=join_arr(p->string_first[i],n->first[k]);
- } else {
- for(k=0; k<n->len; k++)
- if(n->N[k]==p->pro[i]->back[j])
- break;
- temp=join_arr(p->string_first[i],n->first[k]);
- break;
- }
- j++;
- }
- if(p->pro[i]->back[j]=='#')
- p->string_first[i][temp]='&';
- }
- }
- printf("-----------------------------------------\n");
- printf("The First Set of the right of produce\n");
- for(i=0; i<p->len; i++) {
- printf("First(");
- j=0;
- if(p->pro[i]->back[0]=='#')
- printf("&");
- else
- while(p->pro[i]->back[j]!='#') {
- printf("%c",p->pro[i]->back[j]);
- j++;
- }
- printf(")={");
- j=0;
- while(p->string_first[i][j]!='\0') {
- printf("%c ",p->string_first[i][j]);
- j++;
- }
- printf("}\n");
- }
- printf("\n\n");
- return ;
- }
- void get_follow_set(Prod p,NTer n,Ter t,char s_syb)
- {
- int i,j,k,len,m,x,loop;
- int tags[n->len];
- int flags[n->len];
- for(i=0; i<n->len; i++) {
- tags[i]=0;
- flags[i]=0;
- }
- printf("=====================================================\n");
- printf("start finding follow set\n");
- for(i=0; i<n->len; i++)
- if(s_syb==n->N[i]) {
- n->follow[i][0]='#';
- tags[i]++;
- break;
- }
- loop=1;
- while(loop==1) {
- loop=0;
- for(i=0; i<n->len; i++)
- flags[i]=tags[i];
- for(i=0; i<p->len; i++) {
- j=0;
- while(p->pro[i]->back[j]!='#') {
- if(belong_N(p->pro[i]->back[j],n)) {
- for(k=0; k<n->len; k++)
- if(n->N[k]==p->pro[i]->back[j])
- break;
- if(p->pro[i]->back[j+1]!='#') {
- if(belong_N(p->pro[i]->back[j+1],n)) {
- for(m=0; m<n->len; m++)
- if(n->N[m]==p->pro[i]->back[j+1])
- break;
- tags[k]=join_arr(n->follow[k],n->first[m]);
- if(belong_Arr(n->N[m],n->p_emp)) {
- for(x=0; x<n->len; x++)
- if(n->N[x]==p->pro[i]->front)
- break;
- tags[k]=join_arr(n->follow[k],n->follow[x]);
- }
- } else if(belong_T(p->pro[i]->back[j+1],t)) {
- if(!belong_Arr(p->pro[i]->back[j+1],n->follow[k])) {
- len=strlen(n->follow[k]);
- n->follow[k][len]=p->pro[i]->back[j+1];
- tags[k]++;
- }
- }
- }
- else {
- for(x=0; x<n->len; x++)
- if(n->N[x]==p->pro[i]->front)
- break;
- tags[k]=join_arr(n->follow[k],n->follow[x]);
- }
- }
- j++;
- }
- }
- for(i=0; i<n->len; i++)
- if(flags[i]!=tags[i]) {
- loop=1;
- break;
- }
- }
- printf("The not terminal symbols follow sets are:\n");
- for(i=0; i<n->len; i++) {
- j=0;
- printf("Follow(%c)={",n->N[i]);
- while(n->follow[i][j]!='\0') {
- printf("%c ",n->follow[i][j]);
- j++;
- }
- printf("}\n");
- }
- }
- void get_select_set(Prod p, NTer n, Ter t) {
- int i, j, k;
- int flag = 0;
- for (i = 0; i < p->len; i++) {
- if (p->pro[i]->back[0] == '#') {
- for (k = 0; k < n->len; k++)
- if (n->N[k] == p->pro[i]->front)
- break;
- join_arr(p->select[i], n->follow[k]);
- continue;
- }
- j = 0;
- flag = 0;
- while (p->pro[i]->back[j] != '#') {
- if (!belong_Arr(p->pro[i]->back[j], n->p_emp)) {
- //flag=1;
- break;
- }
- j++;
- }
- if (p->pro[i]->back[j] == '#') {
- flag = 1;
- }
- if (flag == 0) {
- join_arr(p->select[i], p->string_first[i]);
- } else if (flag == 1) {
- join_arr(p->select[i], p->string_first[i]);
- for (k = 0; k < n->len; k++)
- if (n->N[k] == p->pro[i]->front)
- break;
- join_arr(p->select[i], n->follow[k]);
- }
- }
- printf("=============================================\n");
- printf("\nThe select set:\n");
- for (i = 0; i < p->len; i++) {
- printf("select(%c->", p->pro[i]->front);
- j = 0;
- while (p->pro[i]->back[j] != '#') {
- printf("%c", p->pro[i]->back[j]);
- j++;
- }
- printf(")={");
- j = 0;
- while (p->select[i][j] != '\0') {
- printf("%c ", p->select[i][j]);
- j++;
- }
- printf("}\n");
- }
- printf("=============================================\n");
- }
- int isLL1(Prod p)
- {
- int i=0;
- int j;
- for(i=0;i<p->len-1;i++)
- for(j=i+1;j<p->len;j++){
- if(p->pro[i]->front==p->pro[j]->front)
- if(strcmp(p->select[i],p->select[j])==0){
- printf("\nThis is not LL1\n");
- return 0;
- }
- }
- printf("\nThis is LL1\n");
- printf("\n===========================================\n");
- printf("\n===========================================\n");
- return 1;
- }
- int main()
- {
- int i=0,j=0;
- char temp;
- char tem[100];
- //char pro_e[length],npro_e[length];//the symbol can can't produce empty
- G g=(G)malloc(sizeof(grame));
- g->t_symbol=(Ter)malloc(sizeof(ter));
- g->n_symbol=(NTer)malloc(sizeof(nter));
- g->produce=(Prod)malloc(sizeof(prodx));
- //get not-terminal symbol
- printf("Enter not-terminal\n");
- while(1) {
- scanf("%c",&temp);
- if(temp=='$') {
- g->n_symbol->len=i;
- i=0;
- break;
- }
- g->n_symbol->N[i++]=temp;
- }
- //get terminal symbol
- getchar();
- printf("Enter terminal\n");
- while(1) {
- scanf("%c",&temp);
- if(temp=='$') {
- g->t_symbol->len=i;
- i=0;
- break;
- }
- g->t_symbol->T[i++]=temp;
- }
- //get start symbol-------->S
- printf("Enter the start symbol(end pressing Enter)\n");
- getchar();
- scanf("%c",&temp);
- g->start_symbol=temp;
- //get produce
- j=0;
- printf("Enter Produce\n");
- while(1) {
- scanf("%s",tem);
- if(tem[0]=='$') {
- g->produce->len=j;
- j=0;
- break;
- }
- g->produce->pro[j]=(Pro)malloc(sizeof(prox));
- g->produce->pro[j]->front=tem[0];
- for(i=3; i<sizeof(tem); i++) {
- g->produce->pro[j]->back[i-3]=tem[i];
- }
- j++;
- }
- //printf("%s\n",g->produce->pro[0]->back);
- find_null(g->produce,g->n_symbol,g->t_symbol);
- get_first_set(g->produce,g->n_symbol,g->t_symbol);
- get_follow_set(g->produce,g->n_symbol,g->t_symbol,g->start_symbol);
- get_select_set(g->produce,g->n_symbol,g->t_symbol);
- isLL1(g->produce);
- return 0;
- }
这段代码呢,里面写了点注释,如果各位高手们看到我写的代码的不足之处,请之处,谢谢……
对了,这里附上两个测试用例:
1:EeTtF$ +*()i$ E E->Te# e->+Te# e-># T->Ft# t->*Ft# t-># F->i# F->(E)# $
2 : SACB$ ab$ S S->Ab# S->Ba# A->aC# C->A# C-># B->a# $
如果在Linux环境下的话,我们可以用管道命令来简化输入,把上面的两个例子分别放在两个文件两面,如果命名为test,则在终端输入:cat test|./compile
声明:此程序,我是在gcc编译环境下编译的,在windows中用VC的话运行好像是有错的,可以试试用Dev
阅读(7688) | 评论(1) | 转发(0) |