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.