mirror of
https://github.com/Insality/druid.git
synced 2025-06-27 10:27:47 +02:00
164 lines
3.9 KiB
Lua
164 lines
3.9 KiB
Lua
local parser = require("druid.editor_scripts.defold_parser.system.parser")
|
|
|
|
local M = {}
|
|
|
|
|
|
--- Check if table-array contains element
|
|
---@param table table
|
|
---@param element any
|
|
---@return number|boolean index of element or false
|
|
function M.contains(table, element)
|
|
for index, value in pairs(table) do
|
|
if value == element then
|
|
return index
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
|
|
---@param file_path string
|
|
---@return string|nil, string|nil @success, reason
|
|
function M.read_file(file_path)
|
|
local file = io.open(file_path, "r")
|
|
if file == nil then
|
|
return nil, "Could not open file: " .. file_path
|
|
end
|
|
|
|
local content = file:read("*a")
|
|
file:close()
|
|
|
|
return content, nil
|
|
end
|
|
|
|
|
|
---@param file_path string
|
|
---@param content string
|
|
---@return boolean, string|nil @success, reason
|
|
function M.write_file(file_path, content)
|
|
local file = io.open(file_path, "w")
|
|
if file == nil then
|
|
return false, "Could not open file: " .. file_path
|
|
end
|
|
|
|
file:write(content)
|
|
file:close()
|
|
|
|
return true, nil
|
|
end
|
|
|
|
|
|
---@param line string
|
|
function M.unescape_line(line)
|
|
-- Trim whitespaces
|
|
line = line:match("^%s*(.-)%s*$")
|
|
|
|
-- Remove first and last quote symbols only if exists
|
|
if line:sub(1, 1) == '"' and line:sub(-1) == '"' then
|
|
line = line:sub(2, -2)
|
|
end
|
|
|
|
-- Trim whitespaces
|
|
line = line:match("^%s*(.-)%s*$")
|
|
|
|
-- Splitting the value by new lines and processing each line
|
|
line = line:gsub('\\"', '"') -- Unescaping quotes
|
|
line = line:gsub("\\n", "") -- Removing newline escapes
|
|
line = line:gsub("\\", "") -- Unescaping backslashes
|
|
|
|
return line
|
|
end
|
|
|
|
|
|
---@param line string
|
|
---@return string, string, string, boolean @new_object_name, name, value, end_struct_flag
|
|
function M.split_line(line)
|
|
local new_object_name = line:match(parser.REGEX_START_TABLE)
|
|
local name, value = line:match(parser.REGEX_KEY_COLUM_VALUE)
|
|
local end_struct_flag = line:match(parser.REGEX_END_TABLE)
|
|
|
|
-- We hit a line what is contains only value, like multiline strings
|
|
if not name and not value then
|
|
value = line
|
|
end
|
|
|
|
return new_object_name, name, value, end_struct_flag
|
|
end
|
|
|
|
|
|
-- what a crap...
|
|
local LAST_USED_NAME = nil
|
|
|
|
---@param unescaped_line string @line to parse
|
|
---@param stack table @stack of objects
|
|
---@return boolean
|
|
function M.parse_line(unescaped_line, stack)
|
|
unescaped_line = unescaped_line:match("^%s*(.-)%s*$")
|
|
|
|
-- Use last object to insert data
|
|
local object = stack[#stack]
|
|
local line = M.unescape_line(unescaped_line)
|
|
local inner_object_name, name, value, end_struct_flag = M.split_line(line)
|
|
|
|
local is_just_new_line = (unescaped_line == "\"\\n\"")
|
|
if not end_struct_flag and (line == "\"" or line == "") and (not is_just_new_line) then
|
|
if LAST_USED_NAME ~= "text" then
|
|
end_struct_flag = true
|
|
end
|
|
end
|
|
|
|
if inner_object_name then
|
|
parser.new_inner_struct(object, inner_object_name, stack)
|
|
object = stack[#stack]
|
|
end
|
|
|
|
if name and value ~= nil then
|
|
-- If value is nested object...
|
|
if value:sub(1, 1) == '"' then
|
|
value = value:sub(2, -1)
|
|
end
|
|
if value:sub(-1) == '"' then
|
|
value = value:sub(1, -2)
|
|
end
|
|
|
|
local unescape_line = M.unescape_line(value)
|
|
local new_object_name, field_name, _, end_flag = M.split_line(unescape_line)
|
|
|
|
if (new_object_name or field_name or end_flag) and name ~= "text" then
|
|
parser.new_inner_struct(object, name, stack)
|
|
object = stack[#stack]
|
|
|
|
M.parse_line(value, stack)
|
|
else
|
|
-- Just a hack honestly
|
|
-- If first character is a quote, then remove it
|
|
if value:sub(1, 1) == '"' then
|
|
value = value:sub(2, -1)
|
|
end
|
|
if value:sub(-1) == '"' then
|
|
value = value:sub(1, -2)
|
|
end
|
|
|
|
value = parser.decode_value(value, name)
|
|
LAST_USED_NAME = name
|
|
parser.apply_value(object, name, value)
|
|
end
|
|
end
|
|
|
|
if not name and value and not inner_object_name and not end_struct_flag then
|
|
-- We should to add value to the last as a multiline data
|
|
parser.apply_multiline_value(object, LAST_USED_NAME, value)
|
|
end
|
|
|
|
if end_struct_flag then
|
|
-- Go back to the parent object
|
|
table.remove(stack)
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
|
|
return M
|