Использование регулярных выражений в Python для определения функций C ++ и их параметров - PullRequest
2 голосов
/ 07 апреля 2011

Так что я делаю что-то не так в этом скрипте Python, но он становится запутанным, и я теряю из виду, что я делаю неправильно.

Я хочу, чтобы скрипт просматривал файл, находил все определения функций, а затем извлекал имя, тип возвращаемых данных и параметры функции и выводил комментарий в стиле «doxygen», например:

/******************************************************************************/
  /*!
    \brief
      Main function for the file

    \return
      The exit code for the program
  */
/******************************************************************************/

Но я делаю что-то не так с регулярным выражением, пытаясь разобрать параметры ... Вот сценарий:

import re
import sys

f = open(sys.argv[1])

functions = []

for line in f:
  match = re.search(r'([\w]+)\s+([\S]+)\(([\w+\s+\w+])+\)',line)
  if line.find("\\fn") < 0:
    if match:
      returntype = match.group(1)
      funcname = match.group(2)
      print '/********************************************************************'
      print "  \\fn " + match.group()
      print ''
      print '  \\brief'
      print '    Function description for ' + funcname
      print ''
      if len(match.groups()) > 2:
        params = []
        count = len(match.groups()) - 2
        while count > 0:
          matchingstring = match.group(count + 2)
          if matchingstring.find("void") < 0:
            params.append(matchingstring)
          count -= 1
        for parameter in params:
          print "  \\param " + parameter
          print '    Description of ' + parameter
          print ''
      print '  \\return'
      print '    ' + returntype
      print '********************************************************************/'
      print ''

Любая помощь будет оценена. Спасибо

Ответы [ 3 ]

3 голосов
/ 07 апреля 2011

Грамматика C ++ далеко не сложна, чтобы ее можно было обработать простым регулярные выражения. Вам понадобится хотя бы минимальный парсер. Я нашел это для ограниченных случаев, где я не обеспокоен с C ++ в целом, но только в моем собственном стиле, я часто могу уйти с токенайзером на основе flex и простым конечным автоматом. это потерпит неудачу во многих случаях законного C ++ - для начала, конечно, если кто-то использует препроцессор для изменения синтаксиса; но также потому, что < может иметь разные значения, в зависимости от что предшествует названию шаблона или нет. Но это часто подходит для конкретной работы.

2 голосов
/ 07 апреля 2011

Я с большим успехом использовал анализатор PEG при попытке выполнить простой анализ формата. pyPeg - очень простая реализация такого парсера, написанного на Python.

Пример кода Python для синтаксического анализатора функции C ++:

РЕДАКТИРОВАТЬ: параметры шаблона адреса. Протестировано с помощью ввода из логики SK, и вывод правильный.

import pyPEG
from pyPEG import parseLine
import re

def symbol(): return re.compile(r"[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&*][\w:]+")
def type(): return symbol
def functionName(): return symbol
def templatedType(): return symbol, "<", -1, [templatedType, symbol, ","], ">"
def parameter(): return [templatedType, type], symbol
def template(): return "<", -1, [symbol, template], ">"
def function(): return [type, templatedType], functionName, -1, template, "(", -1, [",", parameter], ")" # -1 -> zero or more repetitions.


sourceCode = "std::string foobar(std::vector<int> &A, std::map<std::string, std::vector<std::string> > &B)"
results = parseLine(sourceCode, function(), [], packrat=True)

Когда это выполнено, результат будет:

([(u'type', [(u'symbol', 'std::string')]), (u'functionName', [(u'symbol', 'foobar')]), (u'parameter', [(u'templatedType', [(u'symbol', 'std::vector'), (u'symbol', 'int')]), (u'symbol', '&A')]), (u'parameter', [(u'templatedType', [(u'symbol', 'std::map'), (u'symbol', 'std::string'), (u'templatedType', [(u'symbol', 'std::vector'), (u'symbol', 'std::string')])]), (u'symbol', '&B')])], '')
0 голосов
/ 07 апреля 2011

C ++ на самом деле не может быть проанализирован с помощью (нормального) регулярного выражения: они являются кошмаром, когда речь идет о вложении.

Есть и другая проблема, определяющая, когда анализировать, а когда нет.Функция может быть объявлена:

  • в области видимости файла
  • в пространстве имен
  • в классе

И два последних могутбыть вложенным на произвольной глубине.

Я бы предложил использовать здесь CLang .Это настоящий интерфейс C ++ с полнофункциональным синтаксическим анализатором, в котором есть:

  • API C, с (в частности) API для библиотеки индексации
  • привязки Python сверхуC API

Привязки C API и Python далеки от полного раскрытия базовой модели C ++, но для такой простой задачи, как перечисление функций, этого должно быть достаточно.


Тем не менее, я бы поставил под сомнение полезность проекта: если документация может быть сгенерирована простым анализатором, то она избыточна с кодом.А избыточность в лучшем случае бесполезна и в худшем случае опасна: она представляет потенциальную угрозу десинхронизации ...

Если функция достаточно сложна, чтобы ее использование требовало документации, то разработчик, который знает ограничения и другие, должен написать эту документацию.

...