Parser

Aus SibiWiki
Zur Navigation springen Zur Suche springen



Ein Parser zu einer Grammatik ist ein Algorithmus, mit dem sich überprüfen lässt, ob ein Wort zu der von der Grammatik erzeugten Sprache gehört, d.h. ob es syntaktisch korrekt ist. Der Algorithmus lässt sich dann in Java implementieren.

Man könnte auch sagen: Ein Parser simuliert den zu der Grammatik gehörenden Automaten.

Beispiel

Es soll ein Parser für den KGB-Automaten erstellt werden.

Der KGB-Automat erkennt Wörter, die nur aus den Ziffern 0,...,9 bestehen und die irgendwo die Zahlenkette "007" enhalten.

Implementierung mit switch-case

Die Implementierung mit switch-case bildet den Automaten ab.

Sie ist jedoch relativ fehleranfällig in der Programmierung.

Einfacher ist die Programmierung mit einer HashMap - siehe unten.

import gui.GUI;

public class KGBAutomat {

  private char[] alphabet = {'0', '1', '2','3','4','5','6','7','8','9'};

  public boolean imAlphabet(char pZeichen){
      for(char zeichen: alphabet){
          if(zeichen == pZeichen){
              return true;
          }
      }
      return false;
  }

  public boolean parse(String pWort){
      char zustand = 'S';
      for(char zeichen: pWort.toCharArray()){
          if(!imAlphabet(zeichen)){
              return false;
          }
          switch(zustand){
              case 'S': switch(zeichen){
                          case '0': zustand = 'A'; continue;
                          default: zustand = 'S'; continue;
                      }
            
              case 'A': switch(zeichen){
                          case '0': zustand = 'B'; continue;
                          default: zustand = 'S'; continue;
                      }
                    
              case 'B': switch(zeichen){
                          case '0': zustand = 'B'; continue;
                          case '7': zustand = 'C'; continue;
                          default: zustand = 'S'; continue;
              }
              case 'C': switch(zeichen){
                          default: zustand = 'C'; continue;
              }
          }
      }
      return (zustand == 'C');
  }

  public static void main(String[] args) {
      new GUI(new KGBAutomat());
  }
}

Implementierung mit einer HashMap

Bei dieser Implementierung werden alle Übergänge in eine Hashmap eingetragen! Dann kann man aus der HashMap direkt den neuen Zustand auslesen, der sich aus einem Zustand und einem Zeichen ergibt.

Einfache Implementierung

Bei der einfachen Implementierung wird jeder Übergang einzeln in die HashMap eingetragen.

Das kann ggf. langatmig sein, ist aber logisch sehr einfach.

In der Klausur darf man sich mit "..." Schreibarbeit sparen!

Kurze Implementierung

Die kurze Implementierung legt die Default-Übergänge mithilfe einer for-Schleife fest und überschreibt dann die Ausnahmen.


import java.util.HashMap;

import gui.GUI;

 
public class KGBAutomat {
   // parametrisierte HashMap, in der die Uebergange gespeichert werden
   private HashMap<String, Character> u;
   
   public KGBAutomat(){
       u = new HashMap<String, Character>();

       // die Default-Uebergaenge fuer alle 4 Zustaende
       for(int i=0; i<=9; i++){
           u.put("S"+i, 'S');
           u.put("A"+i, 'S');
           u.put("B"+i, 'S');
           u.put("C"+i, 'C');
       }
       
       // jetzt kommen die Ausnahmen!
       // die ueberschreiben die bisherigen Default-Uebergaenge
       u.put("S0", 'A');
       u.put("A0", 'B');
       u.put("B0", 'B');
       u.put("B7", 'C');
   }
   
   public boolean parse(String pWort){
       System.out.println(pWort);
       // den Startzustand festlegen
       char zustand = 'S';
       // die Zeichen von pWort mit einer Schleife durchlaufen
       for(char zeichen: pWort.toCharArray()){
           System.out.println(zustand+": "+zeichen);
           // den Schluessel fuer die HashMap bauen
           String key = ""+zustand+zeichen;
           // den neuen Zustand aus der HashMap auslesen
           // man nutzt die Wrapper-Klasse Character,
           // damit man abfragen kann, ob neuerZustand null ist.
           Character neuerZustand = u.get(key);
           if(neuerZustand == null){
               return false;
           }
           zustand = neuerZustand;
       }    // end for
      
       // es wird zurueckgegeben, ob der zustand == 'C' ist.
       // d.h. true oder false
       return (zustand == 'C');
   }

   public static void main(String[] args) {
       new GUI(new KGBAutomat());
   }
   
}