Die Dokumentation für dieses Modul kann unter Modul:Expr/Doku erstellt werden
--[=[ 2016-05-26 Expr * max * min * TemplateMax * TemplateMin * booland ]=] local messagePrefix = "lua-module-Expr-" local l10nDef = {} l10nDef[ "en" ] = { ErrorExpr = "Error in mathematical expression, function#parameter" } l10nDef[ "de" ] = { ErrorExpr = "Fehler in mathematischem Ausdruck, Funktion#Parameter" } local function factory( say ) -- Retrieve localized message string in content language -- Precondition: -- say -- string; message ID -- Postcondition: -- Return some message string -- Uses: -- > messagePrefix -- > l10nDef -- mw.language.getContentLanguage() -- mw.message.new() local c = mw.language.getContentLanguage():getCode() local m = mw.message.new( messagePrefix .. say ) local r = false if m:isBlank() then local l10n = l10nDef[ c ] if not l10n then l10n = l10nDef[ "en" ] end r = l10n[ say ] else m:inLanguage( c ) r = m:plain() end if not r then r = "(((" .. say .. ")))" end return r end -- factory() local function eval( source, frame ) -- Evaluate expression -- Precondition: -- source -- string; mathematical expression -- frame -- object return frame:callParserFunction( "#expr", source ) end -- eval() local function expr( source, frame, show ) -- Safe evaluation of presumable expression -- Precondition: -- source -- string; mathematical expression -- frame -- object -- show -- string; details about source -- Postcondition: -- throws error, if expression failed -- returns number with resulting figure -- Uses: -- factory() local lucky, r = pcall( eval, source, frame ) local n = tonumber( r, 10 ) if not lucky or n == nil then r = r .. " " .. factory( "ErrorExpr" ) .. " ''" .. show .. "'' (" .. source .. ")" error( r, 0 ) else r = n end return r end -- expr() local function base62( value ) -- Convert number from and to base62 encoding -- Precondition: -- value -- number or string to be converted -- number: to base62 -- string: base62 to number -- Lua limitation at 10^53; larger numbers are less precise -- Postcondition: -- returns string, or number, or false local r = false local state = type( value ) if state == "number" then local k = math.floor( value ) if k == value and value > 0 then local m r = "" while k > 0 do m = k % 62 k = ( k - m ) / 62 if m >= 36 then m = m + 61 elseif m >= 11 then m = m + 55 else m = m + 48 end r = string.char( m ) .. r end elseif value == 0 then r = "0" end elseif state == "string" then if value:match( "^%w+$" ) then local n = #value local k = 1 local c r = 0 for i = n, 1, -1 do c = value:byte( i, i ) if c >= 48 and c <= 57 then c = c - 48 elseif c >= 65 and c <= 90 then c = c - 55 elseif c >= 97 and c <= 122 then c = c - 61 else -- How comes? r = nil break -- for i end r = r + c * k k = k * 62 end -- for i end end return r end -- base62() function logicaland(args) local r = true; local k, v, s local b for k, v in pairs(args) do s = mw.text.trim(v) b = (s or '') ~= '' r = r and b end return r end function logicalor(args) local r = false; local k, v, s local b for k, v in pairs(args) do s = mw.text.trim(v) or ''; if s == '' then b = false; elseif s=='0' then b = false; elseif s=='false' then b = false; elseif s=='falsch' then b = false; else b = true; end if b then r = true; end end return r end local function minmax( params, frame, low, lazy ) -- Find extremum of unnamed params values -- Precondition: -- params -- table; like args -- .minus -- .zeroBlank -- frame -- object -- low -- true: minimum; false: maximum -- lazy -- true: try numeric result; false: return string -- Postcondition: -- throws error, if expression failed -- returns number, or -- string if formatting required, or -- false if no data provided -- Uses: -- expr() local k, v, n, scope local light = ( params.minus ~= "-" ) local luxury = ( params.minus and light ) local c = mw.ustring.char( 8722 ) -- minus local scan = "^%s*%-?[0-9]*%.?[0-9]*%s*$" local r = false for k, v in pairs( params ) do if type( k ) == "number" then scope = type( v ) if scope == "string" then if v:match( "^%s*$" ) then n = false else if mw.ustring.match( v, c ) then luxury = light v = mw.ustring.gsub( v, c, "-" ) end if not mw.ustring.match( v, scan ) then if low then scope = "min()#" else scope = "max()#" end scope = scope .. tostring( k ) v = expr( v, frame, scope ) end n = tonumber( v ) end elseif scope == "number" then n = v else n = false end if n then if r then if low then if n < r then r = n end else if n > r then r = n end end else r = n end end end end -- for k, v if r then if luxury and r < 0 then r = c .. tostring( -1 * r ) elseif not lazy then if r == 0 then if params.zeroBlank then r = "" else r = "0" end else r = tostring( r ) end end end return r end -- minmax() -- Export local p = {} function p.base62( frame ) local r local s = frame.args[ 1 ] if s then local s2 = frame.args[ 2 ] if s2 then s2 = mw.text.trim( s2 ) end if s2 == "D2B" then s = tonumber( s ) else s = mw.text.trim( s ) s2 = false end r = base62( s ) if r and not s2 then r = string.format( "%17d", r ) end end return r or "" end function p.max( frame ) local lucky, r = pcall( minmax, frame.args, frame, false, false ) return r or "" end function p.min( frame ) local lucky, r = pcall( minmax, frame.args, frame, true, false ) return r or "" end function p.TemplateMax( frame ) return p.max( frame:getParent() ) end function p.TemplateMin( frame ) return p.min( frame:getParent() ) end function p.booland(frame) local fr=frame:getParent() return logicaland(fr.args) end function p.boolor(frame) local fr=frame:getParent() return logicalor(fr.args) end function p.Expr( f, a ) local r = false if f == "min" or f == "max" then local frame = mw.getCurrentFrame() local low = ( f == "min" ) local lucky lucky, r = pcall( minmax, a, frame, low, true ) elseif f == "base62" then r = base62( a ) end return r end -- .Expr() return p -- Expr