Удаление строк из исходного кода C

Может кто-нибудь указать мне на программу, которая удаляет строки из исходного кода C? пример

#include <stdio.h>
static const char *place = "world";
char * multiline_str = "one \
two \
three\n";
int main(int argc, char *argv[])
{
        printf("Hello %s\n", place);
        printf("The previous line says \"Hello %s\"\n", place);
        return 0;
}

становится

#include <stdio.h>
static const char *place = ;
char * multiline_str = ;
int main(int argc, char *argv[])
{
        printf(, place);
        printf(, place);
        return 0;
}

То, что я ищу, - это программа, очень похожая только на stripcmt, которую я хочу вырезать, а не комментарии.

Причина, по которой я ищу уже разработанную программу, а не просто удобное регулярное выражение, заключается в том, что когда вы начинаете рассматривать все угловые случаи (кавычки в строках, многострочные строки и т. Д.), Вещи обычно начинают (намного) сложнее, чем она. первый появляется. И есть ограничения на то, чего могут достичь RE, я подозреваю, что это невозможно для этой задачи. Если вы думаете, что у вас очень сильное регулярное выражение, не стесняйтесь отправлять, но, пожалуйста, не наивно sed 's/"[^"]*"//g' как предложения.

(Нет необходимости в специальной обработке (возможно, не заканчивающейся) строк в комментариях, они будут удалены в первую очередь)

Поддержка многострочных строк со встроенными символами новой строки не важна (не допустимый C), но должны поддерживаться строки, охватывающие несколько строк, заканчивающиеся на \ в конце.

Это почти то же самое, что и некоторые другие вопросы, но я не нашел ссылок на какие-либо инструменты.

4 ответа

Решение

Вы можете загрузить исходный код в StripCmt (.tar.gz - 5kB). Он очень маленький, и его не должно быть слишком сложно адаптировать для чередования строк (он выпущен под лицензией GPL).

Возможно, вы также захотите изучить официальные правила лексического языка для строк C. Я нашел это очень быстро, но это не может быть окончательным. Он определяет строку как:

stringcon ::= "{ch}", where ch denotes any printable ASCII character (as specified by isprint()) other than " (double quotes) and the newline character.

Все токены в C (и большинстве других языков программирования) являются "обычными". То есть они могут соответствовать регулярному выражению.

Регулярное выражение для строк C:

"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"

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

  • не специальные символы (без кавычек / обратной косой черты / новой строки)
  • побеги, которые начинаются с обратной косой черты, а затем состоят из одного из:
    • простой побег персонаж
    • От 1 до 3 восьмеричных цифр
    • х и 1 или более шестнадцатеричных цифр

Это основано на разделах 6.1.4 и 6.1.3.4 спецификации C89/C90. Если что-то еще закралось в C99, это не поймет, но это не должно быть трудно исправить.

Вот скрипт Python для фильтрации исходного файла C, удаляющий строковые литералы:

import re, sys
regex = re.compile(r'''"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"''')
for line in sys.stdin:
  print regex.sub('', line.rstrip('\n'))

РЕДАКТИРОВАТЬ:

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

import re, sys
str_re = r'''"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"'''
chr_re = r"""'([^'\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))'"""

regex = re.compile('|'.join([str_re, chr_re]))

def repl(m):
  m = m.group(0)
  if m.startswith("'"):
    return m
  else:
    return ''
for line in sys.stdin:
  print regex.sub(repl, line.rstrip('\n'))

По сути, мы находим токен строкового и символьного литералов, а затем оставляем литералы-символы в покое, но удаляем строковые литералы. Регулярное выражение char literal очень похоже на строковое литерал.

В рубине:

#!/usr/bin/ruby
f=open(ARGV[0],"r")
s=f.read
puts(s.gsub(/"(\\(.|\n)|[^\\"\n])*"/,""))
f.close

выводит на стандартный вывод

В Python используется pyparsing:

from pyparsing import dblQuotedString

source = open(filename).read()
dblQuotedString.setParseAction(lambda : "")
print dblQuotedString.transformString(source)

Также печатает на стандартный вывод.

Другие вопросы по тегам