首页 > 代码库 > 《编译原理》学习总结(1)

《编译原理》学习总结(1)

语法:描述一个程序语言的正确性

语义:描述一个程序的含义
 
上下文无关文法是用来描述语法的一种办法,而描述语义的难度太大。
 
上下文无关文法中的一些概念:
终结符号
     可以理解为关键字或者一些最小单元的字符,比如while if 0 1 3 之类
非终结符号
     是终结符号的集合,是自己命名的一个东西比如 digit -> 0 | 1|2|3…|8|9,这里digit称为非终结符号
产生式
     产生式由两部分组成,左边是非终结符号,右边是非终结符号和终结符号的集合
     比如:digit -> 0 | 1|2|3…|8|9,这一行本身就是产生式
开始符号
     一段文法的第一行称为开始符号
 
文法的二义性
list -> list + digit | list - digit
list -> digit
digit -> 0|1|2|3|4|5|6|7|8|9
 
上面定义了一个文法,然后一个demo:9 - 5 + 3
 
用语法树来解析,过程如下:
 
1.先列出来目标内容
9 - 5 + 3
 
2.然后把他们都看成某个非终结符号
 
digit      digit       digit 
9       -    5     +     3 
 
3.再往上找关系
list
digit      digit       digit 
9       -    5     +     3  
 
可以发现,list - digit可以组成list。
     list
  /         \
list        digit
digit        |          digit 
9       -    5     +     3   
 
4.继续
                list
       /                   \
     list           +   digit
  /         \               |
list    -   digit          |
digit        |             |  
 9       -   5     +     3    
 
这样就根据一个文法定义,一个语句,生成了唯一的语法书,那么这个语句就没有二义性。
你可以试试,先将 5 + 3 -> list + digit,这就变成了list了,然后 9 - list,也就是 digit - list 或者是 list - list ,你就会发现文法中并没有这样的定义,也就是不存在这样的语法,这样也就造成了以上的内容只有一种解析结果。
 
如果从叶子节点开始计算,计算顺序就是 (9 - 5) + 3 是正确的
如果有二义性,那么有可能出现不同的计算顺序,导致结果出错,所以文法的定义没有二义性很重要
 
运算符的结合性
结合性有左结合和右结合。
 
左结合
当一个数字左右两边都有运算符的时候,要根据运算符的结合性来决定数字是属于哪一边的
比如+是左结合
1+2+3 -> (1+2)+3 因为2左右两边都有+号,+号是左结合的,所以2是属于左边的运算符。
用文法定义的时候:
result -> result + digit | result
digit -> [0-9]
用语法树来表示
              result
       result       digit
result    digit       |
 digit        |         |
  1      +   2   +   3
 
再看右结合
a = b = c
b的左右两边有运算符 = 
=运算符是右结合的,所以b 是优先属于右边的操作符
a = (b = c)
 
文法定义:
result -> char = result | char
char-> [a-z]
 
用语法树表示:
      result
char     result
|       char  result
|         |       char
a   =   b   =   c 
 
运算符的优先级
比如 * / 和 +- 就是两个级别的运算符,设计文法的时候可以将两个独立的分开比如如下的文法
 
expr -> expr + term | expr - term | term     //expr是加减表达式
term-> term* factor | term/ factor | factor     //term是乘除表达式
factor -> digit | expr
digit -> [0-9]
 
例子
1 + 2 * 3 //我们应该优先计算 2 * 3,直接在本子上画个语法树就出来了,我只能说,真的很巧妙!
 
任意优先级层次的语法
factor理解为一个因子,不可以被任何运算符分开,因为它就是数字本身了
高优先级的运算符可以把低优先级的运算符分开
比如 1 + 2 * 3 
可以看成 1 + x 但是 * 比+的优先级更高,它可以把x分开
 
真心觉得这些东西都非常的巧妙,智慧无穷……
 
原文地址:http://www.cnblogs.com/kross/p/4100317.html
作者:kross(krossford@foxmail.com)

《编译原理》学习总结(1)