表达式的语法 表达式可表示为树结构,但为了在程序中表示,线性化是 需要的。 前缀(波兰前缀)记法。 这是波兰数学家发明的无括号记号法 如:fxy,z) X+ab-ca LISP使用了该记号法的变种,称为剑桥波兰,用括号 将操作符及其操作数括起来,如:(X(+ab-ca)。 后缀(逆波兰)记号法 类似于前缀,但操作符数在后面,如: ab+ca-X 中缀记号法 最适合二元操作,也是我们最常用的方式
•表达式的语法 表达式可表示为树结构,但为了在程序中表示,线性化是 需要的。 •前缀(波兰前缀)记法。 这是波兰数学家发明的无括号记号法。 如:f(x,y,z) ×+ab-ca LISP使用了该记号法的变种,称为剑桥波兰,用括号 将操作符及其操作数括起来,如:(X(+ab)(-ca))。 •后缀(逆波兰)记号法 类似于前缀,但操作符数在后面,如: ab+ca-× •中缀记号法 最适合二元操作,也是我们最常用的方式
表达式(a+b)×(C-a)的树结构
表达式(a+b)×(c-a)的树结构
表达式的语义 上三种记号法对语言的设计都有一些有用的属性,在如何计 算表达式值方面也有不同。 前缀计值 可以通过一遍扫描计值每个表达式,然而需要知道每个 操作的操作数量。除了可省去括号外,前缀表达式在语 言设计中有如下价值 般的函数调用均采用前缀方式。 2、可表示有任意数量操作数的操作,写表达式只需 个语法规则。 3、解码可以机械地很容易地进行,将其翻译成简单 代码序是容易的。 下面算法用一个执行栈计值表达式:对表达式P, 1、如P中下一项是操作子,压入栈项,设置所需参数 数目。 2、如P中下一项是操作数,压入栈项 3、如栈项n项是操作数(对栈中第一个n元操作), 则可以进行计值,用计值结果替代该操作符和操作数
•表达式的语义 上三种记号法对语言的设计都有一些有用的属性,在如何计 算表达式值方面也有不同。 •前缀计值 可以通过一遍扫描计值每个表达式,然而需要知道每个 操作的操作数量。除了可省去括号外,前缀表达式在语 言设计中有如下价值: 1、一般的函数调用均采用前缀方式。 2、可表示有任意数量操作数的操作,写表达式只需 一个语法规则。 3、解码可以机械地很容易地进行,将其翻译成简单 代码序是容易的。 下面算法用一个执行栈计值表达式:对表达式P, 1、如P中下一项是操作子,压入栈项,设置所需参数 数目。 2、如P中下一项是操作数,压入栈项。 3、如栈项n项是操作数(对栈中第一个n元操作), 则可以进行计值,用计值结果替代该操作符和操作数
后缀计值 后缀计值时,操作符紧跟其操作数后而且操作数已被计值 1、如P中下一项是操作数,压入栈顶 2、如P中下一项是n元操作符,n个参数必须是栈顶部 的n个元素,计算结果并替换这n个元素 这种计值策略直接、简单,是很多翻译器中生成表达 式代码的基础 中缀计值 中缀是常见的,但用于程序语言中会导致一些问题 1、只适合于二元操作。语言单用中缀是不够的,还需 使用前缀,这二者的混合使翻译更为复杂。 2、表达式中涉及多个中缀操作时,如不使用括号,则 存在固有二义性。为解决这个问题,通常引入隐含的 规则
•后缀计值 后缀计值时,操作符紧跟其操作数后而且操作数已被计值。 1、如P中下一项是操作数,压入栈顶 2、如P中下一项是n元操作符,n个参数必须是栈顶部 的n个元素,计算结果并替换这n个元素。 这种计值策略直接、简单,是很多翻译器中生成表达 式代码的基础。 •中缀计值 中缀是常见的,但用于程序语言中会导致一些问题: 1、只适合于二元操作。语言单用中缀是不够的,还需 使用前缀,这二者的混合使翻译更为复杂。 2、表达式中涉及多个中缀操作时,如不使用括号,则 存在固有二义性。为解决这个问题,通常引入隐含的 规则
操作子计值顺序 X X 3 3
操作子计值顺序