![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как корректно выделить все функции и процедуры из *.pas файла? [D6, WinXP]
Volf_555 © (2005-12-15 22:43:00)Для того, чтобы выудить все функции с процедурами из *.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-18 02:35:00) [1]
> 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)
А ещё надо чтобы программа автоматом переходила на следующую строку для поиска+считывала значения после двоеточия+после точки запятой....
Пробывал сам подобное реализовать - частично выходит, частично нет
Separator (2005-12-17 12:42:00) [2]а если взять pas файл от TurboPascal?
jack128 (2005-12-17 11:53:00) [3]Separator © (17.12.05 5:16) [25]
В .pas файле их может и не быть.
в произвольном файле с расшерением pas действительно может и не быть. А в синтаксически правельном юните эти секции быть обязаны.
PS Есть еще такая вещь как комментарий ;)
Separator (2005-12-17 05:16:00) [4]А причем тут вообще interfaceи implementation? В .pas файле их может и не быть.
Самый простой алгоритм (по моему):
1) Поиск functionили procedure;
2) поиск " ;", если по ходу поиска встречается " (", то соответсвенно ищем " )", но если была найдена " (" и " '", то сначала долна встретися еще одна " '" и только после этого " )";
3) анализ следующих выражений, если встречаются external, cdecl, varargs, stdcall, либо другие директив типа virtual, override, то переходим к шагу 2.
В общем ничего сложного не вижу.
Игорь Шевченко (2005-12-16 16:22:00) [5]
> Дай мне толчок в нужном направлении про корректное распарсивание
> кода :-)
исходники freepascal
jack128 (2005-12-16 16:11:00) [6]Volf_555 (16.12.05 15:02) [18]
Это я так понял объявление типа? Или как понять?
У-у-у.. Ну-ну. С такими знаниями долго ты будешь свой парсер писать.
"Обычно сначала изучают возможности языка, а уже потом пытаются написать парсер этого языка" (c) Я
PS слово function встречается еще и контексте объявления(реализации) классов, интерфейсов и (если собираемся поддерживать Delphi8 и выше) записей.
PPS В справке есть формальное описания языка Delphi. Вот с разбора этих правил вообще то и следовало бы начать..
Volf_555 (2005-12-16 15:20:00) [7]
> evvcom © (16.12.05 15:15) [20]
> Это-то как раз и не проблема. Проблема - корректно распарсить
> код.
Дай мне толчок в нужном направлении про корректное распарсивание кода :-)
Volf_555 (2005-12-16 15:16:00) [8]
> Плохиш © (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]
> Допустим, есть следующая функция, которая не заключается в скобки:
Имел в виду функцию без параметров
evvcom (2005-12-16 15:15:00) [9]
> Это я так понял объявление типа?
правильно понял
> при чём тут функция вообще-то?
это тип, с которым объявляешь переменную и по ней вызываешь функцию такого типа.
> выясняется, что функция может находиться в любом участке
> кода
более того, она может находиться даже в любом другом месте (dll, bpl и пр.)
> Остаётся разъяснить одну проблему - проблема слияния всех
> строк одной функции или процедуры в одну строку
Это-то как раз и не проблема. Проблема - корректно распарсить код.
Плохиш (2005-12-16 15:05:00) [10]
> Volf_555 (16.12.05 15:02) [18]
Сказал бы уж простыми словами, что сделать хочешь?
Автошему уже до тебя изобрели.
Volf_555 (2005-12-16 15:02:00) [11]
> 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:02:00) [12]
> Плохиш © (16.12.05 11:03) [7]
> Если знаешь, что описания параметров функций/процедур всегда
> заключаются в скобки, т.е. если имеется открывающая скобка,
> то и обязательно будет закрывающая.
Так это начало, теперь по отзывам
> Amoeba © (16.12.05 12:36) [10]
> Не всегда.Не надо забывать про процедуры и ф-ии без параметров.
А теперь приведи функцию/процедуру с параметрами, у которой эти параметры не заключены в скобки.
Кстати, хотелось бы узнать связь между функциями спараметрами и функциями безпараметров в контексте вопроса из [4]?
> Volf_555 (16.12.05 14:21) [13]
> Допустим, есть следующая функция, которая не заключается в скобки:
Сам-то понял о чём городишь?
Anatoly Podgoretsky (2005-12-16 14:45:00) [13]Задачка явно не для начинающего.
jack128 (2005-12-16 14:34:00) [14]Volf_555 (16.12.05 14:21) [13]
Тогда что ты предлагаешь в таком случае?
В простейшем варианте
а) сканим интерфейсную секцию на наличие деклараций функций и сохраняем их в список. Не забываем учитывать флаг overload;
б) сканим секцию implementation.
Для каждой функции делаем следующее:
Если функция с таким именем уже была найдена в интерфейсной части, То
Начало
Если функция перегружена, То
Начало
Выдераем параметры
Если функция НЕ совпадает по списку параметров ни с одной из найденных ранее одноименных функций, То
сохраняем её с наш список
Конец
Конец
Иначе
Сохраняем декларадию в Наш список
evvcom (2005-12-16 14:26:00) [15]
> Допустим, есть следующая функция, которая не заключается
> в скобки:
>
> function GetVersionExA; external kernel32 name 'GetVersionExA';
>
Это как раз в implementation, о чем и было тебе сказано в
> jack128 © (16.12.05 12:43) [11]
а ты посмотри теперь в интерфейсной части модуля.
Volf_555 (2005-12-16 14:21:00) [16]
> 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.... И тут необходимо полностью получить всю эту функцию. Также она может быть написана в несколько строк.
jack128 (2005-12-16 12:44:00) [17]PS Обычно сначала изучают возможности языка, а уже потом пытаются написать парсер этого языка ;))
jack128 (2005-12-16 12:43:00) [18]Учитывая
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;
Amoeba (2005-12-16 12:36:00) [19]
> описания параметров функций/процедур всегда заключаются
> в скобки
Не всегда. Не надо забывать про процедуры и ф-ии без параметров.
Плохиш (2005-12-16 11:50:00) [20]
> Lamer@fools.ua © (16.12.05 11:47) [8]
Кто-то, где-то гарантирует, что синтаксический анализ текста является лёгкой операцией с использованием одной команды?