Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi ScriptingEngine? (https://www.delphipraxis.net/5175-scriptingengine.html)

CalganX 26. Mai 2003 15:31


ScriptingEngine?
 
Hi,
ich suche derzeit nach einer Art ScriptingEngine...
Ich habe Scripte, die ungefähr so aussehen:
Code:
findwindow "wndname" $1      // findet das Fenster
findchild $1 "pagecontrol" $2   // findet das pagecontrol
findchild $2 "label" $3      // findet das Label
getnumber $3 "Nr. " " um" $4   // findet die Nummer x heraus, x steht in $4
findchild $2 "btn".$4 $5
sendmessage bm_click $5

END
($x sind Variablen; alles andere Strings bzw. Anweisungen; ist eines der komplizierteren... ;))

Nun frage ich mich, wie man sowas machen kann, dass man das ganze sozusagen interpretiert.
Muss ich das ganze etwa per copy, delete, ... machen??? Dann würde ich glatt durchdrehen! :freak:

Naja... das Problem sind da eher Knackpunkte wie die zusammensetzung eines Strings und einer Variable (z.B. "btn".$4).

Gibt es irgendwo so eine Art "Vorlage"?
Oder habt ihr eine Idee, wie man sowas machen kann?

Chris

Christian Seehase 26. Mai 2003 15:47

Moin Chris,

mit einer Idee kann ich dienen ;-)

Da es sich offensichtlich um ein sequentiell abzuarbeitendes Script handelt, könntest Du es so machen:

Voraussetzungen:
  • Das Script steht in einer Stringliste.
  • Du hast eine Liste der vordefinierten Schlüsselworte (z.B. FindWindow, FindChild...)
  • Du hast eine, am Anfang leere, Liste, in der die Variablen gespeichert werden

Jetzt kannst Du die Liste in einer Schleife durchgehen, und die einzelnen Zeilen in ihre Bestandteile zerlegen, wobei als erstes wohl immer ein Schlüsselwort steht (hoffentlich ;-) ), gefolgt von Parametern, in Abhängigkeit des Schlüsselwortes.

Als Beispiel mal Deine erste Zeile:
Schlüsselwort findwindow. Jetzt weisst Du, dass als nächstes der Name es Fensters erscheinen muss, und dann der Name einer Variablen, in der das Ergebnis gespeichert werden soll.
Dann kannst Du die Funktion ausführen, und das Ergebnis in der Variablenliste speichern.
Soll der Wert einer Variablen verwendet werden, muss dieser dann aus der Liste ausgelesen werden. Ggf. kann die Liste auch eine einfache Stringliste in der Form Variablenname=Wert sein.
Für eventuelle vordefinierte Konstanten (bm_click) wäre eine entsprechende weitere Liste ganz sinnvoll.

chris 26. Mai 2003 16:03

hi,

guck doch mal hier nach -> Innerfuse Pascal Script 3

CalganX 26. Mai 2003 16:11

Hi,
@Christian: also so, oder so ähnlich, hatte ich mir das auch schon gemacht, allerdings überlegte ich nach einer Möglichkeit das ohne es so kompliziert zu machen (wobei man sagen muss, dass deine Möglichkeit viel einfacher ist, als ich sie mir ausgedacht hab).
[EDIT]
Da fällt mir: das Problem ist, dass für jeden Befehl ich eine if-Abfrage machen muss, weil ja jeder Befehl eine andere Struktur hat und andere Befehle verwendet.
Also zum Beispiel sendmessage verlangt andere Parameter, als findwindow. Auch die Anzahl ist unterschiedlich.

Das Problem ist z.B. auch, dass Zusammensetzen (wie gesagt: ein String.eine Variable). Wie bitte soll ich das anstellen? :|
[/EDIT]

Deswegen...
...@chris: werde mir das mal ansehen. Allerdings scheint mir das schon wieder ein wenig zu aufwendig. Aber ich habe jetzt nur mal einen Blick drauf geworfen!

Chris

Christian Seehase 26. Mai 2003 16:19

Moin Chris,

je komplizierter/flexibler die zu verarbeitende Sprache ist, umso komplizierter wird halt auch die Verarbeitung.

Solange sich das ganze sequentiell abarbeiten lässt und dabei die einzelnen Funktionen und Paramter leicht zu trennen sind, ist die Umsetzung nicht ganz so schwierig.

