一、设计要求
使用任一种编程语言实现对非文法、0型文法、1型文法、2型文法、3型文法这四种文法类别进行分类。程序的输入为一行文法,非终结符有英文大写字母构成,终结符包含{小写字母、数字、基本运算符、左右括弧},文法的书写格式形如 “A::=aB”、“aB::=cDaa”。
二、算法原理
Chomsky按产生式的类型把文法分为0、1、2、3型文法四种类型。
【0型文法】
产生式形式:α→β,箭头左边的α至少含有一个非终结符,其余不加任何限制。此时文法即满足0型文法。
【1型文法】
产生式形式:α→β,在0型文法的基础上,要求|α|≤|β|,即产生式左端的长度小于等于右端的长度(S→ε除外),此时文法即满足1型文法。
【2型文法】
产生式形式:A→β,在1型文法的基础上,A∈VN,β∈V *(VN∪VT),此时文法即满足2型文法。
【3型文法】
产生式形式:A→a,A→aB。在2型文法的基础上,a∈VT,A,B∈VN,即产生式右边的第一个符号必须为终结符,此时文法即满足3型文法。
【非文法】
不满足0型文法的表达式。
【文法类型判断流程】
文法类型判断流程通常从要求最严格的3型文法开始判断,之后逐级递减,进而判断出每句文法的类型。
首先判断3型文法,要求满足左边只有一个字符且为非终结符,右边最多只能有两个字符。当右边有两个字符时,必须一个为终结符,一个为非终结符;当右边只有一个字符时,此字符必须为终结符。并且,所有右边为两个字符的产生式,终结符和非终结符位置为终结符+非终结符或者非终结符+终结符,且一个文法中终结符和非终结符位置必须相同。如果满足即为3型文法。
如果不满足3型文法,则需要进行2型文法的判断。要求满足左边只有一个字符且为非终结符,并且所有产生式的右边可以含有有限个终结符和非终结符,但终结符和非终结符的数量没有限制。如果满足即为2型文法。2型文法的特点是在1型文法的基础上,左边只有一个非终结符。
如果不满足2型文法,则需要进行1型文法的判断。要求所有产生式左边至少有一个非终结符,并且所有产生式的右边可以含有有限个终结符和非终结符,但终结符和非终结符的数量没有限制,如果满足即为1型文法。1型文法的特点是右边字符个数不小于左边字符个数。
如果不满足1型文法,则需要进行0型文法的判断。0型文法的特点是满足左边有非终结符即可。若不满足0型文法,则为非文法。
【流程图】
三、源代码
【窗体设计】
用户可在文本框内输入形如“A::=aB”、“aB::=cDaa”的一行文法,之后点击“识别”按钮,即可显示出文法的类型。点击“退出”即可退出程序。程序源代码如下:
Program.cs:
using System;
using System.Windows.Forms;
namespace Grammar_type_discriminator
{
internal sealed class Program
{
[STAThread]
private static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
MainForm.cs:
/*
* 作者:JeronZhou
* 时间:2022-04-17
* 名称:文法类型判别器
* 功能:程序的输入为一行文法,点击识别按钮后即可实现对非文法、0型文法、1型文法、2型文法、3型文法这四种文法类别进行分类,
* 非终结符由英文大写字母构成,终结符包含小写字母、数字、基本运算符和左右括弧,文法的书写格式形如 “A::=aB”、“aB::=cDaa”
*/
using System;
using System.Windows.Forms;
/*文法类型判别器*/
namespace Grammar_type_discriminator
{
public class Gram //文法类
{
public int left_length; //文法左边长度
public int right_length; //文法右边长度
public string s; //文法对应的字符串
public Gram(string ss) //构造函数
{
this.s = ss;
}
public int Judge() //判断文法类型
{
int r=-1,i,len;
int enabled=0,flag,flag1,flag2,flagl,flagr;
flag=flag1=flag2=flagl=flagr=1;
char[] Vn = new char[100]; //非终结字符集
char[] Vt = new char[100]; //终结字符集
left_length = 0;
right_length = 0;
len = s.Length;
for(i=0;i<len;i++) //判断文法格式是否正确
{
if(s[i]==':' && s[i+1]==':' && s[i+2]=='=')
{
enabled = 1;
break;
}
}
for(i=0;i<len;i++)
{
if(s[i]!=':')
{
left_length++;
}
else
{
break;
}
}
right_length = len-left_length-3;
int t=0;
for(i=0;i<left_length;i++) //判断左边是否有非终结符
{
if(s[i]>='A' && s[i]<='Z')
{
t=1;
break;
}
}
if(enabled==1 && left_length<=right_length && t==1) //非0型文法情况
{
flag=0;
}
else if(enabled==1 && len>=5 && t==1) //0型文法情况
{
r=0;
}
if(flag==0) //非0型文法情况
{
if(left_length==1 && (s[0]>='A' && s[0]<='Z')) //非0型、1型文法情况
{
flag1=0;
}
else if(left_length>=1 && right_length>=1) //1型文法的情况
{
r=1;
}
}
if(flag1==0) //非0型、1型文法情况
{
if(left_length==1 && len==5 && (s[0]>='A' && s[0]<='Z') && ((s[4]>='a' && s[4]<='z') || (s[4]>='0' && s[4]<='9') || s[4]=='+' || s[4]=='-' || s[4]=='*' || s[4]=='/' || s[4]=='%' || s[4]=='(' || s[4]==')' || s[4]=='[' || s[4]==']' || s[4]=='{' || s[4]=='}')) //非0型、1型、2型文法情况,即3型文法情况
{
flag2=0;
}
else if(left_length==1 && len==6 && (s[0]>='A' && s[0]<='Z') && ((s[4]>='a' && s[4]<='z') || (s[4]>='0' && s[4]<='9') || s[4]=='+' || s[4]=='-' || s[4]=='*' || s[4]=='/' || s[4]=='%' || s[4]=='(' || s[4]==')' || s[4]=='[' || s[4]==']' || s[4]=='{' || s[4]=='}') && (s[5]>='A' && s[5]<='Z'))
{
flag2=0;
}
else if(left_length==1 && len==6 && (s[0]>='A' && s[0]<='Z') && ((s[5]>='a' && s[5]<='z') || (s[5]>='0' && s[5]<='9') || s[5]=='+' || s[5]=='-' || s[5]=='*' || s[5]=='/' || s[5]=='%' || s[5]=='(' || s[5]==')' || s[5]=='[' || s[5]==']' || s[5]=='{' || s[5]=='}') && (s[4]>='A' && s[4]<='Z'))
{
flag2=0;
}
else //2型文法情况
{
r=2;
}
}
if(flag2==0) //3型文法判断
{
r=3;
}
return r;
}
}
public partial class MainForm : Form //主窗口
{
public MainForm()
{
InitializeComponent();
}
void DiscriminatorClick(object sender, EventArgs e)
{
string grammer = textBox.Text;
Gram g = new Gram(grammer);
int r = g.Judge();
switch(r)
{
case 0:
result.Text = "0型文法"; break;
case 1:
result.Text = "1型文法"; break;
case 2:
result.Text = "2型文法"; break;
case 3:
result.Text = "3型文法"; break;
case -1:
result.Text = "非文法"; break;
}
}
void ExitClick(object sender, EventArgs e)
{
this.Close();
}
}
}
四、测试运行
① 3型文法判断
② 2型文法判断
① 1型文法判断
④ 0型文法判断
⑤ 非文法判断