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

Вниз

Как корректно выделить все функции и процедуры из *.pas файла?   Найти похожие ветки 

 
Volf_555   (2005-12-15 22:43) [0]

Для того, чтобы выудить все функции с процедурами из *.pas файла, необходимо искать их после implementation.
С определением функций и процедур, написанных в одну строку - проблем не возникает. А начинаются они с того момента, когда заголовок функции или процедуры написан в несколько строк. Допустим есть следующий набор функций и процедур из Windows.pas:

function EndDialog; external user32 name "EndDialog";
procedure GlobalUnfix; external kernel32 name "GlobalUnfix";
function CreateWindowW(lpClassName: PWideChar; lpWindowName: PWideChar;
 dwStyle: DWORD; X, Y, nWidth, nHeight: Integer; hWndParent: HWND;
 hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND;
begin
 Result := CreateWindowExW(0, lpClassName, lpWindowName, dwStyle, X, Y,
   nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
end;
function EndMenu; external user32 name "EndMenu";


В обработчике событий пишу следующее:

procedure TForm1.Button1Click(Sender: TObject);
var
a1,a2:Integer;
cur:String;
chk:String;
res:String;
co:Integer;

zbeg,zend:Integer;

val:Integer;
begin
zbeg:=0;
zend:=memo1.Lines.Count-1;

for a1:=zbeg to zend do
begin
 chk:="";
 res:="";
 cur:=memo1.Lines.Strings[a1];
 for a2:=1 to 9 do
  chk:=chk+cur[a2];

 if (chk="function ") OR (chk="procedure") then
 begin
  res:=cur;
  cur:=memo1.Lines.Strings[a1+1];
  chk:="";

  if Length(cur)<>0 then

  for co:=a1 to zend do
  begin
   for a2:=1 to 9 do
    chk:=chk+cur[a2];

   val:=a1;

   repeat
   if (chk<>"function ") AND (chk<>"procedure") AND
      (chk<>"begin    ") AND (chk<>"var      ") AND
      (chk<>"asm      ") then
   begin
    res:=res+cur;
    cur:=memo1.Lines.Strings[val+1];
    for a2:=1 to 9 do
     chk:=chk+cur[a2];
   end until (chk<>"function ") AND (chk<>"procedure") AND
      (chk<>"begin    ") AND (chk<>"var      ") AND
      (chk<>"asm      ");

   chk:="";
  end;

  end;
  ShowMessage(res);
  res:="";

 end;
end;


конечному результату, то есть строке res, если функция содержится в нескольких строках, присваивается несколько одинаковых фрагментов.

Как мне изменить код чтобы функции с процедурами определялись корректно?


 
Volf_555   (2005-12-15 22:46) [1]

P.S.: Необходимо выделить ТОЛЬКО заголовок с параметрами! Сама реализация процедуры или функции мне не нужна!


 
Zeqfreed ©   (2005-12-15 22:57) [2]

Volf_555   (15.12.05 22:46) [1]
Лучше составь регулярное выражение и воспользуйся TRegExpr.


 
The_scorpion   (2005-12-15 22:58) [3]

1)Находишь function или procedure
2) ищешь ";"
3) выводишь результат.
4)Если далее следует Begin, то пропускаешь все строчки, пока не встретишь end.
Пока не закончиться файл повторить указанный алгоритм.


 
Volf_555   (2005-12-16 01:16) [4]


> Лучше составь регулярное выражение и воспользуйся TRegExpr.

В смысле регулярное выражение? И что это за класс TRegExpr?


> The_scorpion   (15.12.05 22:58) [3]
> 1)Находишь function или procedure
> 2) ищешь ";"
> 3) выводишь результат.
> 4)Если далее следует Begin, то пропускаешь все строчки,
> пока не встретишь end.
> Пока не закончиться файл повторить указанный алгоритм.


Тоже думал по поводу составления такого алгоритма - но есть одно НО, которое заключается в том, что в названии функции или процедуры может присутствовать несколько точек с запятыми, например:

Допустим, в следующей функции после PWideChar стоит точка с запятой - получается что результат программы будет следующим:
function CreateWindowW(lpClassName: PWideChar;
А остальную часть тоже ведь надо дописать как то. Вот в этом и вопрос.
Думал вместо точек с запятыми искать скобки - бесполезно, начало вхождения новой функции или процедуры или бегина, энда - бесполезно.
Какой ещё может быть выход из ситуации?

function CreateWindowW(lpClassName: PWideChar; lpWindowName: PWideChar;
dwStyle: DWORD; X, Y, nWidth, nHeight: Integer; hWndParent: HWND;
hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND;
begin
Result := CreateWindowExW(0, lpClassName, lpWindowName, dwStyle, X, Y,
  nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
end;


 
Slym ©   (2005-12-16 04:58) [5]

Искать "begin"


 
evvcom ©   (2005-12-16 10:59) [6]


> Искать "begin"

Внутри функции может быть объявлена другая функция, а также type, const, var и прочее.


 
Плохиш ©   (2005-12-16 11:03) [7]


> Volf_555   (16.12.05 01:16) [4]
> Тоже думал по поводу составления такого алгоритма - но есть
> одно НО, которое заключается в том, что в названии функции
> или процедуры может присутствовать несколько точек с запятыми

И в чём проблема?
Если знаешь, что описания параметров функций/процедур всегда заключаются в скобки, т.е. если имеется открывающая скобка, то и обязательно будет закрывающая.


 
Lamer@fools.ua ©   (2005-12-16 11:47) [8]

function DoSomething(A: String = ");"; B: String = "begin"; C: Integer): Integer;


 
Плохиш ©   (2005-12-16 11:50) [9]


> Lamer@fools.ua ©   (16.12.05 11:47) [8]

Кто-то, где-то гарантирует, что синтаксический анализ текста является лёгкой операцией с использованием одной команды?


 
Amoeba ©   (2005-12-16 12:36) [10]


> описания параметров функций/процедур всегда заключаются
> в скобки

Не всегда. Не надо забывать про процедуры и ф-ии без параметров.


 
jack128 ©   (2005-12-16 12:43) [11]

Учитывая
Volf_555   (15.12.05 22:46) [1]
Необходимо выделить ТОЛЬКО заголовок с параметрами!

Вот это утверждение
Volf_555   (15.12.05 22:43)
Для того, чтобы выудить все функции с процедурами из *.pas файла, необходимо искать их после implementation.

не верно.

в реализации функции можно не указывать её формальные параметры

interface;

// Декларация
function Test(a, b: Integer): boolean;

implementation

{$R *.dfm}

//Реализация
function Test;
begin
 Result := a > b;
end;


 
jack128 ©   (2005-12-16 12:44) [12]

PS Обычно сначала изучают возможности языка, а уже потом пытаются написать парсер этого языка ;))


 
Volf_555   (2005-12-16 14:21) [13]


> jack128 ©   (16.12.05 12:43) [11]
> Учитывая
> Volf_555   (15.12.05 22:46) [1]
> Необходимо выделить ТОЛЬКО заголовок с параметрами!
> Вот это утверждение
> Volf_555   (15.12.05 22:43)
> Для того, чтобы выудить все функции с процедурами из *.pas
> файла, необходимо искать их после implementation.
> не верно.
>
> в реализации функции можно не указывать её формальные параметры
>
> interface;
>
> // Декларация
> function Test(a, b: Integer): boolean;
>
> implementation
>
> {$R *.dfm}
>
> //Реализация
> function Test;
> begin
>  Result := a > b;
> end;


Тогда что ты предлагаешь в таком случае?


> Плохиш ©   (16.12.05 11:03) [7]
>
> > Volf_555   (16.12.05 01:16) [4]
> > Тоже думал по поводу составления такого алгоритма - но
> есть
> > одно НО, которое заключается в том, что в названии функции
>
> > или процедуры может присутствовать несколько точек с запятыми
>
> И в чём проблема?
> Если знаешь, что описания параметров функций/процедур всегда
> заключаются в скобки, т.е. если имеется открывающая скобка,
>  то и обязательно будет закрывающая.

Допустим, есть следующая функция, которая не заключается в скобки:

function GetVersionExA; external kernel32 name "GetVersionExA";

Анализируя эту функцию - можно сказать - что скобок нет, используется функция "GetVersionExA" из kernel32. Скобок тут нет. Даже если были, то после точки с запятой идёт ещё external.... И тут необходимо полностью получить всю эту функцию. Также она может быть написана в несколько строк.


 
evvcom ©   (2005-12-16 14:26) [14]


> Допустим, есть следующая функция, которая не заключается
> в скобки:
>
> function GetVersionExA; external kernel32 name "GetVersionExA";
>

Это как раз в implementation, о чем и было тебе сказано в
> jack128 ©   (16.12.05 12:43) [11]

а ты посмотри теперь в интерфейсной части модуля.


 
jack128 ©   (2005-12-16 14:34) [15]

Volf_555   (16.12.05 14:21) [13]
Тогда что ты предлагаешь в таком случае?


В простейшем  варианте

а) сканим интерфейсную секцию на наличие деклараций функций и сохраняем их в список. Не забываем учитывать флаг overload;
б) сканим секцию implementation.
 Для каждой функции делаем следующее:

 
 Если функция с таким именем уже была найдена в интерфейсной части, То
 Начало
    Если функция перегружена, То
    Начало
      Выдераем параметры
      Если функция НЕ совпадает по списку параметров ни с одной из найденных ранее одноименных функций, То
        сохраняем её с наш список
    Конец
 Конец
 Иначе
   Сохраняем декларадию в Наш список


 
