编译原理与编译构造 课堂笔记9

DFA 转换表

例:

Ii a b
0 1 2
1 1 3
2 3
3 1

则由表的前两行得 I0aI1,I0bI2

大概代码如下

state = 0;
while(1) {
    ch = getchar();
    s = lookup(state, ch);
    if(s == ' ' && s is non-terminal state) {
        error;
    } else if(s == ' ' && s is terminal-state) {
        ungetchar();
        return;
    } else {
        state = s;
    }
}

Language By experience RE

  1. 逐步求精法
  2. FA-based

例:一个2进制数能被3整除,我们做出在某个数后面添加一个0/1后模3余的结果电路转换图

编译原理与编译构造 课堂笔记9_第1张图片

语法分析

自上而下

递归下降分析法

一个非终结符对应一个子程序

若有以下文法:

SaA|bB

AcD|d

BeB|f

Dg

则有对应程序:

int S() {
    ch = getchar();
    if(ch == 'a') {
        return A();
    } else if(ch == 'b') {
        return B();
    } else {
        return 0;
    }
}
int A() {
    ch = getchar();
    if(ch == 'c') {
        return D();
    } else if(ch == 'd') {
        return 1; // 表示结束
    } else {
        return 0; // 表示出错
    }
}
// 其余同理

换一种文法:

SaA|aB

AAd|d

BBe|e

int S() {
    ch = getchar();
    if(ch == 'a') {
        if(A()) {
            return 1;
        } else {
            return B();
        }
    }
}

int A() {
    A();
    if(ch == 'd') {
        return 1;
    } else {
        return 0;
    }
}

在这种情况下会出现回溯和栈溢出

不能出现公共左子表达式和左递归,会出现回溯。

因此想用这种方法的话,对文法的要求比较高。

预测分析法

预处理:

提取最大公共左子表达式

消除左递归

把左递归变成右递归的形式

左递归:

  • 直接左递归: AAα|β
  • 间接左递归: ABα|β,BAβ|θ
消除直接左递归

AAα|ββ,βα,βα2,,βαn,βαn(n0)

αn=A ,则有 AβA,Aϵ|αA

消除间接左递归

SQc|cQRb|bRSa|a

此时有间接左递归

我们强行规定优先级: S>Q>R

SQc|cQRb|bRSa|a(Qc|c)a|aQca|ca|a(Rb|b)ca|ca|aRbca|bca|ca|a

此时由消除直接左递归的方法得, R(bac|ca|a)RRbcaR|ϵ

先消除直接左递归,再消除间接左递归

SQc|cQQd|Rb|bRSa|a

Q(Rb|b)QQdQ|ϵ

SQRSQc|cQ(Rb|b)QQdQ|ϵR(Qc|c)a|aQca|ca|a(Rb|b)Qca|ca|aRbQca|bQca|ca|a

此时再用消除直接左递归的方法再消除一下就好了

你可能感兴趣的:(编译原理与编译构造)