gcc编译器原理------编译原理三:编译过程(2-2)---编译之语法分析

kele-dad kele-dad     2022-12-23     395

关键词:

2.2 语法分析

语法分析器(Grammar Parser)将对由扫描器产生的记号进行语法分析,从而产生语法树(Syntax Tree)。整个分析过程采用了上下文无关语法(Context-free Grammar)的分析手段。

由语法分析器生成的语法树就是以表达式(Expression)为节点的树。如下所示:

技术分享图片

从图中可以知道,整个语句就是一个赋值表达式:赋值表达式的左边是一个数组表达式,右边是一个乘法表达式;数组表达式又由两个符号表达式组成,等等。符号和数字是最小的表达式,它们不是由其他表达式来组成,所以它们通常作为整个语法树的叶节点。

在语法分析的同时,很多运算符号的优先级和含义也被确定下来了。比如乘法表达式比加法表达式的优先级高。

另外有些符号具有多重含义,比如 * 在C语言中可以表示乘法表达式,也可以表示指针取内容的表达式,所以语法分析阶段必须对这些内容进行区分。如果出现了表达式不合法,比如各种括号不匹配、表达式中缺少操作符等,编译器就会报告语法分析阶段的错误。

语法分析工具使用 yacc(Yet Another Compiler Compiler),它像 lex 一样,可以根据用户给定的语法规则对输入的记号序列进行解析,从而构建出一棵语法树。

2.2.1 yacc 介绍

引用:https://blog.csdn.net/zdy0_2004/article/details/54918450

yacc(Yet Another Compiler Compiler),是Unix/Linux上一个用来生成编译器的编译器(编译器代码生成器).

使用巴克斯范式(BNF)定义语法,能处理上下文无关文法(context-free)。出现在每个产生式左边(left-hand side:lhs)的符号是非终端符号,出现在产生式右边(right-hand side:rhs)的符号有非终端符号和终端符号,但终端符号只出现在右端。

yacc是开发编译器的一个有用的工具,采用LR(1)(实际上是LALR(1))语法分析方法。

LR(k)分析方法是1965年Knuth提出的,括号中的k(k >=0)表示向右查看输入串符号的个数。LR分析法正视给出一种能根据当前分析栈中的符号串和向右顺序查看输入串的k个符号就可唯一确定分析器的动作是移进还是规约和用哪个产生式规约。

这种方法具有分析速度快,能准确,即使地指出出错的位置,它的主要缺点是对于一个使用语言文法的分析器的构造工作量相当大,k愈大构造愈复杂,实现比较困难。

  • 一个LR分析器有3个部分组成:
    • 总控程序,也可以称为驱动程序。
      • 对所有的LR分析器总控程序都是相同的。
    • 分析表或分析函数。
      • 不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表也不同,分析表又可分为动作(ACTION)表和状态转换(GOTO)表两个部分,它们都可用二维数组表示。
    • 分析栈,包括文法符号栈和相应的状态栈。
      • 它们均是先进后出栈。 分析器的动作由栈顶状态和当前输入符号所决定(LR(0)分析器不需要向前查看输入符号)。
  • LR分析器工作过程如下 :
    • 其中SP为栈指针,S[i]为状态栈,X[i]为文法符号栈。状态转换表内容按关系GOTO[Si,X] = Sj确定,该关系式是指当栈顶状态为Si遇到当前文法符号为X时应转向状态Sj。X为终结符或非终结符。 ACTION[Si,a]规定了栈顶状态为Si是遇到输入符号a应执行的动作。
  • 执行的动作的分类:
    • 移进:当Sj = GOTO[Si,a]成立,则把Sj移入到状态栈,把a移入到文法符号栈。其中i,j表示状态号。
    • 规约:当在栈顶形成句柄为β时,则用β归约为相应的非终结符A,即当文法中有 A-->β的产生式,而β的长度为r(即|β| = r),则从状态栈和文法符号栈中自栈顶向下去掉r个符号,即栈指针SP减去r。并把A移入文法符号栈内,再把满足Sj = GOTO[Si,A]的状态移进状态栈,其中Si为修改指针后的栈顶状态。
    • 接受acc:当规约到文法符号栈只剩文法的开始符号S时,并且输入符号串已结束即当前输入符是‘#‘,则为分析成功。
    • 报错:当遇到状态栈顶为某一状态下出现不该遇到的文法符号时,则报错,说明输入串不是该文法能接受的句子

2.2.2 YACC 的文件格式

YACC 的文件格式分为三个部分:

  1. ...definitions... %  %   
  2. % % 
  3. ...rules...
  4.  % % 
  5. ...subroutines...  
  • 定义部分:定义部分包括标志(token)定义和C代码(用"%"和"%"括起来)。
  • 规则部分:规则中目标或非终端符放在左边,后跟一个冒号(:),然后是产生式的右边,之后是对应的动作(用包含)
  • 第三部分:该部分是函数部分。当yacc解析出错时,会调用函数yyerror(),用户可自定义函数的实现。
    • 递归的处理:递归处理有左递归和右递归。
    • If-else 的冲突:当有两个IF一个ELSE时,该ELSE和哪个IF匹配是一个问题。有两种匹配方法:与第一个匹配和与第二匹配。现代程序语言都让ELSE与最近的IF匹配,这也是yacc的缺省行为。
    • 出错处理:当yacc解析出错时,缺省的行为是调用函数yyerror(),然后从yylex返回一个值。一个更友好的方法是忽略一段错误输入流,继续开始扫描。这里要涉及到YACC中错误保留字error的应用。

