简述自顶向下的语法分析

  在我们得到了Context-free grammar 之后,下一步就要将它转换成一棵语法分析树了,语法分析树使得我们的编译器能够识别输入串是否符合我们的Context-free grammar(中文翻译为上下文无关语言)

有两种方法能够将Context-free grammar转换为语法分析树。今天我们只介绍自顶向下的方法。

  自顶向下的语法分析是从根节点开始,深度优先地创建语法分析树的各个节点。有递归向下分析和预测分析两大类方法。

递归向下分析

  递归向下的语法分析可能需要回溯(aka需要重复扫描输入),考虑以下文法: S -> aBc ,B -> bc | b ,当我们用递归向下分析,输入为abc时,语法树如下图:

  

  当我们第一次匹配时识别失败了(a匹配a,bc匹配B,最后一个c未匹配到),输入必须回到b,用B的另外一种方式匹配。

  递归向下的分析十分直观,实现起来也比较方便,但效率较低,所以一般不采用。递归向下的分析方法实际上是深度优先搜索+回溯。而下面要说的预测分析则是用高效的动态规划来实现语法分析。

递归预测向下分析

   在讨论使用动态规划的预测向下分析之前,我们先来看一种特殊的预测向下分析。它在本质上也是递归的,唯一的区别在于它不需要回溯。考虑以下文法:A -> aBb | bAB,伪代码实现如下:

 proc A {

case 当前标记 {

  ‘a’:匹配a, 移动到下个标记;

     调用函数B;
     匹配b, 移动到下个标记;
  ‘b’:匹配b,移动到下个标记;
     调用函数A;

     调用函数B;

       }
    }

   其实这种分析方式与前者的区别就在于它用了case语句来预测A的两种可能性,从而做出不同的判断。但这种方式的效率也是不如动态规划的。

非递归预测向下分析

  非递归预测向下分析是表驱动的分析方法,也叫做LL(1)分析。第一个"L"表示从左到右扫描。第二个"L"表示产生最左推导。"1"表示每次只要往前走一步就可以决定语法分析的动作。

所谓表驱动就是通过查表的方式来分析一个输入流是否符合文法。假设我们已经得到了这张语法分析表,现在来具体分析这种方式是如何工作的。

  

首先我们需要一个栈来存储start symbol,即语法树的根。然后从表中查找当栈顶为S,输入为a时对应的文法,然后将S替换为aBa(注意入栈顺序),然后a与输入的a匹配,非终结标志B对应到了b,此时查找表中相应的文法,将B弹出栈,将bB压入栈(注意顺序)。以此类推直到栈底的终止字符匹配到了输入的终止字符,表示匹配成功。

