递归下降语法分析
递归下降本质
递归下降使用递归推导方式来解析语法,其要求文法能够使用递归方法追个推导,最终达到文法匹配的目的。例如如下计算逻辑表达式的BNF文法:
1 <expr> ::= <term> <expr_tail> 2 <expr_tail> ::= '&' <term> <expr_tail> 3 | '|' <term> <expr_tail> 4 | <empty> 5 6 <term> ::= '(' <expr> ')' 7 | '!' <term> 8 | 'y' 9 | 'n'
在上述的逻辑运算表达式文法中,并非只按照递归来编写文法的,而是在递归的同时结合了推导,如果只使用递归,将无法进行解析,如下错误的文法所示:
<expr> ::= <term> <expr_tail> <expr_tail> ::= '&' <term> | '|' <term> | <empty> <term> ::= '(' <expr> ')' | <expr> | '!' <term> | 'y' | 'n'
使用上述的文法是无法正常解析语法的,因为上述的第一个推导式与第三个推导式存在左递归,会进入无限循环,所以在递归下降法要求文法中不能存在左递归,必须要将左递归转为右递归,也就是第一个BNF文法。 注意,左递归转为右递归有一个拆分技巧,例如左递归F = F'ab'可以先展开F = F'abab',其匹配的规则就是'abab...',显然可以写成'a'G启动G = 'ba',从而G = 'a'G'b',其实左递归转为右递归就是推导的方向不同而已,本质是一样的,都是手动构造规约。
递归下降与树的对应关系
递归下降可以使用树形结构来进行推导,一般在进行语法分析时会动态生成语法树(AST),并将语法树作为语义分析的输入。语法树与语法分析一一对应,如下所示。
一般在编写BNF范式时,也经常会使用语法树事先进行推导,并从具体的句子中规约出非左递归文法,最后再使用递归下降法来进行语法分析。
Pratt解析器(算符优先级算法)