views:

186

answers:

8

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

A: 

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.

Kenster
A: 

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.

Mason Wheeler
Well Menus implementation is out of question in my situation because the requirements goes out of abstract calls, for instance you must define the customer id by script and that's not possible by menus you must open a customer profile form then force the user to hit the search button or enter the customer id manually, well the purpose of scripting is eliminate those steps by typing cust prof <ID> directly in the commands line.I looked at the gold parser, and its a great tool but its over my basic requirements.but at any-case thank you very much for sharing your great thoughts and experience.
Objectsberg
A: 

TMS and Greatis have scripters for this, I think.

Chris Thornton
A: 

You could integrate Python with Python for Delphi. In the demos there's "command-line example" if I remember correctly.

Harriv
A: 

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.

skamradt
+1  A: 

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.

thanks for the link, an excellent read
MarkRobinson
I'm a full-time accountant and part-time programmer. I've always said it doesn't take much to get an accountant excited, but I really got excited by reading this "Popular Mechanics" approach to writing a compiler.
+1  A: 

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.

Craig Peterson
A: 

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.

Alistair Ward