上一篇说了词法分析这次说语法分析,这两部分是一脉相承的。(上一篇在这)

  • 要进行语法分析,必须对语言的语法结构进行描述。
  • 采用正规式和有限自动机可以描述和识别语言的单词符号;
  • 用上下文无关文法(前面已经说过了)来描述语法规则。

一、语法分析的任务

语法分析的任务:分析一个文法的句子结构。

语法分析器的功能(不深入探究):按照文法的产生式(语言的语法规则),识别输入符号串是否为一个句子(合式程序)。

二、语法分析的方法:

1. 自下而上分析法(Bottom-up):“了解”

         基本思想:从输入串开始,逐步进行“归约”,直到文法的开始符号。即从树末端开始,构造语法树。所谓归约,是指根据文法的产生式规则,把产生式的右部替换成左部符号。

     算符优先分析法:按照算符的优先关系和结合性质进行语法分析。适合分析表达式。

       LR分析法:规范归约

2.自上而下分析法(Top-down)

       基本思想:它从文法的开始符号出发,反复使用各种产生式,寻找"匹配"的推导。

 递归下降分析法:对每一语法变量(非终结符)构造一个相应的子程序,每个子程序识别一定的语法单位,通过子程序间的信息反馈和联合作用实现对输入串的识别。

       预测分析程序 优点:直观、简单和宜于手工实现。

三、自上而下分析的问题

自上而下就是从文法的开始符号出发,向下推导,推出句子。

  • 带“回溯”的
  • 不带回溯的递归子程序(递归下降)分析方法。

     自上而下分析的主旨:对任何输入串,试图用一切可能的办法,从文法开始符号(根结点)出发,自上而下地为输入串建立一棵语法树。或者说,为输入串寻找一个最左推导。

例 :  假定有文法G(S):            (1) S→xAy

(2) A→**|*            分析输入串x*y(记为α)。

则推导过程为:

 

由上图给出的的一种过程以及A的产生式集合可以看出该推导过程是不唯一的,也就是说A既可以用*来表示也可以用**来表示

       上例的说明就带来了以下问题:

       当某个非终结符有多个产生式候选时,可能带来如下问题:

  • 1. 分析过程中,当一个非终结符用某一个候选匹配成功时,这种匹配可能是暂时的。出错时,不得不“回溯”。
  • 2. 文法左递归问题。一个文法是含有左递归的,如果存在非终结符P

               ps:含有左递归的文法将使自上而下的分析陷入无限循环。

四、LL(1)分析法

  • 构造不带回溯的自上而下分析算法
  • 要消除文法的左递归性
  • 克服回溯

1.左递归的消除

      直接消除见诸于产生式中的左递归:假定关于非终结符P的规则为  P→Pα|β,其中β不以P开头。 我们可以把P的规则等价地改写为如下的非直接左递归形式: P→βP'  , P'→αP' |ε,即将上述的左递归文法改为了右递归文法。

一般而言,假定P关于的全部产生式是     P→Pα1 | Pα2 | … | Pαm | β1 | β2|…|βn 其中,每个β都不等于ε,每个β都不以P开头    那么,消除P的直接左递归性就是把这些规则改写成:

  • P→β1P'| β2P' | … | βnP'
  • P'→α1P' | α2P' |… | αmP' | ε

例      文法G(E):

E→E+T | T

T→T*F | F

F→(E) | i

经消去直接左递归后变成:

E→TE'     

E'→+TE' | ε  

T→FT'    

T'→*FT' | ε   

F→(E) | i    

该例就是用了将左递归的文法改成右递归,这样一来就不含有右递归了

2.消除回溯、提左因子

消除回溯

为了消除回溯就必须保证:对文法的任何非终结符,当要它去匹配输入串时,能够根据它所面临的输入符号准确地指派它的一个候选去执行任务,并且此候选的工作结果应是确信无疑的。

这个地方要用到First集跟Follow集,不懂得可以看这篇

       (点这里:first、Follow)

