= Parse和Translate数学表达式 = 希望看到的产出:一系列执行期望动作的汇编语句 == 目标表达式 == {{{x = 2*y + 3/(4*z)}}} === single digits === 将expression定义为single digit并输出解析它的汇编语句 ||<#00FF00>输入单个数字测试程序通过|| === binary expressions === 将expression扩展为二元表达式并输出相应汇编语句. {{{ 1+2 or 4-3 or, in general, +/- }}} ||<#00FF00>输入1+2 Pass|| ||<#FF0000>输入单个数字 Failed|| === general expressions === {{{ ::= [ ]* }}} === using the stack === {{{ 1+(2-(3+(4-5))) }}} 由该表达式引出的问题。凡事有记录现场并转而干其他事情的情景,可能都需要Stack。 === MULTIPLICATION AND DIVISION === 关于优先级的问题,在这里的处理方式中根本就不存在:通过top-down分解、各个击破的方式,优先级问题被化解于无形。 这里只需要将term扩展一下即可: {{{ ::= [ ::= () }}} So easy!!! 注意expression用括号包围着。这里也是'''递归'''引入的地方,因expression定义链中的部分构成要素就是factor,而这里factor却又由expression定义。 === UNARY MINUS === 这里处理负号的策略是:在进行上面对expression的处理之前,先检测当前token是否为负号:若为是,则将该token当做负号特别处理;反之则进入已有的expression处理。 === A WORD ABOUT OPTIMIZATION === 优化就是提高生成的代码质量。有些优化只需要略施小计,在现有的parser中添加一点点代码即可达成。 两种策略: * Try to fix up the code after it's generated * 号称“peephole”的优化方法:发现可以优化掉的指令序列,用更优的指令序列代替。预置一些可以优化掉的指令序列套路,用“peephole”查看生成的代码,从中找出这些套路并执行替换。通常是编译器的第二遍,second pass。 * Try to generate better code in the first place * 生成代码前进行更多的test,使得特殊情况特殊对待,对应生成更高效的代码。 额外提一个作者独家优化秘方:少用stack,多用CPU寄存器。 ---- <>