Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.01.22;
Скачать: CL | DM;

Вниз

Как корректно выделить все функции и процедуры из *.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;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.039 c
6-1128587101
Pul
2005-10-06 12:25
2006.01.22
CONNECTION CLOSED GRACEFULLY


2-1135774036
Ice
2005-12-28 15:47
2006.01.22
Модальное окно


14-1135688727
Ale_x_ey
2005-12-27 16:05
2006.01.22
Виртуальная машина


3-1132670077
Alexandr1
2005-11-22 17:34
2006.01.22
РБД без взаимосвязанных таблиц???


9-1123486620
ПЛОВ
2005-08-08 11:37
2006.01.22
Вопрос по OpenGL