赞
踩
1、设计一个表示文法的数据结构;
2、从文本文件中读入文法,利用定义的数据结构存放文法,并输出;
文法定义的4个部分:
G( Vn, Vt, S, P)
Vn文法的非终结符号集合,在实验中用大写的英文字母表示;
Vt文法的终结符号集合,在实验中用小写的英文字母表示;
s开始符号,在实验中是Vn集合中的一个元素;
产生式,分左部和右部,左部为非终结符号中的一个,右部为终结符号或非终结符号组成的字符串,如S->ab|c
输入数据举例:
编辑一个文本文件 text.txt,在文件中输入如下内容:
- S->Qc;
- S->c;
- Q->Rb;
- Q->b;
- R->Sa;
- R->a;
上述文法整理后的输出形式:
- S->Qc|c
- Q->Rb|b
- R->Sa|a
- 终结符:c b a
- #include <stdio.h>
- #include <string.h>
- #define N 50 // 符号的最大数目
- #define char_len 5 // 符号的最大长度+1
- #define symbol_len 21 // 产生式符号的最大长度+1
-
-
-
- typedef struct non_terminal *Nonterminal;
- struct non_terminal { // 非终结符结构体
- char name[char_len]; // 字符
- char production[N][symbol_len]; // 产生式们
- };
-
-
- typedef struct data *grammar;
- struct data{ // 文法结构体
- // 因为看长度都是找到指向为空的指针说明结束,所以要初始化
- // 第一个就是开始符,没有溢出警告,N可以设大点,留点盈余
- Nonterminal Vn[N]; // 非终结符包含产生式
- // 终结符里没有空,所有空用@代替
- char Vt[N]; // 终结符,假定都是一个字
- };
-
- // 生成一个初始化后的文法框架
- grammar new_grammar()
- {
- int i;
- grammar x = (grammar)malloc(sizeof(struct data)); // 文法框架
- for(i=0;i<N;i++)
- {
- x->Vt[i]='\0';
- x->Vn[i]=NULL;
- }
- return x;
- }
-
-
- // 读入文法函数,一行一行读文件,生成文法
- void Generative_grammar(char* str,grammar my_grammar)
- {
- int t=0,i=0,j=0,k=0;
- char front[char_len],behind[symbol_len]; //产生式的前端和后端
- while(1)
- {
- if(str[i]=='\0'||str[i]=='\n'||str[i]==';') // 读到字符串结尾就结束
- {
- if(t) // 正确录入了前后端
- {
- behind[j] = '\0'; // 先来个结束符
- for(i=0;i<N;i++) // 后面用不到i了,在这做个遍历标记
- {
- if(my_grammar->Vn[i]==NULL) // 没找到,就建一个
- {
- my_grammar->Vn[i]=(Nonterminal)malloc(sizeof(struct non_terminal));
- for(j=0;j<char_len;j++)
- {
- my_grammar->Vn[i]->name[j] = front[j];
- if(front[j]=='\0')
- break;
- }
- for(j=0;j<N;j++) // 初始化产生式
- {
- my_grammar->Vn[i]->production[j][0]='\0';
- }
- break;
- }
- if(strcmp(my_grammar->Vn[i]->name,front)==0) //找到首部位置
- {
- break;
- }
- }
- // 到这里i就指向了需要更改的位置了,给他添加产生式
- for(j=0;j<N;j++) // 找一个空的位置
- {
- if(my_grammar->Vn[i]->production[j][0]=='\0')
- {
- t=0;
- for(k=0;k<symbol_len;k++)
- {
- if(behind[k]=='|')
- {
- my_grammar->Vn[i]->production[j][k-t] = '\0';
- j++;
- t=k+1;
- continue;
- }
- my_grammar->Vn[i]->production[j][k-t] = behind[k];
- if(behind[k]=='\0')
- break;
- }
- break;
- }
- }
- }
- break;
- }
- if(str[i]=='-'&&str[i+1]=='>') // 前端后端分界点
- {
- t=1; // 前后端标志更改,
- front[j] = '\0'; // 来个结束符
- j=0; // 计数器归零
- i+=2; // 跳过这两个
- continue;
- }
- if(t) // 当前在后端
- {
- behind[j]=str[i]; // 记录当前符号
- j++; // 位置标记右移
- }
- else // 当前在前端
- {
- front[j]=str[i]; // 记录当前符号
- j++; // 位置标记右移
- }
- i++;
- }
- }
-
- // 给出文法,提取出终结符
- void get_Vt(grammar my_grammar)
- {
- int i,j,k,ii,jj,kk,t,maxjj;
- for(i=0;i<N;i++) // i第一层遍历非终结符
- {
- if(my_grammar->Vn[i]==NULL)
- break;
- for(j=0;j<N;j++) // j第一层遍历产生式
- {
- if(my_grammar->Vn[i]->production[j][0]=='\0')
- break;
- else // 遍历每一个产生式,找出终结符存到Vt
- {
- for(k=0;k<symbol_len;k++) // 遍历该产生式
- {
- if(my_grammar->Vn[i]->production[j][k]=='\0')
- break;
- maxjj = 0;//最长的非终结符
- for(ii=0;ii<N;ii++) // 在所有非终结符中找有没有它
- {
- if(my_grammar->Vn[ii]==NULL)
- break;
- else
- {
- if(my_grammar->Vn[ii]->name[0]==my_grammar->Vn[i]->production[j][k])
- {
- t=1;
- for(jj=1;jj<char_len;jj++)
- {
- if(my_grammar->Vn[ii]->name[jj]=='\0')
- break;//到头了
- if(my_grammar->Vn[ii]->name[jj]!=my_grammar->Vn[i]->production[j][k+jj])
- {
- t=0;//这个不是
- break;
- }
- }
- if(t&&maxjj<jj) // 找到了,且比之前长
- {
- maxjj=jj;
- }
- }
- }
- }
- for(kk=0;kk<N;kk++) // 看看非终结符集有没有
- {
- t=0;
- if(my_grammar->Vt[kk]=='\0')
- break;
- if(my_grammar->Vt[kk]==my_grammar->Vn[i]->production[j][k])
- {
- t=1;//找到了
- break;
- }
-
- }
- if(t)
- continue;
- if(maxjj==0) //走到这里,最大jj是0时,终结符和非终结符都没有
- {
- my_grammar->Vt[kk]=my_grammar->Vn[i]->production[j][k];
- }
- else
- {
- k=k+maxjj-1;
- }
- }
- }
- }
- }
- }
- // 文法的输出函数
- void Output_grammar(grammar my_grammar)
- {
- int i,j;
- for(i=0;i<N;i++)
- {
- if(my_grammar->Vn[i]==NULL)
- break;
- printf("%s->",my_grammar->Vn[i]->name);
- for(j=0;j<N;j++)
- {
- if(my_grammar->Vn[i]->production[j][0]=='\0')
- break;
- if(j!=0)
- printf("|");
- printf("%s",my_grammar->Vn[i]->production[j]);
-
- }
- printf("\n");
- }
- printf("终结符:");
- for(i=0;i<N;i++)
- {
- if(my_grammar->Vt[i]=='\0')
- break;
- printf("%c ",my_grammar->Vt[i]);
- }
- }
-
- int main()
- {
- FILE *p=fopen("text.txt","r"); //只读打开文件
- if(p==NULL) // 没有文件提示
- {
- printf("缺少文件“text.txt”");
- exit(0);
- }
- char str[N];
- grammar my_grammar = new_grammar();
-
- while(fgets(str, N, p) != NULL) // 一行一行读取
- {
- Generative_grammar(str,my_grammar);
- }
- fclose(p); // 关闭文件
- get_Vt(my_grammar);
- Output_grammar(my_grammar);
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
同样支持这样的输入:
- S->Qc|c|cc|da|Q1
- Q->Rb|b|V
- R->Sa|a|cV2
- Q1->aa|bd
- V2->d|Q2
- Q2->a
- V->V2|e
结果:
- S->Qc|c|cc|da|Q1
- Q->Rb|b|V
- R->Sa|a|cV2
- Q1->aa|bd
- V2->d|Q2
- Q2->a
- V->V2|e
- 终结符:c d a b e
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。