Module:Road data/parser

-- 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