Форум: "Основная";
Текущий архив: 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