自顶向下语法分析原理与设计思想

      这里重在讲解设计思想和原理,由于时间久远,一些知识的记忆不太清晰,若有不当之处,请多多指出。

      编译原理中的自顶向下语法分析的算法步骤有点麻烦,但是原理与设计思想,及其简单,甚至于没有技术含量。

      首先解释语法树,语法树中主要包含了终结符与非终结符,什么是终结符,终结符就是不能继续往下扩展,它就是叶子节点的符号,终结符就是我们实际些的代码一一对应的符号,注意这里是一一对应,不是一样。我们代码里写的是什么,是一堆字符,说白了就是26个英文字母,外加空格和各种符号。这些并不直接与终结符对应,我们看代码怎么看,这是int ,这是for,这是变量名,我们都是以单词为单位来看的。同样,我们在设计编译器时也是这么来的,首先将这些字符合并成一个个单词,单词里还包含了一些特定的信息,这是变量名,但是到底对应到那种类型,以及它的值等等,这些信息我们都要保存。这部分工作由词法分析(本质是状态机)完成,这里我们不展开。词法分析得到的符号流与我们的终结符一一对应起来。

       非终结符做什么,就是扩展,按照给定的文法不断扩展(当然不是瞎扩展,有它内在的结构和逻辑关系的),所以我们的程序可以写的很长。语法判断就是从根节点(非终结符)开始向下生长,一直生长成叶子节点都是终结符才停止,这里的终结符和我们程序代码相对应。这里大家可以简单理解,非终结符就是用来按照一定的结构和逻辑顺序生出更多的终结符的,终结符才和程序相对应。可以看下面的图,加以理解,A、B、C为非终结符,int、i、char、c等为终结符。

自顶向下语法分析原理与设计思想_第1张图片

       如何判断程序是否符合语法,如果按照文法可以生成相应的语法树,树的叶子节点,及终结符与我们的程序的符号流一一对应,我们的程序就正确,如果不是就错误。每个非终结符会不断扩展,最终扩展出来一颗树,我们先求出这课树的第一个叶子节点是什么。一个非终结符可以有很多种扩展方式,假如我们知道了这个非终结符要扩展出来的第一个终结符,那么我们就可以确定这个非终结符该如何扩展,如果非终结符扩展不出来这个终结符则错误,如果这个终结符可以由多种扩展方式得到我们也认为错误(这里只考虑最简单的语法分析,可以有其它的方法进行进一步判断)。这样我们只需要得一个非终结符对应的树的第一个叶子节点即可。

       怎么得到呢?把生成的叶子节点看做一行,如果我们知道了这个非终结符生成的第一个终结符前面的终结符,我们就可以通过比较,略过前面的部分,找到它生成的第一个终结符。如C生成的char,如果知道了int和i,那么很容易知道知道char的位置,再根据char来扩展C。

      怎么做?图中B先扩展后就知道了C生成的第一个终结符,所以,我们按照树的先序遍历过程就可以做到,一个节点的左兄弟节点先被遍历,知道了左兄弟节点扩展出来的终结符,然后再遍历该节点,此时已经可以确定该节点生成的第一个非终结符的位置,进而可以判断该非终结符如何继续扩展,或者出现错误。如果遍历的是叶子节点,及终结符,就要和符号流里的结果进行比较,一致的话继续,不一致错误。如果整个过程没有出现错误,则会生成一棵树,这个树的叶子节点就是我们词法分析生成的符号流。

你可能感兴趣的:(自顶向下语法分析原理与设计思想)