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


图69
接下来 , 要对e进行和第二个and操作符的整合处理 , 这个处理由函数实现 , 此时 , 会将e中的信息 , 转化为指令 , 得到图70的结果:
图70
完成处理之后 , 会调用函数 , 获取下一个token < , d > , 然后将其装载到新的结构e2中 , 得到图71的结果:
图71
接下来又到了 , 整合e和e2的流程了 , 完成整合之后 , 我们得到图72的结果:
图72
到这一步 , 我们的expr函数的处理就完成了 , 但是为了讨论的完整性 , 这里要将结构内的信息 , 转化为指令 , 于是得到如图73的结果:
图73
到这里为止 , 逻辑运算包含比较运算的情况 , 我就完成了论述了 , 当然还有or的情况 , 还有其他更复杂的组合 , 不过相信读者通过读懂上面这个例子 , 能够举一反三 , 自行推导 。最后我通过展示a==b为true或false , c和d都为true的情况 , 来展示一下指令的执行流程 , 其他的情况由读者自己推导 。
图74
a==b为true的情况 。
图75
a==b为false的情况 。
7、处理
这一部分 , 实际上就是对一个table进行编译 , 实际上 , 这个操作也并不复杂 , 现在通过一个例子来说明:
{ a, b, c = 10, d }
我们从图75-2开始 , 直至完整展现编译流程 。
图75-2
当lua编译器 , 遇到{的时候 , 直接生成指令 , 图75-2中的A域是0 , 表示生成的table放置在R(A)也就是R(0)上 。B域和C域均为0 , 表示它的和都是0 , 现在是个空表 。然后我们进入下一个操作之中 。
图75-3
回顾一下图6 , 在内部的处理流程之中 , 只有单个的 , 则是 , 这种exp需要直接生成入栈指令 , 稍后一并处理 。接下来 , 我们获得的token则是’,‘ , 这里直接跳过 , 直接获取下一个token < , b > , 此时生成新的指令 , 如图75-4所示:
图75-4
此时 , 直接跳过’,‘ , 处理下一个field , 得到图75-5的结果:
图75-5
这里对c=10生成了指令 , 这里并没有生成入栈指令 , 而是直接赋值 。然后我们进入到最后一个filed的处理之中 , 也就是将d生成入栈指令 , 得到图75-6的结果:
图75-6
最后 , 我们需要将已经入栈的参数 , 设置到table里 , 这些在栈中的变量 , 会被设置到table的array域中 , 于是得到图75-7的结果:
图75-7
最后这里生成了一个指令 , 它的A、B和C域的值分别是0、3和1 , A域指明了table在栈中的位置 , B域说明了从R(A+1)开始 , 一共有多少个栈上的变量 , 要被设置到table的array中 。我们现在来回顾一下 , 的含义:
OP_SETLIST A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B
A域指向了操作目标 , B域指明了从R(A+1)开始 , 一共有多少个栈上的变量 , 要被设置到R(A)的array列表中 , C域指明了它的array区间 , FPF指明了 , 一次通过指令 , 设置到table array列表中的最大批次 , 默认是50 。举个例子 , 比如我们现在有一个table , 现在有100个变量 , 要被设置到array中 , 那么这里需要生成两个指令 , 假设目标table在R(0) , 那么第一个指令则是