Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2006.06.04;
Скачать: [xml.tar.bz2];

Вниз

Есть ли функция удаления всех комментариев?   Найти похожие ветки 

 
Точка Ру   (2006-05-08 04:06) [0]

Чтобы не пугать иностранцев русским языком. Комментарии бывают разных типов, и поэтому удалить их все очень не легко.


 
Джо ©   (2006-05-08 04:21) [1]

Стандартного ничего такого нету, остается:
1. Написать самому, выйдет не очень уж и сложный конечный автомат;
2. Поискать из уже написанного. Тут указать, например, на RemObjects PascalScript — он бесплатен и с исходниками. Но, честно говоря, разбираться в той туче коду себе дороже :) Легче, ИМХО, п. 1.


 
Точка Ру   (2006-05-08 04:27) [2]

Так дайте функцию то?


 
Джо ©   (2006-05-08 04:34) [3]

> [2] Точка Ру   (08.05.06 04:27)
> Так дайте функцию то?

А почему ты решил, что я за тебя ее напишу?


 
Anatoly Podgoretsky ©   (2006-05-08 09:06) [4]

Точка Ру   (08.05.06 04:27) [2]
Одной функцией не обойдешься.
Алгоритм довольно сложный и требует алгоритмического склада ума.
А готовую работу можно получить на www.job.ru


 
TUser ©   (2006-05-08 10:06) [5]

Можно и тут. Я готов реализивать п. 1 из [1]. Мыло в анкете.


 
atruhin ©   (2006-05-08 11:28) [6]


> Алгоритм довольно сложный

Это шутка или как? Думаю не более 2-3 часов работы.


 
wicked ©   (2006-05-08 11:29) [7]

есть еще рецепт - не писать комменты по-русски.... ну или по-украински, белорусски, казахски итыды....
я, например, комментарии пишу по-английски, а описание уже на том языке, на котором нужно.....


 
Юрий Зотов ©   (2006-05-08 12:54) [8]

> atruhin ©   (08.05.06 11:28) [6]

Думаю, что все же побольше выйдет. :o)


 
easy ©   (2006-05-08 13:02) [9]


> Есть ли функция удаления всех комментариев?


uses RegExpr;
(* http://regexpstudio.com/RU/TRegExpr/TRegExpr.html *)
const
 commentexpr = "(?is)({.*?})|(\(\*.*?\*\))|(//.+?)\n";
begin
 Memo1.Text:= ReplaceRegExpr(commentexpr, Memo1.Text, "");


потестировать, доработать commentexpr - и будет функция


 
homm ©   (2006-05-08 13:17) [10]


> "(?is)({.*?})|(\(\*.*?\*\))|(//.+?)\n";

Какая выразительность языка :)


 
TUser ©   (2006-05-08 13:48) [11]

Символы (**) {} и // могут встречаться в строковых константах, - это первоек очевидное замечание к такому регэкспу.

Зы. Берусь на спор написать соответствующий автомат за 2 часа. Ставлю ящик пива :)


 
Плохиш ©   (2006-05-08 13:50) [12]


> TUser ©   (08.05.06 13:48) [11]
> Зы. Берусь на спор написать соответствующий автомат за 2
> часа. Ставлю ящик пива

А если не уложишься, то два ящика?


 
Юрий Зотов ©   (2006-05-08 14:17) [13]

> TUser ©   (08.05.06 13:48) [11]

Удовлетворюсь даже одной виртуальной бутылкой. К 16:30 по Москве жду код. Неглючный, конечно.
:о)


 
Юрий ©   (2006-05-08 14:23) [14]

Не совсем понятна ставка :о) т.е. если TUser победит ему ящик? А если проиграет то от него Юрию Зотову бутылку пива?


 
Юрий Зотов ©   (2006-05-08 14:54) [15]

> Юрий ©   (08.05.06 14:23) [14]

А какая разница? Пиво каждый из нас и сам может себе купить, без напряга. Не в нем дело.

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


 
Юрий ©   (2006-05-08 14:58) [16]


> [15] Юрий Зотов ©   (08.05.06 14:54)


Конечно ;) Но всё равно азарт, нужен азарт!!!


 
KilkennyCat ©   (2006-05-08 15:00) [17]


> Юрий Зотов ©  


если только русский комментарий, задача несложная, особенно для тех вариантов, где делфи еще не поддерживает русские имена переменных, если память не изменяет, до 2005-ой... :)


 
saa   (2006-05-08 15:02) [18]

А еше полезнее утилита, которая бы автоматически их перевела.


 
KilkennyCat ©   (2006-05-08 15:02) [19]

и удалила :)))


 
Привидение Хозяина   (2006-05-08 15:04) [20]

Удалено модератором


 
Пусик ©   (2006-05-08 15:05) [21]

Задача не сложная. Опыта в использовании конечных автоматов вполне достаточно. И даже 2 часа на это не нужно. достаточно 1.


 
Юрий Зотов ©   (2006-05-08 15:15) [22]

> Пусик ©   (08.05.06 15:05) [21]

Так в чем же дело? :о)


 
Привидение Хозяина   (2006-05-08 15:16) [23]

Удалено модератором


 
KilkennyCat ©   (2006-05-08 15:16) [24]


> Пусик ©   (08.05.06 15:05)


если конечный автомат - это руки, то да... за один час я дофига удалю. приблизительно 3660 строк комментариев.


 
Sergey Masloff   (2006-05-08 15:17) [25]

Пусик ©   (08.05.06 15:05) [21]
Срок известен, задачи определены - за дело, товарищи. До 16-30 как раз час - уложитесь


 
KilkennyCat ©   (2006-05-08 15:57) [26]

Осталось полчаса :)


 
Привидение Хозяина   (2006-05-08 16:07) [27]

Удалено модератором


 
Пусик ©   (2006-05-08 16:21) [28]

Те условия, которые смогла определить, реализовала. Конечно, могла что-нибудь и пропустить, но, как мне кажется, работает:

unit uParseComment;

interface

uses
 Sysutils;

type
 TStateParse=(spNone,spSlash1,spSlash2,spLeft1,spLeft2,spFLeft1,spFLeft2,spRight1 ,spLiteral1);
 TParseError=Exception;

