Jump to content

Module:Road data/parser/sandbox

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Chinissai (talk | contribs) at 13:00, 18 April 2016 (Added support for no substitutions of args.). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
local p = {}
local format = string.format
local gsub = mw.ustring.gsub
local trim = mw.text.trim
local upper = mw.ustring.upper

-- Change the following to main module upon deployment.
local parserHooksModule = "Module:Road data/parser/hooks/sandbox"

local prepattern = "%[(%w+)%|(.*)%|(.*)%|(.*)%]"
local pattern = "%%(%w+)%%"

local function subst(formatStr, args)
	local function testArgs(test, equals, ifexists, ifnot)
		local value = args[test] or ''
		if equals ~= '' then
			return value == equals and ifexists or ifnot
		else
			return value ~= '' and ifexists or ifnot
		end
	end
	local preprocessed = gsub(formatStr, prepattern, testArgs)
	local parsedStr = gsub(preprocessed, pattern, args)
	return trim(parsedStr)
end

local function ifexists(name, form)
	if name == '' then return false end
	local namespaceModule = mw.loadData('Module:Road data/parser/namespace')
	local namespace = namespaceModule[form] or 0
	local title = mw.title.new(name, namespace);
	return title.exists
end

local function parser(formatStr, args, form, needSubst)
	if type(formatStr) ~= "table" then
		return needSubst and subst(formatStr, args) or formatStr
	elseif formatStr.hook then
		-- Requires: Parser hook must have hook field.
		local hook = formatStr.hook
		local hooksModule = require(parserHooksModule)
		local hookFunction = hooksModule[hook] or error("Hook '" .. hook .. "' does not exist", 0)
		return parser(hookFunction(formatStr, args), args, form, needSubst)
	elseif formatStr.arg or formatStr.default then
		-- Requires: Switch table must have
		--           arg or default fields
		--           but not hook field.
		local arg = args[formatStr.arg or "route"]
		if formatStr[arg] then return parser(formatStr[arg], args, form, needSubst) end
		if formatStr.default == nil then return nil end
		local defaultValue = parser(formatStr.default, args, form, needSubst)
		if formatStr.ifexists then
			if ifexists(defaultValue, form) then return defaultValue end
			return formatStr.otherwise and parser(formatStr.otherwise, args, form, needSubst) or nil
		else
			return defaultValue
		end
	else
		-- Process each table element
		local result = {}
		for key,entry in pairs(formatStr) do
			result[key] = parser(entry, args, form, needSubst)
		end
		return result
	end
end

local function getTypeData(module, type, form)
	local success, moduleData = pcall(mw.loadData, module)
	if not success then return nil end
	local typeTable = moduleData[type] or moduleData['']
	local defaultTable = moduleData[''] or {}
	if typeTable then
		local alias = typeTable.alias
		if alias then
			local aliasedModule = "Module:Road data/strings/" .. alias.module
			local aliasedType = alias.type
			return getTypeData(aliasedModule, aliasedType, form)
		end
		return typeTable[form] or defaultTable[form] or nil
	else
		return nil
	end
end

local function formatString(args, form, path, kind)
	local stateCountries = {USA = true, CAN = true}
	local state = upper(args.state or '')
	local country
	if args.country then
		country = upper(args.country)
	else
		local countryModule = mw.loadData("Module:Road data/countrymask")
		country = countryModule[state] or 'UNK'
	end
	local typeArg = kind or args.type
	local module
	if path then
		module = path
	elseif stateCountries[country] and state ~= '' then
		module = format("Module:Road data/strings/%s/%s", country, state)
	else
		module = format("Module:Road data/strings/%s", country)
	end
	return getTypeData(module, typeArg, form)
end

--[[
Similar to parser(args, form, path, kind),
but with the result unsubstituted with actual args values.
]]
function p.unsubstParser(args, form, path, kind)
	local formatStr = formatString(args, form, path, kind)
	if formatStr == nil then return nil end
	return parser(formatStr, args, form, false)
end

function p.parser(args, form, path, kind)
	local formatStr = formatString(args, form, path, kind)
	if formatStr == nil then return nil end
	return parser(formatStr, args, form, true)
end

return p