令G是一个不含左递归的文法,对G的所有非终结符的每个候选α定义它的终结首符集FIRST(α)为:

特别是,若α=*> ε  ,则规定ε ∈ FIRST(α)。

如果非终结符A的所有候选首符集两两不相交,即A的任何两个不同候选α i和α j                                                         FIRST(αi)∩FIRST(α j)=∅

当要求A匹配输入串时,A就能根据它所面临的第一个输入符号a,准确地指派某一个候选前去执行任务。这个候选就是那个终结首符集含a的α。

提取公共左因子:

假定关于A的规则是          A→ δβ1 | δβ2 | …| δβn | γ1 | γ2 | … |γm

(其中,每个γ不以δ开头)

那么,可以把这些规则改写成        A→δA' | γ1 |γ2 | … | γm

A'→β1 | β2 | … | βn

经过反复提取左因子,就能够把每个非终结符(包括新引进者)的所有候选首符集变成为两两不相交。

五、LL(1)分析条件

假定S是文法G的开始符号,对于G的任何非终结符A,我们定义

特别是,若S=*>......A   则规定 #∈FOLLOW(A)

构造不带回溯的自上而下分析的文法条件

1. 文法不含左递归,

2. 对于文法中每一个非终结符A的各个产生式的候选首符集两两不相交。

即,若 A→α1|α2|…|αn     则  FIRST(α i)∩FIRST(αj)=∅      (i ≠ j)

3. 对文法中的每个非终结符A,若它存在某个候选首符集包含 ε

则 FIRST(αi)∩FOLLOW(A)=∅      i=1,2,...,n

     如果一个文法G满足以上条件,则称该文法G为LL(1)文法。

对于一个满足上述条件的文法,可以对其输入串进行有效的无回溯的自上而下分析。假设要用非终结符A进行匹配,面临的输入符号为a,A的所有产生式为

A→α1 |α2 | … | αn

1. 若aFIRST(αi),则指派αi执行匹配任务;

2. 若a不属于任何一个候选首符集,则:

(1) 若ε 属于某个FIRST(αi )且 a∈FOLLOW(A), 则让A与α自动匹配。

(2) 否则,a的出现是一种语法错误。

六、First集与Follow集(详细的解释看这篇)

1.First集的构造

对每一文法符号X∈Vt∪Vn构造FIRST(X)

连续使用下面的规则,直至每个集合FIRST不再增大为止:

1. 若X∈Vt,则FIRST(X)={X}。

2. 若X∈Vn,且有产生式X→a…,则把a加入到FIRST(X)中;若X→ε也是一条产生式,则把ε也加到FIRST(X)中。

3. 若X→Y…是一个产生式且Y∈Vn,则把FIRST(Y)中的所有非ε-元素都加到FIRST(X)中;

4. 若X→Y1Y2…Yk是一个产生式,Y1,…,Yi-1都是非终结符,而且,对于任何j,1≤j≤i-1,FIRST(Yj)都含有ε(即Y1…Yi-1 =*>ε), 则把FIRST(Yi)中的所有非ε-元素都加到FIRST(X)中;

5. 特别是,若所有的FIRST(Yj)均含有ε,j=1,2,…,k,则把ε加到FIRST(X)中。

对文法G的任何符号串α=X1X2…Xn构造集合FIRST(α)。

1. 置FIRST(α)=FIRST(X1)\{ε};

2. 若对任何1≤j≤i-1,ε∈FIRST(Xj),则把FIRST(Xi)\{ε}加至FIRST(α)中;特别是,若所有的FIRST(Xj)均含有ε,1≤j≤i-1,则把ε也加至FIRST(α)中。显然,若α=ε则FIRST(α)={ε}。

2.Follow集的构造

对于文法G的每个非终结符A构造FOLLOW(A)的办法

  连续使用下面的规则,直至每个FOLLOW不再增大为止:      

1. 对于文法的开始符号S,置#于FOLLOW(S)中;

2. 若A→αBβ是一个产生式,则把FIRST(β)\{ε}加至FOLLOW(B)中;