function DeleteComments(const s: String): String;

implementation

function DeleteComments(const s: String): String;
var
 i: Integer;
 State: TStateParse;
 Len: Integer;
begin
 State := spNone;
 Result := "";
 Len := Length(s);

 i := 1;
 while i<=Len do
 begin
   case State of
     spNone:
       begin
         if s[i]="/" then
         begin
           State := spSlash1;
           Inc(i);
           Continue;
         end;
         if s[i]="(" then
         begin
           State := spLeft1;
           Inc(i);
           Continue;
         end;
         if s[i]="{" then
         begin
           State := spFLeft1;
           Inc(i);
           Continue;
         end;
         if s[i]="""" then
         begin
           State := spLiteral1;
           Result := Result + s[i];
           Inc(i);
           Continue;
         end;
         Result := Result + s[i];
         Inc(i);
       end;
     spSlash1:
       begin
         if s[i]="/" then
         begin
           Inc(i);
           State := spSlash2;
         end
         else
         begin
           State := spNone;
           Result := Result + s[i-1];
         end;
         Continue;
       end;
     spSlash2:
       begin
         if s[i]=#13 then
         begin
           State := spNone;
         end;
         Inc(i);
         Continue;
       end;
     spLeft1:
       begin
         if s[i]="*" then
         begin
           Inc(i);
           State := spLeft2
         end
         else
         begin
           State := spNone;
           Result := Result + s[i-1];
         end;
         Continue;
       end;
     spFLeft1:
       begin
         if s[i]<>"$" then State := spFLeft2
         else
         begin
           State := spNone;
           Result := Result + s[i-1];
           Result := Result + s[i];
         end;
         Inc(i);
         Continue;
       end;
     spLeft2:
       begin
         if s[i]="*" then
         begin
           State := spRight1;
           Inc(i);
           Continue;
         end
         else Result := Result + s[i];
       end;
     spFLeft2:
       begin
         if s[i]="}" then State := spNone;
         Inc(i);
       end;
     spRight1:
       begin
         if s[i]=")"
           then State := spNone
           else State := spLeft2;
         Inc(i);
       end;
     spLiteral1:
       begin
         if s[i]="""" then
         begin
           if i<>Len then
           begin
             if s[i+1]="""" then
             begin
               Result := Result + s[i+1];
               Inc(i,2);
             end
             else
             begin
               State := spNone;
               Result := Result + s[i];
               Inc(i);
             end;
           end
           else Inc(i);
           Continue;
         end
         else Result := Result + s[i];
         Inc(i);
       end;
   end;
 end;
 if State<>spNone then raise TParseError.Create("Ошибка в синтаксисе");
end;

end.


 
Пусик ©   (2006-05-08 16:22) [29]

Не уверена за точность с определением литералов с апострофами внутри строки...


 
sniknik ©   (2006-05-08 16:38) [30]

Пусик ©   (08.05.06 16:21) [28]
не проверял, но судя по всему после этой процедуры и от всех директив компилятора тоже останутся "рожки да ножки"  наряду с комментариями...

глюк`с.


 
sniknik ©   (2006-05-08 16:40) [31]

хотя может и нет...
> if s[i]<>"$" then State := spFLeft2

надо бы всетаки проверить


 
Пусик ©   (2006-05-08 16:41) [32]


> не проверял, но судя по всему после этой процедуры и от
> всех директив компилятора тоже останутся "рожки да ножки"
>  наряду с комментариями...


Вряд ли. Этот пунктик учтен.


 
KilkennyCat ©   (2006-05-08 16:45) [33]

и этот?
(*$NOINCLUDE CommCtrl *)


 
KilkennyCat ©   (2006-05-08 16:47) [34]

Однако, TUser опаздывает ;)


 
Пусик ©   (2006-05-08 16:51) [35]


> KilkennyCat ©   (08.05.06 16:45) [33]
>
> и этот?
> (*$NOINCLUDE CommCtrl *)


А это что за незнакомая конструкция? Вроде бы простой комментарий - удален будет.


 
sniknik ©   (2006-05-08 16:52) [36]

сглючило на таком
// -= Prepare Definations =- //

на этом повисло
(*$NOINCLUDE CommCtrl *)


 
KilkennyCat ©   (2006-05-08 16:52) [37]

unit Controls;

{$P+,S-,W-,R-,T-,H+,X+}
{ WARN SYMBOL_PLATFORM OFF}
{$C PRELOAD}

interface

{$R Controls.res}

{ CommCtrl.hpp is not required in Controls.hpp }
(*$NOINCLUDE CommCtrl *)


 
Пусик ©   (2006-05-08 16:57) [38]

(*$NOINCLUDE CommCtrl *) у меня вообще невозможно в программу добавить. При компиляции выдает ошибку - Undeclared IDentifier "CommCtrl"


 
Вовчик   (2006-05-08 17:07) [39]

Удалено модератором


 
KilkennyCat ©   (2006-05-08 17:08) [40]

это из генофонда. controls.pas
компилятор не считает это комментарием.


 
sniknik ©   (2006-05-08 17:08) [41]

Пусик ©   (08.05.06 16:57) [38]
CommCtrl обьяви в модуле, после исключай

и еще попробуй
procedure TForm1.Button1Click(Sender: TObject);
begin
 (*$IFDEF name*)
 if OpenDialog1.Execute then
   Memo1.Lines.LoadFromFile(OpenDialog1.FileName);
 (*$ENDIF*)
end;


 
KilkennyCat ©   (2006-05-08 17:09) [42]


> компилятор не считает это комментарием.

тем более, что выдает ошибку :))


 
sniknik ©   (2006-05-08 17:10) [43]

> компилятор не считает это комментарием.
директива компилятора, в принципе это и есть комментарий (в код не включается)... но только он нужен.


 
KilkennyCat ©   (2006-05-08 17:12) [44]


> [43] sniknik ©   (08.05.06 17:10)


ну уж нет. комментарий - это комментарий, а директива - это директива :)


 
Пусик ©   (2006-05-08 17:12) [45]

Вот одна ошибка исправлена:

     spLeft2:
       begin
         if s[i]="*" then State := spRight1
         else Result := Result + s[i];
         Inc(i);
         Continue;
       end;


А разве директивы компилятора не только в {} могут быть, но и в (* *) ?


 
Пусик ©   (2006-05-08 17:14) [46]

A compiler directive starts with a $ as the first character after the opening comment delimiter, immediately followed by a name (one or more letters) that designates the particular directive. You can include comments after the directive and any necessary parameters.


 
Пусик ©   (2006-05-08 17:15) [47]

Действительно, этот момент не знала.
Сейчас буду подправлять.


 
sniknik ©   (2006-05-08 17:17) [48]

а смысл? время то тютю.
пора Зотову пиво слать... факсом ;о))


 
Юрий Зотов ©   (2006-05-08 17:18) [49]

> Пусик ©   (08.05.06 16:21) [28]

Увы, протестировать код не удалось - после запуска программа надолго ушла в глубокую задумчивость. Ждал минут 10, но так и не дождался, пока она все же закончит работу.

Тестирующий код:

procedure TForm1.Button1Click(Sender: TObject);
begin
 with TOpenDialog.Create(nil) do
 try
   if Execute then
   begin
     with TStringList.Create do
     try
       LoadFromFile(FileName);
       Text := DeleteComments(Text);
       SaveToFile(ChangeFileExt(FileName, ".new"))
     finally
       Free
     end
   end
 finally
   Free
 end
end;

Тестовые данные:

unit Unit2;

interface

{$R+}
{$DEFINE CompilerOption}

const
 Literal = "// This { is } a (* string *)";

(* comment 1 *)  A = 0;
{ comment 2 }    B = 0;
// comment 3     C = 0;

(* { comment 4 } *)
(* // comment 5  *)

{ (* comment 6 *) }
{ // comment 7  }

// (* comment 8 *)
// { comment 9 }

implementation

end.

Если имелось в виду, что за час можно написать код, который не работает, то с этим я полностью согласен. Даже более того - неработающий код можно написать и еще намного быстрее.
:o)


 
KilkennyCat ©   (2006-05-08 17:19) [50]


> Ждал минут 10, но так и не дождался


машина слабая? :))


 
sniknik ©   (2006-05-08 17:19) [51]

если для народа стараешся то убери еще глюк с
> // -= Prepare Definations =- //
символы лишние остаются


 
Привидение Хозяина   (2006-05-08 17:20) [52]

Удалено модератором


 
sniknik ©   (2006-05-08 17:22) [53]

> машина слабая? :))
да не, оно виснет, также как и это  (*$NOINCLUDE CommCtrl *)


 
KilkennyCat ©   (2006-05-08 17:25) [54]

мне, что ли, написать....
в принципе, у меня есть парсер самодельный для НТМЛ.... эт тоже самое.


 
Пусик ©   (2006-05-08 17:29) [55]


> Юрий Зотов ©   (08.05.06 17:18) [49]


Сейчас на этом коде потестирую, тем более, что уже подправила.


 
Привидение Хозяина   (2006-05-08 17:31) [56]

Удалено модератором


 
Пусик ©   (2006-05-08 17:31) [57]

Проверила.
Вот подправленный код:

unit uParseComment;

interface

uses
 Sysutils;

type
 TStateParse=(spNone,spSlash1,spSlash2,spLeft1,spLeft2,spFLeft1,spFLeft2,spRight1 ,spLiteral1);
 TParseError=Exception;

function DeleteComments(const s: String): String;

implementation

function DeleteComments(const s: String): String;
var
 i: Integer;
 State: TStateParse;
 Len: Integer;
begin
 State := spNone;
 Result := "";
 Len := Length(s);

 i := 1;
 while i<=Len do
 begin
   case State of
     spNone:
       begin
         if s[i]="/" then
         begin
           State := spSlash1;
           Inc(i);
           Continue;
         end;
         if s[i]="(" then
         begin
           State := spLeft1;
           Inc(i);
           Continue;
         end;
         if s[i]="{" then
         begin
           State := spFLeft1;
           Inc(i);
           Continue;
         end;
         if s[i]="""" then
         begin
           State := spLiteral1;
           Result := Result + s[i];
           Inc(i);
           Continue;
         end;
         Result := Result + s[i];
         Inc(i);
       end;
     spSlash1:
       begin
         if s[i]="/" then
         begin
           Inc(i);
           State := spSlash2;
         end
         else
         begin
           State := spNone;
           Result := Result + s[i-1];
         end;
         Continue;
       end;
     spSlash2:
       begin
         if s[i]=#13 then
         begin
           State := spNone;
         end;
         Inc(i);
         Continue;
       end;
     spLeft1:
       begin
         if s[i]="*" then
         begin
           if i<Len then
           begin
             if s[i+1]<>"$" then State := spRight1
             else
             begin
               Result := Result+s[i-1];
               State := spNone;
               Continue;
             end;
           end;
           Inc(i);
           State := spLeft2;
         end
         else
         begin
           State := spNone;
           Result := Result + s[i-1];
         end;
         Continue;
       end;
     spFLeft1:
       begin
         if s[i]<>"$" then State := spFLeft2
         else
         begin
           State := spNone;
           Result := Result + s[i-1];
           Result := Result + s[i];
         end;
         Inc(i);
         Continue;
       end;
     spLeft2:
       begin
         if s[i]="*" then State := spRight1;
         Inc(i);
         Continue;
       end;
     spFLeft2:
       begin
         if s[i]="}" then State := spNone;
         Inc(i);
       end;
     spRight1:
       begin
         if s[i]=")"
           then State := spNone
           else State := spLeft2;
         Inc(i);
       end;
     spLiteral1:
       begin
         if s[i]="""" then
         begin
           if i<>Len then
           begin
             if s[i+1]="""" then
             begin
               Result := Result + s[i+1];
               Inc(i,2);
             end
             else
             begin
               State := spNone;
               Result := Result + s[i];
               Inc(i);
             end;
           end
           else Inc(i);
           Continue;
         end
         else Result := Result + s[i];
         Inc(i);
       end;
   end;
 end;
 if State<>spNone then raise TParseError.Create("Ошибка в синтаксисе");
