Module: 沙盒 / Siyuwj/1

local p = {

STATION_SEPARATOR = ' – ',

DEFAULTSTATIONSUFFIX = ' 站 ',

BLOCKALIGNPATTERN = '##BLOCK_ALIGN##',

BLOCK_START = ' ',

BLOCKSTARTPURE = ,

BLOCKLINESEPARATOR = ,

BLOCK_END = ' > ',

BLOCKENDPURE =

}

p.sep_translate = {

'%% dash%%' = '–',

'%% rarrow%%' = '→',

'%% larrow%%' = '←',

'%% darrow%%' = '↔',

'%% ldarrow%%' = '⇐',

'%% rdarrow%%' = '⇒',

'%% ddarrow%%' = '⇔'

}

p.stationsuffix = p.DEFAULTSTATION_SUFFIX

function p.truncateEnds (s, l)

if l == nil then l = 1 end

return string.sub (s, l + 1, string.len (s) - l)

end

function p.appendStyle (s, a)

s = mw.text.trim (s)

if s == then

return a

elseif string.find (s, ';$') ~= nil then

return s .. ' ' .. a

else

return s .. '; ' .. a

end

end

function p.loadSystemStationData (system, station_link)

	local status

	local system_data

	local adj_result

	if string.sub (system, 1, 3) ~= 'AS:' then

		status, system_data = pcall (mw.loadData, "Module:RailSystems/" .. system)

		if status then

			return systemdata.stationNamesstationlink

		end

	else

		system = string.sub (system, 4)

	end

	adjresult = require ('Module:Adjacent stations').station ({

		system = system,

		station = station_link,

		line = nil,

		type = nil,

	}, )

	return string.sub (adjresult, 3, string.len (adjresult) - 2)

end

function p.marshalStation (station_link, style, system, frame)

	local station_name

	local station_data = nil

	function marshal (stationlink, stationname, style)

	 if style == nil or mw.text.trim (style) == then

	 return .. station_name ..

	else

	return .. station_name ..

	end

	end

	if system ~= nil and mw.text.trim (system) ~= then

		stationdata = p.loadSystemStationData (system, stationlink)

	end

	if station_data ~= nil then

local i, datum

local repr =

local station_parts

if type (station_data) ~= 'table' then

stationdata = {stationdata,}

end

for i, datum in ipairs (station_data) do

if string.find (datum, '|', 1, true) == nil or string.find (datum, , 1, true) ~= nil then

repr = repr .. datum

else

station_parts = mw.text.split (datum, '|')

stationlink = stationparts1

stationname = table.concat (stationparts, '|', 2)

if frame ~= nil and string.find (station_name, '{', 1, true) ~= nil then

stationname = frame:preprocess (table.concat (stationparts, '|', 2))

end

repr = repr .. marshal (stationlink, stationname, style)

end

end

return repr

else

local linknamesplit = mw.text.split (station_link, '!')

if table.getn (linknamesplit) == 1 then

stationname, match = string.gsub (stationlink, p.station_suffix .. ' +%(.+%)$', )

if match == 0 then

stationname, match = string.gsub (stationlink, p.station_suffix .. '$',)

end

if match == 0 then

stationname = stationlink

stationlink = stationlink .. p.station_suffix

end

else

stationlink = linkname_split1

stationname = linkname_split2

end

return marshal (stationlink, stationname, style)

end

end

function p.parseLink (station_link, style, system, frame)

local station_name, match

local prefix, suffix = ,

local linknamesplit

if string.find (station_link, "^%%.+%%$") ~= nil then

	return p.renderPlain (p.truncateEnds (station_link), style, system, frame)

end

local has_decorator = true

while has_decorator do

local prefix_patterns = {"^s.+s$" = { prefix=, suffix=, len=1},

"^'.+'$" = {prefix="'", suffix="'", len=1},

"^%(.+%)$" = {prefix='(', suffix=')', len=1 },

"^（.+）$" = {prefix='（', suffix='）', len=1},

}

has_decorator = false

if string.find (station_link, "^g.+g$") ~= nil then

stationlink = p.truncateEnds (stationlink)

style = p.appendStyle (style, 'color:gray')

has_decorator = true

end

for patt, ps in pairs (prefix_patterns) do

if string.find (station_link, patt) ~= nil then

