根据文法规则,判断文法类型

2023-05-16

根据文法规则,判断文法类型

1、实验要求

输入:文法规则

输出:文法类型

2、实验原理

文法规则:
以四元组的形式展示出来:
文法G 定义为四元组G={Vn,Vt ,P,S}
Vn :非终结符集
Vt :终结符集
P :产生式集合(规则集合)
S :开始符号(识别符号)

文法类型:
文法类型分为四种:0型文法、1型文法、2型文法和3型文法

  • 0型文法:通俗的说,写出来的文法规则都输出0型文法
  • 1型文法:又称上下文有关文法。
    满足条件:0型文法的基础上,右边字符个数不小于左边字符个数
    例如:S->aBC
    a->Bb
    C->c
  • 2型文法:又称上下文无关文法。
    满足条件:在1型文法的基础上,左部只有一个非终结符
    例如:S->aBC
    B->b
    C->c
  • 3型文法:又称规范文法。
    满足条件:在2型文法的基础上,产生式的右边字符数不超过2个且所有产生式要么都是左递归,要么都是右递归
    例如:S->aB
    B->bC
    C->c
    注:
    S->aB
    B->Cb
    C->c
    不成立,因为字符串既有左递归,又有右递归

四种文法的关系可用如下图表示:
在这里插入图片描述

3、实验步骤

  1. 从键盘上输入文法规则(字符串)
  2. 对字符串进行按行比较,判断其所属的文法类型(先逐行判断文法类型1,然后再逐行判断文法类型2,最后在整个字符串判断文法类型3)
  3. 显示出结果(文法类型)

4、实验过程

  1. 首先是进行结构体的构建,并且为了方便实用定义了全局变量
//结构体 
struct Rule{
	char str[10];
	int k;//记录局部文法类型 
	int left;//记录产生式左边长度 
	int right;//记录产生式右边长度 
}r[10];

int temp;//记录字符串行数 
int level=0;//记录文法类型 

  1. 主函数运到了5个调用函数,分别是输入板块、文法类型1判断板块、文法类型2判断板块、文法类型3判断板块和输出板块
//主函数 
int main(){
	Input();//输入文法规则 
	Transform1();//类型1判断 
	Transform2();//文法类型2判断 
	Transform3();//文法类型3判断 
    Output();//输出文法类型 
	return 0;
} 
  1. 在输入板块进行了文法规则的输入,一字符串的形式从键盘输入,存储到结构体中
//输入文法规则 
void Input(){
	int i,j;
	printf("输入文法规则:\n");
	printf("大写字母为非终止符,小写字母为终止符,第一个产生式左边为开始符,结束用$表示\n");
	for(i=0;i<10;i++){
		scanf("%s",r[i].str);
		j=0;
		if(r[i].str[j]=='$')
		break;
	}
	temp=i; 
}
  1. 文法类型1板块时进行判断文法规则的类型是否符合类型1,符合之后才能进行类型2的判断
//判断文法类型1
void Transform1(){
	int i,j;
	int length;
	for(i=0;i<temp;i++){
		r[i].k=0;
		length=strlen(r[i].str);//字符串长度 
		r[i].left=0;
		for(j=0;r[i].str[j]!='-';j++)//左边长度 
		r[i].left++;
		r[i].right=length-r[i].left-2;//右边长度,减2表示减去字符'-'和'>' 
		if(r[i].right>=r[i].left)
		r[i].k=1;
	}
}
  1. 文法类型2板块时进行判断文法规则的类型是否符合类型2,符合之后才能进行类型3的判断
//判断文法类型2
void Transform2(){
	int i,j,ss=0;
	for(i=0;i<temp;i++){//判断是否字符串是否都为类型1 
		if(r[i].k!=1)
		ss=1;
	}
	if(ss==0)//字符串都为类型1,进行类型2的判断 
	for(i=0;i<temp;i++){
		j=0;
	    if(r[i].left==1)//左边只有一个且是非终结符的类型1,则为类型2 
	    if(r[i].str[j]>='A'&&r[i].str[j]<='Z')
	    r[i].k=2;
	}
	level=1;	
}
  1. 文法类型3板块时进行判断文法规则的类型是否符合类型3