end;

end.


Вот результат обработки примера Ю. Зотова:

unit Unit2;

interface

{$R+}
{$DEFINE CompilerOption}

const
Literal = "// This { is } a (* string *)";

 A = 0;
   B = 0;

implementation

end.


 
Пусик ©   (2006-05-08 17:36) [58]

Строка (*$NOINCLUDE CommCtrl *) сейчас тоже корректно обрабатывается.


 
KilkennyCat ©   (2006-05-08 17:44) [59]

и все-таки что-то мне кажется, что можно гораздо проще...


 
Пусик ©   (2006-05-08 17:47) [60]


> Если имелось в виду, что за час можно написать код, который
> не работает, то с этим я полностью согласен. Даже более
> того - неработающий код можно написать и еще намного быстрее.
>


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


 
KilkennyCat ©   (2006-05-08 17:47) [61]

Начинаю. Как раз два часа есть. Скоро будет мой неработающий вариант :)


 
sniknik ©   (2006-05-08 17:51) [62]

> Строка (*$NOINCLUDE CommCtrl *) сейчас тоже корректно обрабатывается.
зато коверкаются cтроки
Caption:= "Ok""";

+ там хинт на строке
if s[i+1]<>"$" then State := spRight1
значение не используется... зачастую это ошибка в логике.


 
Пусик ©   (2006-05-08 17:54) [63]


