Basically I don't know from where to start, I need to add a line script for my application that is not so complicated, just to execute pre-defined commands, for instance:
command> New Invoice --> create new invoice
command> customer profile --> open customer form where cust id = CustID
command> run End-Of-Day - run the end of day process
command> scr 1020 --> open form id = 1020
How can I start? I have no problem of recommending any third party components (parsers,evaluators,etc..).
whats missing is the basic structure no details, just a theory for implementation.
Thanks, Objectberg
Maybe you will like this, maybe not. But it sounds actually like you would like to get some basic understanding, too. You might like what I think is a classic first reading on how to build a compiler by Jack Crenshaw. You can find it at this address. It is more than what you are looking for but it's written in Turbo Pascal and the narrative is actually kind of fun to read.
Good luck.
If it's sufficiently simple (even with optional arguments), something based on TStringList actually works decently. Here's a simple example to get you started:
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;
If you have multiple optional arguments (e.g., FIND CUST BY NAME John AND LASTNAME Smith
) then, rather than hardcoding the stringlist offsets like I've done above, delete each argument from the stringlist as you process it (or add it to your query). That way, when it's empty you know you're done with the line, and you only need to look at AArgs[0]
to see if you recognize the next bit.
You could look at tcl. That was its original purpose--to be a tool command language framework which you could embed into another program. Tcl provides a language syntax with variables and control structures (loops etc). You would add tcl commands and functions to access your program's features.
First question: If it's a limited number of canned commands, why not just implement it using menus?
But if you want real scripting, there are plenty of script engines that you can plug into Delphi. Most of them are based on real programming languages, though, which sounds a bit more complicated than what you're looking for.
If you want to design your own simple scripting language, you'll need a bit of knowledge about parser theory. I'd recommend looking around on the GOLD Parser site, which has some theoretical information available and also some tools that will help you set up your own language rules. It has a Delphi implementation available on the site.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With