Difference between revisions of "Module:Road data/parser"
Jump to navigation
Jump to search
blackwiki>Fredddie (sync to main) |
blackwiki>Fredddie (Reverted to revision 721024695 by Imzadi1979 (talk): Reverting to the before times (TW)) |
||
| Line 1: | Line 1: | ||
| − | local p = {} | + | -- Export package |
| − | + | local p = {} | |
| − | |||
| − | |||
| − | |||
| − | |||
-- Local library aliases | -- Local library aliases | ||
local format = string.format | local format = string.format | ||
local gsub = mw.ustring.gsub | local gsub = mw.ustring.gsub | ||
| + | local trim = mw.text.trim | ||
local upper = mw.ustring.upper | local upper = mw.ustring.upper | ||
| − | -- | + | -- Regex substitution patterns |
| − | + | local prepattern = "%[(%w+)%|(.*)%|(.*)%|(.*)%]" -- [arg|equal to (blank for existence)|if true|if false] | |
| − | + | local pattern = "%%(%w+)%%" -- %arg% | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | local prepattern = "%[(%w+)%|( | ||
| − | -- | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | local pattern = "%%(%w+)%%" | ||
| − | + | local function parser(formatStr, args, form) | |
| − | + | local function ifexists(name) | |
| − | + | -- Check whether a page or file named name exists | |
| − | + | if name == '' then return false end -- Page doesn't exist if name is blank | |
| − | local function | + | local title -- mw.title object |
| − | + | if form == 'shield' then | |
| − | + | title = mw.title.new(name, 'Media') -- Shields are in the Media namespace | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
else | else | ||
| − | + | title = mw.title.new(name, 0) -- Links are in the mainspace | |
end | end | ||
| + | return title.exists -- A boolean for whether the page exists | ||
end | end | ||
| − | + | local function testArgs(test, equals, ifexists, ifnot) | |
| − | local | + | -- Implement the if test |
| − | + | if equals ~= '' then -- Argument equals something | |
| − | + | if args[test] == equals then return ifexists else return ifnot end | |
| − | + | else -- Existence of argument | |
| − | + | if args[test] and args[test] ~= '' then return ifexists else return ifnot end | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | -- | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | end | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | -- | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
end | end | ||
| − | |||
end | end | ||
| − | -- | + | local formatTable = {} -- Table with definitions |
| − | + | -- Recursively dig into tables that could be parser hooks or argument tables. | |
| − | + | local function formatStrInTable(formatStr) | |
| − | + | if type(formatStr) ~= "table" then return formatStr end -- formatStr is a scalar | |
| − | -- | + | formatTable = formatStr |
| − | + | local hook = formatStr.hook -- Possible hook | |
| − | + | local both = formatStr[2] -- Second shield | |
| − | + | if both then | |
| − | + | local first = formatStrInTable(formatStr[1]) | |
| − | + | local second = formatStrInTable(both) | |
| − | + | return {first, second} -- First and second shield | |
| − | + | elseif hook then | |
| − | local function | + | local hooksModule = require "Module:Road data/parser/hooks" |
| − | + | local hookFunction = hooksModule[hook] or error("Hook '" .. hook .. "' does not exist", 0) | |
| − | + | return formatStrInTable(hookFunction(formatStr, args)) -- Call hook | |
| − | + | else -- Switch on an argument | |
| − | + | local arg = args[formatStr.arg or "route"] | |
| − | + | return formatStrInTable(formatStr[arg] or formatStr.default) | |
| − | |||
| − | -- | ||
| − | local | ||
| − | |||
| − | local hookFunction = | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | -- | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
end | end | ||
| − | -- | + | end |
| − | local | + | local function parse(formatStr) |
| − | if | + | local preprocessed = gsub(formatStr, prepattern, testArgs) -- If statements |
| − | + | local parsedStr = gsub(preprocessed, pattern, args) -- Variable interpolation | |
| − | + | local final = trim(parsedStr) -- Trim extra spaces | |
| − | + | if formatTable.ifexists then -- Existence test | |
| − | + | local exists = ifexists(final) | |
| − | + | if exists then | |
| − | + | return final | |
| + | else | ||
| + | return parser(formatTable.otherwise, args, form) | ||
| + | end | ||
end | end | ||
| + | return final | ||
| + | end | ||
| + | formatStr = formatStrInTable(formatStr) -- Get formatStr | ||
| + | if not formatStr or formatStr == '' then return '' end -- Return empty string for empty formatStr | ||
| + | if type(formatStr) == 'table' then -- Dual shields | ||
| + | local first = parse(formatStr[1]) | ||
| + | local second = parse(formatStr[2]) | ||
| + | return first, second | ||
else | else | ||
| − | + | return parse(formatStr) | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
end | end | ||
end | end | ||
| − | + | local function formatString(args, form) | |
| − | -- | + | -- Get format string/table from module based on jurisdiction and type |
| − | + | local function getTypeData(module, type) | |
| − | + | -- Get data from module for particular type | |
| − | + | local success, moduleData = pcall(mw.loadData, module) | |
| − | + | if not success then return '' end -- Empty string if module cannot be loaded | |
| − | + | local typeTable = moduleData[type] or moduleData[''] -- Type table or empty string default table | |
| − | local function getTypeData(module, type | + | local defaultTable = moduleData[''] or {} -- Default table |
| − | + | if typeTable then | |
| − | + | local alias = typeTable.alias | |
| − | + | if alias then -- Type is an alias to another module | |
| − | + | local aliasedModule = "Module:Road data/strings/" .. alias.module | |
| − | + | local aliasedType = alias.type | |
| − | + | return getTypeData(aliasedModule, aliasedType) | |
| − | + | end | |
| − | + | return typeTable[form] or defaultTable[form] or '' | |
| − | + | else | |
| − | + | return '' | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
end | end | ||
| − | |||
| − | |||
| − | |||
end | end | ||
| − | + | ||
| − | + | local stateCountries = {USA = true, CAN = true} -- These countries have state/province modules | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | local stateCountries = {USA = true, CAN = true} | ||
local state = upper(args.state or '') | local state = upper(args.state or '') | ||
local country | local country | ||
if args.country then | if args.country then | ||
country = upper(args.country) | country = upper(args.country) | ||
| − | else | + | else -- Find country via a mask |
| − | |||
local countryModule = mw.loadData("Module:Road data/countrymask") | local countryModule = mw.loadData("Module:Road data/countrymask") | ||
country = countryModule[state] or 'UNK' | country = countryModule[state] or 'UNK' | ||
end | end | ||
| + | local typeArg = args.type | ||
| + | local module | ||
if stateCountries[country] and state ~= '' then | if 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 | end | ||
| − | return | + | return getTypeData(module, typeArg) |
end | end | ||
| − | + | function p.parser(passedArgs, form) | |
| − | + | local args = {state = passedArgs.state, type = passedArgs.type, route = passedArgs.route, | |
| − | + | denom = passedArgs.denom, county = passedArgs.county, dab = passedArgs.dab, | |
| − | + | country = passedArgs.country, township = passedArgs.township} | |
| − | + | local formatStr = formatString(args, form) | |
| − | + | if not formatStr or formatStr == '' then return nil end | |
| − | + | return parser(formatStr, args, form) | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | local | ||
| − | if not | ||
| − | |||
| − | return | ||
end | end | ||
return p | return p | ||
Revision as of 13:00, 8 August 2019
Documentation for this module may be created at Module:Road data/parser/doc
-- Export package
local p = {}
-- Local library aliases
local format = string.format
local gsub = mw.ustring.gsub
local trim = mw.text.trim
local upper = mw.ustring.upper
-- Regex substitution patterns
local prepattern = "%[(%w+)%|(.*)%|(.*)%|(.*)%]" -- [arg|equal to (blank for existence)|if true|if false]
local pattern = "%%(%w+)%%" -- %arg%
local function parser(formatStr, args, form)
local function ifexists(name)
-- Check whether a page or file named name exists
if name == '' then return false end -- Page doesn't exist if name is blank
local title -- mw.title object
if form == 'shield' then
title = mw.title.new(name, 'Media') -- Shields are in the Media namespace
else
title = mw.title.new(name, 0) -- Links are in the mainspace
end
return title.exists -- A boolean for whether the page exists
end
local function testArgs(test, equals, ifexists, ifnot)
-- Implement the if test
if equals ~= '' then -- Argument equals something
if args[test] == equals then return ifexists else return ifnot end
else -- Existence of argument
if args[test] and args[test] ~= '' then return ifexists else return ifnot end
end
end
local formatTable = {} -- Table with definitions
-- Recursively dig into tables that could be parser hooks or argument tables.
local function formatStrInTable(formatStr)
if type(formatStr) ~= "table" then return formatStr end -- formatStr is a scalar
formatTable = formatStr
local hook = formatStr.hook -- Possible hook
local both = formatStr[2] -- Second shield
if both then
local first = formatStrInTable(formatStr[1])
local second = formatStrInTable(both)
return {first, second} -- First and second shield
elseif hook then
local hooksModule = require "Module:Road data/parser/hooks"
local hookFunction = hooksModule[hook] or error("Hook '" .. hook .. "' does not exist", 0)
return formatStrInTable(hookFunction(formatStr, args)) -- Call hook
else -- Switch on an argument
local arg = args[formatStr.arg or "route"]
return formatStrInTable(formatStr[arg] or formatStr.default)
end
end
local function parse(formatStr)
local preprocessed = gsub(formatStr, prepattern, testArgs) -- If statements
local parsedStr = gsub(preprocessed, pattern, args) -- Variable interpolation
local final = trim(parsedStr) -- Trim extra spaces
if formatTable.ifexists then -- Existence test
local exists = ifexists(final)
if exists then
return final
else
return parser(formatTable.otherwise, args, form)
end
end
return final
end
formatStr = formatStrInTable(formatStr) -- Get formatStr
if not formatStr or formatStr == '' then return '' end -- Return empty string for empty formatStr
if type(formatStr) == 'table' then -- Dual shields
local first = parse(formatStr[1])
local second = parse(formatStr[2])
return first, second
else
return parse(formatStr)
end
end
local function formatString(args, form)
-- Get format string/table from module based on jurisdiction and type
local function getTypeData(module, type)
-- Get data from module for particular type
local success, moduleData = pcall(mw.loadData, module)
if not success then return '' end -- Empty string if module cannot be loaded
local typeTable = moduleData[type] or moduleData[''] -- Type table or empty string default table
local defaultTable = moduleData[''] or {} -- Default table
if typeTable then
local alias = typeTable.alias
if alias then -- Type is an alias to another module
local aliasedModule = "Module:Road data/strings/" .. alias.module
local aliasedType = alias.type
return getTypeData(aliasedModule, aliasedType)
end
return typeTable[form] or defaultTable[form] or ''
else
return ''
end
end
local stateCountries = {USA = true, CAN = true} -- These countries have state/province modules
local state = upper(args.state or '')
local country
if args.country then
country = upper(args.country)
else -- Find country via a mask
local countryModule = mw.loadData("Module:Road data/countrymask")
country = countryModule[state] or 'UNK'
end
local typeArg = args.type
local module
if 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)
end
function p.parser(passedArgs, form)
local args = {state = passedArgs.state, type = passedArgs.type, route = passedArgs.route,
denom = passedArgs.denom, county = passedArgs.county, dab = passedArgs.dab,
country = passedArgs.country, township = passedArgs.township}
local formatStr = formatString(args, form)
if not formatStr or formatStr == '' then return nil end
return parser(formatStr, args, form)
end
return p