모듈:Mfunctions: 두 판 사이의 차이

리버티게임(개발), 모두가 만들어가는 자유로운 게임
둘러보기로 이동 검색으로 이동
백괴게임>Gustmd7410
잔글 (Gustmd7410님이 모듈:Hooks 문서를 넘겨주기를 만들지 않고 모듈:Mfunctions 문서로 이동했습니다: 역활을 더 명확하게 알려주는 이름으로 변경)
백괴게임>Gustmd7410
(작동 방식 변경, 버그 수정)
1번째 줄: 1번째 줄:
local p = {}
local p, FuncTable = {}, {}
local FuncTable = {}
local default = {}


function FuncTable:parse(text)
function FuncTable:parse(text)
for func in text:gmatch('{%b{}}') do
text = mw.text.decode(mw.text.unstripNoWiki(text)) -- <nowiki> 해제
local innfunc = func:sub(3, -3)
local pi, fi = 1, 1 -- 처리 위치 초기화
if innfunc:match('{%b{}}') then innfunc = self:parse(innfunc) end
local name = innfunc:sub(1, innfunc:find(':') and (innfunc:find(':') - 1))
-- 변수 처리
while text:find('{{%b{}}}', pi) do
local pos, param = text:find('{{%b{}}}', pi), text:match('{{%b{}}}', pi) -- 현재 처리 위치, 호출 문법 기억
local inner = param:sub(4, -4) -- 대괄호 제거
inner = inner:find('{%b{}}') and self:parse(inner) or inner -- 대괄호 내부 파싱 (재귀함수)
local name = inner:find('|') and inner:sub(1, inner:find('|') - 1) or inner -- 변수명
local default = inner:find('|') and inner:sub(inner:find('|') + 1) -- 입력된 변수가 없을 때 대신 표시되는 기본값
local parent = mw.getCurrentFrame():getParent() -- 이 함수를 실행하는 모듈이 호출된 틀의 프레임
local result = parent and parent.args[name] or default or param -- 출력값
pi = pos + #param -- 처리 위치 넘기기
text = text:sub(1, pos - 1) .. result .. text:sub(pi) -- 덮어쓰기
end
-- 함수 처리
while text:find('{%b{}}', fi) do
local pos, func = text:find('{%b{}}', fi), text:match('{%b{}}', fi) -- 현재 처리 위치, 호출 문법 기억
local inner = func:sub(3, -3) -- 대괄호 제거
inner = inner:find('{%b{}}') and self:parse(inner) or inner -- 대괄호 내부 파싱 (재귀함수)
local name = inner:sub(1, inner:find(':') and inner:find(':') - 1) -- 함수명
fi = pos + #func -- 처리 위치 넘기기
if name:match('%b##') then
if name:find('%b##') then -- 임의 함수라면
name = name:sub(2, -2)
name = name:sub(2, -2) -- 이름 전후의 # 제거
local argstr = innfunc:find(':') and innfunc:sub(innfunc:find(':') + 1, -1)
local argstr = inner:find(':') and inner:sub(inner:find(':') + 1) -- 인자 문법
local args = {}
local args, result = {}, '' -- 인자 목록, 출력값 초기화
local result = ''
if argstr then
if argstr then
local index = 1
local ai = 1 -- 인자 번호 초기화
for arg in mw.text.gsplit(argstr, '|') do
for arg in mw.text.gsplit(argstr, '|') do
if arg:find('=') then
if arg:find('=') then -- 속성명이 있으면
args[arg:sub(1, arg:find('=') - 1)] = arg:sub(arg:find('=') + 1, -1)
args[arg:sub(1, arg:find('=') - 1)] = arg:sub(arg:find('=') + 1) -- 인자 목록에 추가
else
else -- 속성명이 없으면
args[index] = arg
args[ai] = arg -- 인자 목록에 현재 번호로 추가
index = index + 1
ai = ai + 1 -- 다음 인자 번호
end
end
end
end
end
end
if (type(self[name]) == 'function')
if type(self[name]) == 'function' then -- 함수로 처리시
then result = self[name](mw.getCurrentFrame():newChild{title = '#' .. name .. '#', args = args}, '{{' .. innfunc .. '}}')
result = self[name](mw.getCurrentFrame():newChild{
else result = self[name]
title = '#' .. name .. '#', -- 함수명
args = args -- 인자
}) -- 처리 함수에 프레임을 인자로 넘기고 결과값을 출력값으로 지정
else -- 정적 값이 있으면
result = self[name] -- 출력값을 지정된 값으로 지정
end
end
text = text:sub(1, text:find(func:sub(1, 1)) - 1) .. result .. text:sub(text:find(func:sub(1, 1)) + func:len(), -1) or ''
text = text:sub(1, pos - 1) .. result .. text:sub(fi) -- 덮어쓰기
elseif name == '#' then
text = text:sub(1, text:find(func:sub(1, 1)) - 1) .. '{{' .. innfunc:sub(3) .. '}}' .. text:sub(text:find(func:sub(1, 1)) + func:len(), -1) or ''
else
text = text:sub(1, text:find(func:sub(1, 1)) - 1) or '' .. '{{' .. innfunc .. '}}'.. text:sub(text:find(func:sub(1, 1)) + func:len(), -1) or ''
end
end
end
end
return mw.getCurrentFrame():preprocess(text)
return mw.getCurrentFrame():preprocess(text) -- 기타 문법 파싱
end
end


