Если это достаточно просто (даже с необязательными аргументами), то что-то на основе TStringList на самом деле работает прилично. Вот простой пример для начала работы:
type
TCommandRec = record
Command: string;
Proc: array(AArgs: TStringList);
end;
const
Commands: array(0..4) of TCommandRec = (
(Command: 'New'; Proc: DoNew),
(Command: 'Customer'; Proc: DoCustomer),
(Command: 'Run'; Proc: DoRun),
(Command: 'Scr'; Proc: DoScr),
(Command: 'Find'; Proc: DoFind));
procedure RunScript(const AFileName: string);
var
Script, Args: TStringList;
i, j: Integer;
begin
Script := TStringList.Create;
try
Script.LoadFromFile(AFileName);
Args := TStringList.Create;
try
Args.Delimiter := ' ';
for i := 0 to Script.Count - 1 do begin
Args.DelimitedText := Script[i];
for j := Low(Commands) to High(Commands) do
if SameText(Args[0], Commands[j].Command) then begin
Commands[j].Proc(Args);
Break;
end;
end;
finally
Args.Free;
end;
finally
Script.Free;
end;
end;
procedure DoRun(AArgs: TStringList);
begin
if SameText(AArgs[1], 'End-of-day') then
RunEndOfDayProcess
else if SameText(AArgs[1], 'Hourly') then
RunHourlyProcess
else
raise EInvalidScript.Create;
end;
procedure DoFind(AArgs: TStringList);
var
FindType: string;
begin
if (AArgs.Count <> 5) or not SameText(AArgs[2], 'by') then
raise EInvalidScript.Create;
if SameText(AArgs[1], 'Cust') then begin
if SameText(AArgs[3], 'Name') then
FindCustomer(AArgs[4], '')
else if SameText(AArgs[3], 'LastName') then
FindCustomer('', AArgs[4])
end
else if SameText(AArgs[1], 'Contact') then begin
...
end
else
raise EInvalidScript.Create;
end;
Если у вас есть несколько необязательных аргументов (например, FIND CUST BY NAME John AND LASTNAME Smith
), тогда вместо жесткого кодирования смещений списка строк, как я делал выше, удалите каждый аргумент из списка строк при его обработке (или добавьте его в свой запрос). Таким образом, когда он пуст, вы знаете, что со строкой покончено, и вам нужно только взглянуть на AArgs[0]
, чтобы увидеть, распознаете ли вы следующий бит.