О применении библиотеки FastScript в своих проектах. Часть-4 «Парсинг раздела «Uses» FS-скрипта»


На предыдущую страницу…

Скачать/посмотреть:
Полный текст статьи в PDF-форматездесь статья в полном объеме;
Исходники иллюстрирующего примера (d12) в ZIP-архиве ;
Исходники в HTML-формате в ZIP-архиве;
Скомпилированный EXE-модуль (иллюстрирующий пример) в ZIP-архиве.

См., также:
О библиотеке FastScript;
Соглашения, термины и сокращения.
Часть-1. Расширение функционала FS (локализация идентификаторов программных объектов).
Часть-2. «Входные и выходные параметры FS-скрипта(при информационном обмене с внешними инициаторами)».
Часть-3. Группировка (распределение по модулям) добавляемых в FS программных объектов.


Автор излагает свой собственный подход к применению библиотеки FastScript, совершенно не претендуя на «истину в последней инстанции»


Библиотека FastScript предоставляет отличную возможность − структурировать функционал скриптов, размещая соответствующие программные объекты (библиотечные функции, переменные, константы) в отдельных файлах, а затем − вызывать их из других FS-скриптов (также, как это реализовано в Delphi).
Для этого (по аналогии с Delphi) используется директива «uses».
Пример использования приведен в Руководстве.
На рисунке ниже – скрин со страницы Руководства.

Но проблема в том, что в текущей реализации FastScript в директиве «uses» можно использовать только полные имена файлов, что создает ощутимые неудобства при практическом применении библиотеки FastSript.

Ниже рассмотрен вариант «купирования» этой проблемы на конкретных, иллюстрирующих примерах.


«Отвязка» от «абсолютного пути» в именах библиотечных файлов

Как вариант решения обозначенной в разделе выше проблемы, можно использовать следующий подход.
В рамках обвязки (см. здесь) реализовать (по аналогии с Delphi) механизм «переменных окружения» (далее − EV).

Определение «переменной окружения» приведено следующим образом:

Переменная окружения − внешняя (по отношению к FS-скрипту) текстовая переменная (идентифицируемая определенным образом), значение которой устанавливается обвязкой.
Перед компиляцией FS-скрипта, обвязка производит парсинг текста скрипта и заменяет в тексте скрипта идентификатор внешней переменной на ее значение.

ВАЖНО!
Следует отметить, что механизм «переменных окружения» (применительно к FastScript) далеко НЕ ограничен парсингом только лишь директивы (раздела) uses
FS-скрипта.

Ниже приведен текст функции обвязки fsiBase_Main_Script_EnvVars_Prepare(), которая выполняет парсинг текста скрипта (в контексте рассматриваемой темы).

function fsiBase_Main_Script_EnvVars_Prepare(
scrText:TStrings;
List_EnvVars:TStrings
):boolean;
//Переменные окружения. Парсинг скрипта
// scrText - текст скрипта (TStrings)
// List_EnvVars - список значений преременных окружения
begin
Result:=false;
if Assigned(scrText) then begin
if scrText.Count>0 then begin
Result:=true;
if Assigned(List_EnvVars) then begin
if List_EnvVars.Count>0 then begin
scrText.Text := fsiBase_Main_Script_EnvVars_Prepare(
scrText.Text,
List_EnvVars
);
end;
end;
end;
end;
end;

function fsiBase_Main_Script_EnvVars_Prepare(
sScript:string;
List_EnvVars:TStrings
):string;
//Переменные окружения. Парсинг скрипта
// sScript - текст скрипта
// List_EnvVars - список значений преременных окружения
Var
vn,vv:string;
i:integer;
begin
Result:='';
if Assigned(List_EnvVars) then begin
if List_EnvVars.Count>0 then begin
Result:=sScript;
i:=-1;
while i<(List_EnvVars.Count-1) do
begin
i:=i+1;
vn:=trim(List_EnvVars.Names[i]);
if length(vn)>0 then begin
vv:=trim(List_EnvVars.Values[vn]);
if length(vv)>0 then begin
Result:=Replace_In_String(Result, '$('+vn+')', vv, true);
end;
end;
end;
end;
end;
end;

function Replace_In_String(const S, Srch, Replace: string; CaseIgnore:boolean=true): string;
//замена подстроки в строке
var
N:Integer;
Source:string;
begin
Source:= S;
Result:= '';
repeat
if CaseIgnore then begin
N:=Pos(AnsiUpperCase(Srch), AnsiUpperCase(Source));
end
else begin
N:=Pos(Srch, Source);
end;
if N>0 then begin
Result:=Result+Copy(Source,1,N-1)+Replace;
Source:=Copy(Source,N+Length(Srch),MaxInt);
end
else begin
Result:=Result+Source;
end;
until N<=0;
end;

Пример вызова функции fsiBase_Main_Script_EnvVars_Prepare():


Иллюстрирующий пример

На рисунке ниже приведена структура папок (каталогов), где размещены FS-Скрипты:

Полное имя библиотечного файла:
D:\spFSI\FS\lib\FS_Библиотека_01.pas

При применении функции fsiBase_Main_Script_EnvVars_Prepare() для парсинга текста скрипта, оба (указанные на рисунках выше) варианта будут «работать» корректно.

