Small Command line scripter (like Autocad commands) one line editor
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 bas开发者_开发知识库ic 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.
TMS and Greatis have scripters for this, I think.
You could integrate Python with Python for Delphi. In the demos there's "command-line example" if I remember correctly.
A line scripter like your suggesting is not very hard to write, you could easily use a tStringList, set the delimiter to a space, set the text property for each line, then its a mater of evaluating the first item and dispatching the rest of the "parameters" on the line to a specific function. If you don't match the expected criteria, then you handle the error condition and stop processing the script.
If your looking for something more than a simple line scripter, take a look at PascalScript, which allows you to write scripts using a familiar pascal language.
If you are serious about "rolling your own" get a copy of "The Definitive ANTLR Reference" by Terence Parr.
It is all Java oriented, but gives a good background to parsing, and it generates parser code that is actually understandable.
There is also a commercial ANTLR for Delphi product, but I haven't actually tried it.
精彩评论