Удаление строк из исходного кода C [закрыто]
-
18-09-2019 - |
Вопрос
Кто-нибудь может указать мне на программу, которая удаляет строки из исходного кода 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;
}
То, что я ищу, - это программа, очень похожая стриптизерша только то, что я хочу удалять строки, а не комментарии.
Причина, по которой я ищу уже разработанную программу, а не просто какое-нибудь удобное регулярное выражение, заключается в
потому что, когда вы начинаете рассматривать все угловые случаи (кавычки внутри строк, многострочные строки и т.д.)
обычно все оказывается (намного) сложнее, чем кажется на первый взгляд.И
существуют ограничения на то, чего может достичь REs, я подозреваю, что это невозможно для этой задачи.Если вы действительно думаете, что у вас есть чрезвычайно надежное регулярное выражение, не стесняйтесь отправлять, но, пожалуйста, без наивности sed 's/"[^"]*"//g'
нравятся предложения.
(Нет необходимости в специальной обработке (возможно, незавершенных) строк в комментариях, они будут удалены первыми)
Поддержка многострочных строк со встроенными символами новой строки не важна (это не разрешено C), но строки, охватывающие несколько строк, заканчивающихся на \ в конце, должны поддерживаться.
Это почти то же самое , что и некоторые Другое вопросы, но я не нашел никаких ссылок на какие-либо инструменты.
Решение
Вы можете скачать исходный код для StripCmt (.tar.gz - 5 КБ).Он тривиально мал, и вместо этого его не должно быть слишком сложно адаптировать к чередующимся строкам (это выпущен под лицензией 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 восьмеричных цифр
- x и 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 очень похоже на строковый литерал.
В ruby:
#!/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)
Также печатается в стандартный вывод.