上一篇文章提到了在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