2023年政策修订增补工作正在进行中,欢迎参与!
  • Moegirl.ICU:萌娘百科流亡社群 581077156(QQ),欢迎对萌娘百科运营感到失望的编辑者加入
  • Moegirl.ICU:账号认领正在试运行,有意者请参照账号认领流程

Module:Sandbox/サンムル/While

萌娘百科,万物皆可萌的百科全书!转载请标注来源页面的网页链接,并声明引自萌娘百科。内容不可商用。
跳转到导航 跳转到搜索
Template-info.svg 模块文档  [创建] [刷新]
local module = {}

local getArgs = require('Module:Arguments').getArgs

local pack_inner_loop = function(loop)
    -- 给内层循环的do参数包裹<nowiki>标签
    loop = mw.ustring.gsub(loop, '{{%s-[lL][oO][oO][pP]%s-|', '{{#invoke:loop|main|')
    return mw.ustring.gsub(loop, '({{#invoke:loop.*)', function(a)
        local i = 1
        local stack = {}
        local do_begin = -1
        local do_end = -1
        while (i < mw.ustring.len(a)) do
            if do_begin == -1 and mw.ustring.find(a, '^|%s-do%s-=', i) then
                _, do_begin = mw.ustring.find(a, '^|%s-do%s-=', i)
                do_begin = do_begin + 1
                i = do_begin
            end
            if do_begin ~= -1 then
                if mw.ustring.sub(a, i, i + 2) == '{{{' then
                    i = i + 3
                    table.insert(stack, 3)
                elseif mw.ustring.sub(a, i, i + 1) == '{{' then
                    i = i + 2
                    table.insert(stack, 2)
                elseif mw.ustring.sub(a, i, i + 2) == '}}}' then
                    if #stack ~= 0 and stack[#stack] == 3 then
                        i = i + 3
                        table.remove(stack)
                    elseif #stack ~= 0 and stack[#stack] == 2 then
                        i = i + 2
                        table.remove(stack)
                    else
                        do_end = i - 1
                        break
                    end
                elseif mw.ustring.sub(a, i, i + 1) == '}}' then
                    if #stack ~= 0 then
                        i = i + 2
                        table.remove(stack)
                    else
                        do_end = i - 1
                        break
                    end
                elseif mw.ustring.sub(a, i, i) == '|' and #stack == 0 then
                    do_end = i - 1
                    break
                else
                    i = i + 1
                end
            else
                i = i + 1
            end
        end
        if do_begin ~= -1 and do_end == -1 then do_end = i - 1 end
        if do_begin ~= -1 and do_end ~= -1 then
        -- mw.log('发现内层循环 <nowiki>'..mw.ustring.sub(a, do_begin, do_end)..'</nowiki>')
        return mw.ustring.sub(a, 1, do_begin - 1)..'<nowiki>'..
               mw.text.trim(mw.ustring.sub(a, do_begin, do_end))..'</nowiki>'..
               pack_inner_loop(mw.ustring.sub(a, do_end + 1, -1))
        else
            return a
        end
    end )
end

local _main = function(args, frame, dowhile)
	--初步处理条件语句
    local condition = args['condition'] or ''
    condition = mw.text.unstripNoWiki(condition)
    condition = string.gsub(condition, '<!%-%-.-%-%->', '')
    
    --修整条件语句的格式
    local trim = mw.text.split(condition, '\n')
    condition = ''
    for i, v in ipairs(trim) do
        condition = condition..mw.text.trim(v)
    end
	
    condition = mw.text.decode(condition)
    -- mw.log('循环体= '..condition)
	
	--初步处理循环体
    local loop = args['do'] or ''
    loop = mw.text.unstripNoWiki(loop)
    loop = string.gsub(loop, '<!%-%-.-%-%->', '')
    
	--处理循环体中的次级循环语句
    loop = pack_inner_loop(loop)
    --修整循环体中语句的格式
    local trim = mw.text.split(loop, '\n')
    loop = ''
    for i, v in ipairs(trim) do
        loop = loop..mw.text.trim(v)
    end

    loop = mw.text.decode(loop)
    -- mw.log('循环体= '..loop)

    local result = ''
    if dowhile then
        -- mw.log('执行循环体('..name..'='..tostring(i)..') '..loop)
    	repeat result = result..frame:preprocess(loop) until frame:preprocess(condition) == ''
    else
        -- mw.log('执行循环体('..name..'='..tostring(i)..') '..loop)
    	while frame:preprocess(condition) ~= '' do result = result..frame:preprocess(loop) end
    end
    -- mw.log('循环结果 '..result)
    return result
end

module["while"] = function(frame)
    if (frame:getParent() or frame):getTitle() == 'Template:While' and
        frame.args['do'] == nil then
        args = getArgs(frame)
    else
        args = frame.args
    end
    return _main(args, frame:getParent() or frame, false)
end

module.dowhile = function(frame)
    if (frame:getParent() or frame):getTitle() == 'Template:While' and
        frame.args['do'] == nil then
        args = getArgs(frame)
    else
        args = frame.args
    end
    return _main(args, frame:getParent() or frame, true)
end

return module