【编译原理】【C#】简易Chomsky文法类型判别器

一、设计要求

使用任一种编程语言实现对非文法、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型文法判断
在这里插入图片描述
⑤ 非文法判断
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、资源下载

项目源码及exe文件

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C#编译原理 目 录 译者序 前言 第1章 概论 1 1.1 为什么要用编译 2 1.2 与编译相关的程序 3 1.3 翻译步骤 5 1.4 编译中的主要数据结构 8 1.5 编译结构中的其他问题 10 1.6 自举与移植 12 1.7 TINY样本语言与编译 14 1.7.1 TINY语言 15 1.7.2 TINY编译 15 1.7.3 TM机 17 1.8 C-Minus:编译项目的一种语言 18 练习 19 注意与参考 20 第2章 词法分析 21 2.1 扫描处理 21 2.2 正则表达式 23 2.2.1 正则表达式的定义 23 2.2.2 正则表达式的扩展 27 2.2.3 程序设计语言记号的正则表达式 29 2.3 有穷自动机 32 2.3.1 确定性有穷自动机的定义 32 2.3.2 先行、回溯和非确定性自动机 36 2.3.3 用代码实现有穷自动机 41 2.4 从正则表达式到DFA 45 2.4.1 从正则表达式到NFA 45 2.4.2 从NFA到DFA 48 2.4.3 利用子集构造模拟NFA 50 2.4.4 将DFA中的状态数最小化 51 2.5 TINY扫描程序的实现 52 2.5.1 为样本语言TINY实现一个扫描 程序 53 2.5.2 保留字与标识符 56 2.5.3 为标识符分配空间 57 2.6 利用Lex 自动生成扫描程序 57 2.6.1 正则表达式的Lex 约定 58 2.6.2 Lex输入文件的格式 59 2.6.3 使用Lex的TINY扫描程序 64 练习 65 编程练习 67 注意与参考 67 第3章 上下文无关文法及分析 69 3.1 分析过程 69 3.2 上下文无关文法 70 3.2.1 与正则表达式比较 70 3.2.2 上下文无关文法规则的说明 71 3.2.3 推导及由文法定义的语言 72 3.3 分析树与抽象语法树 77 3.3.1 分析树 77 3.3.2 抽象语法树 79 3.4 二义性 83 3.4.1 二义性文法 83 3.4.2 优先权和结合性 85 3.4.3 悬挂else问题 87 3.4.4 无关紧要的二义性 89 3.5 扩展的表示法:EBNF和语法图 89 3.5.1 EBNF表示法 89 3.5.2 语法图 91 3.6 上下文无关语言的形式特性 93 3.6.1 上下文无关语言的形式定义 93 3.6.2 文法规则和等式 94 3.6.3 乔姆斯基层次和作为上下文无关 规则的语法局限 95 3.7 TINY语言的语法 97 3.7.1 TINY的上下文无关文法 97 3.7.2 TINY编译的语法树结构 98 练习 101 注意与参考 104 第4章 自顶向下的分析 105 4.1 使用递归下降分析算法进行自顶向下 的分析 105 4.1.1 递归下降分析的基本方法 105 4.1.2 重复和选择:使用EBNF 107 4.1.3 其他决定问题 112 4.2 LL(1)分析 113 4.2.1 LL(1)分析的基本方法 113 4.2.2 LL(1)分析与算法 114 4.2.3 消除左递归和提取左因子 117 4.2.4 在LL(1)分析中构造语法树 124 4.3 First集合和Follow集合 125 4.3.1 First 集合 125 4.3.2 Follow 集合 130 4.3.3 构造LL(1)分析表 134 4.3.4 再向前:LL(k)分析程序 135 4.4 TINY语言的递归下降分析程序 136 4.5 自顶向下分析程序中的错误校正 137 4.5.1 在递归下降分析程序中的错误 校正 138 4.5.2 在LL(1)分析程序中的错误校正 140 4.5.3 在TINY分析程序中的错误校正 141 练习 143 编程练习 146 注意与参考 148 第5章 自底向上的分析 150 5.1 自底向上分析概览 151 5.2 LR(0)项的有穷自动机与LR(0)分析 153 5.2.1 LR(0)项 153 5.2.2 项目的有穷自动机 154 5.2.3 LR(0)分析算法 157 5.3 SLR(1)分析 160 5.3.1 SLR(1)分析算法 160 5.3.2 用于分析冲突的消除二义性 规则 163 5.3.3 SLR(1)分析
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jeron Zhou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值