Sobald Du mit bedingtem Programmablauf (womöglich verschachtelt) und Schleifen anfängst wird's merklich komplexer.

Christian Seehase 26. Mai 2003 16:23

Moin Chris,

Du kannst doch den Wert einer Variablen aus der vorgeschlagenen Tabelle auslesen (Eigenschaft z.B. sWert := slVariablen.Values['$4'];).

Diesen verbindest Du dann mittels + mit der Konstanten.

CalganX 26. Mai 2003 16:24

Mit Schleifen usw. will ich gar nichts anfangen...
Denn eigentlich bringen mir Schleifen nichts.

Ich habe gerade dieses Innerfuse-Teil heruntergeladen. Also wirklich begeistert bin ich nicht. Nicht einmal eine install.txt. :evil:

Naja... werde das ganze mal versuchen.

Chris

CalganX 26. Mai 2003 16:25

Stimmt... Warum mach ich die Sache eigentlich selber so scher??? :wall:

Chris

CalganX 26. Mai 2003 18:58

Hi,
ich hab gerade bei der ganzen Sache ein Problem (die Klasse an sich funktioniert wunderbar):
Ich bräuchte eine Funktion, die mir den n. Parameter liefert. Also z.B.:
Code:
findwindow "test window" $1
dann ist findwindow der 0., test window der 1. und $1 der 2.
Hat jemand dafür eine Funktion parat?