上面是实例,下面我们给出一个高度的分析行为概括:

  当栈顶为X,当前输入为a时,有以下四种分析行为:

  1.如果X和a都为终止符号$,匹配成功,停止匹配。

  2.如果X和a都是同一种终结标志(terminal symbol),将X弹出栈,将输入移动到下个标志。(表示该标志成功匹配,准备匹配下个标志)

  3.如果X是非终结标志(nonterminal symbol),查询语法分析表,找到[S,a],如果[S,a]为 X->Y1Y2Y3...Yk,则将Y1Y2Y3...Yk逆序放入栈中。(即Y1为栈顶)

  4.不符合以上三种情况,匹配失败,进入错误恢复模式。

  可以看到,有了这张语法分析表之后分析起来非常的方便。那么我们如何构建这张语法分析表呢?

  首先我们需要用到两个函数first(a),follow(A),下面详细解释两个函数的含义以及如何计算他们。

  first(a) : 可以从a推导得到的串的首符号(终结符号)的合集。

  计算规则如下:

  1.如果X是终结符号,first(X)={X}

  2.如果X是非终结符号且X->ε是一个文法规则,那么ε属于first(X)

  3.如果X是非终结符号且X->Y1Y2Y3...Yn是一个文法规则,那么:①如果终结符号a在first(Yi)中且ε在所有的first(Yj) (j-1,2,...i-1)中,那么a也属于first(X) ②如果ε在所有的first(Yj) (j=1,2...n) 那么ε也属于first(X)

  4.如果X本身为ε,那么first(X)={ε}

  以上的规则将一直使用直到没有元素能够加入到任何first()当中。

  follow(A):从A之后可以立即得到(可以理解为与A相邻)的终结符号的集合,其中A是非终结符号。

  计算规则如下:

  1.如果A->aBb是一个文法规则,那么所有在first(b)中的元素除了ε都包含在follow(B)中。

  2.如果A->aB是一个文法规则或者A->aBb是一个文法规则且ε包含在first(b)中,那么在follow(A)中的所有元素都在follow(B)中。即follow(A)属于follow(B)

  以上的规则也将一直使用直到没有元素能够加入到任何follow()当中。

  下面给出两个实例让读者自行思考。

                           

  接下来让我们使用这两个函数来完成语法分析表构建的算法。

  对于在语法合集G中的每条语法 ,(以A->a来表示):

  for 每个终结符号 p in first(a):

    将A->a 加入到表中的M[A,p]

    if ε in first(a)

    for 每个follow(A)中的终结符号p:

      将A->a 加入到M[A,p]

  if  ε in first(a) 并且 $ 属于follow(A):

    将A->a 加入到M[A,$]

当然并不是所有的语法规则都是LL文法的,也就是说有可能出现在一个表中的某行某列存在多个文法规则,比如下图

  在M[E,e]中出现了两个文法规则使得语法分析产生了二义性(ambiguity)。可以看出LL文法并不是万能的。那么如果我们碰到了这样的情况应该怎么办呢?

首先我们可以先将存在左递归的文法消除成非左递归的文法。其次我们还可以提取左公因子,如果这样处理之后还是不行的话那么说明这个语法本身就存在二义性或者它天生就不是LL文法。

时间: 2024-08-29 07:46:27

简述自顶向下的语法分析的相关文章

如何消除左递归

首先,什么叫做左递归呢? 一个左递归的语法通常有这样的形式 :  A-> Aa .而自顶向下的语法分析是无法处理左递归语法的.为什么呢?无论是递归分析还是预测分析或者是LL文法分析,在碰到左递归这种语法时都会陷入死循环当中.如果我们用递归分析,那么在分析A这个非终结符号的时候就会调用functionA,functionA将A分解成A,a,然后在我们再次碰到A的时候又会调用functionA,这样便形成了无限递归.如果我们用非递归的LL文法分析,那么在我们将把A->Aa无限次地压入到栈中,即每次

简单的语法分析器

语法分析的主要任务是接收词法分析程序识别出来的单词符号串,判断它们是否由某种语言的文法产生,即判断被识别符号串是否为某语法成分,除此之外,还要进行语法检查,为后面的语义分析和代码生成做准备. 通过语法分析,可以建立相应的语法树,根据建立语法树方式的不同,可以把语法分析过程分为两大类,即自顶向下和自底向上的分析方法.顾名思义,自顶向下的语法分析程序是沿着从树根到树叶的方向建立,而自底向上的方法则是沿着从树叶到树根的方向建立. import java.io.File; import java.io.

【龙书笔记】用Python实现一个简单数学表达式从中缀到后缀语法的翻译器(采用递归下降分析法)

上篇笔记介绍了语法分析相关的一些基础概念,本篇笔记根据龙书第2.5节的内容实现一个针对简单表达式的后缀式语法翻译器Demo. 备注:原书中的demo是java实例,我给出的将是逻辑一致的Python版本的实现. 在简单后缀翻译器代码实现之前,还需要介绍几个基本概念. 1. 自顶向下分析法(top-down parsing) 顾名思义,top-down分析法的思路是推导产生式时,以产生式开始符号作为root节点,从上至下依次构建其子节点,最终构造出语法分析树.在具体实现时,它会把输入字符串从左到右

