Modul:Expr

Aus skandinavien-wiki.net
Version vom 26. Mai 2013, 19:37 Uhr von wikipedia>PerfektesChaos (Setup)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)

Die Dokumentation für dieses Modul kann unter Modul:Expr/doc erstellt werden

--[=[ 2013-05-25
Expr
* max
* min
* TemplateMax
* TemplateMin
]=]



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 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
            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.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.Expr( f, a )
    local frame = mw.getCurrentFrame()
    local r = false
    if f == "min"  or  f == "max" then
        local lucky
        local low = ( f == "min" )
        lucky, r = pcall( minmax, a, frame, low, true )
    end
    return r
end -- .Expr()

return p -- Expr