[create]
The documentation for this module is missing. Click here to create it.
--<nowiki>
--| Process a Lua source file, extracting comments and function
--| prototypes.
--b Pedro Miller Rabinovitch <miller@inf.puc-rio.br>
--$Id: proc_src.lua,v 1.7 2003/10/20 03:35:08 miller Exp $
--TODO: most of the work. >;)
--http://lua-users.org/wiki/ExpLua
local util = require ('Dev:Codedoc/util')
local ProcLua = {}
-- prefix char list
local HEADER_PREF = '|b$T-'
local FUNC_PREF = '%%@:Tb-'
local CMT_BEGIN = '\n%s*%-%-'
-- special patterns
local FUNC_PTRN = { '(f)unction%s+(%a%w*)', }
local FUNC_PTRN = '^%s*(f)unction%s+([%w:._]*)'
local FUNC_LOCAL_PTRN = '^%s*local%s+(f)unction%s+([%w:._]*)'
local PARAM_PTRN = '%s*([%w.]+)%s*%((%w+)%)%s*(.-)$'
local OPTN_PARAM_PTRN = '%s*%[([%w.]+)%]%s*%((%w+)%)%s*(.-)$'
local RET_PTRN = '%s*%((%w+)%)%s*(.-)$'
--% Find commentary and relevant lines
--@ text (string) program code
--@ prefix (string) class of characters to come after `--'
--@ [special] (string) optional special patterns that should also be matched
--: (table) line list
function ProcLua:scan_lines( text, prefix, special )
if not text then
return
end
util.check_types( 'string', text, prefix )
local lines = {n=0}
local ptrn = CMT_BEGIN..'(['..prefix..'])%s*(.-)\n()'
if special == nil then
text = string.gsub( text, '\n', '\n\n' )
string.gsub( '\n'..text..'\n', ptrn, function( t, str, pos )
util.check_types( 'string', t, str )
table.insert( lines, { t, str } )
end )
else
string.gsub( text..'\n', '(.-\n)', function( line )
local a, b, c1, c2 = string.find( '\n'..line, ptrn )
if a and c1 then
if c1 == '-' then
-- concatenate to the previous line
local ll = lines[lines.n]
if ll then
ll[2] = ll[2]..' '..c2
end
a = nil
end
else
-- find a function declaration
a, b, c1, c2 = string.find( line, special )
-- On failure to find the function, try a 'local function'
if not a and special == FUNC_PTRN then
a, b, c1, c2 = string.find( line, FUNC_LOCAL_PTRN )
end
end
if a then
table.insert( lines, { c1, c2 } )
end
end)
end
return lines
end
--% Build function commentary structure from text
--@ text (string) program code
--: (table) function structure
function ProcLua:get_functions( text )
-- util.check_types( 'string', text )
local functions = {}
-- Get function lines
local lines = self:scan_lines( text, FUNC_PREF, FUNC_PTRN )
util.check_types( 'table', lines )
local a, b
local curr = nil
for i, v in ipairs( lines ) do
if v[1] == '%' then
curr = curr or {}
curr.purpose = (curr.purpose or '')..v[2]..'\n'
elseif v[1] == ':' then
assert( type(curr) == 'table', 'use --% before --'..v[1] )
assert( type(v[2]) == 'string', 'missing return, correct syntax : "--: (return type) return description"' )
curr.returns = curr.returns or {}
local ret = {}
a, b, ret.type, ret.purpose =
string.find( v[2], RET_PTRN )
ret.purpose = util.add_punctuation( ret.purpose )
table.insert( curr.returns, ret )
elseif v[1] == '@' then
assert( type(curr) == 'table', 'use --% before --'..v[1] )
curr.parameters = curr.parameters or {}
local param = {}
a, b, param.name, param.type, param.purpose =
string.find( v[2], PARAM_PTRN )
if param.purpose == nil then
a, b, param.name, param.type, param.purpose =
string.find( v[2], OPTN_PARAM_PTRN )
param.optional = true
end
assert( type(param.purpose) == 'string', 'missing param purpose, correct syntax : "--@ paramname (paramtype) paramdescription" ' )
param.purpose = util.add_punctuation( param.purpose )
table.insert( curr.parameters, param )
elseif v[1] == 'f' then
if curr then
curr.name = v[2]
curr.purpose = util.add_punctuation( curr.purpose )
if self.options and not self.options.proc_private then
-- check if it's a pvt function (risqué)
-- accept E: or Name: as public methods
local _, __, class = string.find( curr.name, '(%w+)[.:]' )
if class and (class == 'E' or string.len( class) > 1) then
table.insert( functions, curr )
end
else
table.insert( functions, curr )
end
end
curr = nil
end
end
return functions
end
--% Build header commentary structure from text
--@ text (string) program code
--: (table) header structure
function ProcLua:get_header( text )
util.check_types( 'string', text )
local header = {
authors = {},
purpose = '',
todo = {},
revision = '',
}
-- Get header lines
local lines = self:scan_lines( text, HEADER_PREF )
util.check_types( 'table', lines )
for i, v in ipairs( lines ) do
if v[1] == '$' then
header.revision = '$'..v[2]
elseif v[1] == 'T' then
table.insert( header.todo, (string.gsub( v[2], '^ODO:?%s*', '' )))
elseif v[1] == 'b' then
table.insert( header.authors, v[2] )
elseif v[1] == '|' then
header.purpose = header.purpose .. v[2] .. '\n'
end
end
return header
end
--% Build comment structure from text
--@ text (string) program code
--@ options (table) optional options table
--: (table) commentary structure
function ProcLua:process( text, options )
self.options = options or {}
util.check_types( 'string', text )
local commentary = {}
-- Get header info
commentary.header = self:get_header( text )
-- Scan for function declarations
commentary.functions = self:get_functions( text )
return commentary
end
return ProcLua