From 82a68e3d97f88454ed0ca1b639aa61c0f59e352f Mon Sep 17 00:00:00 2001 From: ubq323 Date: Mon, 26 Aug 2024 14:24:25 +0100 Subject: init --- xml.lua | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 xml.lua (limited to 'xml.lua') diff --git a/xml.lua b/xml.lua new file mode 100644 index 0000000..7a0758a --- /dev/null +++ b/xml.lua @@ -0,0 +1,73 @@ +local function parseargs(s) + local arg = {} + string.gsub(s, "([%-%w]+)=([\"'])(.-)%2", function (w, _, a) + arg[w] = a + end) + return arg +end + +local psingle + +local function pmulti(s, i, parent) + ::again:: + local nexti, child = psingle(s, i) + if child.close and child.label == parent.label then + return nexti, parent + else + table.insert(parent, child) + i = nexti + goto again + end +end + +psingle = function(s, i) + i = i or 1 + local ts,j,c,label,xarg,empty = s:find("<(%/?)([%w:]+)(.-)(%/?)>", i) + if not ts then + local rest = s:sub(i) + if rest:find("<",i) then + error('ill formed (eof?)') + elseif #rest == 0 then + error('empty string') + else + return i+#rest, rest + end + end + local nexti = j+1 + + local pretext = s:sub(i, ts-1) + if not pretext:find("^%s*$") then -- not entirely whitespace + return ts, pretext + end + + if empty == "/" then + return nexti, {label=label, xarg=parseargs(xarg), empty=true} + elseif c == "" then -- start tag + return multi(s, nexti, {label=label, xarg=parseargs(xarg)}) + else -- end tag + return nexti, {label=label, close=true} + end +end + +local wrap +do + local _, cqa = pcall(require, 'cqueues.auxlib') + wrap = cqa and cqa.wrap or coroutine.wrap +end +local function stanzae(getmore) + return wrap(function() + local buf = '' + while true do + local ok, ni, el = pcall(psingle, buf) + if ok then + coroutine.yield(el) + buf = buf:sub(ni) + else + buf = buf..getmore() + end + end + end) +end + + +return { psingle = psingle, stanzae = stanzae, wrap=wrap } -- cgit v1.2.3