gcc编译器原理------编译原理三:编译过程(2-2)---编译之语法分析

2.2语法分析语法分析器(GrammarParser)将对由扫描器产生的记号进行语法分析,从而产生语法树(SyntaxTree)。整个分析过程采用了上下文无关语法(Context-freeGrammar)的分析手段。由语法分析器生成的语法树就是以表达式(Expressio... 查看详情

gcc编译器原理------编译原理一:elf文件(代码片段)

 二、ELF文件介绍 2.1可执行文件格式综述相对于其它文件类型,可执行文件可能是一个操作系统中最重要的文件类型,因为它们是完成操作的真正执行者。可执行文件的大小、运行速度、资源占用情况以及可扩展性、可移... 查看详情

gcc编译链接原理及使用(代码片段)

 gcc的使用方法:gcc  【选项】  文件名 gcc常用选项:  -v:查看gcc编译器的版本,显示gcc执行时的详细过程  -o  <file>       Place theoutput into & 查看详情

gcc编译器原理------交叉编译器制作和gcc组件及命令

1.1交叉编译器制作默认安装的GCC编译系统所产生的代码适用于本机,即运行GCC的机器,但也可将GCC安装成能够生成其他的机器代码。安装一些必须的模块,就可产生多种目标机器代码,而且可通过命令行选择一种希望使用的代码... 查看详情

编译原理:引论

阅读的教材为:编译原理(张素琴等编著,清华大学出版社)编译过程就是将高级语言翻译为低级语言编译过程分为前段(frontend)和后端(backend)阅读过程中遇到的疑问是:解释程序和编译程序的区别?1、编译程序直接生成... 查看详情

零基础初学者学习编译原理

编译原理就是什么?编译原理作为一门大学必开课程,既然存在那么就一定有他的道理。我从百度上看到的资料,大多都是说编译原理如何难如何难如何抽象如何烦之类的话,现采用一句话来介绍编译原理,编译原理就是翻译的... 查看详情

我对编译原理的理解

1.编译原理就是什么?    编译就是计算机将人类语言翻译成机器语言的过程,也就是将高级语言翻译成低级语言(0/1),而学习编译原理就是要我们学习整个的翻译过程,即计算机内部如何将高级语言翻译成低级... 查看详情

谈编译原理

...个中转站,有点类似于我们生活中的翻译,而“编译原理”就是编译原理是一门关于编译实现的课程,就是想要编译必须通过学习编译原理才能实现。二:可以对自己所写的程序和程序语言有更深的本质认识,让你学习新... 查看详情

编译原理

  简单来说,编译原理就是能够实现将一种高级语言翻译成一种低级的计算机语言的过程,是一种实现语言的原理。编译原理就像是一座连接人与计算机进行交互的桥梁,通过编译原理能够将编程员所写的代码翻译成计算机能... 查看详情

编译原理

  大二的第一学期,开始学习编译原理。  初次接触这门课程,我什么都是不懂的。所以我根据老师指导去网上了解编译原理的相关知识。  编译原理是计算机专业的一门重要专业课,是介绍编译程序构造的一般原理和基... 查看详情

浅谈编译原理

什么是编译原理?编译原理顾名思义,编译就是将源语言(高级程序语言)翻译成等价的目标语言(机器语言即计算机可以识别的语言即0和1或汇编语言)的过程。原理就是研究这一过程的思想方法、理论和技术。从本质上来讲... 查看详情

我对编译原理的看法

...为二进制语言的过程。而学习编译原理,能够让我们明白编译器是如何进行工作的,了解语言之间的转换过程,懂得代码的本源是什么,可以更好的理解程序,解决编程中的问题,如果不学习编译原理,那就无法理解自己写的程... 查看详情

编译原理

...用:1.可以为今后的考研做准备;2.可以深入的了解别人编译器的操作以致于不会成为别人的 查看详情

编译原理-链接实例分析(代码片段)

gcc-arm-none-eabi工具链功能1.arm-none-eabi-gcc:c语言编译器,可以将.c文件编译为.o的执行文件2.arm-none-eabi-g++:c++编译器,可以将.cpp文件编译成.o的执行文件3.arm-none-eabi-ld:链接器,链接所有的.o文件生成... 查看详情

学习编译原理的好处

1.编译原理是一门对实践要求较高的课程,学习编译原理可以更好的提升我的实践能力。同时,编译原理中编译程序是现代计算机系统的基本组成部分之一,对于我们这些编程人员是有极大帮助的。2.编译原理的一个重要性体现... 查看详情

编译原理123

1.编译原理就是什么?个人理解,编译就是像翻译一样,将一种语言翻译成另一种语言,编译就是将高级语言或汇编语言翻译成电脑能识别的二进制机器语言,编译原理就是讲解这个编译的过程。内容包括语言和文法、词法分析... 查看详情

对编译原理的理解

...以后学习工作打下基础,而且编译原理并不仅仅是用来写编译器的,还可以 查看详情

深入分析java的编译原理

...机做的,这个过程也叫编译。是更深层次的编译。在编译原理中,把源代码翻译成机器指令,一般要经过以 查看详情