编译原理学习基本概念汇总

对于计算机专业的学生来说,肯定听说过或者上过一门课,叫做--编译原理,被称为计算机专业的天书,反正不管是学习这门课的时候,还是现在,我都是没搞懂其中的技术和知识.但就期末考试而言,提前做了几道题目,得到了90+的分数,也算是可喜可贺.各位ITer如果想检验自己的智商的话,大可以去学习编译原理,你会收获很多的.现在我把大学时整理的编译原理最基本的概念分享出来. 第一章-绪论 1. 翻译,是指在计算机中放置一个能由计算机直接执行的翻译程序,它以某一种程序设计语言(源语言)所编写的程序(源程序)作为翻

编译原理pdf

下载地址:网盘下载 内容简介  · · · · · · 本书全面.深入地探讨了编译器设计方面的重要主题,包括词法分析.语法分析.语法制导定义和语法制导翻译.运行时刻环境.目标代码生成.代码优化技术.并行性检测以及过程间分析技术,并在相关章节中给出大量的实例.与上一版相比,本书进行了全面的修订,涵盖了编译器开发方面的最新进展.每章中都提供了大量的系统及参考文献. 本书是编译原理课程方面的经典教材,内容丰富,适合作为高等院校计算机及相关专业本科生及研究生的编译原理课程的教材,也是广大技术人员的极佳参

编译原理_2

编译器在分析阶段把一个源程序划分成各个组成部分,并生成源程序的内部表现形式.这种内部表现称为中间代码.然后,编译器在合成阶段将这个中间代码翻译成目标程序. 分析阶段的工作是围绕这编译语言的"语法展开的".一个程序设计语言的语法描述了该语言程序的正确形式.而该语言的语义定义了程序的含义.即每个程序运行的时候应该做什么事.比如: 广泛使用的表示方法来描述语法.上下文无关的文法或bnf范式. 使用现有语义表示方法来描述一个语言的语义的难度远远大于描述语言语法的难度. 上下文无关文法不仅可以描

编译原理--01 复习大纲(清华大学出版社第3版)

前言 目前以手中这本清华大学出版社出版的编译原理(第3版,张素琴等编著)作为复习总结,因为考试都是大题,一部分概念会被忽略.所有内容都需要通过举例和推导来帮助加深理解,优先为过几天的考试服务.该文实现了教材中那些特别复杂的推导符号,并且这几天会加紧持续更新. 第2章 文法和语言 符号和符号串 空符号串用\(\varepsilon\)表示,长度为0 若 \(\Sigma=\{0,1\}\) ,则 \(\Sigma^*=\{\varepsilon,0,1,00,11,000,001,...\}\),

编译原理课后作业【自顶向下分析法】语法分析

实验二: 题目:语法分析 目的:通过该实验掌握描述语法的文法和自顶向下分析法中的预测分析法. 要求:对给定的文法建立预测分析表:利用预测分析法对实验一的结果进行语法分析,对不符合给定文法的表达式给出出错位置信息. 内容:给定描述语法的文法为: E->E+T|T T->T*F|F F->i|(E) 题目如上描述. 用了STL里的MAP写了个程序,写的比较简单也可能有BUG,欢迎大家指出修正 Source code: 1 //Jeremy Wu {Wushuaiyi} CS1301 2 //

编译原理(四)语法分析之自顶向下分析

语法分析之自顶向下分析 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 基本过程分析 1. 一般方法:对任一字符串,试图用一切可能的方法,从树根节点(开始符号)出发,根据文法自上而下地为输入符号串建立一棵语法树.直观理解为从开始符号出发,依据规则建立推导序列,最后推至目标字符串. 2. 特点:分析过程是带有预测的,是一种试探过程.试探失败就会出现回溯问题,降低了分析的效率. 3. 存在问题:左递归问题.回溯问题. 问题一:左递归问题 1. 左递归文法:文法规则中有形如 \(