//判断文法类型3
void Transform3(){
	int i,j,t,m,n=0,sum=0,ss=0;
	for(i=0;i<temp;i++){//判断是否字符串是否都为类型2 
		if(r[i].k!=2)
		ss=1; 
	} 
	if(ss==0){//字符串都为类型2,进行类型3的判断 
		level=2;
    	for(i=0;i<temp;i++){
	    	m=r[i].left+2;//产生式右边第一个字符 
     	    if(r[i].str[m]>='a'&&r[i].str[m]<='z')
	    	t=1;
	    	if(r[i].str[m]>='A'&&r[i].str[m]<='Z')
	    	t=0;
	    	sum+=t;
	    	if(r[i].right>2)
	    	n=1;
    	}
     	if(n==0)//保证产生式右边不超过2个字符 
    	if(sum==temp|sum==0)//保证产生式右边是左递归或右递归 
    	level=3;
    }
}

7.在输出板块需要注意的是,不仅要将文法的类型输出,小编也将该四元组进行显示出来

//输出文法类型
void Output(){
	int i,j,m=0,n=0;
	int t,p,ss;
	char S,V1[100],V2[100],Vn[10]={},Vt[10]={};
	S=r[0].str[0];//开始符 
	for(i=0;i<temp;i++){
		for(j=0;j<strlen(r[i].str);j++){
			if(r[i].str[j]>='a'&&r[i].str[j]<='z')
			V1[m++]=r[i].str[j];
			if(r[i].str[j]>='A'&&r[i].str[j]<='Z')
			V2[n++]=r[i].str[j]; 
		}
	}
	t=0;
	for(i=0;i<m;i++){//终止符 
		ss=1;
		for(j=0;j<t;j++){
     		if(V1[i]==Vt[j])
	    	ss=0;
	    }
	    if(ss==1)
	    Vt[t++]=V1[i];
	}
	p=0;
	for(i=0;i<n;i++){//非终止符 
		ss=1;
		for(j=0;j<p;j++){
     		if(V2[i]==Vn[j])
	    	ss=0;
	    }
	    if(ss==1)
	    Vn[p++]=V2[i];
	}
	printf("该文法为第%d类型\n",level);//输出 
	printf("该文法的四元组为:\n");
	printf("S:%c\n",S); 
	printf("Vn=");
	for(i=0;i<p;i++)
	printf("%2c",Vn[i]);
	printf("\nVt=");
	for(i=0;i<t;i++)
	printf("%2c",Vt[i]);
	printf("\nP:\n");
	for(i=0;i<temp;i++)
	printf("%s\n",r[i].str);	
} 

5、源代码和截图

代码已经过调试,无编译错误

#include<stdio.h>
#include<string.h>

//结构体 
struct Rule{
	char str[10];
	int k;//记录局部文法类型 
	int left;//记录产生式左边长度 
	int right;//记录产生式右边长度 
}r[10];

int temp;//记录字符串行数 
int level=0;//记录文法类型 

//输入文法规则 
void Input(){
	int i,j;
	printf("输入文法规则:\n");
	printf("大写字母为非终止符,小写字母为终止符,第一个产生式左边为开始符,结束用$表示\n");
	for(i=0;i<10;i++){
		scanf("%s",r[i].str);
		j=0;
		if(r[i].str[j]=='$')
		break;
	}
	temp=i; 
}

//输出文法类型
void Output(){
	int i,j,m=0,n=0;
	int t,p,ss;
	char S,V1[100],V2[100],Vn[10]={},Vt[10]={};
	S=r[0].str[0];//开始符 
	for(i=0;i<temp;i++){
		for(j=0;j<strlen(r[i].str);j++){
			if(r[i].str[j]>='a'&&r[i].str[j]<='z')
			V1[m++]=r[i].str[j];
			if(r[i].str[j]>='A'&&r[i].str[j]<='Z')
			V2[n++]=r[i].str[j]; 
		}
	}
	t=0;
	for(i=0;i<m;i++){//终止符 
		ss=1;
		for(j=0;j<t;j++){
     		if(V1[i]==Vt[j])
	    	ss=0;
	    }
	    if(ss==1)
	    Vt[t++]=V1[i];
	}
	p=0;
	for(i=0;i<n;i++){//非终止符 
		ss=1;
		for(j=0;j<p;j++){
     		if(V2[i]==Vn[j])
	    	ss=0;
	    }
	    if(ss==1)
	    Vn[p++]=V2[i];
	}
	printf("该文法为第%d类型\n",level);//输出 
	printf("该文法的四元组为:\n");
	printf("S:%c\n",S); 
	printf("Vn=");
	for(i=0;i<p;i++)
	printf("%2c",Vn[i]);
	printf("\nVt=");
	for(i=0;i<t;i++)
	printf("%2c",Vt[i]);
	printf("\nP:\n");
	for(i=0;i<temp;i++)
	printf("%s\n",r[i].str);	
} 

