Modul:SimpleStruct

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen

Die Dokumentation für dieses Modul kann unter Modul:SimpleStruct/Doku erstellt werden

--[=[ SimpleStruct 2021-12-21
Module for generating tables and strukts from simple strings
Author: Vollbracht
* SimpleStruct.parse(string)
]=]

-- Module globals
local SimpleStruct = {}

local ElmList
local currentIndex
local StopIndex

-- Iterator, omitting all ipairs
local namePairs = function(namedTable)
  local nmKeys = {}
  for elm in pairs(namedTable) do
    if type(elm) == 'string' then table.insert(nmKeys, elm) end
  end
  local i = 0
  local namePairs_iterator = function()
    i = i + 1
    return nmKeys[i], namedTable[nmKeys[i]]
  end
  return namePairs_iterator
end

local function generateStruct()
  local result = {}
  while currentIndex <= StopIndex do
    if type(ElmList[currentIndex]) == 'string' then
      table.insert(result, ElmList[currentIndex])
      currentIndex = currentIndex + 1
    elseif ElmList[currentIndex] == -1 then
      currentIndex = currentIndex + 1
      return result
    else
      -- assert no changes to ElmList structure: only string, table, or -1
      assert(type(ElmList[currentIndex]) == 'table')
      local name = ElmList[currentIndex][1]
      currentIndex = currentIndex + 1
      local childValue = generateStruct()
      if name == '' then
        -- containing unnamed structure
        -- copy name-value pairs from child
        for pname, value in namePairs(childValue) do result[pname] = value end
        -- copy unnamed values from child
        for _, value in ipairs(childValue) do table.insert(result, value) end
      else
        -- assert store
        if result[name] == nil then result[name] = {} end
        -- copy name-value pairs from child
        for pname, value in namePairs(childValue) do
          if type(value) == 'table' and #value == 1 and type(value[1]) == 'string'
            then result[name][pname] = value[1]
            else result[name][pname] = value
          end
        end
        -- copy unnamed values from child
        for i, value in ipairs(childValue) do
          table.insert(result[name], value)
        end
      end
    end
  end
  return result
end

SimpleStruct.parse = function (StringPar)
  if StringPar == '' then
    ElmList = {}
    currentIndex = 0
    StopIndex = 0
    return
  end
  local tabR = mw.text.split(StringPar, '}')
  -- trim: prevent tailing empty portion from being processed
  if string.gsub(tabR[#tabR], '^%s*(.-)%s*$', '%1') == '' then tabR[#tabR] = nil end
  -- process all portions
  ElmList = {}
  for i, elmR in ipairs(tabR) do
    -- trim:
    elmR = string.gsub(elmR, '^%s*(.-)%s*$', '%1')
    if elmR == '' then -- nothing but closing bracket
      table.insert(ElmList, -1)
    else
      local tabL = mw.text.split(elmR, '{')
      if #tabL == 1 then -- plain value before closing bracket
        -- process plain value
        table.insert(ElmList, elmR)
        -- process bracket
        table.insert(ElmList, -1)
      else
        local j = 1
        while j < #tabL do
          -- process opening brackets
          table.insert(ElmList, {string.gsub(tabL[j], '^%s*(.-)%s*$', '%1')})
          j = j + 1
        end
        -- process plain value
        local v = string.gsub(tabL[j], '^%s*(.-)%s*$', '%1')
        table.insert(ElmList, v)
        -- process bracket
        table.insert(ElmList, -1)
      end
    end
  end
  currentIndex = 1
  StopIndex = #ElmList
  local result = generateStruct()
  return result
end

--[[
	new version
	Aim: keeping order, skaling linear
]]
local function aggregate(source, pointer, debth)
  local p = pointer
  local d = debth
  local result = {}
  local aggregator = {}
  mw.log('aggregate in ' .. pointer .. ' (Tiefe: ' .. debth .. ')')
  while p < #source do
    p = p + 1
    if source[p][2] == false then
      if d == 0 then
        return {["Error"]="Missing opening bracket at element " .. pointer}
      end
      return p, result
    else
      if source[p][4] == false then
        -- 1 0 aggregate with following
        -- save position
        local ap = p
        -- aggregate content
        p, aggregator =  aggregate(source, p, d + 1)
        table.insert(result, {source[ap][1], aggregator})
      else
        -- 1 1 just add an elm
        table.insert(result, {[source[p][1]]=source[p][3]})
      end
    end
  end
  mw.logObject(source[pointer], 'nimmt auf: ')
  mw.logObject(result, 'Elm')
  mw.logObject(source[p], 'next Elm')
  return p, result
end

SimpleStruct.parseNew = function (StringPar)
  local closing = 0
  if StringPar == '' then return end
  mw.log('Stringpar = ' .. StringPar)
  local tabR = mw.text.split(StringPar, '}')
  -- trim: prevent tailing empty portion from being processed
  if string.gsub(tabR[#tabR], '^%s*(.-)%s*$', '%1') == '' then tabR[#tabR] = nil end
  -- process all portions
  local ElmList = {}
  for i, elmR in ipairs(tabR) do
    -- trim:
    elmR = string.gsub(elmR, '^%s*(.-)%s*$', '%1')
    if elmR == '' then
      --elmR is nothing but closing bracket, in "[..]}}"
      table.insert(ElmList, {nil, false, nil, true})
    else
      local tabL = mw.text.split(elmR, '{')
      if #tabL == 1 then
        -- elmR is plain value before closing bracket, in "[..]} value}"
        -- plain value is to be ignored
        -- process bracket
        table.insert(ElmList, {nil, false, nil, true})
      else
        -- elmR contains atleast one opening bracket
        local openOnly = #tabL
        local j = 2
        local leftPart = string.gsub(tabL[1], '^%s*(.-)%s*$', '%1')
        while j < openOnly do
          -- elmR contains atleast two opening brackets
          -- process opening brackets, in "leftPart{[..] {[..]}"
          local rightPart = string.gsub(tabL[j], '^%s*(.-)%s*$', '%1')
          if leftPart == "" then
            -- unnamed opening struct, in "{rightPart{[..]}"
            table.insert(ElmList, {nil, true, nil, false})
          else
            -- named opening struct, in "leftPart{rightPart{[..]}"
            table.insert(ElmList, {leftPart, true, nil, false})
          end
          leftPart = rightPart
          j = j + 1
        end
        local rightPart = string.gsub(tabL[j], '^%s*(.-)%s*$', '%1')
        if leftPart == "" then
          --unnamed containing any string, in "{rightPart}"
          table.insert(ElmList, {nil, true, rightPart, true})
        else
          --named containing any string, in "leftPart{rightPart}"
          table.insert(ElmList, {leftPart, true, rightPart, true})
        end
      end
    end
  end
  local result = {}
  local p = 0
  mw.logObject(ElmList, 'Source')
  p, result = aggregate(ElmList, 0, 0)
  return result
end

return SimpleStruct