> sniknik ©   (08.05.06 17:51) [62]

Да, действительно, хинт был, правильный код
     spLeft1:
       begin
         if s[i]="*" then
         begin
           if i<Len then
           begin
             if s[i+1]<>"$" then
             begin
               Inc(i);
               State := spRight1;
               Continue;
             end



> Caption:= "Ok""";


Значит, есть еще над чем работать.
Спасибо за замечания.


 
sniknik ©   (2006-05-08 17:55) [64]

> Начинаю. Как раз два часа есть. Скоро будет мой неработающий вариант :)
это будет нечестно, имхо, ты уже в курсе всех "подводных камней" на которые Пусик "напоролся". т.е. вникая в задачу на чужом примере ты уже считай начал ей заниматься...


 
Пусик ©   (2006-05-08 17:57) [65]

>sniknik
Вот на последнее замечание исправление:

     spLiteral1:
       begin
         if s[i]="""" then
         begin
           if i<>Len then
           begin
             if s[i+1]="""" then
             begin
               Result := Result + s[i];
               Result := Result + s[i+1];
               Inc(i,2);
             end


 
KilkennyCat ©   (2006-05-08 17:58) [66]


> это будет нечестно, имхо, ты уже в курсе всех "подводных
> камней"


я изначально был в курсе.
К тому же, я занимался парсингом, это плюс.
К тому же, мне неизвестны конечные автоматы, это, наверное, минус.
И вообще. :))


 
Пусик ©   (2006-05-08 17:59) [67]

Удалено модератором


 
KilkennyCat ©   (2006-05-08 18:02) [68]


> [67] Пусик ©   (08.05.06 17:59)


Понятно. Феминистка.


 
Palladin ©   (2006-05-08 18:36) [69]

мда... 25 минут с перерывами на наполнение стакана пивом и поглощение колбасы... в основном тупил из-за Copy :) сколько куда отсчитывать...

Function RemoveComments(Const s:String):String;
// {
// (*
// //
var
i:Integer;
IsString,IsComm:Boolean;
strComm:String;
nCommType:Integer;
Begin
Result:="";
strComm:="";
IsString:=False;
IsComm:=False;
For i:=1 to Length(s) Do
 Begin
  If (s[i]=#39) and (i<>1) and (s[i-1]<>#39) Then IsString:=Not IsString;
  If IsString Then Result:=Result+s[i] Else
   If IsComm Then
    Begin
     strComm:=strComm+s[i];
     Case nCommType Of
      0 : If Length(strComm)>=1 Then IsComm:=strComm[Length(strComm)]<>"}";
      1 : If Length(strComm)>=2 Then IsComm:=Copy(strComm,Length(strComm)-1,2)<>"*)";
      2 : If Length(strComm)>=2 Then IsComm:=Copy(strComm,Length(strComm)-1,2)<>#13#10;
     End;
    End Else
    Begin
     strComm:="";
     If (Copy(s,i,2)="(*") and (Copy(s,i,3)<>"(*$") Then Begin IsComm:=True; nCommType:=1; End Else
     If (s[i]="{") and (Copy(s,i,2)<>"{$") Then Begin IsComm:=True; nCommType:=0; End Else
     If Copy(s,i,2)="//" Then Begin IsComm:=True; nCommType:=2; End;
     If Not IsComm Then Result:=Result+s[i];
    End;
 End;
End;


 
Palladin ©   (2006-05-08 18:43) [70]


>  If (s[i]=#39) and (i<>1) and (s[i-1]<>#39) Then IsString:
> =Not IsString;

+15 минут на исправление этого безобразия ибо  в случае """" исполнится фигня и на добавление условия на под {$ }

итого 50 минут... ну пусть час...


 
Пусик ©   (2006-05-08 18:44) [71]


> Palladin ©   (08.05.06 18:36) [69]

Не смешно. Функция совершенно нерабочая.

Для примера обработай вот такие комментарии(выжимка из моего файла):

 DF1 := TDrawFigureThread.Create(FOrm1.Canvas,tfRectangle,{ """}Form1.ClientRect);

//  ShowWindow(Application.Handle,SW_HIDE);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
//  Application.OnActivate := OnCreateApp;

end;

procedure TForm1.FormShow(Sender: TObject);
begin

end;
end;
(*
qwe lqwie oqiwue oiqwue oiqwu e
qw eoiqwu eoiqweu oiqwu oqwieu//""""{    }
*)


 
Пусик ©   (2006-05-08 18:45) [72]

И это учитывая, что здесь уже были замечания опубликованы.


 
Palladin ©   (2006-05-08 18:47) [73]


> Пусик ©   (08.05.06 18:44) [71]

