语法分析技术简介
语法分析(parsing or syntax analysis)最常用于实现编程语言的编译器,它的作用是输入一串词法单元,验证这些词法单元组成句子的语法是否正确,并输出语法分析树。
这就好比假如词法单元是单词,语法分析就是分析一串单词组成的句子能否套入某类语法句型,并确定每个单词的词性,以便于进一步分析句子的语义。
然而语法分析不仅仅适用于编译器实现,它是一项类似正则表达式般通用的技术。如《Parsing Techniques》介绍,语法分析广泛应用于数据库接口、自描述数据、人工智能等领域。
语法分析技术的核心思想主要包括两方面:
- 描述语法句型的方法——上下文无关文法。
- 根据文法分析语法的算法——自顶向下分析算法、自底向上分析算法。
上下文无关文法(context-free grammar, CFG)
上下文无关文法是一种描述语法句型的方法,其概念与正则表达式非常类似。事实上正则表达式也是一类文法——正则文法(regular grammar),正则文法的表达能力与正则表达式完全等价。
上下文无关文法是正则文法的超集,正则文法只能表达线性语法结构,而上下文无关文法可以表达树状语法结构。诸如编程语言中的嵌套条件、循环等语法,因为是树状语法结构,所以需要用上下文无关文法表达。
一个上下文无关文法由一个四元组定义, :
- 是一组非终结符(nonterminal symbol),它们表示句子或短语句型。
- 是一组终结符(terminal symbol),它们是构成句子的词语。
- 是一组产生式(production rule),它们定义了从 到 的关系。
- 是一个起始符(start symbol),它是 中的一个元素,表示最顶层的句型。
比如,如下的上下文无关文法,定义了涵盖加法、乘法和计算优先级的表达式:
上述文法可推导出表达式: ,并构建如下语法分析树:
编译器的语法分析过程,实质就是根据编程语言定义的文法,构建语法分析树的过程。不过要注意的是,虽然上下文无关文法能够描述编程语言的大部分语法,但诸如标识符先声明后使用这样的约束,并不能通过上下文无关文法来描述。
再介绍几个关于文法的重要概念:
- 二义性(ambiguity):如果一个文法可以为某个句子构建多棵不同的语法树,那么这个文法就是二义性的。设计文法时需要注意消除文法的二义性。
- 左递归(left recursive):如果一个文法中有一个非终结符A,它在经过一次或多次推导后,产生句型的最左边也是非终结符A,那么这个文法就是左递归的。LL分析算法不能处理左递归文法,需要转换消除。
- 推导(derivation):使用一个产生式把一个非终结符替换为产生式右边内容的过程。推导又分为最左推导和最右推导,最左推导总是选择句型最左的非终结符推导(应用于自顶向下分析算法),而最右推导则总是选择句型最右的非终结符推导(应用于自底向上分析算法)。
- 规约(reduction):规约是推导的逆操作,它是使用一个产生式将产生式右边内容替换为一个非终结符的过程。
语法分析算法
语法分析算法大致有三种类型:通用型、自顶向下型和自底向上型。通用型语法分析算法适用于任意文法,但其分析效率非常低,实际并无太多应用,所以主要讨论自顶向下型和自底向上型的语法分析算法。
不论哪一种语法分析算法,分析效率都是首要考虑的目标。因为一个文法可以构建无穷多种语法分析树,如果在分析过程中需要遍历语法分析树,或者做很多无效的尝试和回溯,那可想而知分析效率是无法接受的。
然而,任意设计的文法无法避免低效的分析回溯,而自顶向下型和自底向上型分析算法就是在文法设计中加入一些设计约束,从而使语法分析过程不需要回溯,大大提高语法分析的效率。
自顶向下型语法分析算法是从语法分析树的根节点开始,使用最左推导的方法,推导构建完整的语法分析树,适用于LL(k)文法。LL(k)文法的第一个L是输入从左到右(left to right),第二个L是最左推导(leftmost derivation),k是前瞻符号(lookahead symbol)数量。
比如LL(1)文法,一个文法G是LL(1)的,当且仅当G的任意两个不同的产生式 满足如下条件:
- 如果 、 均不能推导出 ,则 。
- 和 最多只有一个可以推导出 。
- 如果 ,则 。
自底向上语法分析算法是从语法分析树的叶子节点开始,逐渐向上到达根节点,反向构造出一个最右推导序列,从而构建完整的语法分析树,适用于LR(k)文法。LR(k)文法的L是输入从左到右,R是反向最右推导(rightmost derivation in reverse),k是前瞻符号数量。
LR文法没有严格的定义,一个文法只要能构造出语法分析表,适用移入—规约语法分析器解析,它就是LR文法。
LR文法相比LL文法更具备技术优势,原因包括:
- LR文法几乎适用于所有编程语言。
- LR分析算法过程无回溯,是最高效的分析算法之一。
- LR分析算法可尽早地检测到语法错误。
- LR文法是LL文法的超集,LR文法约束非常宽松。
参考文献
[1] Alfred, V. A.等著.编译原理(第2版).赵建华等译.北京:机械工业出版社,2009
[2] Dick Grune,Ceriel J.H. Jacobs著.Parsing Techniques (Second Edition).New York:Springer,2008
[3] https://en.wikipedia.org/wiki/Context-free_grammar
版权声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。