stationlink = p.truncateEnds (stationlink, ps.len)

prefix = ps.prefix .. prefix

suffix = suffix .. ps.suffix

has_decorator = true

end

end

end

	return prefix .. p.marshalStation (station_link, style, system, frame) .. suffix

end

function p.renderPlain (text, style, system, frame)

local spos, epos, station_name = 1, 1, nil

local out_text =

local pos = 1

	while spos ~= nil do

		spos, epos, station_name = string.find (text, '%$(^%$+)%$', pos)

		if spos ~= nil then

			outtext = outtext .. string.sub (text, pos, spos - 1) .. p.parseLink (station_name, style, system, frame)

			pos = epos + 1

		else

			outtext = outtext .. string.sub (text, pos, string.len (text))

		end

	end

	return out_text

end

function p.splitStationExpr (station)

local new_split =

local separators =

local lastelement, curelement

local cur_separator =

local station_split = mw.text.split (station, '#')

for i, spart in ipairs (station_split) do

if i > 1 and (string.find (last_element, '&$') ~= nil -- process html escapes, i.e., ` `

or string.find (last_element, ': *$') ~= nil -- process CSS color, i.e., `color: #cccccc`

or string.find (lastelement, '= $') ~= nil -- process old-fashioned property without quotes, i.e., ``or string.find (lastelement, '= \" *$') ~= nil -- process old-fashioned property with quotes, i.e., ``

) then

table.remove (new_split)

table.remove (separators)

curelement = lastelement .. '#' .. spart

elseif i > 1 and spart == then

table.remove (new_split)

table.remove (separators)

cur_separator = ' '

curelement = lastelement

else

cur_element = spart

end

table.insert (newsplit, curelement)

table.insert (separators, cur_separator)

cur_separator =

lastelement = curelement

end

return new_split, separators

end

function p.parseStation (station, style, system, frame)

local stationstr, stationlink

local stationprefix, stationsuffix

local stationsplit, stationseps = p.splitStationExpr (station, '#')

if table.getn (station_split) == 1 then

station_prefix =

stationexpr = mw.text.trim (stationsplit1)

station_suffix =

elseif table.getn (station_split) == 2 then

stationprefix = mw.text.trim (stationsplit1) .. station_seps1

stationexpr = mw.text.trim (stationsplit2)

station_suffix =

elseif table.getn (station_split) == 3 then

if mw.text.trim (station_split1) ~= then

stationprefix = mw.text.trim (stationsplit1) .. station_seps1

else

station_prefix =

end

stationexpr = mw.text.trim (stationsplit2)

stationsuffix = stationseps2 .. mw.text.trim (station_split3)

end

if station_prefix ~= then

	stationprefix = p.renderPlain (stationprefix, style, system, frame)

	end

if station_suffix ~= then

	stationsuffix = p.renderPlain (stationsuffix, style, system, frame)

	end

stationlink = p.parseLink (mw.text.trim (stationexpr), style, system, frame)

stationstr = stationprefix .. stationlink .. stationsuffix

if stationprefix ~= or stationsuffix ~= then

stationstr = .. stationstr ..

end

return station_str

end

function p.processRoute (route_str, gstyle, condition, system, frame)

if gstyle == nil then

gstyle =

end

if condition == nil then

condition =

end

local style = gstyle

local out_style = gstyle

local stations = mw.text.split (route_str, '~')

local output_str =

local condition = mw.text.trim (condition)

local condexpr, conds, cond, rawcond

local cond_met = true

local graystate, italicstate = false, false

local block_level = 0

local block_align

local station_index = 0

local separator

local nextseparator = p.STATIONSEPARATOR

local userseparator = p.STATIONSEPARATOR

for i, station in ipairs (stations) do

station = mw.text.trim (station)

if string.find (station, '^con *=') ~= nil then

cond_expr = mw.text.trim (mw.text.split (station, '=') 2)

if cond_expr == then

cond_met = true

else

conds = mw.text.split (cond_expr, '#')

cond_met = false

for i, cond in ipairs (conds) do

raw_cond = mw.text.trim (cond)

if string.find (raw_cond, '^- *') ~= nil then

rawcond = string.gsub (rawcond, '^- *',)

if mw.text.trim (raw_cond) ~= condition then

cond_met = true

break

end

else

if mw.text.trim (raw_cond) == condition then

