separate out language-specific parsing strategies
This commit is contained in:
parent
7c02820692
commit
ad2a350806
136
ldoc.lua
136
ldoc.lua
|
@ -37,6 +37,7 @@ ldoc, a documentation generator for Lua, vs 0.3 Beta
|
|||
|
||||
local lexer = require 'ldoc.lexer'
|
||||
local doc = require 'ldoc.doc'
|
||||
local lang = require 'ldoc.lang'
|
||||
local Item,File,Module = doc.Item,doc.File,doc.Module
|
||||
local tools = require 'ldoc.tools'
|
||||
local KindMap = tools.KindMap
|
||||
|
@ -167,139 +168,6 @@ end
|
|||
local quit = utils.quit
|
||||
|
||||
|
||||
class.Lang()
|
||||
|
||||
function Lang:trim_comment (s)
|
||||
return s:gsub(self.line_comment,'')
|
||||
end
|
||||
|
||||
function Lang:start_comment (v)
|
||||
local line = v:match (self.start_comment_)
|
||||
local block = v:match(self.block_comment)
|
||||
return line or block, block
|
||||
end
|
||||
|
||||
function Lang:empty_comment (v)
|
||||
return v:match(self.empty_comment_)
|
||||
end
|
||||
|
||||
function Lang:grab_block_comment(v,tok)
|
||||
v = v:gsub(self.block_comment,'')
|
||||
return tools.grab_block_comment(v,tok,self.end_block1,self.end_block2)
|
||||
end
|
||||
|
||||
function Lang:find_module(tok,t,v)
|
||||
return '...',t,v
|
||||
end
|
||||
|
||||
function Lang:function_follows(t,v)
|
||||
return false
|
||||
end
|
||||
|
||||
function Lang:finalize()
|
||||
self.empty_comment_ = self.start_comment_..'%s*$'
|
||||
end
|
||||
|
||||
function Lang:search_for_token (tok,type,value,t,v)
|
||||
while t and not (t == type and v == value) do
|
||||
if t == 'comment' and self:start_comment(v) then return nil,t,v end
|
||||
t,v = tnext(tok)
|
||||
end
|
||||
return t ~= nil,t,v
|
||||
end
|
||||
|
||||
function Lang:parse_function_header (tags,tok,toks)
|
||||
end
|
||||
|
||||
function Lang:parse_extra (tags,tok,toks)
|
||||
end
|
||||
|
||||
|
||||
class.Lua(Lang)
|
||||
|
||||
function Lua:_init()
|
||||
self.line_comment = '^%-%-+' -- used for stripping
|
||||
self.start_comment_ = '^%-%-%-+' -- used for doc comment line start
|
||||
self.block_comment = '^%-%-%[%[%-+' -- used for block doc comments
|
||||
self.end_block1 = ']'
|
||||
self.end_block2 = ']'
|
||||
self:finalize()
|
||||
end
|
||||
|
||||
function Lua.lexer(fname)
|
||||
local f,e = io.open(fname)
|
||||
if not f then quit(e) end
|
||||
return lexer.lua(f,{}),f
|
||||
end
|
||||
|
||||
-- If a module name was not provided, then we look for an explicit module()
|
||||
-- call. However, we should not try too hard; if we hit a doc comment then
|
||||
-- we should go back and process it. Likewise, module(...) also means
|
||||
-- that we must infer the module name.
|
||||
function Lua:find_module(tok,t,v)
|
||||
local res
|
||||
res,t,v = self:search_for_token(tok,'iden','module',t,v)
|
||||
if not res then return nil,t,v end
|
||||
t,v = tnext(tok)
|
||||
if t == '(' then t,v = tnext(tok) end
|
||||
if t == 'string' then -- explicit name, cool
|
||||
return v,t,v
|
||||
elseif t == '...' then -- we have to guess!
|
||||
return '...',t,v
|
||||
end
|
||||
end
|
||||
|
||||
function Lua:function_follows(t,v,tok)
|
||||
local is_local = t == 'keyword' and v == 'local'
|
||||
if is_local then t,v = tnext(tok) end
|
||||
return t == 'keyword' and v == 'function', is_local
|
||||
end
|
||||
|
||||
function Lua:parse_function_header (tags,tok,toks)
|
||||
tags.name = tools.get_fun_name(tok)
|
||||
tags.formal_args = tools.get_parameters(toks)
|
||||
tags.class = 'function'
|
||||
end
|
||||
|
||||
function Lua:parse_extra (tags,tok,toks)
|
||||
if tags.class == 'table' and not tags.fields then
|
||||
local res
|
||||
local stat,t,v = pcall(tok)
|
||||
if not stat then return nil end
|
||||
res,t,v = self:search_for_token(tok,'{','{',tok())
|
||||
if not res then return nil,t,v end
|
||||
tags.formal_args = tools.get_parameters(toks,'}',function(s)
|
||||
return s == ',' or s == ';'
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local lua = Lua()
|
||||
|
||||
class.CC(Lang)
|
||||
|
||||
function CC:_init()
|
||||
self.line_comment = '^//+'
|
||||
self.start_comment_ = '^///+'
|
||||
self.block_comment = '^/%*%*+'
|
||||
self:finalize()
|
||||
end
|
||||
|
||||
function CC.lexer(f)
|
||||
f,err = utils.readfile(f)
|
||||
if not f then quit(err) end
|
||||
return lexer.cpp(f,{})
|
||||
end
|
||||
|
||||
function CC:grab_block_comment(v,tok)
|
||||
v = v:gsub(self.block_comment,'')
|
||||
return 'comment',v:sub(1,-3)
|
||||
end
|
||||
|
||||
local cc = CC()
|
||||
|
||||
|
||||
-- parses a Lua file, looking for ldoc comments. These are like LuaDoc comments;
|
||||
-- they start with multiple '-'. If they don't define a name tag, then by default
|
||||
-- it is assumed that a function definition follows. If it is the first comment
|
||||
|
@ -492,6 +360,8 @@ elseif args.package == '..' then
|
|||
args.package = path.splitpath(source_dir)
|
||||
end
|
||||
|
||||
local lua, cc = lang.lua, lang.cc
|
||||
|
||||
local file_types = {
|
||||
['.lua'] = lua,
|
||||
['.ldoc'] = lua,
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
------------
|
||||
-- Language-dependent parsing of code.
|
||||
-- This encapsulates the different strategies needed for parsing C and Lua
|
||||
-- source code.
|
||||
|
||||
require 'pl'
|
||||
|
||||
local tools = require 'ldoc.tools'
|
||||
local lexer = require 'ldoc.lexer'
|
||||
|
||||
local tnext = lexer.skipws
|
||||
|
||||
|
||||
class.Lang()
|
||||
|
||||
function Lang:trim_comment (s)
|
||||
return s:gsub(self.line_comment,'')
|
||||
end
|
||||
|
||||
function Lang:start_comment (v)
|
||||
local line = v:match (self.start_comment_)
|
||||
local block = v:match(self.block_comment)
|
||||
return line or block, block
|
||||
end
|
||||
|
||||
function Lang:empty_comment (v)
|
||||
return v:match(self.empty_comment_)
|
||||
end
|
||||
|
||||
function Lang:grab_block_comment(v,tok)
|
||||
v = v:gsub(self.block_comment,'')
|
||||
return tools.grab_block_comment(v,tok,self.end_block1,self.end_block2)
|
||||
end
|
||||
|
||||
function Lang:find_module(tok,t,v)
|
||||
return '...',t,v
|
||||
end
|
||||
|
||||
function Lang:function_follows(t,v)
|
||||
return false
|
||||
end
|
||||
|
||||
function Lang:finalize()
|
||||
self.empty_comment_ = self.start_comment_..'%s*$'
|
||||
end
|
||||
|
||||
function Lang:search_for_token (tok,type,value,t,v)
|
||||
while t and not (t == type and v == value) do
|
||||
if t == 'comment' and self:start_comment(v) then return nil,t,v end
|
||||
t,v = tnext(tok)
|
||||
end
|
||||
return t ~= nil,t,v
|
||||
end
|
||||
|
||||
function Lang:parse_function_header (tags,tok,toks)
|
||||
end
|
||||
|
||||
function Lang:parse_extra (tags,tok,toks)
|
||||
end
|
||||
|
||||
|
||||
class.Lua(Lang)
|
||||
|
||||
function Lua:_init()
|
||||
self.line_comment = '^%-%-+' -- used for stripping
|
||||
self.start_comment_ = '^%-%-%-+' -- used for doc comment line start
|
||||
self.block_comment = '^%-%-%[%[%-+' -- used for block doc comments
|
||||
self.end_block1 = ']'
|
||||
self.end_block2 = ']'
|
||||
self:finalize()
|
||||
end
|
||||
|
||||
function Lua.lexer(fname)
|
||||
local f,e = io.open(fname)
|
||||
if not f then quit(e) end
|
||||
return lexer.lua(f,{}),f
|
||||
end
|
||||
|
||||
-- If a module name was not provided, then we look for an explicit module()
|
||||
-- call. However, we should not try too hard; if we hit a doc comment then
|
||||
-- we should go back and process it. Likewise, module(...) also means
|
||||
-- that we must infer the module name.
|
||||
function Lua:find_module(tok,t,v)
|
||||
local res
|
||||
res,t,v = self:search_for_token(tok,'iden','module',t,v)
|
||||
if not res then return nil,t,v end
|
||||
t,v = tnext(tok)
|
||||
if t == '(' then t,v = tnext(tok) end
|
||||
if t == 'string' then -- explicit name, cool
|
||||
return v,t,v
|
||||
elseif t == '...' then -- we have to guess!
|
||||
return '...',t,v
|
||||
end
|
||||
end
|
||||
|
||||
function Lua:function_follows(t,v,tok)
|
||||
local is_local = t == 'keyword' and v == 'local'
|
||||
if is_local then t,v = tnext(tok) end
|
||||
return t == 'keyword' and v == 'function', is_local
|
||||
end
|
||||
|
||||
function Lua:parse_function_header (tags,tok,toks)
|
||||
tags.name = tools.get_fun_name(tok)
|
||||
tags.formal_args = tools.get_parameters(toks)
|
||||
tags.class = 'function'
|
||||
end
|
||||
|
||||
function Lua:parse_extra (tags,tok,toks)
|
||||
if tags.class == 'table' and not tags.fields then
|
||||
local res
|
||||
local stat,t,v = pcall(tok)
|
||||
if not stat then return nil end
|
||||
res,t,v = self:search_for_token(tok,'{','{',tok())
|
||||
if not res then return nil,t,v end
|
||||
tags.formal_args = tools.get_parameters(toks,'}',function(s)
|
||||
return s == ',' or s == ';'
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class.CC(Lang)
|
||||
|
||||
function CC:_init()
|
||||
self.line_comment = '^//+'
|
||||
self.start_comment_ = '^///+'
|
||||
self.block_comment = '^/%*%*+'
|
||||
self:finalize()
|
||||
end
|
||||
|
||||
function CC.lexer(f)
|
||||
f,err = utils.readfile(f)
|
||||
if not f then quit(err) end
|
||||
return lexer.cpp(f,{})
|
||||
end
|
||||
|
||||
function CC:grab_block_comment(v,tok)
|
||||
v = v:gsub(self.block_comment,'')
|
||||
return 'comment',v:sub(1,-3)
|
||||
end
|
||||
|
||||
return { lua = Lua(), cc = CC() }
|
Loading…
Reference in New Issue