Удаление строк из исходного кода 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)
Также печатает на стандартный вывод.