186 lines
5.1 KiB
Lua
186 lines
5.1 KiB
Lua
---
|
|
--A module with lots of helpers for the VenusParser.
|
|
--
|
|
--@module vp_util
|
|
local vp_util = {}
|
|
|
|
---
|
|
--Find the first match of a set of patterns within a string.
|
|
--
|
|
--The pattern, that can be found at the earliest position within the string is used to match.
|
|
--If two patterns are at the same position the shorter match is returned.
|
|
--
|
|
--@function [parent=#vp_util] find_min_match
|
|
--@param #string str the string to be searched for the patterns
|
|
--@param patterns the pattern or patterns that are searched within the string
|
|
--@return the starting and the end position of the match
|
|
function vp_util.find_min_match(str,patterns)
|
|
local pats
|
|
local patt = type(patterns)
|
|
if patt == "string" then
|
|
pats = {patterns}
|
|
elseif patt == "table" then
|
|
pats = patterns
|
|
else
|
|
error(("bad argument #2 to optmatch, expected string or table got %s"):format(patterns),2)
|
|
end
|
|
local minspos
|
|
local matchepos
|
|
for _, pat in pairs(pats) do
|
|
local spos,epos = str:find(pat)
|
|
if spos then
|
|
if not minspos then
|
|
minspos = spos
|
|
matchepos = epos
|
|
elseif spos < minspos then
|
|
minspos = spos
|
|
matchepos = epos
|
|
elseif spos == minspos then
|
|
if epos < matchepos then
|
|
minspos = spos
|
|
matchepos = epos
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return minspos, matchepos
|
|
end
|
|
|
|
---
|
|
--A generator to iterate over a string splitting it wherever matches of a pattern can be found.
|
|
--
|
|
--A single or multiple patterns are searched within a string.
|
|
--If the string starts with a matching sequence the sequence itself is given to the iteration.
|
|
--If a matching sequence is found further within the string the sequence before the match is given to the iteration.
|
|
--Every sequence given to the iteration is removed from the iterator.
|
|
--Like this it will traverse the string splitting it into the matches and non-matches.
|
|
--
|
|
--@function [parent=#vp_util] optmatch
|
|
--@param #string str the string to search for matches
|
|
--@param patterns the pattern or patterns to split by
|
|
--@return #function the iterator for a loop
|
|
function vp_util.optmatch(str,patterns)
|
|
local cutstr = str
|
|
return function()
|
|
if not cutstr then return end
|
|
local spos, epos = vp_util.find_min_match(cutstr,patterns)
|
|
local match
|
|
local found = (spos == 1)
|
|
if found then
|
|
match = cutstr:sub(1,epos)
|
|
cutstr = cutstr:sub(epos+1)
|
|
--print("f",match,cutstr,pat)
|
|
elseif not spos then
|
|
if cutstr == "" then
|
|
match = nil
|
|
else
|
|
match = cutstr
|
|
end
|
|
cutstr = nil
|
|
--print("n",match,pat)
|
|
else
|
|
match = cutstr:sub(1,spos-1)
|
|
cutstr = cutstr:sub(spos)
|
|
--print("p",match,cutstr,pat)
|
|
end
|
|
return match, found
|
|
end
|
|
end
|
|
|
|
---
|
|
--A function generating a table from an iterator.
|
|
--
|
|
--@function [parent=#vp_util] gen_table
|
|
--@param #function it the iterator to use in a for loop
|
|
--@return #table the table containing the returns of the iterator
|
|
function vp_util.gen_table(it)
|
|
local tab = {}
|
|
for el in it do
|
|
table.insert(tab,el)
|
|
end
|
|
return tab
|
|
end
|
|
|
|
---
|
|
--double flat table compare
|
|
--A function comparing the contents of two tables.
|
|
--
|
|
--It iterates over both tables checking if the other contains the same elements.
|
|
--
|
|
--@function [parent=#vp_util] dftc
|
|
--@param #table t1 the table to compare with t2
|
|
--@param #table t2 the table to compare with t1
|
|
--@return #boolean whether the tables contents are the same
|
|
function vp_util.dftc(t1,t2)
|
|
for i,el in pairs(t1) do
|
|
if t2[i] ~= el then
|
|
return false
|
|
end
|
|
end
|
|
for i,el in pairs(t2) do
|
|
if t1[i] ~= el then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
---
|
|
--concatenate strings
|
|
--if one string is nil the other is returned
|
|
--
|
|
--@function [parent=#vp_util] concat_optnil
|
|
--@param #string fstr the first string to be concatenated
|
|
--@param #string lstr the second string to be concatenated
|
|
--@param #string sep the seperator to be added between the strings if both are present
|
|
--@param #string retstr The string returned if both strings are empty.
|
|
-- Can be true to return an empty string.
|
|
function vp_util.concat_optnil(fstr,lstr,sep,retstr)
|
|
if fstr then
|
|
if lstr then
|
|
if sep then
|
|
if fstr == "" or lstr == "" then
|
|
return fstr..lstr
|
|
else
|
|
return fstr..sep..lstr
|
|
end
|
|
else
|
|
return fstr..lstr
|
|
end
|
|
else
|
|
return fstr
|
|
end
|
|
else
|
|
if lstr then
|
|
return lstr
|
|
else
|
|
if retstr == true then
|
|
return ""
|
|
elseif retstr then
|
|
return retstr
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
---
|
|
--The unit tests for the vp utilities.
|
|
local function tests()
|
|
assert(vp_util.dftc({},{}))
|
|
assert(vp_util.dftc({1},{1}))
|
|
assert(not vp_util.dftc({1},{2}))
|
|
assert(vp_util.dftc({1,"2",true},{1,"2",true}))
|
|
assert(not vp_util.dftc({true,"1",1},{1,1,1}))
|
|
|
|
assert(vp_util.dftc(vp_util.gen_table(vp_util.optmatch("123","123")),{"123"}))
|
|
assert(vp_util.dftc(vp_util.gen_table(vp_util.optmatch("123","321")),{"123"}))
|
|
assert(vp_util.dftc(vp_util.gen_table(vp_util.optmatch("123", "1")), {"1","23"}))
|
|
assert(vp_util.dftc(vp_util.gen_table(vp_util.optmatch("123", "2")), {"1","2","3"}))
|
|
end
|
|
|
|
tests()
|
|
|
|
return vp_util
|