上 构建Lua解释器Part7:构建完整的语法分析器(17)


图58
然后整合e和e2 , 并且生成OP_EQ指令 , 指令和指令 , 如图59所示:
图59
我们需要关注几个地方 , 第一个是被复位了 , 第二个是OP_EQ指令 , 如果测试失败 , 则跳过指令 , 进入第一个指令 , 然后将0值赋值到R(A)中 , 然后PC寄存器跳到蓝色箭头所指向的位置 。如果测试成功 , 则下一个指令执行指令 , 然后PC寄存器跳转到黑色箭头指向的位置 。我们现在先来看一下a==b成立的情况 , 它如图60所示:
图60
图中的黑色箭头 , 就是指令执行的顺序 , 现在我们来看另一种情况 , 当a==b不成立的情况 , 它如图61所示:
图61
黑色箭头是指令的执行顺序 。对于不等于的情况 , 只需要将OP_EQ指令的A域由1变为0即可 , 其他的比较运算 , 读者可以根据前面的虚拟机指令说明 , 将其套入我们刚刚讨论过的指令生成流程之中 , 这个工作就交给读者自己去推演 , 这里不再赘述 。
6、逻辑运算中包含比较运算的情况
我们前面已经讨论了逻辑运算和比较运算的情况 , 现在来讨论一下逻辑运算和比较运算结合的情况 。这点非常重要 , 为什么说这点很重要呢?因为比较运算生成的虚拟机指令 , 和逻辑运算结合 , 会改变原有的一些参数 , 我将结合如下的例子 , 来论述这个流程:
a == b and c and d
和前面的流程一样 , 首先我们获得的第一个token是< , a > , 然后此时要进入到expr函数的执行流程之中 , expr函数首先要识别第一个token , 这是一个 , 因此 , 此时需要将变量a装填到结构之中 , 得到图62所示的情况:
图62
在完成a变量的装填之后 , 此时会调用函数 , 获取下一个token TK_EQ , 然后需要对刚刚装填好的结构变量 , 和这个操作符做一次“中序处理” , 也就是通过函数来处理它们之间的关系 。在这种情况下 , 编译器会将刚刚的信息 , 转化为指令 , 得到图63的结果:
图63
完成函数的调用之后 , 我们获得了下一个token < , b > , 此时需要将b装填到新的结构之中 , 得到图64的结果:
图64
在获得了e和e2两个结构之后 , 我们需要对它们进行后缀表达式来计算 , 操作符是== , 此时需要将e2也转化成虚拟机指令 , 于是得到图65的结果:
图65
现在的情况是 , 两个操作数已经入栈 , 然后需要根据操作符进行后缀表达式运算 , 我们当前的操作符是== , 此时生成OP_EQ和指令 , 如图66所示:
图66
我们现在获得了新的token ,  , 前面经过比较运算得到的结果 , 存储到了结构之中 , 现在要对这个结构中的信息 , 和操作符进行整合处理 , 处理它的函数是函数 , 此时 , 我们需要将e->info的信息 , 赋值给e->f , 并且修改OP_EQ指令的A域 。得到图67的结果:
图67
接下来 , lua 会调用函数 , 获得下一个token < , c > , 并且将token装填到新的结构之 , 得到图68的结果:
图68
此时我们获得了e和e2 , 现在要对他们进行后缀表达式处理 , 处理函数是 , 而操作符是第一个and , 于是有图69的结果: