Модераторы: ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Скрипт, убирающий C++ комментарии, Это моя первая серьёзная программа 
V
    Опции темы
tiggi
Дата 22.5.2010, 22:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 22.5.2010
Где: Подмосковье

Репутация: нет
Всего: нет



Изучаю Perl, для тренировки написал такую прогу, прокомментируйте. Что можно было бы сделать лучше?

C++ комментарии, как известно, бывают:
однострочные //
многострочные /* */

Учтён случай, когда комментирующие скобки являются частью строки.

Код

#! /usr/bin/perl -w
use strict;

open (IN, "$ARGV[0]") || die "$!";
open (OUT, ">$ARGV[1]") || die "$!";

my $analyzed='';     # в этой переменной будет храниться текст, анализируемый с помощью регулярных выражений
my $out='';             # в этой переменной будет храниться финальный (проанализированный текст)

while (<IN>) {
    $analyzed.=$_;
};

while (1) {
    if ($analyzed=~m#(")|(')|(//)|(/\*)#) { #ищет, откуда начинается комментирование или текстовая строка в анализируемом тексте
        if ($1) {                                             # если первой найдена двойная кавычка
            $out.=$`.$&;
            if ($'=~/([^\\]")|(\n)/) {               # где заканчивается строка?
                $out.=$`.$&;
                $analyzed=$';
            } else {
                $out.=$';
                last;
            };
        } elsif ($2) {                                      # если одинарная кавычка           
            $out=$out.$`.$&;
            if ($'=~/^\\?.?'/) {
                $out.=$&;
                $analyzed=$';
            } else {
                $analyzed=$'
            };
        } elsif ($3) {                                      # если однострочный комментарий
            $out=$out.$`;
            if ($'=~/\n/) {
                $analyzed=$&.$';
            } else {
                last;
            };
        } elsif ($4) {                                       # если многострочный комментарий
            $out=$out.$`;
            if ($'=~m|\*/|) {
                $analyzed=$';
            } else {
                last;
            }    
        } 
    }
    else {
        $out.=$analyzed;
        last;
    };
}
print OUT $out;


Это сообщение отредактировал(а) tiggi - 23.5.2010, 00:55
PM MAIL   Вверх
vadiml
Дата 22.5.2010, 23:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 27.7.2007

Репутация: нет
Всего: 7



А Ваша программа как распознает:
int *p;
y=(x/*p++);
f(int /* коммент */ );

ЗЫ Это пример из книги Алена Голуба.
PM MAIL Jabber   Вверх
tiggi
Дата 23.5.2010, 00:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 22.5.2010
Где: Подмосковье

Репутация: нет
Всего: нет



Вот в этом случае она будет работать некорректно, да smile

Спасибо, пример интересный, подумаю, но исправить эту ошибку будет непросто.
Редактор gedit в Linux, например, в этом случае выделяет комментарий неправильно.
PM MAIL   Вверх
Marlik
Дата 14.6.2010, 17:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 212
Регистрация: 25.2.2007
Где: Рязань

Репутация: нет
Всего: нет



Как при помощи регулярных выражений удалить из кода комментарии в стиле C?

Хотя это возможно, это намного сложней, чем кажется. Так, однострочник

perl -0777 -pe 's{/\*.*?\*/}{}gs' foo.c

будет работать во многих, но не во всех случаях. Это слишком просто для отдельных программ на C, в частности, тех, которые содержат «комментарии» внутри строк. В этом случае нужно нечто вроде скрипта, созданного Джефри Фридлом и доработанного Фредом Кёртисом.

$/ = undef;
$_ = <>;
s#/\*[^*]*\*+([^/*][^*]*\*+)*/|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#defined $2 ? $2 : ""#gse;
print;

Конечно, это можно записать более понятно с модификатором /x, если отформатировать шаблон и расставить комментарии. Вот развернутая запись, любезно предоставленная Фредом Кёртисом.

s{
   /\*         ##  Начало комментария /* ... */
   [^*]*\*+    ##  Отличный от * символ с последующим 1 и более *
   (
     [^/*][^*]*\*+
   )*          ##  0 и более подстрок, не начинающихся с /
               ##    но заканчивающихся на '*'
   /           ##  Конец комментария /* ... */

 |         ##     ИЛИ  разные вещи, не являющиеся комментариями:

   (
     "           ##  Начало строки " ... "
     (
       \\.           ##  Экранированный символ
     |               ##    ИЛИ
       [^"\\]        ##  Не "\
     )*
     "           ##  Конец строки " ... "

   |         ##     ИЛИ

     '           ##  Начало строки ' ... '
     (
       \\.           ##  Экранированный символ
     |               ##    ИЛИ
       [^'\\]        ##  Не '\
     )*
     '           ##  Конец строки ' ... '

   |         ##     ИЛИ

     .           ##  Любой другой символ
     [^/"'\\]*   ##  Символы, с которых не начинается комментарий, строка, экранированный символ
   )
 }{defined $2 ? $2 : ""}gxse;

Небольшая доработка также удаляет комментарии C++, не продолжающиеся на нескольких строках при помощи символа продолжения строки:

s#/\*[^*]*\*+([^/*][^*]*\*+)*/|//[^\n]*|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#defined $2 ? $2 : ""#gse;

Источник: http://beshenov.ru/perlfaq/6.html
PM WWW Skype   Вверх
tiggi
Дата 19.8.2010, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 22.5.2010
Где: Подмосковье

Репутация: нет
Всего: нет



Marlik, здорово! Оказывается, всё можно было сделать одним регекспом.
Программа стала в разы меньше)
Спасибо!
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Регулярные выражения | Следующая тема »


 




[ Время генерации скрипта: 0.0431 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.