//判断文法类型3
void Transform3(){
	int i,j,t,m,n=0,sum=0,ss=0;
	for(i=0;i<temp;i++){//判断是否字符串是否都为类型2 
		if(r[i].k!=2)
		ss=1; 
	} 
	if(ss==0){//字符串都为类型2,进行类型3的判断 
		level=2;
    	for(i=0;i<temp;i++){
	    	m=r[i].left+2;//产生式右边第一个字符 
     	    if(r[i].str[m]>='a'&&r[i].str[m]<='z')
	    	t=1;
	    	if(r[i].str[m]>='A'&&r[i].str[m]<='Z')
	    	t=0;
	    	sum+=t;
	    	if(r[i].right>2)
	    	n=1;
    	}
     	if(n==0)//保证产生式右边不超过2个字符 
    	if(sum==temp|sum==0)//保证产生式右边是左递归或右递归 
    	level=3;
    }
} 

//判断文法类型2
void Transform2(){
	int i,j,ss=0;
	for(i=0;i<temp;i++){//判断是否字符串是否都为类型1 
		if(r[i].k!=1)
		ss=1;
	}
	if(ss==0)//字符串都为类型1,进行类型2的判断 
	for(i=0;i<temp;i++){
		j=0;
	    if(r[i].left==1)//左边只有一个且是非终结符的类型1,则为类型2 
	    if(r[i].str[j]>='A'&&r[i].str[j]<='Z')
	    r[i].k=2;
	}
	level=1;	
}

//判断文法类型1
void Transform1(){
	int i,j;
	int length;
	for(i=0;i<temp;i++){
		r[i].k=0;
		length=strlen(r[i].str);//字符串长度 
		r[i].left=0;
		for(j=0;r[i].str[j]!='-';j++)//左边长度 
		r[i].left++;
		r[i].right=length-r[i].left-2;//右边长度,减2表示减去字符'-'和'>' 
		if(r[i].right>=r[i].left)
		r[i].k=1;
	}
}	

//主函数 
int main(){
	Input();//输入文法规则 
	Transform1();//类型1判断 
	Transform2();//文法类型2判断 
	Transform3();//文法类型3判断 
    Output();//输出文法类型 
	return 0;
} 





在这里插入图片描述

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

根据文法规则,判断文法类型 的相关文章