3. 若A→αB是一个产生式,或A→αBβ是一个产生式而β=*> ε(即ε∈FIRST(β)),    则把FOLLOW(A)加至FOLLOW(B)中。

例    文法: S→ABc

A→a|ε

B→b|ε

FIRST(S)={a,b,c} FIRST(A)={a,ε}; FIRST(B)={b,ε};

Follow(S)={#} Follow(A)={b,c} Follow(B)={c}

  First集合求法:能由非终结符号推出的所有的开头符号或可能的ε,但要求这个开头符号是终结符号。如此题A可以推导出a和ε,所以FIRST(A)={a,ε};同理FIRST(B)={b,ε};S可以推导出aBc,还可以推导出bc,还可以推导出c,所以FIRST(S)={a,b,c}

Follow集合的求法:紧跟随其后面的终结符号或#。但文法的识别符号包含#,在求的时候还要考虑到ε。 具体做法是把所有包含你要求的符号的产生式都找出来,再看哪个有用。 Follow(S)={#}如求A的,产生式:S→ABc  A→a|ε ,但只有S→ABc 有用。跟随在A后年的终结符号是FIRST(B)={b,ε},当FIRST(B)的元素为ε时,跟随在A后的符号就是c,所以 Follow(A)={b,c} 同理Follow(B)={c}

七、预测分析表

在对文法G的每个非终结符A及其任意候选α都构造出FIRST(α)和FOLLOW(A)之后,现在可以用它们来构造G的分析表M[A,a]。

1. 对文法G的每个产生式A→α执行第2步和第3步;

2. 对每个终结符a ∈FIRST(α),把A→α加至M[A,a]中;

3. 若ε ∈ FIRST(α),则对任何b∈ FOLLOW(A)把A→α 加至M[A,b]中。

4. 把所有无定义的M[A,a]标上“出错标志”。

对于文法G(E)   E→TE'

E'→+TE' | ε

T→FT'

T'→*FT' | ε

F→(E) | i             构造每个非终结符的FIRST和FOLLOW集合如下

First集

Follow集

E {(,i} {),#}
E' {+, ε} {),#}
T {(,i} {+,),#}
T' {*, ε} {+,),#}
F {(,i} {*,+,),#}

根据First集跟Follow集构建预测分析表如下:

i + * ( ) #
E E→TE'  E→TE'
E' E'→+TE' E'→ε E'→ε
T T→FT'          T→FT'   
T' T'→ε T'→*FT'  T'→ε T'→ε
F F→ i  F→(E) 

如果G是左递归或二义的,那么,M至少含有一个多重定义入口。因此,消除左递归和提取左因子将有助于获得无多重定义的分析表M。 可以证明,一个文法G的预测分析表M不含多重定义入口,当且仅当该文法为LL(1)的。

小结

暂时写到了语法分析的部分,细节后面会补充,写到这可能会停一段时间,要忙一些事情。明白语法分析的过程是构建语法分析器的基础,大家可以好好看看。感谢大家的观看,如有错误还请指正。可以留言,会回复的。

编译原理(4):语法分析(自上而下)相关推荐

  1. 编译原理实验:自上而下语法分析

    编译原理实验:自上而下语法分析 1. 实验题目:自上而下语法分析 实验目的 实验内容 实验要求 输入输出 2. 设计思想 3. 算法流程 4. 源程序 5. 调试数据 1. 实验题目:自上而下语法分析 ...

  2. 编译原理实验二 自上而下语法分析

    自上而下 语法分析实验 一.实验目的 (1)给出 PL/0 文法规范,要求编写 PL/0语言的语法分析程序. (2)通过设计.编制.调试一个典型的自上而下语法分析程序,实现对词法分析程序所提供的单词序 ...

  3. 编译原理2-Bison语法分析

    ps:补上了图 实验要求 了解 Bison 基础知识和理解 Cminus-f 语法(重在了解如何将⽂法产⽣式转换为 Bison 语句) 阅读 /src/common/SyntaxTree.c ,对应头 ...

  4. 编译原理之语法分析(自底向上)(包含源码)

    编译器之语法分析 自底向上 基本概念 算符优先 SLR 规范LR LALR 自底向上 基本概念 自底向上形成语法树的过程就是及逆行归约,将一堆单词串放在一起,形成某个产生式的样子,然后规约成某个产生式 ...

  5. 编译原理之语法分析(预测分析法)

    编译器之语法分析 自顶向下 上下文无关文法 语法树 NFA→CFG 预测分析法 改写CFG 原因 消除二义性 消除左递归 消除左公因子 消除空产生式 消除回路 自顶向下 上下文无关文法 CFG本质上就 ...

  6. 编译原理实验二 自上而下的语法分析器(算术表达式)

    1.语法分析器比之前的词法分析器简单一些,要做语法分析,首先我们需要词法分析器将输入的算术表达式进行分解,将其变为一个String数组,这样我们可以依次对每一个词进行匹配. 2.在执行匹配的时候,思想 ...

  7. 编译原理词/语法分析

    效果: 代码: 1: using System; 2: using System.Collections.Generic; 3: using System.ComponentModel; 4: usi ...

  8. 计算机语法分析,电子科技大学-计算机学院-编译原理实验-语法分析.pdf

    // SyntaxAnalyzer.cpp : 定义控制台应用程序的入口点. // #include #include #include #define MAX_COUNT 1024 #define ...

  9. 【编译原理】Python语法分析LL(1)、LR(1)

    目录 一.实验目的 二.实验任务 三.实验原理 1  LL(1)文法 2  LR文法 四.实验过程 1  LL(1)文法 2  LR文法 五.实验结果 1  LL(1)文法 2  LR(0)文法 3 ...

  10. [编译原理]DO-WHILE循环语句的翻译程序设计(LR(1)方法、输出四元式)C++实现

    题目: DO-WHILE循环语句的翻译程序设计(LR(1)方法.输出四元式) 1 课设任务概述 初始条件: ​ 理论:完成编译原理,数据结构.高级编程语言.汇编语言等相关课程的学习,基于计算机专业知识 ...

最新文章

  1. 终于有人把计算机视觉讲明白了 。。。
  2. python使用matplotlib可视化线图(line plot)、将可视化图像的图例(legend)放置在图像外部、底部区域
  3. Map存值问题的研究
  4. DaVinci Resolve 16中文版
  5. php artisan 命令
  6. Linux下安装oracle的过程
  7. android onitemclicklistener 参数,android – 对listview中的项使用setOnItemClickListener
  8. python自动发送邮件_Python自动发送邮件
  9. 使用no-gui 模式执行分布式测试
  10. vmware-tools安装失败
  11. java颠倒字符串_Java经典实例:按字符颠倒字符串
  12. 基于深度学习的银行卡号识别 卡号识别和分割
  13. 手写原笔迹输入_手写原笔迹
  14. svn status详解
  15. python布尔类型的两个值_布尔人有两个可能的值。是否有三种可能值的类型?
  16. SQL编程-组队学习打卡task06-秋招秘籍ABC
  17. TIOBE编程语言排行榜,使用前二十语言实现HelloWorld程序
  18. DevOps落地实践:普元:PRIMETON DEVOPS
  19. JAVA interrupt、interrupted和isInterrupted的区别
  20. 微软面试程序题100道

热门文章

  1. GTK构件 --- 文本视图控件GTKtextview
  2. 基本概念学习(1001)---外部设备
  3. ADI公司高速PCB布板指南
  4. 如何实现微信和淘宝的扫码登录
  5. Excel合并,VBA代码,最后一列填充文件名
  6. Android Service之设备存储空间监控
  7. 谈产品的差异化思路:进可攻退可守
  8. 【手把手制作三阶魔方模拟器】用MATLAB让你的魔方动起来
  9. 基于外卖平台POI的城市餐饮业空间热点分析系统
  10. Android开发 调用系统相机相册图片功能,解决小米手机拍照或者图片横竖相反问题,及小米手机相册图片路径问题