由于昨天太累了。所以没有学习也没有写博客,今天打算看两课的内容,刚看完了第三课的内容,“上下文无关文法及分析”。这内容前两天大概看了一点,今天再次看的时候跟第二课的正则表达式对比学习,更有些体会。
首先编译器进行第一项工作:扫描程序时,主要是使用正则表达式,也就是在这个阶段去对源代码进行扫描做词法分析,也就是说明正则表达式是可以区分一段文字中的单词词组那样的功能。 在这一工作阶段结尾是生成了源代码的记号,方便进行第二步的工作:词法分析。这一阶段的主要任务就是确定程序的语法,也就是结构。比如在c语言或java程序中,如果定义一个不符合语言语法的代码,那么在语法分析阶段就可以发现错误,并采取相应的报错信息。词法分析进行检测的语法主要是通过上下文无关文法规则定义给出的。上下文无关文法与正则表达式有相似的命名惯例和运算。上下文无关文法的规则是递归,也就是说上下文无关文法里面有可以不断的代入过程,如:A=Aa|a,这个可以理解为,A=a*a*......,这个过程是一个不断的在Aa中的A再次代入A的值的过程。从功能上来说,正则表达式给出的是一个字符串的定义规范,而上下文无关文法则是给出的是一个语言的语法的规范,也就是说正则表达式是以字符为单位,检验字符串的合法性,而上下文无关文法则是以合法的字符串为单位,检验语言语法的合法性。
从规则上来说,正则表达式首先支持的运算是重复,并以等号为名字定义,而上下文无关文法不同,是以-->为名字定义,并没有重复的元符号,不过也好理解,上下文无关文法主要是推导,也就是说是一步一步推导出来的,所谓的推导是不断的由非终符号和终符号去代替非终符号。所以不能用等号来定义名字的。推导为构造来自一个初始的非终符号的特定终结符的串提供了一个方法,但是推导并没有唯一地表示出它们所构成的结构,也就是说同一个串可以有很多推导。而另一种表示法就是树结构:分析树,分析树是一个做了标记的树,内部的结点由非终符号标出,而叶子结点则由终结点标出,不过同一分析树可以有不同的推导方法的表示,如最左推导,最右推导等等,分析树在描述记号串结构上面是很不错的表示法,将分析树的运算符号作为根结点,而值为叶子。则变为抽象语法树,从二叉树的结构上来看,采用二叉树遍历就可以访问该结构了。
分析树和语法树唯一地表达了语法的结构,但是文法有可能允许一个串有多个分析树,这样对于两个不同的分析树就产生了一个问题:二义性,如运算优先的问题,左优先与右优先,if -else匹配的问题。不过这样的问题可以用文法定义的技巧能够解决。