随机推荐

  • 【用示例学习与理解C++系列】类的构造方法

    前言 本文主要是通过简单的示例 xff0c 去学习与理解C 43 43 类的构造方法 构造方法的作用 为什么存在构造方法 xff1f 为什么需要构造方法 xff1f 那是因为当我们在代码中定义一类变量 xff08 实例化一个类的实例 对象时
  • CSP-M2 :神奇的序列

    文章目录 HRZ的序列题目输入输出解题代码 HRZ学英语 滑动窗口题目输入输出解题代码 咕咕东的奇妙序列题目输入输出解题代码 HRZ的序列 题目 相较于咕咕东 xff0c 瑞神是个起早贪黑的好孩子 xff0c 今天早上瑞神起得很早 xff0
  • 转化Foggy_Cityscapes数据集为voc和yolo格式用作目标检测

    目录 一 数据集下载 xff08 1 xff09 解压后文件夹目录 xff08 2 xff09 gtFine格式如下所示 xff1a 二 转换为VOC数据集格式 xff08 1 xff09 生成xml标签 xff08 2 xff09 将le
  • 如何获取数据库的逻辑文件名、数据库文件的路径

    1 sp helpdb 数据库名 2 获取数据库文件路径 select ltrim rtrim filename from 数据库名 sysfiles where charindex 39 MDF 39 filename gt 0 sele
  • Linux进度条以及makefile相关知识

    一 在Linux环境下实现进度条 xff0c 其原理是 xff1a 用sleep函数或usleep函数控制每隔多长时间输出一次 xff0c 每次输出字符会比上次输出字符多一个 在此代码中 xff0c 用 r而不用 n的原因 xff1a n表
  • hdu - 4642 - Fliping game(博弈)

    题意 xff1a Alice和Bob玩游戏 xff0c 一个N M的矩阵 xff0c 里面是1或0 xff0c 每人每次选择一个1的位置 xff0c 然后将这个位置到右下角的整个矩形元素全部取反 xff08 1变0 xff0c 0变1 xf
  • 图形界面报错“已拒绝X11转移申请”的解决方法

    今天想通过本机给虚拟机起x manager图形界面的时候报出 解决办法 xff1a 原来X11 forwarding依赖 xorg x11 xauth 软件包 xff0c 所以必须先安装 xorg x11 xauth 软件包 yum ins
  • bash: ifconfig: command not found 解决办法

    经常遇到 34 bash xxxx command not found 34 这样的问题 xff0c 用root用户也不行 xff0c 在网上查阅了此问题 xff0c 解决方法如下 xff1a 原文1 http hi baidu com j
  • 用CMfcShellTree和CMFCShellListCtrl实现资源管理器并过滤扩展名

    资源管理器 CMfcShellTree和CMFCShellListCtrl是VS2008 SP1和VS2010内自带的控件 xff0c 用这两个控件实现资源管理器只需几行代码 CMFCShellTreeCtrl m tree CMyShel
  • 解决虚拟机下CentOS系统无法识别usb设备

    其实不是什么 解决 xff0c 虚拟机默认是自动挂载usb设备的 只是要注意插usb设备的时候 xff0c 虚拟机必须要处于当前窗口 然后就会自动弹出已安装好usb设备的提示 xff08 如果系统比较卡 xff0c 需要多等一会 xff09
  • 基于MDK的汇编语言编写及小灯闪烁的汇编程序实现

    基于MDK的STM32汇编语言编写及小灯闪烁的汇编程序实现 一 新建工程二 配置环境1 选择设备2 选择运行环境3 添加源文件 三 测试代码1 源码2 仿真器设置3 编译调试 四 HEX文件解读五 闪烁LED的程序六 总结参考 一 新建工程
  • WIndows10连接虚拟机显示connection confused

    Windows10连接虚拟机显示connection confused 当我们想由win10连接虚拟机终端时 xff0c 使用第三方软件Putty或者win10的cmd都可能出现connection confused问题 xff0c 解决这
  • 交换两个数字(不使用其他变量)

    面试题 交换两个数字 xff08 不使用其他变量 xff09 一 题目要求 xff1a 有两个整数变量a 61 6 b 61 100不使用其他变量 xff0c 交换两个变量的值 二 解法 解法1 xff08 使用其他变量 xff09 xff
  • unity如何使用电脑模拟VR环境

    unity如何通过VRTK模拟VR环境 如何在没有HTC VIVE的前提下使用VR xff1f 由于作者研究室课题是基于虚拟现实的人机交互 xff0c 需要用到VR下的场景 xff0c 但由于实验室设备只有一套 xff0c 而当我们想要随时
  • 笔试算法:青蛙跳台阶

    笔试算法 xff1a 青蛙跳台阶 1 题目表述 假设青蛙正在跳台阶 需要 n 阶你能到达楼顶 每次青蛙可以跳 1 或 2 个台阶 xff0c 但不可以连续跳2个 请问有多少种不同的方法可以到楼顶呢 xff1f 注意 xff1a 给定 n 是
  • 输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数

    输入一行字符 xff0c 分别统计出其中英文字母 空格 数字和其他字符的个数 首先需要判断各自所出的范围 xff1a 中英文字母 xff1a a到z A到Z 空格 xff1a 空一个字符 数字 xff1a 1 9 然后则对一串字符进行逐个比
  • 逆波兰式的实现及表达式的值

    逆波兰式的实现 1 概念 逆波兰式也叫后缀表达式 xff0c 这里先简单帮大家理解一下概念性问题 像我们平常使用到的表达式如 a 43 b c
  • C语言栈的用法(创建、入栈、出栈、遍历)

    C语言栈的用法 xff08 创建 入栈 出栈 遍历 xff09 本篇博客主要简单介绍如何使用C语言构建栈 xff0c 元素入栈 xff0c 元素出栈以及遍历所有的栈内元素 1 栈的定义 首先对栈进行定义 xff0c 构建一个简单的结构体 x
  • 我印象中的徐志摩

    我印象中徐志摩 在我上中学的时候 xff0c 徐志摩对于我来说是一个神圣不可侵犯的名字 xff0c 那么一个具有才华和能力 xff0c 从他的作品里感受到他那浪漫的文艺气息和对自由生活的追求 xff0c 无不令我们这些初入青春期的孩子们留下
  • 根据文法规则,判断文法类型

    根据文法规则 xff0c 判断文法类型 1 实验要求 输入 xff1a 文法规则 输出 xff1a 文法类型 2 实验原理 文法规则 xff1a 以四元组的形式展示出来 xff1a 文法G 定义为四元组G 61 Vn Vt P S Vn x