Anatoly Podgoretsky ©   (2005-12-16 14:45) [16]

Задачка явно не для начинающего.


 
Плохиш ©   (2005-12-16 15:02) [17]


> Плохиш ©   (16.12.05 11:03) [7]
> Если знаешь, что описания параметров функций/процедур всегда
> заключаются в скобки, т.е. если имеется открывающая скобка,
>  то и обязательно будет закрывающая.

Так это начало, теперь по отзывам

> Amoeba ©   (16.12.05 12:36) [10]
> Не всегда. Не надо забывать про процедуры и ф-ии без параметров.

А теперь приведи функцию/процедуру с параметрами, у которой эти параметры не заключены в скобки.
Кстати, хотелось бы узнать связь между функциями с параметрами и функциями без параметров в контексте вопроса из [4]?

> Volf_555   (16.12.05 14:21) [13]
> Допустим, есть следующая функция, которая не заключается в скобки:

Сам-то понял о чём городишь?


 
Volf_555   (2005-12-16 15:02) [18]


> jack128 ©   (16.12.05 14:34) [15]
>
> В простейшем  варианте
>
> а) сканим интерфейсную секцию на наличие деклараций функций
> и сохраняем их в список. Не забываем учитывать флаг overload;
>
> б) сканим секцию implementation.


Часть кода из секции implementation:

type
 TThreadStartRoutine = function(lpThreadParameter: Pointer): Integer stdcall;


Это я так понял объявление типа? Или как понять?
<название типа> = function(...): Integer;
при чём тут функция вообще-то? Если поискать функцию TThreadStartRoutine в implementation, то такой функции не будет.

Исходя из следующего кода, выясняется, что функция может находиться в любом участке кода. И для того, чтобы вычислить все функции необходимо все строчки кода перебрать + сравнить. На это уйдёт куча времени (время исполнения программы).

Самый оптимальный вариант, на мой взгляд, это поиск функций и процедур после implementation - даже если параметры не будут указаны в скобках.

Остаётся разъяснить одну проблему - проблема слияния всех строк одной функции или процедуры в одну строку


 
Плохиш ©   (2005-12-16 15:05) [19]


> Volf_555   (16.12.05 15:02) [18]

Сказал бы уж простыми словами, что сделать хочешь?
Автошему уже до тебя изобрели.


 
evvcom ©   (2005-12-16 15:15) [20]


> Это я так понял объявление типа?

правильно понял

> при чём тут функция вообще-то?

это тип, с которым объявляешь переменную и по ней вызываешь функцию такого типа.

> выясняется, что функция может находиться в любом участке
> кода

более того, она может находиться даже в любом другом месте (dll, bpl и пр.)

> Остаётся разъяснить одну проблему - проблема слияния всех
> строк одной функции или процедуры в одну строку

Это-то как раз и не проблема. Проблема - корректно распарсить код.


 
Volf_555   (2005-12-16 15:16) [21]


> Плохиш ©   (16.12.05 15:02) [17]
> Сам-то понял о чём городишь?


А что тут собственно понимать-то?

