Lua数值运算指令解析与实现
以下操作码中OP_POWER对应幂运算,其余指令遵循相似处理逻辑
typedef enum {
/*----------------------------------------------------------------------
name args description
------------------------------------------------------------------------*/
//......
OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
OP_MOD,/* A B C R(A) := RK(B) % RK(C) */
OP_POWER,/* A B C R(A) := RK(B) ^ RK(C) */
OP_UNARY_NEGATE,/* A B R(A) := -R(B) */
OP_LOGICAL_NOT,/* A B R(A) := not R(B) */
//......
} OpCode;
lparser.c中priority数组用于记录操作符的左右优先级,数值越大表示优先级越高
static const struct {
lu_byte left; /* 左侧优先级 */
lu_byte right; /* 右侧优先级 */
} priority[] = { /* 操作符顺序 */
{6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* 加减除取模 */
{10, 9}, {5, 4}, /* 幂运算与连接符(右结合) */
{3, 3}, {3, 3}, /* 等值比较 */
{3, 3}, {3, 3}, {3, 3}, {3, 3}, /* 序关系 */
{2, 2}, {1, 1} /* 逻辑与或 */
};
#define UNARY_PRIORITY 8 /* 一元操作符优先级 */
优先级处理主要通过subexpr函数实现
/*
** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
** 其中`binop`为优先级高于`limit`的二元操作符
*/
static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int current_limit) {
BinOpr op;
UnOpr uop;
enterlevel(ls);
uop = getunopr(ls->t.token);
if (uop != OPR_NOUNOPR) {
// 处理一元操作符
luaX_next(ls);
subexpr(ls, v, UNARY_PRIORITY);
luaK_prefix(ls->fs, uop, v);
}
else simpleexp(ls, v);
/* 循环处理优先级高于限制的操作符 */
op = getbinopr(ls->t.token);
while (op != OPR_NOBINOPR && priority[op].left > current_limit) {
expdesc v2;
BinOpr nextop;
luaX_next(ls);
luaK_infix(ls->fs, op, v);
/* 递归处理右侧表达式 */
nextop = subexpr(ls, &v2, priority[op].right);
luaK_posfix(ls->fs, op, v, &v2);
op = nextop;
}
leavelevel(ls);
return op; /* 返回未处理的操作符 */
}
以2^1^2为例,解析过程如下:
subexpr(0)
读取"2"
调用simpleexp()解析常量
读取"^"
若左侧优先级10大于当前限制0:
调用subexpr(9)处理右侧
读取"1"
调用simpleexp()解析常量
读取"^"
若左侧优先级10大于当前限制9:
调用subexpr(9)处理右侧
读取"2"
调用simpleexp()解析常量