代码之家  ›  专栏  ›  技术社区  ›  darkfrei

如何计算伪SQL风格的算术表达式(Lua 5.1)

  •  2
  • darkfrei  · 技术社区  · 6 月前

    在love2D中,我有一个代表数学表达式的字符串,例如:

    local expr1 = "[p35] div [p36]"
    local expr2 = "((([p35]*100) div [p36]) mod 100)"
    local params = {p35 = 15025, p36 = 100}
    
    local value1 = evaluateExpression(expr1, params) -- expected 150
    local value2 = evaluateExpression(expr1, params) -- expected 25
    

    我如何评估这个表达式?

    local function evaluateExpression(expr, params)
        if not expr or not params then return nil end
    
        expr = expr:gsub("%[p(%d+)%]", function(num)
                local key = "p"..num
                local val = params[key]
                if val == nil then val = 0 end
                return tostring(val)
            end)
    
        expr = expr:gsub("(%d+)%s+div%s+(%d+)", "math.floor(%1 / %2)")
        expr = expr:gsub("div", "/")
        expr = expr:gsub("mod", "%")
    
    -- "math.floor(15025 / 100)+(((15025*100) / 100) % 100)/100"
        local f, err = loadstring("return " .. expr)
        if not f then
            print("parse error:", err)
            return nil
        end
    
        local success, result = pcall(f)
        if not success or type(result) ~= "number" then
            print("runtime error:", result)
            return nil
        end
    
        return result
    end
    
    1 回复  |  直到 6 月前
        1
  •  1
  •   Oka    6 月前

    在该替换字符串中, % 用作转义字符。

    expr = expr:gsub("mod", "%")
    

    string.gsub (s, pattern, repl [, n])

    如果repl是一个字符串,则其值用于替换。字符%用作转义字符:repl中形式为%n的任何序列,n在1到9之间,代表第n个捕获的子字符串的值(见下文)。序列%0代表整个比赛。序列%%代表单个%。

    逃离 % 使您的示例运行良好:

    expr = expr:gsub("mod", "%%")