Ich habe im Moment nämlich keine Idee, wie ich das machen soll, dass Problem ist halt die Sache mit den Strings... :(

Chris

Chewie 26. Mai 2003 19:04

Na ja, im Prinzip werden die Parameter durch Leerzeichen getrennt. Nur wenn vor dem Leerzeichen eine ungerade Anzahl an Gänsefüßchen steht, dann ist das Leerzeichen kein Trennoperator. Also Zeichen für Zeichen durchgehen, zusätzlich boolsche Variable für String oder nicht und falls kein String, trennen am Leerzeichen.
Alternativ dazu die Anzahl der Gänsefüßchen vor dem Leerzeichen ermitteln: Falls ungerade -> Leerzeichen ignorieren, ansonsten trennen.

Christian Seehase 26. Mai 2003 19:08

Moin Chris,

ich würd's leicht anders machen:

Die Zeile zeichenweise durchgehen, dabei in Schlüsselwort und Parameter trennen, indem bei auftreten eines " alle Zeichen ab der Position von " +1 bis zum nächsten " (-1) als String übernommen werden, und ab $ bis zum Auftreten von #32 als Variablenname.

CalganX 26. Mai 2003 19:17

Hi Chris, hi Chewie,
danke für eure Hilfe!
Ich werde versuchen Christians Idee umzusetzen (muss erstmal Onkel Fisch anhören :mrgreen:).

Chris

CalganX 27. Mai 2003 16:25

Hi,
ich habe gerade das ganze mal versucht.
Erstmal meine Funktion:
Delphi-Quellcode:
function GetParam(index: integer; lineStr: string): string;
var
  Params: array[0..5] of string;
  counter: integer;
  paramCounter: integer;
  temp: string;
  oldEnd: integer;
  openString: boolean;
  i: integer;
begin
  counter := 0;
  paramCounter := -1;
  oldEnd := 1;
  repeat
    inc(counter);
    if lineStr[counter] = '"' then begin
      openString := true;
      i := counter;
      while openString do begin
        inc(i);
        if lineStr[i] = '"' then
          openString := false;
      end;
      temp := copy(lineStr, counter, counter + 1 - i);
      inc(paramCounter);
      Params[paramCounter] := temp;
      oldEnd := i;
      counter := i;
    end;
    if lineStr[counter] = ' ' then begin
      temp := copy(lineStr, oldEnd, counter - oldEnd);
      inc(paramCounter);
      Params[paramCounter] := temp;
      oldEnd := counter;
    end;
  until counter = length(lineStr);
end;
Bei lineStr =
Code:
findwindow "test" "test test" $1
wird so ist Paramcount so:
Code:
0: findwindow
1:
2: "
3:
4: "
5:
Das erste ist ja richtig... :mrgreen:

Woran kann das liegen? Wo liegt der Hund begraben?

Chris

CalganX 27. Mai 2003 17:57

Habe gerade noch mal drüber geschaut. Jetzt sieht das ganze so aus:
Delphi-Quellcode:
  counter := 0;
  paramCounter := -1;
  oldEnd := 1;
  repeat
    inc(counter);
    if lineStr[counter] = '"' then begin
      openString := true;
      i := counter;
      while openString do begin
        inc(i);
        if lineStr[i] = '"' then
          openString := false;
      end;
      temp := copy(lineStr, counter, i - counter + 1);
      inc(paramCounter);
      Params[paramCounter] := temp;
      oldEnd := i;
      inc(counter);
    end;
    if (lineStr[counter] = ' ') or (length(lineStr) = counter) then begin
      temp := copy(lineStr, oldEnd, counter - oldEnd);
      inc(paramCounter);
      Params[paramCounter] := temp;
      oldEnd := counter - 1;
    end;
  until counter = length(lineStr);
Das Array geht von 0 bis 10 und die Ausgabe ist:
Code:
0: findwindow
1: "test"
2: " "
3:
4: "test test"
5:
6: " $1
7:
8: " $
9:
10:
Habt ihr eine Idee, wie man das ganze noch verbessern (lauffähig bekommen) könnte?

Chris

Christian Seehase 27. Mai 2003 21:12

Moin Chris,

hier mal ein erweiterbares Muster.
Es wäre u.U. sinnvoller mit einer speziellen Liste für das Ergebnis zu arbeiten (Einträge als Record mit den Feldern Token für die Kennung was es denn nun ist, und Attribute für den Wert).
Der Einfachheit halber mal als StringListe, und die Typen als Konstanten, statt Aufzählungstyp.

Das Muster entspricht im Wesentlichen dem, was ich Dir schon mal vorgeschlagen hatte.

Die Leerzeichen entfallen, da Du sie nach der Aufspaltung der Zeile eh' nicht mehr brauchst.

Delphi-Quellcode:
procedure SplitCommandLine(const AsCommandLine : string;const AslResult : TStrings);

const
  _iIsKeyword    = 1;
  _iIsVariable   = 2;
  _iIsStringConst = 3;

var
  iIndex : integer;
  iCount : integer;

begin
  AslResult.Clear;
  iIndex := 1;
  while iIndex <= length(AsCommandLine) do
  begin
    case AsCommandLine[iIndex] of
      'a'..'z','A'..'Z' : begin // Keyword filtern
        iCount := 1;
        while (iIndex < length(AsCommandLine)) and (AsCommandLine[iIndex+iCount] in ['a'..'z','A'..'Z']) do inc(iCount);
        AslResult.AddObject(copy(AsCommandLine,iIndex,iCount),Pointer(_iIsKeyword));
        inc(iIndex,iCount);
      end;
      '"' : begin // StringKonstante
        iCount := 1;
        while (iIndex < length(AsCommandLine)) and (AsCommandLine[iIndex+iCount] <> '"') do inc(iCount);
        AslResult.AddObject(copy(AsCommandLine,iIndex+1,iCount-1),Pointer(_iIsStringConst));
        inc(iIndex,iCount+1);
      end;
      '$' : begin // Variable
        iCount := 1;
        while (iIndex < length(AsCommandLine)) and (AsCommandLine[iIndex+iCount] in ['0'..'9']) do inc(iCount);
        AslResult.AddObject(copy(AsCommandLine,iIndex,iCount),Pointer(_iIsVariable));
        inc(iIndex,iCount);
      end;
      else begin
        inc(iIndex);
      end;
    end;
  end;
end;

procedure TfrmMAIN.Button1Click(Sender: TObject);

begin
  SplitCommandLine('findwindow "test" "test test" $1',Memo1.Lines);
end;

CalganX 28. Mai 2003 11:31

Öhm... ok... eigentlich wollte ich nur einen Vorschlag für meine Funktion, allerdings ist da deine doch wesentlich komfortabler.
Danke! Werde das ganze jetzt mal ausprobieren...

Chris

Christian Seehase 28. Mai 2003 14:29

Moin Chris,

sorry, aber da ich mich seit geraumer Zeit, und auch gerade jetzt, intensiv mit der Thematik beschäftigt habe, war's für mich einfacher das neu zu machen, als mich in Deine Funktion einzulesen ;-)

CalganX 28. Mai 2003 14:43

Zitat:

Zitat von Christian Seehase
sorry, aber da ich mich seit geraumer Zeit, und auch gerade jetzt, intensiv mit der Thematik beschäftigt habe, war's für mich einfacher das neu zu machen, als mich in Deine Funktion einzulesen ;-)

Ich sag ja nicht, dass das schlecht war!!! Ich finde es sogar besser!

Chris

CalganX 28. Mai 2003 19:57

So... Funktioniert jetzt alles wunderbar, aber wie mache ich das mit "string string string".$4???

[EDIT]
Muss nicht unbedingt "string".$4 sein! Kann z.B. auch "string$4" sein...
[/EDIT]

Chris

Christian Seehase 28. Mai 2003 21:33

Moin Chris,

wenn Du mich mal aufklären könntest, wie Du Dir, so ganz im allgemeinen, die Syntax gedacht hattest, könnte ich Dir vielleicht darauf antworten.

CalganX 28. Mai 2003 22:03

Hm... also gut ich will es versuchen.
Es gibt verschiedene Funktionen (z.B. findwindow) diese Funktionen haben verschiedene Parameter (z.B. Strings, Variablen [$x, ...], Konstanten).
Nun ist es halt auch so, dass man als Parameter auch zusammengesetzte Sachen benutzen kann. Also z.B. "Ein String mit einer Variable: ".$x

Das ganze ist eine einfache Skriptsprache, also soll nix wirklich Großes werden (also Abfragen, Schleifen, ...)!

Hoffe, dass es das war, was du wolltest... ;)