Я имел в виду следующее:
Пример функции с параметрами:
function mci_MSF_Minute(msf: Longint): Byte;
Пример функции без параметров:
function timeGetTime; external mmsyst name "timeGetTime";

> Volf_555   (16.12.05 14:21) [13]
> Допустим, есть следующая функция, которая не заключается в скобки:
Имел в виду функцию без параметров


 
Volf_555   (2005-12-16 15:20) [22]


> evvcom ©   (16.12.05 15:15) [20]
> Это-то как раз и не проблема. Проблема - корректно распарсить
> код.


Дай мне толчок в нужном направлении про корректное распарсивание кода :-)


 
jack128 ©   (2005-12-16 16:11) [23]

Volf_555   (16.12.05 15:02) [18]
Это я так понял объявление типа? Или как понять?

У-у-у..  Ну-ну. С такими знаниями долго ты будешь свой парсер писать.
"Обычно сначала изучают возможности языка, а уже потом пытаются написать парсер этого языка" (c) Я

PS слово function встречается еще и контексте объявления(реализации) классов, интерфейсов и (если собираемся поддерживать Delphi8 и выше) записей.
PPS В справке есть формальное описания языка Delphi.  Вот с разбора этих правил вообще то и следовало бы начать..


 
Игорь Шевченко ©   (2005-12-16 16:22) [24]


> Дай мне толчок в нужном направлении про корректное распарсивание
> кода :-)


исходники freepascal


 
Separator ©   (2005-12-17 05:16) [25]

А причем тут вообще interface и implementation? В .pas файле их может и не быть.
Самый простой алгоритм (по моему):
1) Поиск function или procedure;
2) поиск ";", если по ходу поиска встречается "(", то соответсвенно ищем ")", но если была найдена "(" и """, то сначала долна встретися еще одна """ и только после этого ")";
3) анализ следующих выражений, если встречаются external, cdecl, varargs, stdcall, либо другие директив типа virtual, override, то переходим к шагу 2.

В общем ничего сложного не вижу.


 
jack128 ©   (2005-12-17 11:53) [26]

Separator ©   (17.12.05 5:16) [25]
В .pas файле их может и не быть.

в произвольном файле с расшерением pas действительно может и не быть. А в синтаксически правельном юните эти секции быть обязаны.

PS  Есть еще такая вещь как комментарий ;)


 
Separator ©   (2005-12-17 12:42) [27]

а если взять pas файл от TurboPascal?


 
Volf_555   (2005-12-18 02:35) [28]


> Separator ©   (17.12.05 05:16) [25]
> А причем тут вообще interface и implementation? В .pas файле
> их может и не быть.
> Самый простой алгоритм (по моему):
> 1) Поиск function или procedure;
> 2) поиск ";", если по ходу поиска встречается "(", то соответсвенно
> ищем ")", но если была найдена "(" и """, то сначала долна
> встретися еще одна """ и только после этого ")";
> 3) анализ следующих выражений, если встречаются external,
>  cdecl, varargs, stdcall, либо другие директив типа virtual,
>  override, то переходим к шагу 2.
>
> В общем ничего сложного не вижу.


Результат обработки следующей строки по твоему алгоритму:
function VirtualProtect(lpAddress: Pointer; dwSize, flNewProtect: DWORD;
 lpflOldProtect: Pointer): BOOL; external kernel32 name "VirtualProtect";


Результат:
function VirtualProtect(lpAddress: Pointer; dwSize, flNewProtect: DWORD;
 lpflOldProtect: Pointer)


А ещё надо чтобы программа автоматом переходила на следующую строку для поиска+считывала значения после двоеточия+после точки запятой....

Пробывал сам подобное реализовать - частично выходит, частично нет



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

Форум: "Основная";
Текущий архив: 2006.01.22;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.54 MB
Время: 0.05 c
14-1136009895
begin...end
2005-12-31 09:18
2006.01.22
С Днём рождения! 31 декабря


3-1132771300
alexmember
2005-11-23 21:41
2006.01.22
Задержка отображения записей на pentium 3


2-1136394775
ArtemESC
2006-01-04 20:12
2006.01.22
Форма потеряла фокус...


1-1134638013
Mamed
2005-12-15 12:13
2006.01.22
resourcestring


1-1135011895
bulk
2005-12-19 20:04
2006.01.22
заголовок формы





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский