模块:Lang zh cn/Parser
跳转到导航
跳转到搜索
可在模块:Lang zh cn/Parser/doc创建此模块的帮助文档
---解析器
local p = {}--返回的变量
---@param str string
function p.parseCSV(str)
local cellDatas = {}
local rowHeads = {}
local result;
local tempKeyCount = 1
result = {
rowHeads = rowHeads,
tempKey = nil,
---设置指定行列单元格的值
---* 使用行列号(从1开始的数字)来作为索引
---* 不存在的单元格会自动新建
---@param row number
---@param column number
set = function(row, column, value)
if column == 1 then
tempKeyCount = 1
cellDatas[value] = {}
tempKey = value
end
cellDatas[tempKey][tempKeyCount] = value
tempKeyCount = tempKeyCount + 1
if row == 1 then rowHeads[value] = column end
end,
}
local state_quotationMark = false -- 双引号状态机
local usub = string.sub
local codepoint = string.byte
local StartPos = 1 --用于记录一个需要被剪切的字符串的起始位
local charNum = 0
local posRow= 1
local posColumn = 1
for i=1, #str do
charNum = codepoint(str,i,i)
if state_quotationMark then -- 处于双引号包裹中
state_quotationMark = (charNum ~= 34)--减少分支优化
--[[目前Noita CSV不包括转义符转引号,所以这部分代码暂时不需要
if charNum == 92 then --转义符考虑
i = i + 1 --当前字符是转义符,下一个字符也应该跳过,所以加1,下一次循环再加1
end]]
else
if charNum == 34 then -- 34为"符号
state_quotationMark = true -- 进入双引号包裹
elseif charNum == 44 then -- 分隔符为en逗号 44为,
result.set(posRow, posColumn, usub(str,StartPos,i-1))--i-1是为了不要把,加进去
StartPos = i + 1--重设起始位
posColumn = posColumn + 1
elseif charNum == 10 then --10为\n
-- 对连续换行(空行)和"\n"(Windows换行符)特殊处理
if (codepoint(str, i - 1, i - 1) ~= 10) then
result.set(posRow, posColumn, usub(str,StartPos,i-1))
StartPos = i + 1
posRow = posRow + 1
posColumn = 1
end
end
end
end
result.set(posRow, posColumn, usub(str,StartPos,#str-1))
return {rowHeads = result.rowHeads,cellDatas = cellDatas}
end
return p