上一篇文章提到了在Lua中实现类似于JavaScript中的eval函数,遗憾是该eval函数不支持赋值语句,原因是Lua的赋值运算符是不支持返回值。所以如果要让该eval函数也支持赋值语句,就需要一个额外的工作,让它鉴别一个语句是不是赋值语句,如果是,则return的是被赋值后变量的值。为此,我写了一个isAssignmentExpression函数,比较粗糙,不过够用了,基本思想是检测语句中第一个出现的”=“操作符,且该”=“不能在一对引号当中。
-- Lua code function isAssignmentExpression( str ) local i = 1; local curChar; local quotesType = "none" -- none, single or double local isEscaping = false curChar = string.sub( str, 1, 1 ) while ( curChar ~= "" ) do if ( curChar == "'" and isEscaping == false and quotesType ~= "double" ) then if ( quotesType == "single" ) then quotesType = "none" elseif ( quotesType == "none" ) then quotesType = "single" end end if ( curChar == """ and isEscaping == false and quotesType ~= "single" ) then if ( quotesType == "double" ) then quotesType = "none" elseif ( quotesType == "none" ) then quotesType = "double" end end if ( curChar == "\" and isEscaping == false ) then isEscaping = true else isEscaping = false end if ( curChar == "=" and quotesType == "none" ) then if ( string.sub( str, i+1, i+1 ) ~= "=" ) then return true, string.sub( str, 1, i - 1 ) else return false end end i = i + 1 curChar = string.sub( str, i, i ) end return false end function eval( str ) local bAssign local var bAssign, var = isAssignmentExpression( str ) if ( bAssign ) then print( "Assignment, var=" .. var ) loadstring( str )() return loadstring( "return " .. var )() else return loadstring( "return " .. str )() end end -- 以下是一组测试 print( eval( "3+4" ) ) -- 7 function Multiply( a, b ) return a*b end print( eval( "Multiply( 3, 4 )" ) ) -- 12 print( eval( "i" ) ) -- nil print( eval( "i = 1" ) ) -- Assignment, var=i -- 1 print( eval( "i = i + 1" ) ) -- Assignment, var=i -- 2 print( eval( "i" ) ) -- 2 print( eval( "i+1" ) ) -- 3 print( eval( "i, j = 4, 5" ) ) -- Assignment, var=i, j -- 4 5 print( eval( "i = {}" ) ) -- Assignment, var=i -- table: 003CD818 print( eval( "i[ "0" ] = 0" ) ) -- Assignment, var=i[ "0" ] -- 0 print( eval( "i[ "\"0=" ] = 1" ) ) -- Assignment, var=i[ ""0=" ] -- 1 print( eval( "i.name="hello"" ) ) -- Assignment, var=i.name -- hello print( eval( "i[0], i.name = 4" ) ) -- Assignment, var=i[0], i.name -- 4 nil print( eval( "i == 10" ) ) -- false
Recent Comments