自顶向下语法分析器

参考资料:

  1. 聊聊编译原理(二) - 语法分析
  2. Let’s Build A Simple Interpreter. Part 1.
  3. 编译原理(哈工大) - 19.4-1自顶向下分析概述(Av17649289,P19)
  4. 03-2-34-编译原理-姜守旭-4、03-4-12-编译原理-姜守旭-1
  5. 华保健网易课程
  • 自顶向下分析法
    最左推导和最右推导


    image.png

    image.png

    image.png

下面是参考资料1中自顶向下分析算法,但我在准备自己实现的时候在backtrace这里困住了,网上也找不到资料??

tokens = []
i = 0
stack = [S] # S 是起始符号
while stack is not None:
    if stack[top] is terminal t:
        if t == tokens[i]:
            i += 1
            pop()
        else
            backtrace()  # 回溯
    else stack[top] is nonterminal T:
        pop()
        push(the next right hand of T)
  • 递归下降分析法
    这种好像最后语法要转化好才行,不能出现某个过程里面可以得到两种,如果有两种,那么我们得到其中一种后就回不来了,没有回溯的过程。
    eg:
S->AB
A->aA|空
B->ab

当遇到ab的时候,我们进入A(),由于第一个是'a',符合,我们就退出A(),在进入B(),这样就错啦,实际上A应该解释为空才对。
因为上面的语法的意思就是a*ab的ab串,我们可以写成下面的形式:

S->aAB
A->aA|空
B->b

这样用这种递归下降分析法就没有问题了,所以有可能不是方法不对,而是语法不对。递归下降分析法需要首先调整好语法,或者提前算出各个分支不同的前导项。但实际上这不是很大的问题。
再看华保健网易课程中的例子:
下面给出的表达式开始两个选择都是num不知道选哪个?注意这里语法是左递归


image.png

接着我们改变左递归的做法就可以做了。


image.png
  • 预测分析法
  • 自顶向下的问题
    1.二义性
    给定特定文法画出两棵分析树
    if if else
    2.回溯问题
    3.左递归引起的循环问题
    A->Aa|b 要表示baaaaa...那么可以写成A->bB B->aB|空
    间接左递归也是会引起问题
    A->Ba B->Ab


    image.png
image.png
image.png
  • LL(1)的解释
    第一个L:从左到右输入
    第二个L:最左推导
    1:采用一个前看负号
    递归下降分析法需要回溯,效率比较低
    预测分析是递归下降分析的一个特例,通过向前看固定个数(通常为1)来选择正确的产生式。

多了一个分析表


image

跟上面自顶向下分析法的不同,引入一个分析表,非终结符就查看表,其他的时候如果正确都是弹出跟输入相同的token,若栈顶跟输入不同,那么出错!!:


image.png

FIRST(NT):从非终结符NT开始推导得出的句子开头的所有可能终结符的集合
NT->a...
FIRST(NT) U= {a}
NT->M...
FIRST(NT) U= FIRST(M)

非终结符FIRST集演示:


image.png

我们要求得每条语法(也就是右边对应的串)的FIRST集,利用上面求出来的非终结符FIRST我们进一步可以求出任意串的FIRST集如下:


image.png
  • LL(1)文法:分析表没有多个转移规则


    image.png

你可能感兴趣的:(自顶向下语法分析器)