function FuncTable:set(name, value)
function FuncTable:set(name, value)
self[name] = value
self[name] = value -- 입력된 함수명에 입력된 값을 지정
return self
return self -- 메소드 체이닝을 위해 테이블 반환
end
 
function default.param(frame)
local parent = frame:getParent():getParent()
local value = parent and parent.args[frame.args[1]]
if frame.args[2]
then return value or frame.args[2]
else return value or '{{{' .. frame.args[1] .. '}}}'
end
end
end


function p.newFuncTable()
function p.newFuncTable()
return setmetatable(default, {__index = FuncTable})
return setmetatable({}, {__index = FuncTable}) -- 함수 테이블 생성
end
end


-- 디버깅용
function p.test(frame)
function p.test(frame)
return p.newFuncTable():parse(frame.args[1])
return p.newFuncTable():parse(frame.args[1])

2018년 9월 27일 (목) 17:31 판


모듈 설명문서[보기] [편집] [역사] [새로 고침]

버그가 많아 사용을 권장하지 않습니다. 대신 모듈:TemplateFunction을 사용해 주세요.

Lua 모듈에서 활용할 수 있는 임의의 파서 함수를 생성하고 파싱할 수 있는 모듈입니다.

함수 테이블 생성

local tbl = require('모듈:Mfunctions').new()

함수의 값을 저장하는 함수 테이블을 생성하려면 본 모듈의 new() 함수를 이용합니다. 미리 준비된 테이블이 있다면 첫번째 인자에 해당 테이블을 넣어서 파싱이 가능한 함수 테이블로 전환하실 수 있습니다.

local tbl = {}
tbl = require('모듈:Mfunctions').new(tbl)

함수 추가

임의 파서 함수를 파싱하려면 함수나 값을 함수 테이블에 추가해야 합니다. 함수 테이블에 직접 추가할 수 있지만, set() 함수를 사용할 것을 권장합니다.

tbl:set('함수a', function(frame)
    ...
end):set('함수b', '값b')

set() 함수는 메소드 체이닝을 지원하여 여러 함수를 인라인으로 한번에 추가할 수 있습니다. 함수의 경우 프레임을 인자로 받아 모듈과 같이 만드실 수 있습니다. 특별한 계산이 필요없고 값이 변하지 않을 경우 해당 값을 직접 입력할 수 있습니다. 단, 테이블은 지원하지 않습니다.

함수 사용

