260 lines
6.1 KiB
Lua
260 lines
6.1 KiB
Lua
local outdir = arg[1]
|
|
|
|
function string.trim(self)
|
|
return self:gsub("^%s+", ""):gsub("%s+$", "")
|
|
end
|
|
|
|
local escapes = {
|
|
["\\"] = "\\",
|
|
["n"] = "\n",
|
|
["t"] = "\t",
|
|
["r"] = "\r"
|
|
}
|
|
local docs = {}
|
|
local cdoc
|
|
local cfunc
|
|
local function parse_string(str, close, noesc)
|
|
local s = ""
|
|
local esc = false
|
|
repeat
|
|
local c = str.read()
|
|
if not esc then
|
|
if (c ~= "\\" or noesc) then
|
|
s = s .. c
|
|
else
|
|
esc = true
|
|
end
|
|
else
|
|
if (escapes[c]) then
|
|
s = s .. escapes[c]
|
|
else
|
|
return nil, "invalid escape"
|
|
end
|
|
end
|
|
until str.peek(#close) == close or str.peek(#close) == ""
|
|
str.seek(#close)
|
|
return s
|
|
end
|
|
|
|
local function parse_dec(str)
|
|
local num = ""
|
|
repeat
|
|
num = num .. str.read()
|
|
until not str.peek():match("%d") or str.peek() == ""
|
|
return tonumber(num, 10)
|
|
end
|
|
|
|
local function parse_hex(str)
|
|
if not str.peek():match("%x") then
|
|
return nil, "malformed hex"
|
|
end
|
|
local num = ""
|
|
repeat
|
|
num = num .. str.read()
|
|
until not str.peek():match("%x") or str.peek() == ""
|
|
return tonumber(num, 16)
|
|
end
|
|
local ln = 0
|
|
local function parse_line(line)
|
|
local args = {}
|
|
local idx = 1
|
|
local str = {
|
|
peek = function(amt)
|
|
amt = amt or 1
|
|
return line:sub(idx, idx+amt-1)
|
|
end,
|
|
read = function(amt)
|
|
amt = amt or 1
|
|
local data = line:sub(idx, idx+amt-1)
|
|
idx = idx + amt
|
|
return data
|
|
end,
|
|
seek = function(amt)
|
|
amt = amt or 0
|
|
idx = idx + amt
|
|
return idx
|
|
end
|
|
}
|
|
local function lassert(a, b)
|
|
return assert(a, "line #"..ln..": "..(b or "unknown error"))
|
|
end
|
|
while str.peek() ~= "" do
|
|
if (str.peek() == "\"") then
|
|
str.seek(1)
|
|
args[#args+1] = lassert(parse_string(str, "\"", false))
|
|
elseif (str.peek(2) == "0x") then
|
|
str.seek(2)
|
|
args[#args+1] = lassert(parse_hex(str))
|
|
elseif (str.peek(1):match("%d")) then
|
|
args[#args+1] = lassert(parse_dec(str))
|
|
elseif (str.peek() == "'") then
|
|
str.seek(1)
|
|
args[#args+1] = lassert(parse_string(str, "'", false))
|
|
elseif (str.peek() == " ") then
|
|
--do nothing
|
|
else
|
|
args[#args+1] = lassert(parse_string(str, " ", true))
|
|
end
|
|
end
|
|
return args
|
|
end
|
|
local function is_comment(line)
|
|
if (line:trim():sub(1, 2) == "--") then
|
|
return true, line:sub(3)
|
|
end
|
|
end
|
|
for line in io.stdin:lines() do
|
|
ln = ln+1
|
|
local com, rline = is_comment(line)
|
|
if (com) then
|
|
if (rline:match("^%-@module")) then
|
|
local args = parse_line(rline:sub(10))
|
|
if (cdoc) then
|
|
if (cfunc) then
|
|
cdoc.methods[#cdoc.methods+1] = cfunc
|
|
cfunc = nil
|
|
end
|
|
docs[#docs+1] = cdoc
|
|
end
|
|
cdoc = {
|
|
type = "module",
|
|
methods = {},
|
|
name = args[2],
|
|
mod = args[1]
|
|
}
|
|
elseif (rline:match("^%-@section")) then
|
|
local args = parse_line(rline:sub(11))
|
|
if (cdoc) then
|
|
if (cfunc) then
|
|
cdoc.methods[#cdoc.methods+1] = cfunc
|
|
cfunc = nil
|
|
end
|
|
docs[#docs+1] = cdoc
|
|
end
|
|
cdoc = {
|
|
type = "generic",
|
|
methods = {},
|
|
name = args[2],
|
|
mod = args[1]
|
|
}
|
|
elseif (rline:match("^%-@page")) then
|
|
if (cfunc) then
|
|
cdoc.methods[#cdoc.methods+1] = cfunc
|
|
end
|
|
local args = parse_line(rline:sub(8))
|
|
cfunc = {
|
|
type = "page",
|
|
doc = {},
|
|
name = args[1],
|
|
print_name = args[2]
|
|
}
|
|
elseif (rline:match("^%-@arg") and cfunc.type == "func") then
|
|
local args = parse_line(rline:sub(7))
|
|
cfunc.args[#cfunc.args+1] = {
|
|
name = args[1],
|
|
type = args[2],
|
|
doc = args[3]
|
|
}
|
|
elseif (rline:match("^%-@return") and cfunc.type == "func") then
|
|
local args = parse_line(rline:sub(10))
|
|
cfunc.ret[#cfunc.ret+1] = {
|
|
type = args[1],
|
|
doc = args[2],
|
|
}
|
|
elseif (rline:match("^%-@doc")) then
|
|
local args = parse_line(rline:sub(7))
|
|
cfunc.doc[#cfunc.doc+1] = {
|
|
doc = args[1],
|
|
}
|
|
elseif (rline:match("^%-@see")) then
|
|
local args = parse_line(rline:sub(7))
|
|
cfunc.doc[#cfunc.doc+1] = {
|
|
doc = "See \27_S"..args[1].."\27_E"
|
|
}
|
|
elseif (rline:match("^%-@note")) then
|
|
local args = parse_line(rline:sub(8))
|
|
cfunc.doc[#cfunc.doc+1] = {
|
|
doc = "NOTE: "..args[1]
|
|
}
|
|
elseif (rline:match("^%-@desc")) then
|
|
local args = parse_line(rline:sub(8))
|
|
cfunc.doc[#cfunc.doc+1] = {
|
|
doc = args[1]
|
|
}
|
|
elseif (rline:match("^%-@vararg")) then
|
|
cfunc.vararg = true
|
|
elseif (rline:match("^%-@varret")) then
|
|
cfunc.varret = true
|
|
elseif (rline:match("^%-@func")) then
|
|
if (cfunc) then
|
|
cdoc.methods[#cdoc.methods+1] = cfunc
|
|
end
|
|
local args = parse_line(rline:sub(8))
|
|
cfunc = {
|
|
type = "func",
|
|
doc = {},
|
|
name = args[1],
|
|
ret = {},
|
|
args = {}
|
|
}
|
|
end
|
|
else
|
|
io.stderr:write(line.."\n")
|
|
end
|
|
end
|
|
|
|
if (cfunc) then
|
|
cdoc.methods[#cdoc.methods+1] = cfunc
|
|
end
|
|
if (cdoc) then
|
|
docs[#docs+1] = cdoc
|
|
end
|
|
for i=1, #docs do
|
|
os.execute("mkdir -p \""..outdir.."/"..docs[i].mod:trim().."\"")
|
|
for j=1, #docs[i].methods do
|
|
local docc = ""
|
|
local f = io.open(outdir.."/"..docs[i].mod:trim().."/"..docs[i].methods[j].name:trim()..".tdf", "wb")
|
|
if (docs[i].methods[j].type == "func") then
|
|
local argtext = ""
|
|
local fun = docs[i].mod.."."..docs[i].methods[j].name.."("
|
|
if (#docs[i].methods[j].args > 0) then
|
|
for k=1, #docs[i].methods[j].args do
|
|
fun = fun .. docs[i].methods[j].args[k].name..":"..docs[i].methods[j].args[k].type .. ", "
|
|
argtext = argtext .. docs[i].methods[j].args[k].name .. " - " .. docs[i].methods[j].args[k].doc .. "\n"
|
|
end
|
|
if (docs[i].methods[j].vararg) then
|
|
fun = fun .. "..."
|
|
else
|
|
fun = fun:sub(1, #fun-2)
|
|
end
|
|
else
|
|
argtext = "No arguments"
|
|
end
|
|
fun = fun .. ")"
|
|
|
|
local rettext = ""
|
|
if (#docs[i].methods[j].ret > 0) then
|
|
fun = fun .. ":"
|
|
for k=1, #docs[i].methods[j].ret do
|
|
fun = fun .. docs[i].methods[j].ret[k].type .. ", "
|
|
rettext = rettext .. docs[i].methods[j].ret[k].type .. " - " .. docs[i].methods[j].ret[k].doc .. "\n"
|
|
end
|
|
if (docs[i].methods[j].varret) then
|
|
fun = fun .. "..."
|
|
else
|
|
fun = fun:sub(1, #fun-2)
|
|
end
|
|
else
|
|
rettext = "No return."
|
|
end
|
|
docc = docc .. fun .. "\n\nArguments:\n"..argtext.."\n\nReturns:\n"..rettext.."\n\n"
|
|
else
|
|
docc = docc .. docs[i].methods[j].print_name .. "\n\n"
|
|
end
|
|
for k=1, #docs[i].methods[j].doc do
|
|
docc = docc..docs[i].methods[j].doc[k].doc .. "\n"
|
|
end
|
|
f:write(docc)
|
|
f:close()
|
|
end
|
|
end |