Hallo,
mein Problem ist schwer zu erklären, aber ich versuch's mal:
Ich bin dabei, einen Parser zu entwickeln, der eine formale Grammatik analysiert und in PHP abbildet. Formale Grammatiken bilden quasi einen Baum ab. Zum Verständnis folgendes Beispiel, wie meine Grammatik (die stets als String vorliegt) aussieht:
[startplatzhalter] -> [platzhalter1], [platzhalter2]
[platzhalter1] -> [platzhalter3]
[platzhalter2] -> [platzhalter5], [platzhalter6], [platzhalter7]
usw.
Der String wird nun Zeilenweise zerlegt und das entstandene Array wird rekursiv analysiert.
Das funktioniert auch alles. Nun will ich noch ein paar Fehlererkennungsmaßnahmen programmieren, um bei fehlerhaften Grammatiken eine Meldung ausgeben zu können. Dazu hatte ich die 3. Zeile manipuliert, dass sie nicht mit '[' beginnt.
Rein theoretisch müsste folgendes passieren:
Bei der Analyse von Zeile 3 müsste das Skript merken, dass sie nicht mit '[' beginnt und eine Fehlermeldung ausgeben bzw. eine Fehlermeldung dem Fehlerarray hinzufügen. Das passiert auch, aber: Die Meldung kommt ganze 3x im Array vor. Das verstehe ich aber nicht.
Eigentlich müsste doch, so bald der Fehler auftritt, die Funktion per return verlassen werden und bei jedem Funktionsneu-Eintritt erkannt werden, dass das Fehler-Array nicht mehr leer ist, was dann zum sorfortigen Verlassen der Funktion führt. Testausgaben zeigen aber, dass die Funktion trotzdem mehrere Male (eben 3x) komplett durchlaufen wird, weil das Fehler-Array am Funktionsanfang stets leer ist. Erst nach dem Dritten Durchlauf der Funktion scheinen 3 (gleiche) Fehlermeldungen angekomen zu sein.
Hat jemand eine Idee, was das sein kann? Kann es sein, dass die Rekursivität das Schreiben in die Klassenvariable (Fehler-Array) behindert/verzögert?
Mein Quelltext ist sehr umfangreich. Ich habe ihn nur schematisch aufgeführt (also massiv gekürzt). Er ist also nicht alleine Lauffähig.
PHP-Code:
<?php
class konf_control{
var $msg_err = array(); // fatalere Fehlermeldungen
function vorlageEinlesen(){
$this->parsen(1, $platzhalter); // Parser mit Ebene 1; Start-Platzhalter aufrufen
}
function parsen($ebene=1,$platzhalter=''){
if (count($this->msg_err)) return; // trat irgendwo ein Fehler auf, hier nicht erst weiter machen
// Sub-Platzhalter finden:
foreach ($this->rules as $zeile){
$zeichen1 = substr($zeile,0,1); // 1. Zeichen
if ($zeichen1=='['){ // es wurde irgendEIN Platzhalter gefunden
.....
// nachdem alle Subplatzhalter der Zeile gefunden
foreach($found_alle as $einer){
$this->parsen($ebene+1, $pHalter); // Funktion erneut aufrufen
}
} // Ende "wenn 1. Zeichen ein $ oder ["
else{
$this->msg_err[] = 'Zeile '.$zeilennr.' der Regelbeschreibung beginnt nicht mit [ oder $';
return;
}
} // Ende foreach (alle Zeilen durchlaufen)
} // Ende Funktion
} // Klassenende
?>