# 第四节 编译器前端

编程语言用到的编译器,说到底就是一种翻译工具,将一种计算机语言翻译为另一种计算机语言。编译器前端指的是编程语言的语法分析部分。

# BNF(巴科斯-诺尔范式)

在BNF出现之前的年代,计算机先驱们用字符串处理、正则表达式来解析语言文法,对中缀运算符通过波兰、逆波兰表达式等方式格式化处理。这种方式虽然能解析语言代码,但新的问题随之未来:语法解析方式与编译器代码耦合度极高,开发编译器虽然能一把梭,但在需要升级语言,修改语言语法的情况下,改起来如同地狱。

BNF实际是一种文法描述方式,能描述绝大部分计算机语言语法。它有非终结符与终结符两种类型的描述符。非终结符就类似二叉树(多叉树)的根节点和子节点,终结符就类似二叉树(多叉树)的叶子节点。其中根节点与子节点用于描述这棵树允许的生产方式,叶子结点就是编程语言的文本。

非终结符 终结符
描述对象 非终结符及终结符的组合 某一个或多个固定的文法内容

编译过程就像把一串代码塞给二叉树(多叉树)的根节点,然后让二叉树(多叉树)自由生长,当最后生长出来的形状通过中序遍历(打个比方)刚好能输出这一串代码,那么就完成了代码的解析。这棵树不是二叉树,它真实存在,名叫AST(语法解析树)。

# Antlr

Antlr是一个基于BNF改进的文法解析库,它使用了LL方式来解析自定义文法。它是目前使用最广泛的文法解析库。

举例使用Antlr描述四则运算

ADD_SUB:      '+' | '-';
MUL_DIV:      '*' | '/';
four_op:     ADD_SUB | MUL_DIV;
RAW_NUM:     [0-9]+;
num:         ADD_SUB RAW_NUM;
quotexpr:    '(' expr ')';
atom:        num | quotexpr;
expr:        atom (four_op atom)*;

其中大写字母开头的为终结符,小写字母开头的为非终结符,一行描述一种解析规则。规则语法是:

终结符或非终结符名称: 语法表达式;

语法表达式可以写圆括号()代表分组,问号?代表前者匹配0或1次,星号*代表前者匹配任意次数(0次或无数次),加号+代表前者匹配1次以上。

# LL与LR

LL就是从根节点开始,一枝一丫解析代码,最终生成整棵树。LR就是从叶子结点开始,一步一步逆推树结构,最终生成整棵树。

LL LR
理解的难易度
使用情况 广泛使用 极少使用
性能 偏高 偏低
是否有左递归问题 有(可以解决)
表达范围 相同 相同

# LL与LR解决不了的问题

TODO

# 就业方向

  • 基础设施(编程语言)领域