{{#(함수명)#:(변수값1)|(변수값2)|(변수a)=(값a)|(변수b)=(값b)|...}}

임의 파서 함수 문법은 일반 파서 함수와 비슷합니다. 다만 함수명의 앞뒤에 #을 붙여야 합니다.

<nowiki>{{#switch:{{#expr:{{#func#}} - 1}}|0=ㄹ|9=ㄹㄹ|42=ㄹㄹㄹ|300=ㄹㄹㄹㄹ}}</nowiki>

만약 임의 함수를 파서 함수나 틀과 함께 사용하고, 결과에 영향을 끼칠 경우에는 <nowiki>로 묶어 주어야 합니다.

문법 파싱

tbl:parse(frame.args[1])

함수 테이블의 parse() 함수를 사용해서 함수 테이블에 정의된 규칙대로 인자의 텍스트를 파싱합니다.

예제

모듈:Banana
local p = {}

function p.example(frame)
    return require('모듈:Mfunctions'):set('func', function(frame)
        return 'Hello, ' .. frame.args[1] .. '!'
    end):parse(frame.args[1])
end

return p
입력
{{#invoke:Banana|example|{{#func#:World}}}}
출력
Hello, World!


local p, FuncTable = {}, {}

function FuncTable:parse(text)
	text = mw.text.decode(mw.text.unstripNoWiki(text)) -- <nowiki> 해제
	local pi, fi = 1, 1 -- 처리 위치 초기화
	
	-- 변수 처리
	while text:find('{{%b{}}}', pi) do
		local pos, param = text:find('{{%b{}}}', pi), text:match('{{%b{}}}', pi) -- 현재 처리 위치, 호출 문법 기억
		local inner = param:sub(4, -4) -- 대괄호 제거
		inner = inner:find('{%b{}}') and self:parse(inner) or inner -- 대괄호 내부 파싱 (재귀함수)
		local name = inner:find('|') and inner:sub(1, inner:find('|') - 1) or inner -- 변수명
		local default = inner:find('|') and inner:sub(inner:find('|') + 1) -- 입력된 변수가 없을 때 대신 표시되는 기본값
		local parent = mw.getCurrentFrame():getParent() -- 이 함수를 실행하는 모듈이 호출된 틀의 프레임
		local result = parent and parent.args[name] or default or param -- 출력값
		pi = pos + #param -- 처리 위치 넘기기
		text = text:sub(1, pos - 1) .. result .. text:sub(pi) -- 덮어쓰기
	end
	
	-- 함수 처리
	while text:find('{%b{}}', fi) do
		local pos, func = text:find('{%b{}}', fi), text:match('{%b{}}', fi) -- 현재 처리 위치, 호출 문법 기억
		local inner = func:sub(3, -3) -- 대괄호 제거
		inner = inner:find('{%b{}}') and self:parse(inner) or inner -- 대괄호 내부 파싱 (재귀함수)
		local name = inner:sub(1, inner:find(':') and inner:find(':') - 1) -- 함수명
		fi = pos + #func -- 처리 위치 넘기기
		
		if name:find('%b##') then -- 임의 함수라면
			name = name:sub(2, -2) -- 이름 전후의 # 제거
			local argstr = inner:find(':') and inner:sub(inner:find(':') + 1) -- 인자 문법
			local args, result = {}, '' -- 인자 목록, 출력값 초기화
			
			if argstr then
				local ai = 1 -- 인자 번호 초기화
				
				for arg in mw.text.gsplit(argstr, '|') do
					if arg:find('=') then -- 속성명이 있으면
						args[arg:sub(1, arg:find('=') - 1)] = arg:sub(arg:find('=') + 1) -- 인자 목록에 추가
					else -- 속성명이 없으면
						args[ai] = arg -- 인자 목록에 현재 번호로 추가
						ai = ai + 1 -- 다음 인자 번호
					end
				end
			end
			
			if type(self[name]) == 'function' then -- 함수로 처리시
				result = self[name](mw.getCurrentFrame():newChild{
					title = '#' .. name .. '#', -- 함수명
					args = args -- 인자
				}) -- 처리 함수에 프레임을 인자로 넘기고 결과값을 출력값으로 지정
			else -- 정적 값이 있으면
				result = self[name] -- 출력값을 지정된 값으로 지정
			end
			
			text = text:sub(1, pos - 1) .. result .. text:sub(fi) -- 덮어쓰기
		end
	end
	
	return mw.getCurrentFrame():preprocess(text) -- 기타 문법 파싱
end

function FuncTable:set(name, value)
	self[name] = value -- 입력된 함수명에 입력된 값을 지정
	return self -- 메소드 체이닝을 위해 테이블 반환
end

function p.newFuncTable()
	return setmetatable({}, {__index = FuncTable}) -- 함수 테이블 생성
end

-- 디버깅용
function p.test(frame)
	return p.newFuncTable():parse(frame.args[1])
end

return p