Compilerbauhome Compilerbau: Rekursiver Abstieg Prof. Dr. Uwe Schmidt FH Wedel

Rekursiver Abstieg

weiter

weiter

Top-Down Parser

Rekursiver Abstieg
weiter
Idee
.1
Zu jedem Nichtterminal-Symbol wird eine Prozedur für die Analyse von Zeichenreichen entwickelt, die aus dem NT-Symbol abgeleitet werden können.
weiter
.2
In jeder Prozedur wird durch Testen des nächsten Eingabe-Symbols eine Regel (eine rechte Seite einer Produktion) für das NT-Symbol ausgewählt.
weiter
Invariante
für alle Recursive Descent Parser
 
für alle X ∈ N gilt:
 
{input = w}
X();    // die zu X gehörige Prozedur
{input = w2, w = w1 ⋅ w2, X ⊢* w1}
weiter
Rahmen
class Parser {
    // die Terminalsymbole
    // als int kodiert
 
    static final int
        IFSY  = 1,
        ID    = 2,
        ...
        EOFSY = n;
 
    int sy;
 
    // der Scanner
    int nextSymbol () {
        return ...;
    }
 
    void inSymbol() {
        sy = nextSymbol();
    }
 
    void checkSymbol(int sy) {
        if ( this.sy == sy ) {
            inSymbol();
        } else {
            error(...);
        }
    }
    void error(...) {
        // ...
    }
 
    void parse() {
        inSymbol();
        S1();
    }
 
    void S1() {
        S();
        checkSymbol(EOFSY);
    }
 
    // ... Methoden fuer die NT-Symbole
 
    }
weiter
Beispiel
Grammatik für den Anweisungsteil einer einfachen Pascal-ähnlichen Sprache.
Die Terminalsymbole und Nichtterminalsymbole können aus den Regeln extrahiert werden.
Stmt sei das Startsymbol.
 
Stmt    ::= if Expr then Stmt else Stmt fi
Stmt    ::= while Expr do Stmt done
Stmt    ::= begin SL end
Stmt    ::= id := Expr
 
SL      ::= Stmt SL1
SL1     ::=
SL1     ::= ; SL
 
Expr    ::= id
Expr    ::= num
weiter
Parser
Die aus den Regeln erzeugten Routinen für den Recursive Descent Parser
 
void Stmt() {
  switch (sy) {
  case IFSY :
        checkSymbol(IFSY);
        Expr();
        checkSymbol(THENSY);
        Stmt();
        checkSymbol(ELSESY);
        Stmt();
        checkSymbol(FISY);
        break;
 
  case WHILESY :
        checkSymbol(WHILESY);
        Expr();
        checkSymbol(DOSY);
        Stmt();
        checkSymbol(DONESY);
        break;
 
  case BEGINSY :
        checkSymbol(BEGINSY);
        SL();
        checkSymbol(ENDSY);
        break;
 
  case ID :
        checkSymbol(ID);
        checkSymbol(ASSIGNSY);
        Expr();
        break;
 
  default :
        error("if, while, begin or id expected");
  }
}
 
void SL() {             // nur eine Regel für SL
        Stmt();         // keine Auswahl möglich
        SL1();
}
 
void SL1() {
  switch (sy) {
  case SEMICOLON :
        checkSymbol(SEMICOLON);
        SL();
        break;
 
  default : // epsilon Produktion
        break;
  }
}
weiter
Strategie
  1. über das nächste Eingabezeichen die passende Regel auswählen
  2. Terminalsymbole mit checkSymbol oder inSymbol überlesen
  3. für die NT-Symbole die zugehörige Prozedur aufrufen
weiter
merke
Fehlererkennung und Fehlerbehandlung noch ungenau und nur rudimentär realisiert
weiter
merke
Nur eine Regel für ein NT-Symbol: keine Auswahl-Problematik.
weiter
merke
Problem: Die Auswahl der Regeln nur durch Testen des einen nächsten Zeichens.
weiter
merke
Problem: Mit welchen Symbolen kann eine rechte Seite beginnen?
weiter
merke
Problem: Wie behandelt man Epsilon-Produktionen?
weiter
2. Beispiel
deterministische Grammatik für arithmetische Ausdrücke mit den vier Grundrechenarten und mit Klammerschachtelung.
 
E ::= E + T
E ::= E - T
E ::= T
 
T ::= T * F
T ::= T / F
T ::= F
 
F ::= id
F ::= num
F ::= ( E )
weiter
Routine für E
void E() {
  switch (sy) {
  case ??? :
        E();checkSymbol(PLUSSY);T();
        break;
  case ??? :
        E();checkSymbol(MINUSSY);T();
        break;
  case ??? :
        T();
        break;
  default :
        error("??? expected");
  }
}
merke
Wie werden die case-Marken berechnet?
merke
Ist die Berechnung in diesem Fall überhaupt möglich?
weiter
Formalisierung
FIRST- und FOLLOW-Mengen für die Berechnung der Regelauswahl und zum Testen, ob der rekursive Abstieg überhaupt möglich ist.
weiter

Letzte Änderung: 05.12.2016
© Prof. Dr. Uwe Schmidt
Prof. Dr. Uwe Schmidt FH Wedel