Schreiben eines saubereren und modulareren Kommando-Parsers

8

Ich schreibe einen Debugger für einen Z80-Emulator, den wir in einem Schulprojekt mit Java schreiben. Der Debugger liest einen Befehl vom Benutzer, führt ihn aus, liest einen anderen Befehl usw.

Befehle können entweder argumentlos sein, optionale Argumente haben oder eine unbegrenzte Anzahl von Argumenten enthalten. Argumente sind meistens Ganzzahlen, aber gelegentlich sind es Strings.

Momentan verwenden wir die Scanner-Klasse zum Lesen und Analysieren von Eingaben. Die Lesemethode sieht irgendwie so aus (ich schreibe das von ganz oben ab, ohne auf Syntax oder Korrektheit zu achten). >

Dies war eine Klugheit, die zu Beginn des Projekts geschrieben wurde und die schnell außer Kontrolle geriet, als wir dem Debugger mehr und mehr Befehle hinzufügten.

Die Hauptprobleme, die ich mit diesem Code habe, sind die große Menge an Wiederholungen, die hohe Stufe der Wenn-und-Nichts-Verschachtelung und die allgegenwärtige Hässlichkeit.

Ich hätte gerne Vorschläge, wie man diesen Code schöner und modularer macht und welche Art von Patterns für diese Art von Programm geeignet sind.

Ich möchte auch allgemeinere Vorschläge zum Code-Stil.

    
arvixx 04.04.2009, 18:49
quelle

2 Antworten

2

yup, es gibt einen einfacheren / besseren Weg, besonders in Java oder anderen OO-Sprachen.

Die grundlegende Erkenntnis besteht zunächst darin, dass Ihr Befehlsparser ein endlicher Automat ist: Der START-Zustand ist eine leere Zeile (oder Index am Anfang einer Zeile).

Denken wir an echo :

%Vor%
  1. Teilen Sie die Zeile in Stücke:

    "echo" "foo" "bar" "bletch quux"

  2. in einer Shell ist die Grammatik normalerweise Verb noun Substantiv. so interpretieren Sie es so. Sie können es mit einer Sequenz von Wenn-sonst tun, wenn Dinge, aber ein Hash ist besser. Sie laden den Hash mit Strings als Indizes und indizieren etwas anderes. Es könnte nur eine Zahl sein, die in einen Schalter gehen würde:

(das ist Pseudocode):

%Vor%

Noch besser, Sie können die Command- und Object Factory-Pattern anwenden. Jetzt haben Sie eine Klasse Befehl

%Vor%

Jetzt wird Ihr Code

%Vor%

Sehen Sie, wie das funktioniert? Sie suchen das Objekt im Hash nach. Sie rufen die Methode factory auf, um eine neue Kopie zu erhalten. Anschließend rufen Sie die Verarbeitung für diesen Befehl mit der Methode doThis auf.

Aktualisieren

Dies kann ein bisschen zu allgemein sein, da es das Factory-Muster verwendet. Warum eine Fabrikmethode? Hauptsächlich würden Sie das verwenden, so dass jedes Mal, wenn Sie einen Befehl ausführen, das "Verb" -Objekt (wie die Instanz von Echo ) seinen eigenen internen Status haben kann. Wenn Sie den Status für eine lange Zeit nicht benötigen, können Sie dies zu

vereinfachen %Vor%

Jetzt wird es einfach aufgerufen und verwendet das Echo -Objekt, das Sie erstellt haben, als Sie es mit cmds.add("echo", new Echo()); eingerichtet haben.

    
Charlie Martin 04.04.2009 19:17
quelle
1

Haben Sie sich die Disposition mit einer Map angesehen? Ein hashmap wäre ziemlich einfach dort einzubauen. Machen Sie einfach den Schlüssel mit dem Befehl und erstellen Sie eine Schnittstelle oder abstrakte Klasse, die ein Befehl wie folgt ist:

%Vor%

Oder noch besser, Sie könnten die Argumente im Voraus zerhacken:

%Vor%

Dann würden Sie HashMap & lt; String, Command & gt;.

verwenden     
fuzzy-waffle 04.04.2009 19:12
quelle