模块:Wikitable.lua:修订间差异
来自「荏苒之境」
创建空白页面 |
无编辑摘要 |
||
第1行: | 第1行: | ||
local unpack = unpack or table.unpack | |||
local BYTE_ENTER = string.byte('\r') | |||
local BYTE_NEWLINE = string.byte('\n') | |||
local BYTE_OPEN_CURLY = string.byte('{') | |||
local BYTE_CLOSE_CURLY = string.byte('}') | |||
local BYTE_SEPARATOR = string.byte('|') | |||
local BYTE_EXCLAMATION = string.byte('!') | |||
local BYTE_MINUS = string.byte('-') | |||
local wikitable = {} | |||
local function skip_to_next_line(str, pos) | |||
while true do | |||
local b = string.byte(str, pos) | |||
if b == BYTE_NEWLINE or b == BYTE_ENTER then | |||
return pos + 1 | |||
elseif b == nil then | |||
return nil | |||
end | |||
pos = pos + 1 | |||
end | |||
end | |||
local function find_character(str, pos, cbyte) | |||
while true do | |||
local b = string.byte(str, pos) | |||
if b == cbyte then | |||
return pos | |||
elseif b == nil then | |||
return nil | |||
end | |||
pos = pos + 1 | |||
end | |||
end | |||
local function find_table_start(str, pos) | |||
pos = find_character(str, pos, BYTE_OPEN_CURLY) | |||
if pos == nil then return nil end | |||
pos = find_character(str, pos, BYTE_SEPARATOR) | |||
if pos == nil then return nil end | |||
return pos + 1 | |||
end | |||
local function parse_cell(str, pos) | |||
local head = string.byte(str, pos) | |||
pos = pos + 1 | |||
local bytes = {} | |||
while true do | |||
local b = string.byte(str, pos) | |||
if b == BYTE_NEWLINE then | |||
pos = pos + 1 | |||
break | |||
elseif b == nil then | |||
pos = nil | |||
break | |||
end | |||
if b ~= BYTE_ENTER then | |||
bytes[#bytes+1] = b | |||
end | |||
pos = pos + 1 | |||
end | |||
if head == BYTE_EXCLAMATION then | |||
return pos, "header", string.char(unpack(bytes)) | |||
elseif head == BYTE_SEPARATOR then | |||
local fst_byte = bytes[1] | |||
if fst_byte == BYTE_MINUS then | |||
return pos, "row_end" | |||
elseif fst_byte == BYTE_CLOSE_CURLY then | |||
return pos, "table_end" | |||
else | |||
return pos, "text", string.char(unpack(bytes)) | |||
end | |||
end | |||
end | |||
wikitable.parse = function(str) | |||
local header = {} | |||
local rows = { header = header } | |||
local curr_row | |||
local pos = find_table_start(str, 1) | |||
if pos == nil then return rows end | |||
pos = skip_to_next_line(str, pos) | |||
local cell_type, cell_content | |||
while pos ~= nil do | |||
pos, cell_type, cell_content = parse_cell(str, pos) | |||
if cell_type == "header" then | |||
header[#header+1] = cell_content | |||
elseif cell_type == "row_end" | |||
or cell_type == "table_end" then | |||
if curr_row then | |||
rows[#rows+1] = curr_row | |||
end | |||
curr_row = {} | |||
if cell_type == "table_end" then | |||
break | |||
end | |||
else | |||
if curr_row == nil then | |||
curr_row = {} | |||
end | |||
curr_row[#curr_row+1] = cell_content | |||
end | |||
end | |||
return rows | |||
end | |||
return wikitable |
2025年8月6日 (三) 00:31的版本
此模块的文档可以在模块:Wikitable.lua/doc创建
local unpack = unpack or table.unpack
local BYTE_ENTER = string.byte('\r')
local BYTE_NEWLINE = string.byte('\n')
local BYTE_OPEN_CURLY = string.byte('{')
local BYTE_CLOSE_CURLY = string.byte('}')
local BYTE_SEPARATOR = string.byte('|')
local BYTE_EXCLAMATION = string.byte('!')
local BYTE_MINUS = string.byte('-')
local wikitable = {}
local function skip_to_next_line(str, pos)
while true do
local b = string.byte(str, pos)
if b == BYTE_NEWLINE or b == BYTE_ENTER then
return pos + 1
elseif b == nil then
return nil
end
pos = pos + 1
end
end
local function find_character(str, pos, cbyte)
while true do
local b = string.byte(str, pos)
if b == cbyte then
return pos
elseif b == nil then
return nil
end
pos = pos + 1
end
end
local function find_table_start(str, pos)
pos = find_character(str, pos, BYTE_OPEN_CURLY)
if pos == nil then return nil end
pos = find_character(str, pos, BYTE_SEPARATOR)
if pos == nil then return nil end
return pos + 1
end
local function parse_cell(str, pos)
local head = string.byte(str, pos)
pos = pos + 1
local bytes = {}
while true do
local b = string.byte(str, pos)
if b == BYTE_NEWLINE then
pos = pos + 1
break
elseif b == nil then
pos = nil
break
end
if b ~= BYTE_ENTER then
bytes[#bytes+1] = b
end
pos = pos + 1
end
if head == BYTE_EXCLAMATION then
return pos, "header", string.char(unpack(bytes))
elseif head == BYTE_SEPARATOR then
local fst_byte = bytes[1]
if fst_byte == BYTE_MINUS then
return pos, "row_end"
elseif fst_byte == BYTE_CLOSE_CURLY then
return pos, "table_end"
else
return pos, "text", string.char(unpack(bytes))
end
end
end
wikitable.parse = function(str)
local header = {}
local rows = { header = header }
local curr_row
local pos = find_table_start(str, 1)
if pos == nil then return rows end
pos = skip_to_next_line(str, pos)
local cell_type, cell_content
while pos ~= nil do
pos, cell_type, cell_content = parse_cell(str, pos)
if cell_type == "header" then
header[#header+1] = cell_content
elseif cell_type == "row_end"
or cell_type == "table_end" then
if curr_row then
rows[#rows+1] = curr_row
end
curr_row = {}
if cell_type == "table_end" then
break
end
else
if curr_row == nil then
curr_row = {}
end
curr_row[#curr_row+1] = cell_content
end
end
return rows
end
return wikitable