Вопрос

Кто-нибудь может указать мне на программу, которая удаляет строки из исходного кода 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)

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top