Я поклонник генерации кода и считаю, что это разумная ситуация для его развертывания.
Если вы немного дисциплинированны в написании своих Doxygen DocStrings и воздерживаетесь от сложной разметки в них, не так сложно написать небольшой синтаксический анализатор, который извлекает их и подставляет обратно в Python DocStrings.
Вот небольшой пример. Он не будет достаточно мощным, чтобы справиться с любым реалистичным вариантом использования, но я считаю, что его расширение не будет сложным и стоит усилий, если только у вас нет только нескольких функций для документирования.
Поместите специальный комментарий перед каждой строкой документа Doxygen, который дает имя следующему блоку комментариев. Здесь я использую синтаксис
// DocString: sum
/**
* @brief Sum two integers
* @param a an integer
* @param b another integer
* @return sum of integers
*
*/
int sum(int a, int b);
чтобы связать имя sum
со следующей строкой документа.
Затем поместите другую специальную строку внутри привязок Python, которая ссылается на это имя. Здесь я использую следующий синтаксис.
BOOST_PYTHON_MODULE(pymodule)
{
def("sum",&sum,args("a","b"), "@DocString(sum)");
};
Теперь нам нужен инструмент для извлечения DocStrings Doxygen и подстановки их в привязки Python.
Как я уже сказал, этот пример надуманный, но он должен показать идею и продемонстрировать, что это не так сложно сделать.
import re
import sys
def parse_doc_string(istr):
pattern = re.compile(r'@(\w+)\s+(.*)')
docstring = list()
for line in map(lambda s : s.strip(), istr):
if line == '/**':
continue
if line == '*/':
return docstring
line = line.lstrip('* ')
match = pattern.match(line)
if match:
docstring.append((match.group(1), match.group(2)))
def extract(istr, docstrings):
pattern = re.compile(r'^//\s*DocString:\s*(\w+)$')
for line in map(lambda s : s.strip(), istr):
match = pattern.match(line)
if match:
token = match.group(1)
docstrings[token] = parse_doc_string(istr)
def format_doc_string(docstring):
return '\n'.join('{}: {}'.format(k, v) for (k, v) in docstring)
def escape(string):
return string.replace('\n', r'\n')
def substitute(istr, ostr, docstrings):
pattern = re.compile(r'@DocString\((\w+)\)')
for line in map(lambda s : s.rstrip(), istr):
for match in pattern.finditer(line):
token = match.group(1)
docstring = format_doc_string(docstrings[token])
line = line.replace(match.group(0), escape(docstring))
print(line, file=ostr)
if __name__ == '__main__':
sourcefile = sys.argv[1]
docstrings = dict()
with open(sourcefile) as istr:
extract(istr, docstrings)
with open(sourcefile) as istr:
with sys.stdout as ostr:
substitute(istr, ostr, docstrings)
Запуск этого сценария над исходным файлом приводит к следующему результату.
#include <boost/python.hpp>
using namespace boost::python;
// DocString: sum
/**
* @brief Sum two integers
* @param a an integer
* @param b another integer
* @return sum of integers
*
*/
int sum(int a, int b)
{
return a+b;
}
BOOST_PYTHON_MODULE(pymodule)
{
def("sum",&sum,args("a","b"), "brief: Sum two integers\nparam: a an integer\nparam: b another integer\nreturn: sum of integers");
};
Добавьте два часа полировки сценария, и все готово.
Поскольку это, вероятно, будет интересно и другим людям, я не удивлюсь, если кто-то уже написал такой сценарий. А если нет, то публикацию ваших программ в качестве свободных программ наверняка приветствовали бы другие.
person
5gon12eder
schedule
20.01.2016