c语言结构体语法分析,C语言结构体struct的语法解析
本节内容需要结合视频讲解才能更容易理解,视频播放地址如下:
用java开发编译器
本节,我们着重研究结构体定义,也就是struct 这种变量定义,C语言编译器是如何解析的,本节我们要解析的结构体定义如下:
struct tag {
int x;
long y;
char z;
struct tag* p;
}name;
1.1 结构体定义的解析语法
* TYPE_SPECIFIER -> STRUCT_SPECIFIER
*
* STTUCT_SPECIFIER -> STRUCT OPT_TAG LC DEF_LIST RC
* | STRUCT TAG
*
* OPT_TAG -> TAG
*
* TAG -> NAME
*
* DEF_LIST -> DEF
*
* DEF_LIST -> DEF_LIST DEF
*
*
*
*
*
* DEF -> SPECIFIERS DECL_LIST SEMI
* | SPECIFIERS SEMI
*
*
* DECL_LIST -> DECL
* | DECL_LIST COMMA DECL
*
* DECL -> VAR_DECL
*
* VAR_DECL -> NEW_NAME
* | VAR_DECL LP RP
* | VAR_DECL LP VAR_LIST RP
* | LP VAR_DECL RP
* | START VAR_DECL
*
我们先看这一句定义:
STTUCT_SPECIFIER -> STRUCT OPT_TAG LC DEF_LIST RC
STRUCT 是关键字struct 对应的标签, OPT_TAG 对应的是结构体变量的名字tag, LC 对应左大括号, DEF_LIST 对应结构体内部变量的定义序列,RC就是右大括号。这一句语法就已经描述了整个结构体的定义,解析的终点其实在 DEF_LIST, 这个非终结符描述的是结构体内部变量的定义规则,对DEF_LIST的解析是整个解析过程的难点。
1.2语法解析流程描述
解析开始时,词法解析器会把关键字struct读入,并返回一个STRUCT标签。
读入struct 后面的变量名tag, 返回对应标签NAME.
根据表达式 TAG -> NAME, 将NAME转换成非终结符TAG.
通过表达式 OPT_TAG -> TAG , 将TAG转换成非终结符OPT_TAG.
读入左大括号{, 并返回对应标签LC.
*读入关键字int, 并返回对应的标签TYPE
*根据表达式TYPE_SPECIFIER -> TYPE, 将TYPE替换成非终结符TYPE_SPECIFIER. 这个表达式在前面的章节中讲解过,本节没有列出来。
*根据表达式 TYPE_OR_CLASS -> TYPE_SPECIFIER 将非终结符TYPE_SPECIFIER 转换成TYPE_OR_CLASS.
*通过表达式 SPECIFIER -> TYPE_OR_CLASS, 将非终结符TYPE_OR_CLASS转换成SPECIFIERS.
上面几步完成了对关键字int 的解析。
接着读入变量名x, 返回对应的标签NAME.
*根据表达式NEW_NAME -> NAME, 将非终结符NEW_NAME 压入堆栈。
*根据表达式VAR_DECL -> NEW_NAME 将非终结符换成VAR_DECL.
*通过表达式DECL -> VAR_DECL 将非终结符DECL替换掉VAR_DECL.
*通过表达式DECL_LIST -> DECL 将非终结符DECL_LIST 压入堆栈。
*读入分号,并返回对应的标签SEMI
*根据表达式DEF -> SPECIFIERS DECL_LIST SEMI 将解析堆栈上的符号全部弹出,换成非终结符DEF.
再次通过 DEF_LIST -> DEF 将非终结符压入堆栈。
在这一步我们可以看到,”int x ; “, 这一个变量定义语句可以被非终结符DEF_LIST所描述。
接下来,解析器读入语句 “long y ;”,该语句的解析也同样经历前面带*号的解析步骤,最后”long y;” 会解析成非终结符DEF,此时解析堆栈顶部有两个非终结符DEF, DEF_LIST.
通过表达式 DEF_LIST -> DEF_LIST DEF 将两个非终结符归纳成一个非终结符DEF_LIST.
解析器继续读入 “char z;”, 同样经历带*号的解析步骤后,把该语句解析成非终结符DEF, 这时解析堆栈头部又在此含有两个非终结符 DEF_LIST, DEF, 于是又可以通过表达式 DEF_LIST -> DEF_LIST DEF 将两个非终结符归纳为一个非终结符DEF_LIST.
接下来解析器再次遇到关键字struct, 读入后返回对应标签STRUCT.
入读struct 后面的变量名tag,返回对应标签NAME.
运用表达式 TAG -> NAME, 将非终结符TAG压入堆栈。
采用表达式STRUCT_SPECIFIER -> STRUCT TAG 将堆栈顶部的两个非终结符替换成STRUCT_SPECIFIER.
再通过TYPE_SPECIFIER -> STRUCT_SPECIFIER 将栈顶非终结符替换成TYPE_SPECIFIER.
接着分别通过两个表达式TYPE_OR_CLASS -> TYPE_SPECIFIER 和 SPECIFIERS -> TYPE_OR_CLASS, 将栈顶元素替换成SPECIFIERS.
然后把代表指针的* 读入,返回对应标签STAR.
读入星号后面的变量名p, 返回对应的标签NAME.
通过表达式NEW_NAME -> NAME, 将非终结符NEW_NAME压入解析堆栈。
通过VAR_DECL -> NEW_NAME 将栈顶元素替换成VAR_DECL.
此时栈顶元素包含VAR_DECL, 和 STAR, 这两个元素正好形成表达式:
VAR_DECL -> STAR VAR_DECL 的右边部分,于是经过一次reduce,将堆栈顶部的两个元素替换成VAR_DECL.
继续通过表达式DECL -> VAR_DECL, 将非终结符DECL压入堆栈。
DECL 可以通过表达式DECL_LIST -> DECL 替换成DECL_LIST.
接着读入变量p后面的分号,返回对应标签SEMI
此时,解析堆栈上含有三个元素:SEMI, DECL_LIST, SPECIFIERS, 他们正好构成表达式DEF -> SPECIFIERS DECL_LIST SEMI 的右边,于是通过该表达式进行一次reduce, 将DEF替换掉这三个符号。
此时,堆栈顶部有两个元素,DEF, DEF_LIST, 又正好构成表达式:
DEF_LIST -> DEF_LIST DEF 的右边,于是又可以用DEF_LIST 替换掉堆栈顶部的两个元素。
接着读入右括号 }, 返回对应标签RC.
这时,堆栈顶部的5个元素正好对应表达式:
STRUCT_SPECIFIER -> STRUCT OPT_TAG LC DEF_LIST RC 的右边,于是解析器可以一下子将这5个元素全部替换成STRUCT_SPECIFIER.
接着解析器可以通过TYPE_SPECIFIER -> STRUCT_SPECIFIER 将TYPE_SPECIFIER压入堆栈。
然后把}后面的变量名name,读入,解析流程跟前面讲解的流程一样。
读入最后的分号后,解析堆栈上的元素正好构成表达式:
EXT_DEF -> .OPT_SPECIFIERS EXT_DECL_LIST SEMI
的右边部分,于是整个解析堆栈顶部的元素全部弹出,换成符号EXT_DEF.
接下来的推导跟以前一样,经过一系列固定步骤后,全局非终结符PROGRAM会被压入堆栈,从而使得解析器接收输入文本。
由此可见,依赖本节给出的语法定义,解析器能够顺利的分解结构体的代码。
通过这几节的解析流程分析,我们可以看到,写的再繁杂,再杂乱无章的程序代码,只要符合语法,那么这些看似随机组合的字符或单词,本质上遵从着一种非常严谨的层次和结构,这种层次和结构可以通过语法定义的方式描述出来,大道至简,任何复杂的系统,其本质都可以归因为若干简单的原理。这就是科学之美,编译原理的算法之美,学习编译原理或任何科学知识,其实是一种享受美的过程。
要体验这种系统逻辑之美,需要巨大的耐心,和不厌其烦的探索,持之以恒的意志力,有这种恒心的人,才有可能“会当凌绝顶,一览众山小”,学习是一个不断攀爬,跌倒,再攀爬的过程,只有要紧牙,永不放弃的人,才有可能在光明顶感受到“荡胸生层云,决眦入归鸟”的人生成就感。
再次以王安石《游褒禅山记》为每一位愿意“吾将上下而求索”的同学共勉:
“古人之观于天地、山川、草木、虫鱼、鸟兽,往往有得,以其求思之深而无不在也。夫夷以近,则游者众;险以远,则至者少。而世之奇伟、瑰怪,非常之观,常在于险远,而人之所罕至焉,故非有志者不能至也。有志矣,不随以止也,然力不足者,亦不能至也。有志与力,而又不随以怠,至于幽暗昏惑而无物以相之,亦不能至也。然力足以至焉,于人为可讥,而在己为有悔;尽吾志也而不能至者,可以无悔矣,其孰能讥之乎?此余之所得也!”
相信我,你,并不孤独!
c语言结构体语法分析,C语言结构体struct的语法解析相关推荐
- C语言结构体struct的语法解析
本节内容需要结合视频讲解才能更容易理解,视频播放地址如下: 用java开发编译器 本节,我们着重研究结构体定义,也就是struct 这种变量定义,C语言编译器是如何解析的,本节我们要解析的结构体定义如 ...
- 简单介绍C语言使用四种方法初始化结构体
这篇文章说明了什么是结构体,介绍了结构体的概念和使用优点,在C语言中如何使用和初始化结构体方法,通过详细的代码展开进行说明,希望该篇文章对你有所帮助 什么是结构体 在实际问题中,一组数据往往有很多种不 ...
- c语言结构内部定义指针,C语言知识补漏(一)结构体指针以及位域定义
一.结构体指针 typedef struct { unsigned long int DATA; unsigned long int DIRECTION; unsigned long int INTE ...
- c语言 结构体的,c语言之结构体
c语言之结构体 1.结构体基础知识 C语言提供了两种类型的聚合数据类型(能够同时存储超过一个的单独数据),数组和结构.数则是相同类型的元素的集合,而结构也是一些值的集合,这些值称为它的成员,单一个结构 ...
- c语言定义学生结构体类型,C语言中结构体的三种定义方式
c语言中结构体的定义: struct 结构体名{ 成员列表: ..... }结构体变量: 7.1.1 结构体类型变量的定义 结构体类型变量的定义与其它类型的变量的定义是一样的,但由于结构体类型需要针对 ...
- c语言学习笔记【结构体02】结构体指针变量与结构体变量的函数参数,C语言学习笔记结构体02结构体指针变量与结构体变量的函数参数.docx...
C 语言学习笔记[结构体02]结构体指针变量与结构体变量 的函数参数 C 语言学习笔记之结构体指针变量一提指针,那可 是 C 语言的核心了,有多少学子曾拜倒在指针的脚下.单纯的说指针,其实并不难,但是 ...
- c语言有2维结构体没,c语言结构体说明
关键词:语言,结构 摘要:1.直接声明结构体变量: struct{ int length; int width; }box1; 这样就声明了一个名为box1的结构体变量,但是同时要注意,如果在同一个程 ...
- c语言函数的参数是结构变量,何去运用结构体变量和结构的变量的指针作为函数的参数...
在C语言中我们如何去运用结构体变量和结构的变量的指针作为函数的参数呢,其实我们对于结构体的变量是有一定的了解的,他们就是将一个结构体变量的值传递给另外一个函数,那么这种有三种方法,希望大家都能够了解一 ...
- 请输入30名同学的c语言成绩,求大神帮忙做这几道结构体的c语言!今天就要交实验报告!急啊急!!!!! (1)一个班级共有30名学...
问题描述: 求大神帮忙做这几道结构体的c语言!今天就要交实验报告!急啊急!!!!! (1)一个班级共有30名学 求大神帮忙做这几道结构体的c语言!今天就要交实验报告!急啊急!!!!! (1)一个班级共 ...
最新文章
- 清除administrator密码 方法
- WinForm应用只运行一次
- 【腾讯Bugly干货分享】H5 视频直播那些事
- 【渝粤教育】电大中专学前儿童语言教育 (4)作业 题库
- [新功能]查看好友最新随笔
- linux下 安装tengine
- android图片异步加载解决步骤
- sql---字段类型转换,sql获取当前时间,时间处理
- 主板开机重启条线安装图
- Unity方便查看日志的插件Reporter
- winhex常用快捷键
- 安卓系统目录说明大全,各文件夹是什么,可以删除吗?(以MIUI为例)
- 学习要有但行好事,莫问前程的心态
- IIS7.5 500.19的解决方法 错误代码 0x8007007e
- Java bean 复制克隆工具
- 一.正则表达式转换为有限状态自动机:正则表达式转NFA
- python round_Python3 round() 函数
- Linux 压缩、解压工具
- 华为田奇:人工智能两大趋势,大模型,AI+X
- python3 class写法_Python抽象类的新写法
热门文章
- 解决tab切换的时候,swiper不生效
- 微信小程序wx.showToast
- mac java myeclipse_Myeclipse mac版-Myeclipse 2015 Mac版下载 V2015免费版-PC6苹果网
- 新乡学院2019计算机报名,新乡学院2019年招生章程
- 怎么解决 数据丢失的问题_硬盘数据丢失怎么恢复
- linux服务器调优列表,2018-10-24(linux服务器常见的各种参数调优)
- uwp post php,在UWP應用程序使用PHP腳本
- linux 访问文件软件,Linux下访问文件的基本模式
- qt qgis linux,QT_QGIS_基本使用
- springboot 分页查询参数_精通SpringBoot--分页查询功能的实现