cond_met = true

break

end

end

end

end

elseif cond_met then

	if string.find (station, '^style *=') ~= nil then

	 style = mw.text.trim (mw.text.split (station, '=') 2)

	 if style == then

	 style = gstyle

	 end

	 elseif string.find (station, '^sep *=') ~= nil then

		 separator = mw.text.trim (mw.text.split (station, '=') 2)

		 if separator == then

		 separator = p.STATION_SEPARATOR

		 else

		 separator = ' ' .. separator .. ' '

		 for spatt, sep in pairs (p.sep_translate) do

		 separator = string.gsub (separator, spatt, sep)

		 end

		 end

		 next_separator = separator

		 user_separator = separator

	 elseif station == 'blstart' then

	 blocklevel = blocklevel + 1

	 if station_index > 0 then

	 nextseparator = string.gsub (p.BLOCKSTART, p.BLOCKALIGNPATTERN, 'left')

	 else

	 nextseparator = string.gsub (p.BLOCKSTARTPURE, p.BLOCKALIGN_PATTERN, 'right')

	 end

	 elseif string.find (station, '^blstart *=') ~= nil then

	 blocklevel = blocklevel + 1

	 block_align = mw.text.trim (mw.text.split (station, '=') 2)

	 if station_index > 0 then

	 nextseparator = string.gsub (p.BLOCKSTART, p.BLOCKALIGNPATTERN, block_align)

	 else

	 nextseparator = string.gsub (p.BLOCKSTARTPURE, p.BLOCKALIGNPATTERN, blockalign)

	 end

	 elseif station == 'blline' then

	 nextseparator = p.BLOCKLINE_SEPARATOR

	 elseif station == 'blend' then

	 blocklevel = blocklevel - 1

	 nextseparator = p.BLOCKEND

	 elseif station == 'gstart' then

	 gray_state = true

	 elseif station == 'gend' then

	 gray_state = false

	 elseif station == 'istart' then

	 italic_state = true

	 elseif station == 'iend' then

	 italic_state = false

	 elseif station == 'line' then

	 while block_level > 0 do

	 blocklevel = blocklevel - 1

	 outputstr = outputstr .. p.BLOCKENDPURE

	 end

	 next_separator =

	 else

	 stationindex = stationindex + 1

	 if stationindex > 1 or blocklevel > 0 then

	 outputstr = outputstr .. next_separator

	 end

	 out_style = style

	 if gray_state then

	 out_style = p.appendStyle (style, 'color:gray')

	 end

	 if italic_state then

	 out_style = p.appendStyle (style, 'font-style:italic')

	 end

	 outputstr = outputstr .. p.parseStation (station, out_style, system, frame)

	 nextseparator = userseparator

	 end

	 end

end

while block_level > 0 do

blocklevel = blocklevel - 1

outputstr = outputstr .. p.BLOCKENDPURE

end

return output_str

end

function p.route (frame)

local gstyle = frame.args'style'

local route_str = frame.args'stations'

local condition = frame.args'condition'

local system = frame.args'system'

p.stationsuffix = mw.text.trim (frame.args'stationsuffix' or p.DEFAULTSTATIONSUFFIX)

return p.processRoute (string.gsub (route_str, '\n',), gstyle, condition, system, frame)

end

function p.testCase (frame)

local result

cases = {

{{stations=' 東環南路～style=color:gray ~ 邱隘東站～寶幢站 (地鐵) ~ style= ~ 鄔隘站 (地鐵)', system=' '},

' 東環南路 – 邱隘東 – 寶幢 – 鄔隘 '

},

{{stations=' 東環南路～gstart ~ 邱隘東站～寶幢站 (地鐵) ~ gend ~ 鄔隘站 (地鐵)'},

' 東環南路 – 邱隘東 – 寶幢 – 鄔隘 '

},

{{stations='（$ 高橋西 $ 方向）# 東環南路～霞浦～左邊站！右邊～% 原來的東西 %', system='UseCase'},

'（高橋西方向）東環南路 – 霞浦 – 右邊 – 原來的東西 '

},

}

for _idx, case in ipairs (cases) do

result = p.route {args=case1}

if result ~= case2 then

error ('Test ' .. tostring (_idx) .. ' failed.\nExpect: ' .. case2 .. '\nActual: ' .. result)

end

end

end

return p