Chomsky将文法分红4中类型

文法G 定义为四元组(VN ,VT ,P,S)

VN :非闭幕符集

VT :闭幕符集

P :规矩集合

S :开始符

首先定义一个产生式

α→β

0型文法:

α∈(VN∪VT)* ,且至少含一个VN,β∈(VN∪VT)*

0型文法的能力相当于图灵机(Turing),或者说,任何0型语言都是递归可枚举的;反之,递归可枚举集必定是一个0型语言

1型文法(上下文有关文法context-sensitive):

对任一产生式α→β,都有|β|>=|α|,仅仅 S→ε除外

产生式的形式描述:α1Aα2→α1βα2

(其中,α1、α2、β∈(VN∪VT)*,β≠ε,A∈VN)

即:A只有出现在α1α2的上下文中,才允许用β替换。

产生的语言称“上下文有关语言”

2型文法( 上下文无关文法context-free):

对任一产生式α→β,都有α∈VN,β∈(VN∪VT)*

产生式的形式描述:A→β(A∈VN),即β代替A时,与A所处的上下文无关。

3型文法:正规文法

每一个产生式均为“A→aB”或“A→a”—— 右线性

“A→Ba”或“A→a”—— 左线性

其中,A、B∈VN,a∈VT*

下面用C语言模拟文法类型的判断



#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> char vn[26];//非闭幕符,默认为大写字符 char vt[26];//闭幕符,默认为小写字符 int len1,len2;//非闭幕符和闭幕符的个数 int num;//规矩的数目 int ans;//判断是几型文法 struct guize {  char s1[20];//规矩的左部  char s2[20];//规矩的右部 }guize[100]; int hash[200];//哈希标记非闭幕字符和闭幕字符 void init() {  int i;  len1=strlen(vn);  len2=strlen(vt);  memset(hash,0,sizeof(hash));  for(i=0;i<len1;i++)  hash[vn[i]]=-1;//非闭幕符标记为-1  for(i=0;i<len2;i++)  hash[vt[i]]=1;//闭幕符标记为1 } //判断该文法是不是合法 int judge(char s[20])  {  int len=strlen(s);  int i;  for(i=0;i<len;i++)  {   if(hash[s[i]]==0) //产生式中的字母未在闭幕和非闭幕符号中出现   {    return 0;   }  }  return 1; } //判断该文法是不是是0型文法,即s1中应含有非闭幕符 int judge0(char s[20]) {  int i,len=strlen(s);  for(i=0;i<len;i++)  if(hash[s[i]]==-1)  return 1;  return 0; } //判断是不是为1型文法,即s2的长度大于等于s1的长度 int judge1(char s1[20],char s2[20]) {  int l1,l2;  l1=strlen(s1);  l2=strlen(s2);  return (l2>=l1?1:0); } //判断是不是为2型文法,即s1为非闭幕符 int judge2(char s1[20],char s2[20]) {  if(strlen(s1)==1&&hash[s1[0]]==-1)  return 1;  return 0; } //判断是不是为3型文法,即A->aB||A->a或A->Ba||A->a(A,B∈VN,a∈VT*) int judge3(char s1[20],char s2[20]) {  int i,len,tnum,size;  if(strlen(s1)==1&&hash[s1[0]]==-1) //左部长短闭幕符  {   len=strlen(s2);   //记载非闭幕符的个数和出现的位置         tnum=0;   size=-1;   for(i=0;i<len;i++)   if(hash[s2[i]]==-1)   {    tnum++;    size=i;   }   if(tnum==0)   return 1;//A->a   if(tnum==1&&size==(len-1))   return 2;//A->aB   if(tnum==1&&size==0)   return 3;//A->Ba   return 0;//非3型文法  }     return 0; } int main() {  int i,temp,flag2,flag3;  printf("G=(VN,VT,P,S)\n");  printf("please input VN\n");  scanf("%s",vn);  printf("please input VT\n");  scanf("%s",vt);  init();  printf("please input P\n");  printf("please input the num of the P ");  scanf("%d",&num);  for(i=0;i<num;i++)  scanf("%s -> %s",guize[i].s1,guize[i].s2);     ans=3;  flag2=flag3=0;  for(i=0;i<num;i++)  {   if(!judge(guize[i].s1)||!judge(guize[i].s2))//如果文法合法,直接跳出循环   {       ans=-1;       break;   }   temp=judge3(guize[i].s1,guize[i].s2);//判断是不是为3型文法      if(temp==2)//A->aB   flag2++;   if(temp==3)//A->Ba   flag3++;   if(temp==0||(flag2&&flag3)) //A->aB与A->Ba不能同时出现   {    ans=2;    if(!judge2(guize[i].s1,guize[i].s2))//判断是不是为2型文法    {     ans=1;     if(!judge1(guize[i].s1,guize[i].s2))//判断是不是为1型文法     {         ans=0;      if(!judge0(guize[i].s1))      {       ans=-1;       break;      }     }    }   }  }  switch(ans)  {          case -1:printf("该文法合法\n");break;    case 0:printf("该文法为0型文法\n");break;    case 1:printf("该文法为1型文法\n");break;    case 2:printf("该文法为2型文法\n");break;    case 3:printf("该文法为3型文法\n");break;  }  return 0; }

型文法文法文法的类型_#include