см [70]


 
Пусик ©   (2006-05-08 18:49) [74]


> Palladin ©   (08.05.06 18:47) [73]
>
>
> > Пусик ©   (08.05.06 18:44) [71]
>
> см [70]


А что там? Непонятно, что означает тот пост.


 
Пусик ©   (2006-05-08 18:54) [75]

А-а, понятно. Надо те строки закомментировать?
Ну тогда вроде работает:-)


 
Palladin ©   (2006-05-08 18:59) [76]

Означает что нужно отработать поподробней работу со строковыми константами.


 
Palladin ©   (2006-05-08 19:02) [77]


> Пусик ©   (08.05.06 18:54) [75]

Кто сказал? Нет, их комментировать не нужно, их нужно исправить. На самом деле все равно то что я привел это чушь... Хоть и лаконичная, но чушь. Выработка условий приоритета между определением начала комментария и начала строковой константы довольно сложна. И если начать в это углубляться, то уж лучше сразу поставить задачу парсинга синтаксиса Паскаля.


 
Пусик ©   (2006-05-08 19:02) [78]


> Palladin ©   (08.05.06 18:59) [76]
>
> Означает что нужно отработать поподробней работу со строковыми
> константами.


+ Оптимизировать код на предмет постоянного перераспределения памяти под строки.


 
KilkennyCat ©   (2006-05-08 19:03) [79]

а я мучался-мучался, родил такую жуть:

function RemComm(Data : String) : string;
var
 l, i : integer;
 fsString, fsSlash, fsDir, fsFig, fsScob  : boolean;
begin
 result := "";
 i := 0;
 l := length(data);
 fsString := false;
 fsSlash := false;
 fsFig := false;
 fsScob := false;
 repeat
   inc(i);
   case data[i] of
     """" : begin
              if fsString then begin
                result := result + data[i];
              end;
              fsString := not fsString;

            end;
     "/" : if not fsString then if  i < l then if data[i+1] = "/" then fsSlash := true;
     "{" :  if not fsString then fsFig := true;
     "}" :  if not fsString then begin
              fsFig := false;
               Continue;
            end;
     "(" : if not fsString then if data[i+1] = "*" then fsScob := true;
     ")" : if not fsString then if data[i-1] = "*" then begin
            fsScob := false;
            continue;
           end;
     else
       if ord(data[i]) = 13 then fsslash := false;
    end;
    if fsString then result := result + data[i] else begin
      if not fsSlash and not fsFig and not fsScob then result := result + data[i];
    end
   until i = l;
end;


не учитывает директивы пока. ну и фиг. я сдаюсь. не хочу пива.


 
KilkennyCat ©   (2006-05-08 19:04) [80]

Но у меня шустрее всех работать будет.


 
Palladin ©   (2006-05-08 19:06) [81]


> Пусик ©   (08.05.06 19:02) [78]

Поверь, это пока не самая важная задача :) Ну установлю я SetLength(Result,Length(s))
посчитаю сколько я там наназначал резалту, ну обрежу, смысл?


 
Пусик ©   (2006-05-08 19:08) [82]


> Palladin ©   (08.05.06 19:06) [81]


А как насчет постоянных вызовов Copy?


 
KilkennyCat ©   (2006-05-08 19:10) [83]

function RemComm(Data : String) : string;
var
 l, i : integer;
 fsString, fsSlash, fsDir, fsFig, fsScob  : boolean;
begin
 result := "";
 i := 0;
 l := length(data);
 fsString := false;
 fsSlash := false;
 fsFig := false;
 fsScob := false;
 fsDir := false;
 repeat
   inc(i);
   case data[i] of
     """" : begin
              if fsString then result := result + data[i];
              fsString := not fsString;
            end;
     "/" : if not fsString then if  i < l then if data[i+1] = "/" then fsSlash := true;
     "{" : if not fsString then if data[i+1] <> "$" then fsFig := true else fsDir := true;
     "}" : if not fsString then begin
             if fsDir then result := result + data[i];
             fsFig := false;
             fsDir := false;
             Continue;
           end;
     "(" : if not fsString then if data[i+1] = "*" then fsScob := true;
     ")" : if not fsString then if data[i-1] = "*" then begin
             fsScob := false;
             continue;
           end;
   else
     if ord(data[i]) = 13 then fsslash := false;
   end;
   if fsString then result := result + data[i] else if not fsSlash and not fsFig and not fsScob then result := result + data[i];
 until i = l;
end;


с учетом директив, кроме хитрой.


 
Marser ©   (2006-05-08 19:28) [84]

Пусик, респект! Красивый код :-)
> [66] KilkennyCat ©   (08.05.06 17:58)
>
> > это будет нечестно, имхо, ты уже в курсе всех "подводных
>
> > камней"
>
>
> я изначально был в курсе.
> К тому же, я занимался парсингом, это плюс.
> К тому же, мне неизвестны конечные автоматы, это, наверное,
> минус.

Хм... После того как я два года назад познакомился с конечными автоматами, а в прошлом году изучал их в универе, выстраивая автоматы Милли и Мура на триггерах, я себе смутно представляю хороший парсер без их использования.


 
Palladin ©   (2006-05-08 19:34) [85]


> Пусик ©   (08.05.06 19:08) [82]

А что Copy? CompareMem устроит?


 
TUser ©   (2006-05-08 19:36) [86]

В 16:30 ждете, хе, я только сечас Ваш пост прочитал, так что звиняйте.


 
ECM ©   (2006-05-08 19:57) [87]

> Есть ли функция удаления всех комментариев?

http://www.zeitungsjunge.de

DIPP is a Pascal Preprocessor. The purpose of DIPP is to manipulate Pascal source code files.

DIPP can
remove comments
process compiler directives and switches
remove compiler conditionals by wild card masks
remove compiler directives by wild card masks
insert, read, or skip include files by wild card masks
extract units" interface sections


Сам пользуюсь - иногда очень полезная весЧь


 
TUser ©   (2006-05-08 20:31) [88]

program RemRem.dpr;
{$apptype console}
uses Classes;
{
 started at 19:40
 finished at 20:32
}

