-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathparser.lua
More file actions
312 lines (281 loc) · 8.15 KB
/
parser.lua
File metadata and controls
312 lines (281 loc) · 8.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
local config = require("config")
function dump(o)
if type(o) == 'table' then
local s = '{ '
for k, v in pairs(o) do
if type(k) ~= 'number' then k = '"' .. k .. '"' end
s = s .. '[' .. k .. '] = ' .. dump(v) .. ','
end
return s .. '} '
else
return tostring(o)
end
end
local parser = {}
---utility func
---@param str string
---@param substr string
---@return number
local function find_last_index(str, substr)
local last_index = -1
for i = #str, 1, -1 do
local index = string.find(str, substr, i, true)
if index then
last_index = index
break
end
end
return last_index
end
---utility func
local function isSpecialType(r)
return (r
and r ~= 'String'
and r ~= 'Boolean'
and r ~= 'Number'
and r ~= 'Numbers'
and r ~= 'Constant'
and r ~= 'Function'
and r ~= 'Array'
and r ~= 'Table'
and r ~= 'TYPE'
and r ~= 'Object'
and r ~= 'Library'
and r ~= 'Module'
and r ~= 'CoronaClass'
and r ~= 'Event'
and r ~= 'Listener'
-- and r ~= 'Userdata'
)
end
---To get a folder name and file name
---@param str string
---@return string
function GetLastPathItem(str)
local lastSlashIndex = find_last_index(str, "/")
if lastSlashIndex == -1 then
return ""
end
return string.sub(str, lastSlashIndex + 1) --[[@as string]]
end
local function extractInfo(filename)
local parent
local overview = ""
local i = 0
local inOverview = false
local f = io.open(filename, 'r')
if f == nil then return end
for l in f:lines() do
i = i + 1
if l:find("^> __Parent__") then
parent = l:match("%[(.-)%]")
elseif l:find("Overview") then
inOverview = true
elseif inOverview then
if l:find("##") then
inOverview = false
else
overview = overview .. l
end
end
end
f:close()
return parent, overview
end
---utility func
---@param s string
---@param piece string
---@return boolean
local function startswith(s, piece)
return string.sub(s, 1, string.len(piece)) == piece
end
---utility func
function parser.beforeComma(line)
for i = 1, line:len() do
if line:sub(i, i) == '.' then
return line:sub(1, i - 1)
end
end
return line
end
--- @class TitleContent
--- @field d string
--- @field t string
---Gets everything inside a Header in markdown
---@param markdown_text string
---@param heading string
---@return table<TitleContent>
local function parseTitles(markdown_text, heading)
local content = {}
local index = 1
for line in markdown_text:gmatch("([^\n]*)\n?") do
if content[index] == nil then
content[index] = { t = "global", d = "" }
end
if string.match(line, "^" .. heading .. " .+$") then
index = index + 1
content[index] = { t = line:gsub(heading .. " ", ""), d = "" }
else
content[index].d = content[index].d .. "\n" .. line
end
end
return content
end
--- @class ExtractedArg
--- @field name string
--- @field type string
--- @field optional boolean
--- @field docs string
--- @class ExtractedMethod
--- @field arguments table<ExtractedArg>
--- @field name string
--- @class ExtractedData
--- @field type string
--- @field methods table<ExtractedMethod>
--- @field docs string
--- @field returnv string | nil
---utility func
---@param str string
---@return string
local function extractStringBetweenBrackets(str)
local start, stop = string.find(str, "%[(.-)%]")
if start and stop then
return string.sub(str, start + 1, stop - 1) --[[@as string]]
else
return ""
end
end
---Removes unnecesary things from a name
---@param str string
---@return string
local function cleanTitle(str)
---@type string
local p = string.gsub(str, " ~%^%(required%)%^~", "") --[[@as string]]
p = string.gsub(p, " ~%^%(optional%)%^~", "") --[[@as string]]
p = string.gsub(p, "%[...%]", "...") --[[@as string]]
p = string.gsub(p, "%[", "") --[[@as string]]
p = string.gsub(p, "%]", "") --[[@as string]]
p = string.gsub(p, " ", "") --[[@as string]]
return p
end
---@param input string
---@return string
local function extractArgumentDocs(input)
if not config.generate_arguments_docs then
return ""
end
local pattern = "_%b[]%b[]%._ "
local s = string.gsub(input, "\n", "") --[[@as string]]
s = string.gsub(s, pattern, "") --[[@as string]]
return s
end
---Parse arguments from text
---@param arg TitleContent
---@param data ExtractedMethod
local function generateArgument(arg, data)
local sepnames = (arg.t .. ","):gmatch("(.-),")
for compname in sepnames do
for singlename in (compname .. "/"):gmatch("(.-)/") do
local argument = {
name = cleanTitle(singlename),
type = extractStringBetweenBrackets(arg.d),
docs = extractArgumentDocs(arg.d),
optional = not (arg.t:find("optional") == nil)
} --[[@as ExtractedArg]]
data.arguments[#data.arguments + 1] = argument
end
end
end
---comment
---@param raw string
---@param data ExtractedData
---@param title string
local function genMethod(raw, data, title)
if title ~= "main" and title == "global" then
return
end
local args = parseTitles(raw, "#####")
---@type ExtractedMethod
local method = {
name = title,
arguments = {}
}
for _, arg in ipairs(args) do
if not (arg.t == "global") then
generateArgument(arg, method)
end
end
data.methods[#data.methods + 1] = method
end
---comment
---@param filename string
---@return ExtractedData
local function extractTypeArgsReturns(filename)
local data = {
type = "",
methods = {},
docs = ""
} --[[@as ExtractedData]]
local f = io.open(filename, 'r')
if f == nil then return data end
local blocks = parseTitles(f:read("a"), "##")
for _, value in ipairs(blocks) do
local ccc = value.d --[[@as string]]
if value.t == "global" then
-- Parse general info here
for line in ccc:gmatch("([^\n]*)\n?") do
if startswith(line, '> __Type__') then
data.type = line:match('%[api%.type%.(%a*)%]', 1):lower()
elseif startswith(line, '> __Return value__') then
data.returnv = line:match('%[(%a*)%]', 1)
end
end
elseif value.t == "Overview" then
data.docs = string.gsub(value.d, "\n", " ") .. "\n"
elseif value.t == "Syntax" then
-- Parse function info here
local variants = parseTitles(ccc, "###")
if #variants == 1 then
genMethod(ccc, data, "main")
else
for _, variant in ipairs(variants) do
genMethod(variant.d, data, variant.t)
end
end
elseif value.t == "Example" or value.t == "Examples" then
-- Parse for documentation, todo
end
end
f:close()
return data
end
---Parses a markdown file to a buffer
---@param path string
---@param name string
---@param buffer table
function parser.parseFile(path, name, buffer)
local data = extractTypeArgsReturns(path)
buffer.childs[parser.beforeComma(name)] = data
end
---comment
---@param category string
---@param name string
---@param api table
---@return string
function parser.parseSingleFile(category, name, api)
local package = parser.beforeComma(name)
if api[package] == nil then
api[package] = { type = "", description = '', childs = {}, category = category }
end
return package
end
---Parses and sets a directory to a buffer
---@param path string
---@param buffer table
---@param force boolean
function parser.parseIndex(path, buffer, force)
local parent, overview = extractInfo(path)
if parent and (isSpecialType(parent) or force) then buffer.inherits = parent end
buffer.overview = overview
end
return parser