Chris

Christian Seehase 28. Mai 2003 22:26

Moin Chris,

das mit dem Zusammensetzen hatten wir doch schon mal weiter oben im Thread?


Wenn es "string".$4 und "string$4" geben soll (was soll eigentlich der Punkt? Ersatz für +?), müssest Du noch eine Möglichkeit finden, eine Variable in einem String als solche zu erkennen. Das liesse sich dann z.B. so machen wie in C, mit Hilfe eines Escape Characters. In C dient dazu der \. Soll dieser dargestellt werden muss man ihn doppelt schreiben.
(siehe z.B. auch Dateipfade in REG Dateien, da hat MS es auch so übernommen (warum eigentlich?)).

Statt beide Möglichkeiten ins Auge zu fassen, halte ich es für sinnvoll, wenn Du Dich für eine entscheidest. Leichter umsetzen lassen dürfte sich die erste. Ich empfinde sie auch als übersichtlicher.

Um so eine Zeile zu ermöglichen, musst Du Dir Regeln einfallen lassen, was alles auf was folgen darf, und was für eine Bedeutung das dann hat. Deshalb halte ich es für empfehlenswert beim Aufspalten einer Kommandozeile den einzelnen Teilen eine Kennung mitzugeben, soll heissen:
Beim Aufspalten werden die Bestandteile in, sogenannten, Token gespeichert. Dazu kannst Du einfach einen Record erstellen, der zwei Felder enthält. Eines für die Kennung um was es sich handelt (Schlüsselwort, Variable, Stringkonstante, Operator ...), und eines das das zugehörige Attribut enthält (findwindow, $1...) wobei natürlich bei festliegenden Attributwerten (z.B. Schlüsselworten) das Eintragen des Attributes entfallen kann.
Da Du Variablen verwenden willst wirst Du auch noch eine Variablenliste brauchen, in der Du dann die aktuellen Wert merken kannst.

Was nun die Regeln angeht:
Du musst prüfen, was auf (z.B.) FindWindow folgt, und ob es folgen darf (ggf. Fehler). Stösst Du auf eine Stringkonstante, so kann der Parameter damit komplett sein, oder aber ein . (+) folgen. Ist letzteres der Fall, so muss entweder ein Weiterer String folgen, oder eine Variable usw.

Ich hoffe, dass alles war einigermassen verständlich.

CalganX 29. Mai 2003 09:11

Verständlich!
Ich wollte sowieso nur eine Möglichkeit nutzen. Jenachdem, was einfacherer ist. Ich versuch das ganze mal weiter zuführen (deine Funktion ein wenig modifizieren :roll:).

Chris


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:39 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz