모듈:Mfunctions: 두 판 사이의 차이
둘러보기로 이동
검색으로 이동
백괴게임>Gustmd7410 잔글편집 요약 없음 |
백괴게임>Gustmd7410 편집 요약 없음 |
||
(같은 사용자의 중간 판 18개는 보이지 않습니다) | |||
1번째 줄: | 1번째 줄: | ||
local p | local p, FuncTable = {}, {} | ||
function FuncTable:parse(text) | function FuncTable:parse(text) | ||
text = mw.text.decode(mw.text.unstripNoWiki(text)) -- <nowiki> 해제 | |||
local | local pi, fi = 1, 1 -- 처리 위치 초기화 | ||
local name = | -- 변수 처리 | ||
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) -- 함수명 | |||
local result = '' -- 출력값 초기화 | |||
fi = pos + #func -- 처리 위치 넘기기 | |||
if name: | if name:find('%b##') then -- 임의 함수라면 | ||
name = name:sub(2, -2) | name = name:sub(2, -2) -- 이름 전후의 # 제거 | ||
local argstr = | local argstr = inner:find(':') and inner:sub(inner:find(':') + 1) -- 인자 문법 | ||
local args = {} | local args = {} -- 인자 목록 초기화 | ||
if argstr then | if argstr then | ||
local | 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 | args[arg:sub(1, arg:find('=') - 1)] = arg:sub(arg:find('=') + 1) -- 인자 목록에 추가 | ||
else | else -- 속성명이 없으면 | ||
args[ | args[ai] = arg -- 인자 목록에 현재 번호로 추가 | ||
ai = ai + 1 -- 다음 인자 번호 | |||
end | end | ||
end | end | ||
end | end | ||
if | if self[name] then -- 정의된 값이 있으면 | ||
if type(self[name]) == 'function' then -- 함수로 처리시 | |||
else result = | result = self[name](mw.getCurrentFrame():newChild{ | ||
title = '#' .. name .. '#', -- 함수명 | |||
args = args -- 인자 | |||
}) -- 처리 함수에 프레임을 인자로 넘기고 결과값을 출력값으로 지정 | |||
else -- 정적 값이 있으면 | |||
result = self[name] -- 출력값을 지정된 값으로 지정 | |||
end | |||
if type(result) == 'table' then | |||
error("임의 파서 함수 '" .. name .. "'에 문제가 있습니다 (반환될 값의 타입은 table이 될 수 없습니다)") -- 반환된 값이 테이블이면 에러 발생 | |||
end | |||
else -- 정의된 값이 없다면 | |||
result = '{{' .. inner .. '}}' -- 그대로 반환 | |||
end | end | ||
else -- 아니라면 | |||
result = '{{' .. inner .. '}}' -- 그대로 반환 후 파싱 대기 | |||
end | end | ||
text = text:sub(1, pos - 1) .. result .. text:sub(fi) -- 덮어쓰기 | |||
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 | if type(value) == 'table' then | ||
error('임의 함수값의 타입은 table이 될 수 없습니다') -- 함수값이 테이블이면 에러 반환 | |||
end | else | ||
self[name] = value -- 입력된 함수명에 입력된 값을 지정 | |||
return self -- 메소드 체이닝을 위해 테이블 반환 | |||
end | |||
end | end | ||
function | function p.new(t) | ||
local | local tbl = {} -- 테이블 초기화 | ||
if | if type(t) == 'table' then -- 기초 테이블이 있다면 | ||
for key in pairs(t) do | |||
tbl[key] = t[key] -- 예외 가능성 제거를 위해 내용만 복사 | |||
end | |||
end | end | ||
return setmetatable(tbl, {__index = FuncTable}) -- 함수 테이블 생성 | |||
end | end | ||
function | -- 디버깅용 | ||
return | function p.test(frame) | ||
return p.new():parse(frame.args[1]) | |||
end | end | ||
return p | return p |
2018년 10월 8일 (월) 23:33 기준 최신판
버그가 많아 사용을 권장하지 않습니다. 대신 모듈: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!
위 설명은 모듈:Mfunctions/설명문서의 내용을 가져와 보여주고 있습니다. (편집 | 역사) 이 모듈에 대한 수정 연습과 시험은 연습장 (만들기 | 미러)과 시험장 (만들기)에서 할 수 있습니다. 분류는 /설명문서에 넣어주세요. 이 모듈에 딸린 문서. |
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) -- 함수명
local result = '' -- 출력값 초기화
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 = {} -- 인자 목록 초기화
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 self[name] then -- 정의된 값이 있으면
if type(self[name]) == 'function' then -- 함수로 처리시
result = self[name](mw.getCurrentFrame():newChild{
title = '#' .. name .. '#', -- 함수명
args = args -- 인자
}) -- 처리 함수에 프레임을 인자로 넘기고 결과값을 출력값으로 지정
else -- 정적 값이 있으면
result = self[name] -- 출력값을 지정된 값으로 지정
end
if type(result) == 'table' then
error("임의 파서 함수 '" .. name .. "'에 문제가 있습니다 (반환될 값의 타입은 table이 될 수 없습니다)") -- 반환된 값이 테이블이면 에러 발생
end
else -- 정의된 값이 없다면
result = '{{' .. inner .. '}}' -- 그대로 반환
end
else -- 아니라면
result = '{{' .. inner .. '}}' -- 그대로 반환 후 파싱 대기
end
text = text:sub(1, pos - 1) .. result .. text:sub(fi) -- 덮어쓰기
end
return mw.getCurrentFrame():preprocess(text) -- 기타 문법 파싱
end
function FuncTable:set(name, value)
if type(value) == 'table' then
error('임의 함수값의 타입은 table이 될 수 없습니다') -- 함수값이 테이블이면 에러 반환
else
self[name] = value -- 입력된 함수명에 입력된 값을 지정
return self -- 메소드 체이닝을 위해 테이블 반환
end
end
function p.new(t)
local tbl = {} -- 테이블 초기화
if type(t) == 'table' then -- 기초 테이블이 있다면
for key in pairs(t) do
tbl[key] = t[key] -- 예외 가능성 제거를 위해 내용만 복사
end
end
return setmetatable(tbl, {__index = FuncTable}) -- 함수 테이블 생성
end
-- 디버깅용
function p.test(frame)
return p.new():parse(frame.args[1])
end
return p