Более предметно «все это» можно посмотреть, скачав исходные тексты иллюстрирующего примера, прилагаемого к этой статье (на roamer55.ru).

На рисунке ниже приведен пример директивы uses с применением «переменных окружения».


Корректная выгрузка библиотечных FS-скриптов, хранящихся в БД, и «подключение» их к «вызывающему» FS-скрипту

В тех случаях, когда библиотечные FS-скрипты (подключаемые к другим FS-скриптам с использованием директивы «uses») хранятся в таблицах БД, то дополнительно (к «отвязке» от «абсолютного пути», см. раздел выше) необходимо предусматривать
какой-то механизм, который бы позволял в рамках директивы «uses» корректно и однозначно обозначать (идентифицировать) библиотечный (подключаемый) FS-скрипт, хранящийся в БД.

Обвязка должна «уметь» распознавать это «обозначение», чтобы:
1. Найти соответствующий FS-Скрипт в БД;
2. Выгрузить его в соответствующую папку (файловой системы);
3. Изменить соответствующим образом строку в «uses».

Автор, для этих целей, использует такой же подход, как и с «переменными окружения»).

В качестве идентификатора FS-скрипта, хранящегося в БД, может быть использовано значение ключевого поля (primary key) в соответствующей таблице БД.

Автор предпочитает для этих целей использовать МнемоКоды:

Автор предпочитает для этих целей использовать МнемоКоды:

На рисунке ниже представлено содержание таблицы fs_scripts БД (см., также, Приложение-1).

Выноски на рисунке выше:

выноска-1 – функция обвязки fsiBase_Main_Script_Mnemo_Prepare(), см. листинг ниже (в этом разделе);
выноска-2 – функция обвязки fsiBase_Main_Script_EnvVars_Prepare(), см. листинг выше (раздел ««Отвязка» от «абсолютного пути» в именах библиотечных файлов»).

function fsiBase_Main_Script_Mnemo_Prepare(Q:TFDQuery;
scrText:TStrings;
List_EnvVars:TStrings
):boolean;
//Выгрузка библиотечных скриптов из БД. Парсинг скрипта
Var
ListScr:TStrings;
sDir, sMnemo:string;
Sx:string;
InUses:boolean;
N,i:integer;
begin
Result:=false;
if Assigned(Q) then begin
if Assigned(List_EnvVars) then begin
if List_EnvVars.Count>0 then begin
//Получить имя папки для сохранения библиотечных файлов из БД
sDir:=DirName_from_List_EnvVars(List_EnvVars);
if DirectoryExists(sDir) then begin
//удалить все PAS-файлы из папки (если требуется)
Files_Delete(sDir+'*.pas');
if Assigned(scrText) then begin
if scrText.Count>0 then begin
Result:=true;
end;
end;
end;
end;
end;
end;
if Result then begin
//==========================================
//Поиск раздела USES и его парсинг
ListScr:=TStringList.Create;
TRY
InUses:=false;
i:=-1;
while i<(scrText.Count-1) do
begin
i:=i+1;
Sx:=trim(scrText[i]);
sMnemo:='';
//---------------------------------------------------
if InUses then begin
if Sx<>'' then begin
//................................
//Выделить мнемокод из строки FS-скрипта
//если он там присутствует
sMnemo:=Mnemo_Extract(Sx);
//................................
if sMnemo<>'' then begin
//................................
//Загрузить скрипт из БД
ListScr.Text:=FS_LoadFromDB(Q,
sMnemo,
true);
//................................
if ListScr.Count>0 then begin
//Сохранить срипт в папку
ListScr.SaveToFile(sDir+sMnemo+'.pas');
end;
ListScr.Text:='';
//................................
//Заменить строку в скрипте
Sx:=Replace_In_String(scrText[i], '${'+sMnemo+'}', sMnemo+'.pas', true);
scrText[i]:=Sx;
//................................
end;
end;
end;
//---------------------------------------------------
//................................
//Определение начала раздела Uses FS-Скрипта
if AnsiUpperCase(Sx) = 'USES' then InUses:=true;
//................................
if InUses then begin
//................................
//Оценка: это конец раздела USES?
if Sx<>'' then begin
if Sx[length(Sx)]=';' then begin
InUses:=false;
i:=(scrText.Count+1); //Выход из парсинга
end;
end;
//................................
end;
end;
FINALLY
FreeAndNil(ListScr);
END;
//==========================================
end;
end;

Исходные тексты дополнительных функций, используемых в fsiBase_Main_Script_Mnemo_Prepare(), см. в Приложении-2.

Пример вызова функций обвязки fsiBase_Main_Script_Mnemo_Prepare() и fsiBase_Main_Script_EnvVars_Prepare() приведен на рисунке ниже.


Иллюстрирующий пример

На рисунке 10 представлен результат выгрузки заданного в разделе «uses»
FS-скрипта.

На рисунке 11 представлен скрин главной формы приложения FS_04_uses_parsing.exe (иллюстрирующий пример), открытой на вкладке «База данных (выгрузка)».

Более детально – см. исходники иллюстрирующего примера


См., также, Приложение-1 и Приложение-2.


На предыдущую страницу…


Дата: 07.04.2024