type
TState = (stNone, stFigStarted, stFig, stAstStarted, stAst, stAstEnded, stLineStarted, stLine, stApstr, stString);

var Txt: TStrings;
var Comms: array of
          array [0..1] of integer;

procedure Add (B, E: integer);
begin
 if B <= 0 then exit;

 SetLength (Comms, length (Comms) + 1);
 Comms [high(Comms)][0] := B;
 Comms [high(Comms)][1] := E;
end;

procedure Preprocess;
var i: integer;
   s: TState;
   started: integer;
begin
 s := stNone; started := -1;
//for i := 1 to length (Txt.Text) do
 i:=1;
 while i <= length (Txt.Text) do begin
   case s of
     stNone:
      begin
        case Txt.Text[i] of
          "{":
           begin
             s:=stFigStarted;
             started := i;
           end;
          "/":
           begin
             s:=stLineStarted;
             started := i;
           end;
          "(":
           begin
             s:=stAstStarted;
             started := i;
           end;
          """": s:=stString;
          end;
      end;
     stFigStarted:
      begin
        case Txt.Text[i] of
          "$":
           begin
             started := -1;
             s := stFig;
           end;
          "}":
           begin
             s := stNone;
             Add (started, i);
           end;
          else
           s := stFig;
          end;
      end;
     stFig:
      begin
        case Txt.Text[i] of
          "}":
           begin
             s := stNone;
             Add (Started, i);
           end;
          end;
      end;
     stAstStarted:
      begin
        case Txt.Text[i] of
          "*":
           s := stAst;
          else
           begin
             s := stNone;
             dec (i);
           end;
          end;
      end;
     stAst:
      begin
        case Txt.Text[i] of
          "*":
           s := stAstEnded;
          end;
      end;
     stAstEnded:
      begin
        case Txt.Text[i] of
          ")":
           begin
             s := stNone;
             Add (started, i);
           end;
          else
           s := stAst;
          end;
      end;
     stLineStarted:
      begin
        case Txt.Text[i] of
         "/":
          s := stLine;
         else
          begin
            s := stNone;
            dec (i);
          end;
         end;
      end;
     stLine:
      begin
        case Txt.Text[i] of
          #10, #13:
           begin
             s := stNone;
             Add (started, i - 1);
           end;
          end;
       end;
     stString:
      begin
        case Txt.Text[i] of
          """":
           s := stApstr;
          #10, #13:
           s := stNone; // unterminated string;
          end;
      end;
     stApstr:
      begin
        case Txt.Text[i] of
          """":
           s := stString;
          else
           s := stNone; // possible untstr
          end;
      end;
     end;
   inc (i);
   end;
end;

procedure Print;
var i, j , k: integer;
begin
 i := 0;
 for j := 0 to high (Comms) do begin
   for k := i + 1 to Comms[j][0] - 1 do
     write (Txt.Text[k]);
   i := Comms[j][1];
   end;
 for k := i + 1 to length (Txt.Text) do
   write (Txt.Text[k]);
end;

begin
 Txt := TStringList.Create;
 Txt.LoadFromFile (ParamStr(1));
 Preprocess;
 Print;
 Txt.Free;
end.


 
TUser ©   (2006-05-08 20:36) [89]

Сразу честно признаюсь, что предыдущие решения и комментарии к ним я не читал, код долбать надо было )

И дабы ненужные подозрения сразу пресечь - приведенный в [88] хронометраж абсолютно правильный, а раньше я не постил не потому, почему некоторые может быть подумали, а потому что приглашения Юрия не видел.


 
Юрий Зотов ©   (2006-05-08 20:39) [90]

> All

Просто мне как-то довелось писать нечто подобное. Сама задача была, конечно, куда более сложной, но подзадача выделения комментариев была ее составной частью. Тоже сначала подумал, что это - ерунда, раз плюнуть, но когда начал писать, то убедился, что не все уж так совсем просто, как это показалось с первого взгляда. Хотя и несложно, конечно.

Думаю, мы в этом убедились - все же с первого захода никто не привел полностью рабочего варианта. Обязательно что-то или не обрабатывалось, или обрабатывалось как-то не так, или еще какие-то глюки. А ведь программа правит святая святых - сырцы. Здесь цена ошибки может быть ОЧЕНЬ высокой и поэтому она должна работать безукоризненно. Отсюда и выползает время, которое надо на нее потратить.


 
vertal ©   (2006-05-08 20:42) [91]

Видать мне тоже делать нечего. Сделал такой вариант за 50 минут (Кроме функции GetFileText - это из старого кода):

program COmmentCutter;

{$APPTYPE CONSOLE}
{$O-}
uses
 SysUtils;

type

 TLexemType = (ltMainContent, ltString, ltDirective, ltComment, ltSingleLineComment);

function CutAllComments(const s: string): string;
var
 CurPos, CurLength: Integer;
 CurLexemType: TLexemType;

 procedure DoComment(const CommentStart, CommentEnd: string);
 var
   EndOfComment: PChar;
 begin
   EndOfComment := StrPos(@s[CurPos + Length(CommentStart)], PChar(CommentEnd));
   if EndOfComment = nil then
     raise Exception.CreateFmt("Unterminated comment at pos %u:"#13#10"%s", [CurPos, Copy(s, CurPos, 100)]);
   if (CurLexemType = ltComment) and (s[CurPos + Length(CommentStart)] = "$") then
     CurLexemType := ltDirective;
   if (CurLexemType = ltSingleLineComment) then
     Dec(EndOfComment, Length(CommentEnd));
   CurLength := (EndOfComment - PChar(s) + 1) - CurPos + Length(CommentEnd);
 end;

 function GetNextLexem: Boolean;
 begin
   Inc(CurPos, CurLength);
   if Length(s) < CurPos then
   begin
     Result := False;
     Exit;
   end;
   Result := True;
   case s[CurPos] of
     "{":
       begin
         CurLexemType := ltComment;
         DoComment("{", "}");
         Exit;
       end;
     """":
       begin
         CurLexemType := ltString;
         DoComment("""", """");
         Exit;
       end;
     "(":
       begin
         if (Length(s) >= CurPos + 1) and (s[CurPos + 1] = "*") then
         begin
           CurLexemType := ltComment;
           DoComment("(*", "*)");
           Exit;
         end;
       end;
     "/":
       begin
         if (Length(s) >= CurPos + 1) and (s[CurPos + 1] = "/") then
         begin
           CurLexemType := ltSingleLineComment;
           DoComment("//", #13#10);
           Exit;
         end;
       end;
   end;//case s[CurPos]
   CurLength := 1;
   CurLexemType := ltMainContent;
 end;

 procedure WriteCurLexem;
 begin
   Result := Result + Copy(s, CurPos, CurLength);
 end;

begin
 Result := "";
 CurPos := 1;
 CurLength := 0;
 while GetNextLexem do
   if not (CurLexemType in [ltComment, ltSIngleLineComment]) then
     WriteCurLexem;
end;

function GetFileText(const FileName: string): string;
var
 f: file;
 LastMode: Integer;
begin
 LastMode := FileMode;
 FileMode := fmOpenRead;
 try
   assign(f, FileName);
   reset(f, 1);
   try
     SetLength(Result, FileSize(f));
     BlockRead(f, PChar(Result)^, Length(Result));
   finally
     close(f);
   end;
 finally
   FileMode := LastMode;
 end;
end;

procedure WriteUsageInfoAndExit;
begin
 writeln("This program cuts all comments from Delphi source file");
 writeln("Usage: ThisProgram.exe SrcFle > DestFile");
 Halt;
end;

begin
 if ParamCount <> 1 then
   WriteUsageInfoAndExit;
 writeln(CutAllComments(GetFileText(ParamStr(1))));
end.


 
TUser ©   (2006-05-08 20:42) [92]

> все же с первого захода никто не привел полностью рабочего варианта.

Как насчет [88]?


 
Юрий Зотов ©   (2006-05-08 20:49) [93]

> TUser ©   (08.05.06 20:42) [92]

Удаляет директивы компилятора вида (*$директива*).


 
TUser ©   (2006-05-08 20:58) [94]

Не знал, что такие бывают. Высылаю пиво :(
http://monkey.belozersky.msu.ru/~evgeniy/remrem.dpr


 
jack128 ©   (2006-05-08 21:45) [95]

procedure RemoveComments(var S: string);
var
 CharIndex: Integer;

 procedure RemoveFromCurrent(const LimitStr: string);
 var
   Temp: Integer;
 begin
   Temp := PosEx(LimitStr, S, CharIndex);
   if Temp <= 0 then Exit;
   S := Copy(S, 1, CharIndex - 1) + Copy(S, Temp + Length(LimitStr), MaxInt);
 end;

 procedure SkipLiteralString;
 begin
   Inc(CharIndex);
   while CharIndex <= Length(S) do
   begin
     if S[CharIndex] = """" then
     begin
       Inc(CharIndex);
       if S[CharIndex + 1] <> """" then
         Exit;
     end;
     Inc(CharIndex);
   end;
 end;

begin
 CharIndex := 1;
 while CharIndex <= Length(S) - 1 do
 begin
   case S[CharIndex] of
     "/":
       if S[CharIndex + 1] = "/" then
         RemoveFromCurrent(#13#10)
       else
         Inc(CharIndex);
     "(":
       if (S[CharIndex + 1] = "*") and (S[CharIndex + 2] <> "$")then
         RemoveFromCurrent("*)")
       else
         Inc(CharIndex);
     "{":
       if S[CharIndex + 1] <> "$" then
         RemoveFromCurrent("}")
       else
         Inc(CharIndex);
     """":
       SkipLiteralString;
   else
     Inc(CharIndex);
   end;
 end;
end;


Криво и тормознуто, конечно, но вроде работает.. За 1 час написано..


 
programania ©   (2006-05-08 23:24) [96]

в php удаление коментариев полезнее
ведь они при каждом выполнении читаются
хотя и бесполезны ведь на сервере их никто не видит
поэтому сделал для php а может даже и для C и javы
и заодно лишние пробелы удаляются

{$B-}
procedure RemoveComments(var S: string);
var
r: string;
k,k1,k2,kk,p2: boolean;
i: integer;
c: char;

begin
 r:="";
 k:=false; k1:=false; k2:=false; kk:=false;
 for i:=1 to length(s) do begin
   c:=s[i];
   if not k and not kk and (i>1) then begin
     if (c=""")  and     k2 and not k1 and ((s[i-1])<>"\") then k2:=false else
     if (c=""")  and not k2 and not k1 then k2:=true;
     if (c="""") and     k1 and not k2 and ((s[i-1])<>"\") then k1:=false else
     if (c="""") and not k1 and not k2 then k1:=true;
   end;

   if not k1 and not k2 and (i<length(s)) then begin
     if (c="/") and (s[i+1]="/") and not kk and not k then k:=true;
     if (c="/") and (s[i+1]="*") and not k  and not k then kk:=true;
     if (i>2)   and (s[i-2]="*") and (s[i-1]="/") and kk and not k then kk:=false;
     if c<" " then k:=false;
   end;
   p2:=(c=" ") and (i>1) and (s[i-1]<=" ") and not k2 and not k1;
   if not k and not kk and not p2 then r:=r+s[i];
 end;
 s:=r;
end;


 
Игорь Шевченко ©   (2006-05-08 23:37) [97]

А lex незаслуженно забыт ? :)


 
Пусик ©   (2006-05-09 00:11) [98]


> Вовчик   (08.05.06 17:07) [39]
>
> рад приветствовать еще одну женщину-программистку


Спасибо, конечно. А ты себя к мужчинам-программистам причисляешь?
Ссылочку на твои вопросы/ответы дашь? Чтобы заценить?


 
Джо ©   (2006-05-09 00:37) [99]

> [98] Пусик ©   (09.05.06 00:11)
> Ссылочку на твои вопросы/ответы дашь? Чтобы заценить?

Пока у Вовчика один вопрос: "Фотку вышлешь?", да и тот остается без ответа :)


 
Пусик ©   (2006-05-09 00:43) [100]


> Джо ©   (09.05.06 00:37) [99]


Ну фотку можно. Но только за приличный код;)


 
Gero ©   (2006-05-09 00:44) [101]

> [100] Пусик ©   (09.05.06 00:43)

5 баллов!


 
sniknik ©   (2006-05-09 01:04) [102]

приличный код, только за неприличную фотку! ;)


 
Джо ©   (2006-05-09 01:10) [103]

> [102] sniknik ©   (09.05.06 01:04)
> приличный код, только за неприличную фотку! ;)

Тут уже на 5+ тянет :)


 
Левчик   (2006-05-09 09:23) [104]

Удалено модератором


 
Левчик   (2006-05-09 09:29) [105]

Удалено модератором
Примечание: п. 5.


 
Вовчик   (2006-05-09 09:35) [106]

Удалено модератором
Примечание: п. 5.


 
TUser ©   (2006-05-09 09:50) [107]

> А lex незаслуженно забыт ? :)

Надо чтобы он был под рукой, а также уметь им пользоваться. А когда секундомер тикает учиться как-то не хочется - кнопки жать надо. А так конечно, lexx, yacc, GOLD и кто там еще полезны были бы.

> дициметрах?

Как такое отношение может измеряться в дециметрах?


 
programania ©   (2006-05-09 12:18) [108]


procedure RemoveComments(var S: string);
const
q=4;
z: array[1..q,1..5] of string=(
  ( "//",  #0,     #13#10, "",   #13#10 ),
  ( "{",   "{$",   "}",    "",   " "    ),
  ( "(*",  "(*$",  "*)",   "",   ""     ),
  ( """",  #0,     """",   "1",  """"   ));
var
r:     string;
i,j,n: integer;
begin
r:="";
i:=1;
s:=s+"   ";
while i<=length(s) do begin
 n:=i;
 for j:=1 to q do
   if (s[i]=z[j,1][1]) and (copy(s,i,length(z[j,1]))= z[j,1])
                       and (copy(s,i,length(z[j,2]))<>z[j,2])
   then begin
     while (i<=length(s))  and
        ((copy(s,i,length(z[j,3]))<> z[j,3]) or (i=n)) do
     begin
       if z[j,4]<>"" then r:=r+s[i];
       inc(i);
     end;
     r:=r+z[j,5];
     inc(i,length(z[j,3])-1);
     break;
   end;

 if n=i then r:=r+s[i];
 inc(i);
end;
s:=copy(r,1,length(r)-3);
end;


Эта же процедура может работать для html php java
а может и для всех языков и для lex тоже
если заменить константы

q=3; //html
z: array[1..q,1..5] of string=(
  ( "<!--", #0,     "-->",   "",   ""     ),
  ( """",   #0,     """",    "1",  """"   ),
  ( """,    #0,     """,     "1",  """    ));

q=4; //php java
z: array[1..q,1..5] of string=(
  ( "//",   #0,     #13#10, "",    #13#10 ),
  ( "/*",   #0,     "*/",    "",   ""     ),
  ( """",   #0,     """",    "1",  """"   ),
  ( """,    #0,     """,     "1",  """    ));


Предлагю проверить еще случай
begin i:=1{коментарий}end;
У меня оставляет пробел.

И есть более тяжелый случай когда после правильного удаления
коментариев программа не компилируется
потому что delphi удаляет методы form если в них ничего нет
а их присвоение не удаляет


 
TUser ©   (2006-05-09 13:54) [109]


> И есть более тяжелый случай когда после правильного удаления
> коментариев программа не компилируется
> потому что delphi удаляет методы form если в них ничего
> нет а их присвоение не удаляет

Все он удаляет что надо. И в IDE, и в консоли компилируется.


 
Alx2 ©   (2006-05-09 14:02) [110]

>TUser ©   (09.05.06 13:54) [109]

Я сейчас не проверял сам.

что если в тексте программы где-то имеет место присваивание

SomeObject.OnCick := SomeMethod;

А потом SomeMethod "исчезнет" вышеописанным способом?


 
Gero ©   (2006-05-09 14:03) [111]

> TUser ©   (09.05.06 13:54)

Иммется ввиду следующее:

procedure TForm1.Button1Click(Sender: TObject);
begin
 //
end;

Button1.OnClick := Button1Click;

Скомпилируется ли программа после удаления всех комментариев?


 
TUser ©   (2006-05-09 14:20) [112]

> Скомпилируется ли программа после удаления всех комментариев?

Да, на таком примере и проверял. dcc32 Project1.exe - нормально компилируется! Только IDE вольничает, но то ж для "удобства".

Зы. Именно поэтому тут кто-то рекомендовал не вставлять пустого комментария, а писать например {Do nothing}.


 
Gero ©   (2006-05-09 14:23) [113]

> Зы. Именно поэтому тут кто-то рекомендовал не вставлять
> пустого комментария, а писать например {Do nothing}.

В данном случае разницы-то нет, удаляются все комментарии.


 
TUser ©   (2006-05-09 14:26) [114]

Это да, только редко ставится задача удалить все комментарии. Чаще ставится обратная задача - написать их :(

{$warnings off}
 {$Do nothing :}
{$warnings on}


 
Alx2 ©   (2006-05-09 14:41) [115]

>Это да, только редко ставится задача удалить все комментарии

Здесь как  раз тот редкий случай. :)



Страницы: 1 2 3 вся ветка

Форум: "Прочее";
Текущий архив: 2006.06.04;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.82 MB
Время: 0.043 c
3-1145011975
Владимир
2006-04-14 14:52
2006.06.04
Проблема в MySQL с Regexp и кодеровкой cp1251.


15-1147414464
Ламот
2006-05-12 10:14
2006.06.04
Диспетчер сервера терминалов отображает не всех пользователей


2-1147939972
elena_pp
2006-05-18 12:12
2006.06.04
Как узнать и записать версию exe-ника в строковую переменную?


3-1144992872
gvv
2006-04-14 09:34
2006.06.04
коннект к ДБФ файлам при помощи АДО D5


15-1146824709
iamdanil
2006-05-05 14:25
2006.06.04
Пополнение кошелька с мобильного телефона





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский