SlideShare ist ein Scribd-Unternehmen logo
1 von 75
Downloaden Sie, um offline zu lesen
Von Automaten zu Programmen
Manuelle und automatische Entwicklung von Parsern




                           Tim Furche
        Compilerbau, Wintersemester 2008/09, Prof. F. Bry



                                                            1
Formale Sprachen:



   Beispiele aus der Praxis




                              2
Formale Sprachen:



   Nicht nur in Compilern!




                             3
Browser




          4
5
URIs
                     Google
                     Anfrage

                      HTML


                  JavaScript


                     CSS



Browser: Formale Sprachen
                               6
Spreadsheets: Excel/
 Numbers/OpenCalc




                       7
8
Formeln


Format
Felder



Macros




     9
A
 Endliche
Automaten
Parser für Reguläre Sprachen
              z.B.: URIs, Datumsangaben, Gleitpunktzahlen



                                                        10
Beispiel:
Gleitpunktzahlen




                   11
-666.797E-14


  parsen, normalisieren



                          12
$

java
‐jar
FPParser.jar
‐666.797E‐14
‐‐step
(Initial,
‐666.797E‐14)

        |‐
(WholeNrDigit,
666.797E‐14)

        |‐
(WholeNrDigit_or_Fraction_or_Exponent,
66.797E‐14)

        |‐
(WholeNrDigit_or_Fraction_or_Exponent,
6.797E‐14)

        |‐
(WholeNrDigit_or_Fraction_or_Exponent,
.797E‐14)

        |‐
(FractionDigit,
797E‐14)

        |‐
(FractionDigit_or_Exponent,
97E‐14)

        |‐
(FractionDigit_or_Exponent,
7E‐14)

        |‐
(FractionDigit_or_Exponent,
E‐14)

        |‐
(Exponent,
‐14)

        |‐
(ExponentDigit,
14)

        |‐
(ExponentDigit_or_End,
4)

        |‐
(ExponentDigit_or_End,
)

Success:
‐6.66797E‐12

‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐

                                                  Gleitpunktzahlen
                                                 Parsen und Normalisieren mit Endlichem Automaten



                                                                                                13
14
Wie?


z.B. in Java



               15
16
Bibliothek:
Double.parseDouble()




                       17
Bibliothek:
Double.parseDouble()


   Regulärer Ausdruck über Bibliothek:
   java.util.regex.Pattern&Matcher




                                         17
Bibliothek:
Double.parseDouble()


   Regulärer Ausdruck über Bibliothek:
   java.util.regex.Pattern&Matcher


              Endliche Automaten Bibliothek:
              dk.brics.automaton




                                               17
Bibliothek:
Double.parseDouble()


   Regulärer Ausdruck über Bibliothek:
   java.util.regex.Pattern&Matcher


              Endliche Automaten Bibliothek:
              dk.brics.automaton



                        Manuelle Implementierung

                                               17
Bibliothek:
Double.parseDouble()


   Regulärer Ausdruck über Bibliothek:
   java.util.regex.Pattern&Matcher


              Endliche Automaten Bibliothek:
              dk.brics.automaton



                        Manuelle Implementierung

                                               17
41    }

                                                              ‘0’–‘9’
                 ‘ -’

     start   I                  F           ‘0’–‘9’                R


                           ‘0’–‘9’


                        Ganzzahlen in Java
                    Endlicher Automat für den Ganzzahlparser in Long.parseLong



                                                                             18
1   public static long parseLong(String s, int radix) throws NumberFormatException
     {
 3       if (s == null) throw new NumberFormatException(quot;nullquot;);
         [...]
 5       int max = s.length();
         [...]
 7       // State 1: Treat the sign
         if (s.charAt(0) == ’-’) {
 9           negative = true;
             limit = Long.MIN_VALUE;
11           i++;
         } else
13           limit = -Long.MAX_VALUE;


15       // State 2: Treat first digit
         if (i < max) {
17           digit = Character.digit(s.charAt(i++),radix);
             if (digit < 0) // Not a digit
19            throw NumberFormatException.forInputString(s);
             else
21            result = -digit;
         }
23
         // State 3: Treat all other digits
                                                                                      19
25       while (i < max) {
             digit = Character.digit(s.charAt(i++),radix);
21             result = -digit;
          }
23
          // State 3: Treat all other digits
25        while (i < max) {
              digit = Character.digit(s.charAt(i++),radix);
27            if (digit < 0) // Not a digit
               throw NumberFormatException.forInputString(s);
29            result *= radix;
              // Check if out-of-bounds [...]
31            result -= digit;
          }
33        if (negative) {
              if (i > 1)
35               return result;
              else  /* Only got quot;-quot; */
37               throw NumberFormatException.forInputString(s);
          } else
39            return -result;


41    }

                                                   ‘0’–‘9’
                        ‘ -’

     start         I             F       ‘0’–‘9’     R

                                                                  20
                               ‘0’–‘9’
21
en, die unser Parser erkennen soll:
        2.1 Regulärer Ausdruck für Gleitpunktzahlen

      (‘Für -’)? digit+ (‘.’ digit+)? ((‘e’|‘E’) digit+)? Aus
        +’|‘ unser Beispiel beginnen wir mit einem regulären
        Gleitpunktzahlen, die unser Parser erkennen soll:

0’ | ‘1’ | ‘2’ | ‘3’ | ‘4’ | ‘5(‘+’|‘-’ | ‘7’ | ‘8’.|’ ‘9’
                               ’ | ‘6 ’)? digit+ (‘ digit+)? ((‘e’|‘E’) digit
digit digit*
        digit         := ‘0’ | ‘1’ | ‘2’ | ‘3’ | ‘4’ | ‘5’ | ‘6’ | ‘7’ | ‘8’ | ‘9’
        digit+        := digit digit*
tion ist fast wie in den Übungen behandelt, allerdin
omma-Anteil wegfallenfast wie in den der Exponent). a
         Die Spezifikation ist kann (wie Übungen behandelt,
        dass der Nachkomma-Anteil wegfallen kann (wie der Expon
                            Gleitpunktzahlen in Java
utomat für Gleitpunktzahlen
     2.2 Endlicher Automat für Gleitpunktzahlen
                                                           Spezifikation: Regulärer Ausdruck



                                                                                          22
ache können wir durch folgenden Automaten besch
      Die gleiche Sprache können wir durch folgenden Automate
‘+’, ‘-’

start   S s,d                 Sd


                                ‘0’–‘9’      ‘.’                       ‘0’–‘9’
                ‘0’–‘9’
                            S d ,p,e      ‘0’–‘9’    Fd      ‘0’–‘9’    F d ,e




                                          ‘e’, ‘E’                     ‘e’, ‘E’
                                                     E s,d
                                                                       ‘0’–‘9’

                                                       ‘+’, ‘-’


                                                     Ed      ‘0’–‘9’    E d ,#


                                                                       ‘0’–‘9’    23

Der Automat verwendet die folgenden Zustände, benannt nach d
gibt. Dabei nennen wir für eine Gleitpunktzahl s. f · 10 : s den significand (oder
Vorkomma-Anteil der Mantisse), f die fraction (oder Nachkomma-Anteil der Man-
tisse), und e den exponent.

     Zustand Teil der Zahl          Nachfolgerzeichen                         Beschreibung

     S s,d        significand   Ziffer (d ) oder Vorzeichen (s )   Anfangszustand, erkennt optionales Vor-
                                                                  zeichen
     Sd           –”–                       Ziffer                stellt sicher, dass zumindest eine Ziffer im
                                                                  significand vorkommt
     S d , f ,e   –”–             Ziffer, Punkt (p ) oder e       erkennt beliebige Folgen von Ziffern, fährt
                                                                  mit Erkennung von fraction oder expo-
                                                                  nent fort, Endzustand

     Fd           fraction                  Ziffer                stellt sicher, dass zumindest eine Ziffer in
                                                                  fraction vorkommt
     F d ,e       –”–                    Ziffer or e              erkennt beliebige Folgen von Ziffern, fährt
                                                                  mit Erkennung von exponent fort, Endzu-
                                                                  stand

     E s,d        exponent        Ziffer oder Vorzeichen          Ziffer oder Vorzeichen als Beginn des ex-
                                                                  ponent
     Ed           –”–                       digit                 stellt sicher, dass zumindest eine Ziffer in
                                                                  exponent vorkommt
     Ed           –”–                       digit                 erkennt beliebige Folgen von Ziffern, End-
                                                                  zustand

                                                                                                                 24
Implementierung Endlicher Automaten
                                                   Ansätze …
  Implicit state: wie Long.parseLong(); Zustand implizit
   Bereich im Programm identifiziert den aktuellen Zustand (PC)
   für einfach, im wesentlichen sequentielle Automaten geeignet
  Loop-and-switch:
   Schleife über Eingabe + goto/switch je nach akt. Zustand und Symbol
   effizient nur wenn Sprünge berechnet werden können
   typisch für komplexere Automaten mit oft wiederkehrenden Zuständen

  Loop-and-lookup: Schleife + Nachschlagen in Tabellenrepr. von δ
   Zeilen: Zustände, Spalten: Eingabesymbole, Zelleninhalt: Folgezustand
   Zeit-effizient auf Kosten von Speicher, nur bei kleinem Eingabealphabet
   z.B. reguläre Ausdrücke über Basispaarsequenzen (nur A, T, G, C).
                                                                            25
Implementierung Endlicher Automaten
           Umgebung für FP-Parser …
  FPParser: abstrakte Oberklasse für alle Floating-Point-Parser
   Attribute & Methoden zur Verwaltung & Berechnung der FP-Zahl
   FPPaser.FPNumberPart: hält ganzzahligen Anteil einer FP-Zahl
    significand (Vorkomma-Anteil), fraction (Nachkomma-Antail), exponent
   #parse(char): Transition & Berechnung des Automaten
    bei Eingabe eines einzelnen Zeichens
   #parse(String): Schleife über die Eingabe
    für jedes Zeichen wird #parse(char) aufgerufen




                                                                          26
Implementierung Endlicher Automaten
           Umgebung für FP-Parser …
  FPParser: abstrakte Oberklasse für alle Floating-Point-Parser
   Attribute & Methoden zur Verwaltung & Berechnung der FP-Zahl
   FPPaser.FPNumberPart: hält ganzzahligen Anteil einer FP-Zahl
    significand (Vorkomma-Anteil), fraction (Nachkomma-Antail), exponent
   #parse(char): Transition & Berechnung des Automaten
    bei Eingabe eines einzelnen Zeichens
   #parse(String): Schleife über die Eingabe
    für jedes Zeichen wird #parse(char) aufgerufen



                                                                     FPParser
                                                                                26
einer Ziffer bleiben wir im gleichen Zustand und fügen die Ziffer zur aktu-
         ellen Repräsentation des significand hinzu. Bei einem Punkt gehen wir in
         den Zustand F d , also erwarten die erste Ziffer der fraction (würden wir hier
          Implementierung Endlicher Automaten
         in F d ,e übergehen, wären auch Zahlen der Form 12.E10 erlaubt). Bei einem
         e oder E gehen wir in Zustand E s,d (STATE_Exponent). In den beiden letzten
                                        Loop-and-Switch …
         Fällen dienen die Zeichen nur als Trennzeichen und werden nicht zur aktu-
         ellen Repräsentation hinzugefügt.
     1               case STATE_SignifDigit_Fraction_Exponent:
                           if(Character.isDigit(c)) {
     3                           state = STATE_SignifDigit_Fraction_Exponent;
                                 significand.addDigit(c);
     5                     }
                           else if(c == ’.’) {
     7                           state = STATE_FractionDigit;
                           }
     9                     else if(c == ’e’ || c == ’E’) {
                                 state = STATE_Exponent;
    11                     }
                           else state = STATE_Failure;
    13                     break;


Loop-and-Lookup: realisiert in MatrixFPParser. Die Idee von loop-and-lookup Im-
      plementierungen ist, in der Schleife über die Eingabezeichen mit Hilfe ei-          27
      ner (konstanten) Lookup-Tabelle den Folgezustand (und eventuelle Berech-
einer Ziffer bleiben wir im gleichen Zustand und fügen die Ziffer zur aktu-
         ellen Repräsentation des significand hinzu. Bei einem Punkt gehen wir in
         den Zustand F d , also erwarten die erste Ziffer der fraction (würden wir hier
          Implementierung Endlicher Automaten
         in F d ,e übergehen, wären auch Zahlen der Form 12.E10 erlaubt). Bei einem
         e oder E gehen wir in Zustand E s,d (STATE_Exponent). In den beiden letzten
                                        Loop-and-Switch …
         Fällen dienen die Zeichen nur als Trennzeichen und werden nicht zur aktu-
         ellen Repräsentation hinzugefügt.
     1               case STATE_SignifDigit_Fraction_Exponent:
                           if(Character.isDigit(c)) {
     3                           state = STATE_SignifDigit_Fraction_Exponent;
                                 significand.addDigit(c);
     5                     }
                           else if(c == ’.’) {
     7                           state = STATE_FractionDigit;
                           }
     9                     else if(c == ’e’ || c == ’E’) {
                                 state = STATE_Exponent;
    11                     }
                           else state = STATE_Failure;
    13                     break;

                                                             PlainFPParser
Loop-and-Lookup: realisiert in MatrixFPParser. Die Idee von loop-and-lookup Im-
      plementierungen ist, in der Schleife über die Eingabezeichen mit Hilfe ei-          27
      ner (konstanten) Lookup-Tabelle den Folgezustand (und eventuelle Berech-
0

             Implementierung Endlicher Automaten
                 SIGNIF_DIGIT_FRACTION_EXPONENT {
         2
                                        Loop-and-Switch …
                      State transition(char c, FPNumberPart nr){
                                 if(Character.isDigit(c)) {
         4                             nr.addDigit(c);
                                       return SIGNIF_DIGIT_FRACTION_EXPONENT;
         6                       }
                                 else if(c == ’.’) {
         8                             return FRACTION_DIGIT;
                                 }
        10                       else if(c == ’e’ || c == ’E’) {
                                       return EXPONENT;
        12                       }
                                 else return FAILURE;
        14            }
                      FPNumberPart select(FPNumberPart s, FPNumberPart f, FPNumberPart←
                           e){ return s; }
        16            boolean isFinal(){ return true; }
                      boolean isFailure(){ return false; }
        18       },


                                                                                          28
    3.1 Tests
0

             Implementierung Endlicher Automaten
                 SIGNIF_DIGIT_FRACTION_EXPONENT {
         2
                                        Loop-and-Switch …
                      State transition(char c, FPNumberPart nr){
                                 if(Character.isDigit(c)) {
         4                             nr.addDigit(c);
                                       return SIGNIF_DIGIT_FRACTION_EXPONENT;
         6                       }
                                 else if(c == ’.’) {
         8                             return FRACTION_DIGIT;
                                 }
        10                       else if(c == ’e’ || c == ’E’) {
                                       return EXPONENT;
        12                       }
                                 else return FAILURE;
        14            }
                      FPNumberPart select(FPNumberPart s, FPNumberPart f, FPNumberPart←
                           e){ return s; }
        16            boolean isFinal(){ return true; }
                      boolean isFailure(){ return false; }
        18       },                                             EnumFPParser
                                                                                          28
    3.1 Tests
nungsschritte) zu spezifizieren. In der Lookup-Tabelle sind den Zuständen
     Zeilen, den Eingabezeichen Spalten zugeordnet.

      Implementierung Endlicher Automaten
     Die Lookup-Tabelle findet sich in MatrixFPParser#stateMatrix und ist eine
     ziemlich direkte Umsetzung der δ Übergangsfunktion des Automaten. Für

                                 Loop-and-Lookup …
     den gleichen Zustand wie oben ergibt sich z.B. folgender Eintrag in der Ma-
     trix:
 1                    // STATE_SignifDigit_Fraction_Exponent
                      { // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Digit)
 3                          new DigitEffect(STATE_SignifDigit_Fraction_Exponent,←
                                 significand),
                            // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Sign)
 5                          new Effect(STATE_Failure, significand),
                            // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Expn)
 7                          new Effect(STATE_Exponent, significand),
                            // (STATE_Initial, SCLASS_Period)
 9                          new Effect(STATE_FractionDigit, significand),
                            // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Rest)
11                          new Effect(STATE_Failure, significand)
                      },


     In jeder Zelle der Lookup-Tabelle findet sich ein Effect Objekt, dass
     den nächsten Zustand und die auszuführenden Berechnungsschritte
     enthält. Um die Berechnungsschritte zu paramerterisieren verwendet 29
     MatrixFPParser Funktionsobjekte (wo Sprachen wie C++ Funktionspointer
nungsschritte) zu spezifizieren. In der Lookup-Tabelle sind den Zuständen
     Zeilen, den Eingabezeichen Spalten zugeordnet.

      Implementierung Endlicher Automaten
     Die Lookup-Tabelle findet sich in MatrixFPParser#stateMatrix und ist eine
     ziemlich direkte Umsetzung der δ Übergangsfunktion des Automaten. Für

                                 Loop-and-Lookup …
     den gleichen Zustand wie oben ergibt sich z.B. folgender Eintrag in der Ma-
     trix:
 1                    // STATE_SignifDigit_Fraction_Exponent
                      { // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Digit)
 3                          new DigitEffect(STATE_SignifDigit_Fraction_Exponent,←
                                 significand),
                            // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Sign)
 5                          new Effect(STATE_Failure, significand),
                            // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Expn)
 7                          new Effect(STATE_Exponent, significand),
                            // (STATE_Initial, SCLASS_Period)
 9                          new Effect(STATE_FractionDigit, significand),
                            // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Rest)
11                          new Effect(STATE_Failure, significand)
                      },


     In jeder Zelle der Lookup-Tabelle findet sich MatrixFPParser
                                                  ein Effect Objekt, dass
     den nächsten Zustand und die auszuführenden Berechnungsschritte
     enthält. Um die Berechnungsschritte zu paramerterisieren verwendet 29
     MatrixFPParser Funktionsobjekte (wo Sprachen wie C++ Funktionspointer
Implementierung Endlicher Automaten
                                Loop-and-Lookup …
                   Ziffer        Vorzeichen   ‘e’, ‘E’    Punkt
  Initial       SignifD_F_E        SignifD    Failure    Failure

  SignifD         SignifD          Failure    Failure    Failure

SignifD_F_E     SignifD_F_E        Failure    Exponent   FractionD

 FractionD      FractionD_E        Failure    Failure    Failure

FractionD_E     FractionD_E        Failure    Exponent   Failure

  Exponent      ExponentD_End     ExponentD   Failure    Failure

 ExponentD      ExponentD_End      Failure    Failure    Failure

ExponentD_End   ExponentD_End      Failure    Failure    Failure

  Failure         Failure          Failure    Failure    Failure



                                                                     30
$

java
‐jar
FPParser.jar
33E0
‐‐step
‐‐pEnum

           (INITIAL,
33E0)

           


|‐
(SIGNIF_DIGIT_FRACTION_EXPONENT,
3E0)

           


|‐
(SIGNIF_DIGIT_FRACTION_EXPONENT,
E0)

           


|‐
(EXPONENT,
0)

           


|‐
(EXPONENT_DIGIT_END,
<epsilon>)

   Success:



33.0

   ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐





                                       Gleitpunktzahlen
                                       Parsen und Normalisieren mit Endlichem Automaten



                                                                                      31
32
B
    Keller-
  Automaten
Parser für kontextfreie Sprachen++
                 z.B. für arithmetische Ausdrücke und Erweiterungen



                                                                  33
Beispiel:
Arithmetischer Ausdruck




                          34
2 + 4 * 11 - 2 * 3 + 2


      parsen, ausrechnen



                           35
2
+
4
*
11
‐
2
*
3
+
2
$

java
‐jar
ParserGenerators.jar
‐‐pIntExpr
‐‐file
plain‐intexpr

  <no
output>
(=
no
error)

$

java
‐jar
ParserGenerators.jar
‐‐pIntExpr_Eval
‐‐file
plain‐intexpr

  Expression
in
line
1:
42


$

java
‐jar
ParserGenerators.jar
‐‐pIntExpr_AST
‐‐file
plain‐intexpr

  (+
(‐
(+
2
(*
4
11))
(*
2
3))
2)




                              Arithmetische Ausdrücke
                                                      Parsen und Ausrechnen mit Kellerautomaten



                                                                                              36
37
x
=
78
                             y
=
2
                             112
+
4
*
x
‐
2
*
y
+
z
*
2
                             5
+
3
‐
2
$

java
‐jar
ParserGenerators.jar
‐‐pIntExpr
‐‐file
var‐intexpr

  <no
output>
(=
no
error)

$

java
‐jar
ParserGenerators.jar
‐‐pIntExpr_Var
‐‐file
var‐intexpr

  line
3:24
rule
atom
failed
predicate:
{
declaredVariables.contains($ID.text)
}?

$

java
‐jar
ParserGenerators.jar
‐‐pIntExpr_Eval
‐‐file
var‐intexpr
  line
3:24
rule
atom
failed
predicate:
{undeclared
variable
z}?
  Expression
in
line
3:
420
  Expression
in
line
4:
6



                                                               + Variablen
                                                      Parsen und Ausrechnen mit Kellerautomaten



                                                                                              38
39
1   /*------------------------------------------------------------------

Arithmetik & Parsergeneratoren
 3
     * PARSER RULES
     *------------------------------------------------------------------*/


                                                     Grammatik
     prog: stat+ ;
 5
     stat: expr NEWLINE
 7      |ID ’=’ expr NEWLINE
        |NEWLINE
 9      ;


11   expr
        : multExpr ( (’+’ |’-’) multExpr )*
13      ;


15   multExpr
        : atom (’*’ atom )*
17      ;


19   atom
        : INT
21      |ID
        |’(’ expr ’)’
23      ;
                                                                             40

25   /*------------------------------------------------------------------
17      ;


19   atom
      Arithmetik & Parsergeneratoren
       : INT
        |ID
                Lexer-Regeln der Grammatik
21
        |’(’ expr ’)’
23      ;


25   /*------------------------------------------------------------------
      * LEXER RULES
27    *------------------------------------------------------------------*/

29   ID : (’a’..’z’|’A’..’Z’)+ ;
     INT : ’0’..’9’+ ;
31   NEWLINE:’r’? ’n’ ;
     WS : (’ ’|’t’)+ {skip();} ;



                  Was ist die Aufgabe eines Lexers?
     Beispiel: -666.797E-14

     Zum Ausprobieren der Parser einfach folgendem Rezept folgen:
                                                                              41
         • FPParser.jar herunterladen und mit
direkte Ausgaben,
                                                  Fehler




            Lexer                             Parser
Character                      Token                                Abstract
  Strom                        Strom                               Syntax Tree
              (auch Scanner,
                  Tokenizer)




       Struktur eines ANTLR-Parser
                                       Lexer, Parser, AST, Token vs. Character-Strom



                                                                                   42
w i d t h        =        2 0 0 ;     n     Characters

   ID            =         INT   ;              Tokens
            WS       WS              WS




            Von Characters zu Tokens
                                           Aufgabe des Lexers



                                                            43
void multExpr() {
  	try {
  		    atom();
  		    while( <<next input symbol is '*' >> ) {
  		    	    match('*');
  		    	    atom();
  		    }
  	}
  	[... error handling]
}

void atom() {
  	try {
         int alt=3;
         switch (<< next input symbol >>) {
            case INT: alt = 1; break;
            case ID: alt = 2; break;
            case '(': alt = 3; break;
            default: [error]
         }
         switch(alt){
         case 1: match(INT); break;
         case 2: match(ID); break;
         case 3: match('('); expr(); match(')'); break;
         }
                                                          Parser.java
                                                           Was hinten herauskommt …
  	}
  	[... error handling]
}
                                                                                  44
1   /*------------------------------------------------------------------

Arithmetik & Parsergeneratoren
 3
     * PARSER RULES
     *------------------------------------------------------------------*/


                                                     Grammatik
     prog: stat+ ;
 5                                { declaredVariables.add($ID.text); }
     stat: expr NEWLINE
 7      |ID ’=’ expr NEWLINE
        |NEWLINE
 9      ;


11   expr
        : multExpr ( (’+’ |’-’) multExpr )*
13      ;


15   multExpr
        : atom (’*’ atom )*
17      ;


19   atom
        : INT
21      |ID               { declaredVariables.contains($ID.text) }?
        |’(’ expr ’)’
23      ;
                                                                             45

25   /*------------------------------------------------------------------
1   /*------------------------------------------------------------------

Arithmetik & Parsergeneratoren
 3
     * PARSER RULES
     *------------------------------------------------------------------*/


                                                     Grammatik
     prog: stat+ ;
 5                                { declaredVariables.add($ID.text); }
     stat: expr NEWLINE
 7      |ID ’=’ expr NEWLINE
        |NEWLINE
 9      ;


11   expr
        : multExpr ( (’+’ |’-’) multExpr )*
13      ;


15   multExpr
        : atom (’*’ atom )*
17      ;


19   atom
        : INT                                                           Test!
21      |ID               { declaredVariables.contains($ID.text) }?
        |’(’ expr ’)’
23      ;
                                                                                45

25   /*------------------------------------------------------------------
grammar IntExpr_Var;

options {
	    language = Java;
	    superClass = RunnableParser; }

@lexer::header{
	    package de.lmu.ifi.pms.parsergenerators; }

@header{
	    package de.lmu.ifi.pms.parsergenerators;
	    import java.util.Set;
	    import java.util.HashSet; }

@members {

    /** Set for maintaining already declared variables. */
    Set declaredVariables = new HashSet();

  	 public static RunnableParser getParserInstance(ANTLRStringStream stream){
        [...]
	   }

	   public void run(ASTProcessor... processors){
        try {
                                                                     Prolog
            prog();
        } catch (Exception e) [...]
     }
}                                                                               46
prog:   stat+ ;

stat:   // Semantic action for printing out the value returned by the evaluation of each expression
        expr NEWLINE
             { System.out.println(quot;Expression in line quot; +
                input.get(input.index()-1).getLine() + quot;: quot; + $expr.value);}
        // Semantic action for constructing the set of declared variables.
    |   ID '=' expr NEWLINE
             { varValues.put($ID.text, new Integer($expr.value)); }
    |   NEWLINE
    ;

// All rules of the grammar get a return value, the computed value of their matching expression
expr returns [int value]
    :   e=multExpr {$value = $e.value;}
    	 // We need to distinguish addition and subtraction
        (   '+' e=multExpr {$value += $e.value;}
        |   '-' e=multExpr {$value -= $e.value;} )*
    ;

multExpr returns [int value]
    :   e=atom {$value = $e.value;} ('*' e=atom {$value *= $e.value;})*
    ;

atom returns [int value]
    :   INT {$value = Integer.parseInt($INT.text);}
    |   ID
        { Integer v = varValues.get($ID.text);
           if ( v!=null ) $value = v.intValue();
           else throw new FailedPredicateException(input,
               quot;atomquot;, quot;undeclared variable quot;+$ID.text); }
    |   '(' expr ')' {$value = $expr.value;}
                                                                                                      47
    ;
prog:   stat+ ;

stat:   // Semantic action for printing out the value returned by the evaluation of each expression
        expr NEWLINE
             { System.out.println(quot;Expression in line quot; +
                input.get(input.index()-1).getLine() + quot;: quot; + $expr.value);}
        // Semantic action for constructing the set of declared variables.
    |   ID '=' expr NEWLINE
             { varValues.put($ID.text, new Integer($expr.value)); }
    |   NEWLINE
    ;

// All rules of the grammar get a return value, the computed value of their matching expression
expr returns [int value]
    :   e=multExpr {$value = $e.value;}
    	 // We need to distinguish addition and subtraction
        (   '+' e=multExpr {$value += $e.value;}
        |   '-' e=multExpr {$value -= $e.value;} )*
    ;

multExpr returns [int value]
    :   e=atom {$value = $e.value;} ('*' e=atom {$value *= $e.value;})*
    ;

atom returns [int value]
    :   INT {$value = Integer.parseInt($INT.text);}
    |   ID
        { Integer v = varValues.get($ID.text);
           if ( v!=null ) $value = v.intValue();
           else throw new FailedPredicateException(input,
               quot;atomquot;, quot;undeclared variable quot;+$ID.text); }
    |   '(' expr ')' {$value = $expr.value;}
                                                                                                      47
    ;
public int expr() {
  	   int value = 0; // return value
  	   int e = 0;
  	   try {
  	   	   e = multExpr();
  	   	   value = e;
  	   	   loop3: while(true) {
  	   	   	   int alt = 3;
  	   	   	   if (<<next input symbol is '+'>>) alt = 1;
  	   	   	   else if (<<next input symbol is '-'>>) alt = 2;
  	   	   	   switch(alt) {
  	   	   	   case 1: match('+');
  	   	   	           e = multExpr();
  	   	   	           value += e;
  	   	   	           break;
  	   	   	   case 2: [...]
  	   	   	   }
  	   	   }
  	   }

}
  	   [...]                          Parser + Aktionen
                                                      Was hinten herauskommt …



                                                                             48
49
Jenseits von Syntax
                            Semantische Analyse
  Trennung syntaktische / semantische Analyse
   effiziente, kontext-freie Parser für syntaktische Analyse
  Semantische Analyse
   volle Programmiersprache mittels Traversierung/Transformation des AST
   aber: schwer, oft weitgehend unabhängig von Sprache, ineffizient
  Attribute Grammars (Attributgrammatiken), SDDs
   Formalismus zur Einbettung der semantischen in die syntaktische Analyse
   Anreicherung des ASTs durch “semantische” Attribute
   in der Praxis: oft auch Seiteneffekte




                                                                             50
Attribute Grammars

      Produktion               Semantische Aktion
 〈E〉 ::=   〈int〉               E.val = int.val
           | 〈E1 〉 ‘+’ 〈E2 〉   E.val = E1 .val + E2 .val
           | ‘(’ 〈E1 〉 ‘)’     E.val = E1 .val
  Beispiele




                                                           51
Attribute Grammars

                 Produktion               Semantische Aktion
          〈E〉 ::=     〈int〉               E.val = int.val
                      | 〈E1 〉 ‘+’ 〈E2 〉   E.val = E1 .val + E2 .val
                      | ‘(’ 〈E1 〉 ‘)’     E.val = E1 .val
                                                ).5&+$:'(!'$:2+#;(!+(4,&567.(012+$/3
           Beispiele

                                                # M-+(&/U,,,,8,6,49,6,quot;5
                                                # I%?*&'U,,,(&-8 @6A @4@ (&-9 @6A (&-quot; @5A
*,V[R0;
*                                                      L+%)C=-(%&',,,,,,,,,,,,,,,,,2^C0-(%&'
R0;C*,40&),(',
                                                     2,,! 2! 6,29,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2[R0; O,2![R0;,6,29[R0
                                                     2! ! (&-8                                   2![R0;,O,(&-8[R0;,,O,8
'U                                                   29 ! 4,2quot;5,,,,,,,,,,,,,,,,,,,,,,,,29[R0;,O,2quot;[R0;
                                                     2quot; ! 2H 6,28                                2quot;[R0;,O,2H[R0;,6,28[R
                                                     2H ! (&-9                                   2H[R0;,O,(&-9[R0;,O,9
                                                     28 ! (&-quot;                                   28[R0;,O,(&-quot;[R0;,,O,quot;
                 !Z                                                          Prof. Aiken CS 143 Lecture 6
                                                                                                             51
Attribute Grammars

                Produktion                Semantische Aktion
          〈E〉 ::=
            〈int〉             E.val = int.val
            | 〈E1 〉 ‘+’ 〈E2 〉 E.val = E1 .val + E2 .val
      ).5&+$:'(!'$:2+#;(!+(4,&567.(012+$/3
            | ‘(’ 〈E1 〉 ‘)’   E.val = E1 .val
                                                  ).5&+$:'(!'$:2+#;(!+(4,&567.(012+$/3
           Beispiele

      # M-+(&/U,,,,8,6,49,6,quot;5 # M-+(&/U,,,,8,6,49,6,quot;5
                                  # I%?*&'U,,,(&-8 @6A @4@ (&-9 @6A (&-quot; @5A
      # I%?*&'U,,,(&-8 @6A @4@ (&-9 @6A (&-quot; @5A
*,V[R0;
*                                         L+%)C=-(%&',,,,,,,,,,,,,,,,,2^C0-(%&'
             L+%)C=-(%&',,,,,,,,,,,,,,,,,2^C0-(%&'
R0;C*,40&),(',
                                                          2,,! 2! 6,29,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2[R0; O,2![R0;,6,29[R0
            2,,! 2! 6,29,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2[R0; O,2![R0;,6,29[R0;
            2! ! (&-8                                   2!2! ! (&-88[R0;,,O,8
                                                          [R0;,O,(&-                                  2![R0;,O,(&-8[R0;,,O,8
'U          29 ! 4,2quot;5,,,,,,,,,,,,,,,,,,,,,,,,2929 ! 4,2[R0;
                                                          [R0;,O,2quot; quot;5,,,,,,,,,,,,,,,,,,,,,,,,29[R0;,O,2quot;[R0;
            2quot; ! 2H 6,28                                  2quot; ! 2 6,28
                                                        2quot;[R0;,O,2H [R0;,6,28[R0;                     2quot;[R0;,O,2H[R0;,6,28[R
                                                                   H
            2H ! (&-9                                     2H ! (&-9
                                                        2H[R0;,O,(&-9[R0;,O,9                         2H[R0;,O,(&-9[R0;,O,9
            28 ! (&-quot;                                     28 ! (&-quot;
                                                        28[R0;,O,(&-quot;[R0;,,O,quot;                        28[R0;,O,(&-quot;[R0;,,O,quot;
                 !Z                                                             Prof. Aiken CS 143 Lecture 6
                                      Prof. Aiken CS 143 Lecture 6                        !]                      51
/quot;0quot;%1quot;%(2)34$05

            9         +                            # 9'+F,(-7%,8'D%8%7,9
                                                     F'.,-(%,.8-),0-6,)F%,>'8
9!            A       9H                             '))6*D3)%
                                                   # L-)%,)F%,7%/%(7%(+*%.
*()B   5          J   9<         +                  K


       9@                 A
                                     9B

       *()H       2                *()<        3

                              Prof. Aiken CS 143 Lecture 6             HI




                                                                                52
/quot;0quot;%1quot;%(2)34$05

                      9           +                             # 9'+F,(-7%,8'D%8%7,9
                                                                  F'.,-(%,.8-),0-6,)F%,>'8
           9!             A       9H                              '))6*D3)%
                                                                # L-)%,)F%,7%/%(7%(+*%.
          *()B   5            J   9<          +                  K
                                                                          /quot;0quot;%1quot;%(2)34$05
                 9@                    A
                                                  9B                                      9
+-&/3)%7,'0)%6,'88,*).,                                                                             10
%(7%(+1,N6'/F,F'>%,D%%(,
           *()  2     H                         *()<        3             9!     5          A            9H     5

)6*D3)%.,+'(,D%,+-&/3)%7,                  Prof. Aiken CS 143 Lecture 6                             HI
                                                                          *()B       5          J        9<      5                  K

QF%(,)F%6%,'6%,(-,+1+8%.                                                             9@         2         A
                                                                                                                     9B       3
D3)%.,'6%,(-),8%N'8
                                                                                     *()H       2                    *()<      3
                                                                                                                                        52
143 Lecture 6                         H!                                                                      Prof. Aiken CS 143 Lecture 6
Jenseits von Syntax
                               Attribute Grammars
  Attribute grammar :=
   kontextfreie Grammatik mit Attributen und Regeln
   Attribute zu Symbolen, Regeln zu Produktionen
   S.a bezeichnet das Attribut ‘a’ des Symbols ‘S’
  Synthetisiertes Attribut (“Rückgabewerte) a von S
   definiert nur unter Verwendung von Attributen von S und Kinder von S
  Vererbtes Attribut (“Parameter”) b von S
   definiert nur unter Verwendung von Attributen von S, des Vaters von S
   und der Geschwister von S




                                                                          53
Jenseits von Syntax
                                    Attribute Grammars
  Ergebnis: Gleichungssystem
   Auswertungsordnung ist nicht fixiert
   e.g., E3.val = E4.val + E5.val
    E4.val und E5.val nötig um E3.val zu berechnen (dependency)
    aber: ob erst E4.val oder E5.val berechnet wird ist offen

  Parser muß Auswertungsordnung festlegen
   Problem: zyklische Abhängigkeiten
   EXPTIME: für eine gegebene Grammatik feststellen, ob Abhängigkeiten
   für alle Parsebäume zyklenfrei sind.
   daher: Einschränkung von Attribute Grammars



                                                                         54
Jenseits von Syntax
                                       Attribute Grammars
  S-attributed attribute grammar
   entählt ausschließlich synthetisierte Attribute
  L-attributed attribute grammar: alle Attribute entweder
   synthetisiert oder
   vererbt, aber dann, für Regel A ::= X1 X2 … Xn
    Berechnung von Xi.a nur durch
      vererbte Attribute von A oder
      (synthetisierte oder vererbte) Attribute von Xj fuer j < i oder
      (synthetisierte oder vererbte) Attribute von Xi selbst falls nicht abhängig von a
   verwendet vor allem in Recursive Descent Parsern wie ANTLR



                                                                                          55
| ‘(’ 〈E〉1 ‘)’   E.val = E1 .val

                                                                                   bdigits2 .val
〈bnumeral〉       ::= 〈bdigits〉1 ‘.’ 〈bdigits〉2   bnumeral.val = bdigits1 .val +    2bdigits2 .len

〈bdigits〉        ::= 〈bdigits〉1 〈bit〉                bdigits.val = 2 · bdigits2 .val + bit.val
                                                            bdigits.len = bdigits2 .len + 1
                  | 〈bit〉                             bdigits.val = bit.val; bdigits.len = 1
〈bit〉            ::= ‘0’                                                          bit.val = 0
                   | ‘1’                                                          bit.val = 1

  Beispiele




                                                                                                    56
| ‘(’ 〈E〉1 ‘)’   E.val = E1 .val                  Val (<bit>) ! 0
                                                     | 1
                                                                               bdigits2 .val
〈bnumeral〉       ::= 〈bdigits〉1 ‘.’ 〈bdigits〉2   bnumeral.Val= bdigits1 .val + 2bdigits2 .len
                                                          val (<bit>) ! 1

〈bdigits〉        ::= 〈bdigits〉1 〈bit〉              The derivation bdigits2 .val + bit.val illustrates the use of attributes that give the
                                                    bdigits.val = 2 · tree in Figure 3.7
                                                   semantics for the binary numeral 1101.01 to be the real number 13.25.
                                                           bdigits.len = bdigits .len + 1
                                                                                      2
                  | 〈bit〉                             bdigits.val = bit.val; bdigits.len = 1
〈bit〉            ::= ‘0’                                                            bit.val = 0   <binary numeral>
                   | ‘1’                                                            bit.val = 1   Val: 13 + 1/22 = 13.25


  Beispiele
                                                                                     <binary digits>                        <binary digits>
                                                                                     Val : 13                               Val : 1
                                                                                     Len : 4                                Len : 2


                                                                       <binary digits>            <bit>          <binary digits>     <bit>
                                                                       Val : 6                    Val : 1        Val : 0             Val : 1
                                                                       Len : 3                                   Len : 1

                                                                                                     1                                  1
                                                              <binary digits>          <bit>                      <bit>
                                                              Val : 3                  Val : 0                    Val : 0
                                                              Len : 2

                                                                                                                    0
                                                                                           0
                                                     <binary digits>        <bit>
                                                     Val : 1                Val : 1
                                                     Len : 1

                                                                                1
                                                       <bit>
                                                       Val : 1


                                                          1
                                                                                                                                        56
                                                   Figure 3.7: Binary Numeral Semantics Using Synthesized Attributes
D
Fazit
        57
Zusammenfassung
                                  Parsergeneratoren
1. Implementierung von Endlichen Automaten
               loop-and-switch, loop-and-lookup, Lexer,
                       Automatenbibliotheken
   manuelle Implementierung oft in Bibliotheken und bei zeitkritischem
   Parsing (Basispaarsequenzen) verwendet
   Lexer erlauben auch komplexe endliche Automaten
    ohne signifikanten Effizienzverlust
   Automatenbibliotheken
    ineffizienter als Lexer oder manuelle Implementierung
    aber: Konstruktion und Manipulation der Automaten zur Laufzeit möglich


                                                                             58
Zusammenfassung
                                 Parsergeneratoren
2. Implementierung von Kellerautomaten
                           Parsergeneratoren
   manuelle Implementierung meist zu aufwendig
   Parsergeneratoren erzeugen Lexer und Parser
   Mehr als kontextfreie Sprachen dank semantischer Aktionen
    kontext-sensitive Eigenschaften “von Hand” programmieren
   Recursive-descent oder LL(k)/LL(*) Parser wie ANTLR
    einfach zu lesender Code, leichte manuelle Anpassung
   Andere verbreitete Ansätze: LR, LALR, Left-Corner, Earley


                                                               59
Zusammenfassung
                              Parsergeneratoren
 Beispielprogramme + Dokumentation
  im Laufe der Woche auf der Webseite
 Mehr Details zu Attributgrammatiken in den Übungen
 Kapitel 5, Drachenbuch (“Compilers …”, Aho et al., 2007)
 Selber ausprobieren!




                                                            60
E
Fragen
         61

Weitere ähnliche Inhalte

Andere mochten auch

Eraikune, comités estratégicos, julio 2012
Eraikune, comités estratégicos, julio 2012Eraikune, comités estratégicos, julio 2012
Eraikune, comités estratégicos, julio 2012Eraikune
 
Proyecto:recolección de la aceituna
Proyecto:recolección de la aceitunaProyecto:recolección de la aceituna
Proyecto:recolección de la aceitunadeluz06
 
Las estrategias de lectura
Las estrategias de lecturaLas estrategias de lectura
Las estrategias de lecturaJuan Quinde
 
Tarea | 1ra Sesión | Balance personal
Tarea | 1ra Sesión | Balance personal Tarea | 1ra Sesión | Balance personal
Tarea | 1ra Sesión | Balance personal ndimexico
 
Presentación | 1ra Sesión | Lorena Cuéllar, ex Alcaldesa de Tlaxcala, Tlaxcala
Presentación | 1ra Sesión | Lorena Cuéllar, ex Alcaldesa de Tlaxcala, TlaxcalaPresentación | 1ra Sesión | Lorena Cuéllar, ex Alcaldesa de Tlaxcala, Tlaxcala
Presentación | 1ra Sesión | Lorena Cuéllar, ex Alcaldesa de Tlaxcala, Tlaxcalandimexico
 
Cooperativa cristian restrepo 11 b
Cooperativa cristian restrepo 11 bCooperativa cristian restrepo 11 b
Cooperativa cristian restrepo 11 brescri
 
Ensable tecnico en sistemas
Ensable tecnico en sistemasEnsable tecnico en sistemas
Ensable tecnico en sistemasesteban0495
 
Manual de convivencia idep
Manual de convivencia idepManual de convivencia idep
Manual de convivencia idepbedoyajeny
 
Garbage Collection
Garbage CollectionGarbage Collection
Garbage CollectionTim Furche
 
Portafolio Xavier Prado / Versión 2
Portafolio Xavier Prado / Versión 2Portafolio Xavier Prado / Versión 2
Portafolio Xavier Prado / Versión 2Xavier Prado
 
Helpedia Fundraising-Kongress 2009
Helpedia Fundraising-Kongress 2009Helpedia Fundraising-Kongress 2009
Helpedia Fundraising-Kongress 2009Helpedia
 
Curso urbanismo pr7 pa p bj
Curso urbanismo pr7 pa p bjCurso urbanismo pr7 pa p bj
Curso urbanismo pr7 pa p bjEraikune
 
La proteccion juridica del sofware
La proteccion juridica del sofwareLa proteccion juridica del sofware
La proteccion juridica del sofwarelalolaley12
 
Inces 6-2-4 transmision de datos Nro.1
Inces 6-2-4 transmision de datos Nro.1Inces 6-2-4 transmision de datos Nro.1
Inces 6-2-4 transmision de datos Nro.1Dayana Mendez
 

Andere mochten auch (20)

Eraikune, comités estratégicos, julio 2012
Eraikune, comités estratégicos, julio 2012Eraikune, comités estratégicos, julio 2012
Eraikune, comités estratégicos, julio 2012
 
Proyecto:recolección de la aceituna
Proyecto:recolección de la aceitunaProyecto:recolección de la aceituna
Proyecto:recolección de la aceituna
 
Las estrategias de lectura
Las estrategias de lecturaLas estrategias de lectura
Las estrategias de lectura
 
Dispositivos grupo g
Dispositivos grupo gDispositivos grupo g
Dispositivos grupo g
 
Tarea | 1ra Sesión | Balance personal
Tarea | 1ra Sesión | Balance personal Tarea | 1ra Sesión | Balance personal
Tarea | 1ra Sesión | Balance personal
 
Presentación | 1ra Sesión | Lorena Cuéllar, ex Alcaldesa de Tlaxcala, Tlaxcala
Presentación | 1ra Sesión | Lorena Cuéllar, ex Alcaldesa de Tlaxcala, TlaxcalaPresentación | 1ra Sesión | Lorena Cuéllar, ex Alcaldesa de Tlaxcala, Tlaxcala
Presentación | 1ra Sesión | Lorena Cuéllar, ex Alcaldesa de Tlaxcala, Tlaxcala
 
Cooperativa cristian restrepo 11 b
Cooperativa cristian restrepo 11 bCooperativa cristian restrepo 11 b
Cooperativa cristian restrepo 11 b
 
Ensable tecnico en sistemas
Ensable tecnico en sistemasEnsable tecnico en sistemas
Ensable tecnico en sistemas
 
Seguridad informática
Seguridad informáticaSeguridad informática
Seguridad informática
 
equinoterapia
equinoterapiaequinoterapia
equinoterapia
 
Manual de convivencia idep
Manual de convivencia idepManual de convivencia idep
Manual de convivencia idep
 
Codigos binarios
Codigos binariosCodigos binarios
Codigos binarios
 
Garbage Collection
Garbage CollectionGarbage Collection
Garbage Collection
 
Portafolio Xavier Prado / Versión 2
Portafolio Xavier Prado / Versión 2Portafolio Xavier Prado / Versión 2
Portafolio Xavier Prado / Versión 2
 
Helpedia Fundraising-Kongress 2009
Helpedia Fundraising-Kongress 2009Helpedia Fundraising-Kongress 2009
Helpedia Fundraising-Kongress 2009
 
Curso urbanismo pr7 pa p bj
Curso urbanismo pr7 pa p bjCurso urbanismo pr7 pa p bj
Curso urbanismo pr7 pa p bj
 
La proteccion juridica del sofware
La proteccion juridica del sofwareLa proteccion juridica del sofware
La proteccion juridica del sofware
 
Startnbergersee
StartnbergerseeStartnbergersee
Startnbergersee
 
Inces 6-2-4 transmision de datos Nro.1
Inces 6-2-4 transmision de datos Nro.1Inces 6-2-4 transmision de datos Nro.1
Inces 6-2-4 transmision de datos Nro.1
 
Seguridad informática
Seguridad informáticaSeguridad informática
Seguridad informática
 

Ähnlich wie Von Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken

Roslyn - Ein offener Compiler. Ja, und nun?
Roslyn - Ein offener Compiler. Ja, und nun?Roslyn - Ein offener Compiler. Ja, und nun?
Roslyn - Ein offener Compiler. Ja, und nun?Robin Sedlaczek
 
#SpeakRoslyn - Die Microsoft .NET Compiler Plattform
#SpeakRoslyn - Die Microsoft .NET Compiler Plattform#SpeakRoslyn - Die Microsoft .NET Compiler Plattform
#SpeakRoslyn - Die Microsoft .NET Compiler PlattformRobin Sedlaczek
 
Perl 5 Quiz Chemnitz Edition
Perl 5 Quiz Chemnitz EditionPerl 5 Quiz Chemnitz Edition
Perl 5 Quiz Chemnitz Editionlichtkind
 
Perl 6 Regex und Grammars
Perl 6 Regex und GrammarsPerl 6 Regex und Grammars
Perl 6 Regex und Grammarslichtkind
 
Scala : Monads for the Pragmatic Programmer , Composition with Stackable Traits
Scala : Monads for the Pragmatic Programmer , Composition with Stackable TraitsScala : Monads for the Pragmatic Programmer , Composition with Stackable Traits
Scala : Monads for the Pragmatic Programmer , Composition with Stackable TraitsAndreas Neumann
 
A fool with a tool - Scraping Basics
A fool with a tool - Scraping BasicsA fool with a tool - Scraping Basics
A fool with a tool - Scraping BasicsMarkus Uhl
 
JSTF-Workshop Teil 1
JSTF-Workshop Teil 1JSTF-Workshop Teil 1
JSTF-Workshop Teil 1Tobias Adam
 
Perl - die Taschenkettensäge unter den Programmiersprachen - Vortrag 2003
Perl - die Taschenkettensäge unter den Programmiersprachen - Vortrag 2003Perl - die Taschenkettensäge unter den Programmiersprachen - Vortrag 2003
Perl - die Taschenkettensäge unter den Programmiersprachen - Vortrag 2003Brigitte Jellinek
 
31. Teffen der .NET User Group Rhein-Neckar mit Robin Sedlaczek - SpeakRoslyn
31. Teffen der .NET User Group Rhein-Neckar mit Robin Sedlaczek - SpeakRoslyn31. Teffen der .NET User Group Rhein-Neckar mit Robin Sedlaczek - SpeakRoslyn
31. Teffen der .NET User Group Rhein-Neckar mit Robin Sedlaczek - SpeakRoslyn.NET User Group Rhein-Neckar
 
Von Java Zu Groovy
Von Java Zu GroovyVon Java Zu Groovy
Von Java Zu Groovyjlink
 
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"DevDay Dresden
 
Designpatterns in Ruby
Designpatterns in RubyDesignpatterns in Ruby
Designpatterns in Rubypfleidi
 
Programmieren mit PROLOG
Programmieren mit PROLOGProgrammieren mit PROLOG
Programmieren mit PROLOGQAware GmbH
 
Java Streams und Lambdas
Java Streams und LambdasJava Streams und Lambdas
Java Streams und LambdasNane Kratzke
 
Perl 5.20: Feature, Kultur, Module, Werkzeuge
Perl 5.20: Feature, Kultur, Module, WerkzeugePerl 5.20: Feature, Kultur, Module, Werkzeuge
Perl 5.20: Feature, Kultur, Module, Werkzeugelichtkind
 
GE_: mein perl_curse vol II
GE_: mein perl_curse vol IIGE_: mein perl_curse vol II
GE_: mein perl_curse vol IIgiovanni Colombo
 
JAX 2024: Go in der Praxis einsetzen
JAX 2024: Go in der Praxis einsetzenJAX 2024: Go in der Praxis einsetzen
JAX 2024: Go in der Praxis einsetzenJan Stamer
 

Ähnlich wie Von Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken (20)

Ruby on Rails SS09 03
Ruby on Rails SS09 03Ruby on Rails SS09 03
Ruby on Rails SS09 03
 
Roslyn - Ein offener Compiler. Ja, und nun?
Roslyn - Ein offener Compiler. Ja, und nun?Roslyn - Ein offener Compiler. Ja, und nun?
Roslyn - Ein offener Compiler. Ja, und nun?
 
#SpeakRoslyn - Die Microsoft .NET Compiler Plattform
#SpeakRoslyn - Die Microsoft .NET Compiler Plattform#SpeakRoslyn - Die Microsoft .NET Compiler Plattform
#SpeakRoslyn - Die Microsoft .NET Compiler Plattform
 
Perl 5 Quiz Chemnitz Edition
Perl 5 Quiz Chemnitz EditionPerl 5 Quiz Chemnitz Edition
Perl 5 Quiz Chemnitz Edition
 
Perl 6 Regex und Grammars
Perl 6 Regex und GrammarsPerl 6 Regex und Grammars
Perl 6 Regex und Grammars
 
Scala : Monads for the Pragmatic Programmer , Composition with Stackable Traits
Scala : Monads for the Pragmatic Programmer , Composition with Stackable TraitsScala : Monads for the Pragmatic Programmer , Composition with Stackable Traits
Scala : Monads for the Pragmatic Programmer , Composition with Stackable Traits
 
Php Schulung
Php SchulungPhp Schulung
Php Schulung
 
A fool with a tool - Scraping Basics
A fool with a tool - Scraping BasicsA fool with a tool - Scraping Basics
A fool with a tool - Scraping Basics
 
JSTF-Workshop Teil 1
JSTF-Workshop Teil 1JSTF-Workshop Teil 1
JSTF-Workshop Teil 1
 
Perl - die Taschenkettensäge unter den Programmiersprachen - Vortrag 2003
Perl - die Taschenkettensäge unter den Programmiersprachen - Vortrag 2003Perl - die Taschenkettensäge unter den Programmiersprachen - Vortrag 2003
Perl - die Taschenkettensäge unter den Programmiersprachen - Vortrag 2003
 
31. Teffen der .NET User Group Rhein-Neckar mit Robin Sedlaczek - SpeakRoslyn
31. Teffen der .NET User Group Rhein-Neckar mit Robin Sedlaczek - SpeakRoslyn31. Teffen der .NET User Group Rhein-Neckar mit Robin Sedlaczek - SpeakRoslyn
31. Teffen der .NET User Group Rhein-Neckar mit Robin Sedlaczek - SpeakRoslyn
 
Von Java Zu Groovy
Von Java Zu GroovyVon Java Zu Groovy
Von Java Zu Groovy
 
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"
 
Designpatterns in Ruby
Designpatterns in RubyDesignpatterns in Ruby
Designpatterns in Ruby
 
Ruby
RubyRuby
Ruby
 
Programmieren mit PROLOG
Programmieren mit PROLOGProgrammieren mit PROLOG
Programmieren mit PROLOG
 
Java Streams und Lambdas
Java Streams und LambdasJava Streams und Lambdas
Java Streams und Lambdas
 
Perl 5.20: Feature, Kultur, Module, Werkzeuge
Perl 5.20: Feature, Kultur, Module, WerkzeugePerl 5.20: Feature, Kultur, Module, Werkzeuge
Perl 5.20: Feature, Kultur, Module, Werkzeuge
 
GE_: mein perl_curse vol II
GE_: mein perl_curse vol IIGE_: mein perl_curse vol II
GE_: mein perl_curse vol II
 
JAX 2024: Go in der Praxis einsetzen
JAX 2024: Go in der Praxis einsetzenJAX 2024: Go in der Praxis einsetzen
JAX 2024: Go in der Praxis einsetzen
 

Von Automaten zu Programmen–Parsergeneratoren und Attributgrammatiken

  • 1. Von Automaten zu Programmen Manuelle und automatische Entwicklung von Parsern Tim Furche Compilerbau, Wintersemester 2008/09, Prof. F. Bry 1
  • 2. Formale Sprachen: Beispiele aus der Praxis 2
  • 3. Formale Sprachen: Nicht nur in Compilern! 3
  • 5. 5
  • 6. URIs Google Anfrage HTML JavaScript CSS Browser: Formale Sprachen 6
  • 8. 8
  • 10. A Endliche Automaten Parser für Reguläre Sprachen z.B.: URIs, Datumsangaben, Gleitpunktzahlen 10
  • 12. -666.797E-14 parsen, normalisieren 12
  • 13. $

java
‐jar
FPParser.jar
‐666.797E‐14
‐‐step (Initial,
‐666.797E‐14)
 |‐
(WholeNrDigit,
666.797E‐14)
 |‐
(WholeNrDigit_or_Fraction_or_Exponent,
66.797E‐14)
 |‐
(WholeNrDigit_or_Fraction_or_Exponent,
6.797E‐14)
 |‐
(WholeNrDigit_or_Fraction_or_Exponent,
.797E‐14)
 |‐
(FractionDigit,
797E‐14)
 |‐
(FractionDigit_or_Exponent,
97E‐14)
 |‐
(FractionDigit_or_Exponent,
7E‐14)
 |‐
(FractionDigit_or_Exponent,
E‐14)
 |‐
(Exponent,
‐14)
 |‐
(ExponentDigit,
14)
 |‐
(ExponentDigit_or_End,
4)
 |‐
(ExponentDigit_or_End,
)
 Success:
‐6.66797E‐12
 ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
 Gleitpunktzahlen Parsen und Normalisieren mit Endlichem Automaten 13
  • 14. 14
  • 16. 16
  • 18. Bibliothek: Double.parseDouble() Regulärer Ausdruck über Bibliothek: java.util.regex.Pattern&Matcher 17
  • 19. Bibliothek: Double.parseDouble() Regulärer Ausdruck über Bibliothek: java.util.regex.Pattern&Matcher Endliche Automaten Bibliothek: dk.brics.automaton 17
  • 20. Bibliothek: Double.parseDouble() Regulärer Ausdruck über Bibliothek: java.util.regex.Pattern&Matcher Endliche Automaten Bibliothek: dk.brics.automaton Manuelle Implementierung 17
  • 21. Bibliothek: Double.parseDouble() Regulärer Ausdruck über Bibliothek: java.util.regex.Pattern&Matcher Endliche Automaten Bibliothek: dk.brics.automaton Manuelle Implementierung 17
  • 22. 41 } ‘0’–‘9’ ‘ -’ start I F ‘0’–‘9’ R ‘0’–‘9’ Ganzzahlen in Java Endlicher Automat für den Ganzzahlparser in Long.parseLong 18
  • 23. 1 public static long parseLong(String s, int radix) throws NumberFormatException { 3 if (s == null) throw new NumberFormatException(quot;nullquot;); [...] 5 int max = s.length(); [...] 7 // State 1: Treat the sign if (s.charAt(0) == ’-’) { 9 negative = true; limit = Long.MIN_VALUE; 11 i++; } else 13 limit = -Long.MAX_VALUE; 15 // State 2: Treat first digit if (i < max) { 17 digit = Character.digit(s.charAt(i++),radix); if (digit < 0) // Not a digit 19 throw NumberFormatException.forInputString(s); else 21 result = -digit; } 23 // State 3: Treat all other digits 19 25 while (i < max) { digit = Character.digit(s.charAt(i++),radix);
  • 24. 21 result = -digit; } 23 // State 3: Treat all other digits 25 while (i < max) { digit = Character.digit(s.charAt(i++),radix); 27 if (digit < 0) // Not a digit throw NumberFormatException.forInputString(s); 29 result *= radix; // Check if out-of-bounds [...] 31 result -= digit; } 33 if (negative) { if (i > 1) 35 return result; else /* Only got quot;-quot; */ 37 throw NumberFormatException.forInputString(s); } else 39 return -result; 41 } ‘0’–‘9’ ‘ -’ start I F ‘0’–‘9’ R 20 ‘0’–‘9’
  • 25. 21
  • 26. en, die unser Parser erkennen soll: 2.1 Regulärer Ausdruck für Gleitpunktzahlen (‘Für -’)? digit+ (‘.’ digit+)? ((‘e’|‘E’) digit+)? Aus +’|‘ unser Beispiel beginnen wir mit einem regulären Gleitpunktzahlen, die unser Parser erkennen soll: 0’ | ‘1’ | ‘2’ | ‘3’ | ‘4’ | ‘5(‘+’|‘-’ | ‘7’ | ‘8’.|’ ‘9’ ’ | ‘6 ’)? digit+ (‘ digit+)? ((‘e’|‘E’) digit digit digit* digit := ‘0’ | ‘1’ | ‘2’ | ‘3’ | ‘4’ | ‘5’ | ‘6’ | ‘7’ | ‘8’ | ‘9’ digit+ := digit digit* tion ist fast wie in den Übungen behandelt, allerdin omma-Anteil wegfallenfast wie in den der Exponent). a Die Spezifikation ist kann (wie Übungen behandelt, dass der Nachkomma-Anteil wegfallen kann (wie der Expon Gleitpunktzahlen in Java utomat für Gleitpunktzahlen 2.2 Endlicher Automat für Gleitpunktzahlen Spezifikation: Regulärer Ausdruck 22 ache können wir durch folgenden Automaten besch Die gleiche Sprache können wir durch folgenden Automate
  • 27. ‘+’, ‘-’ start S s,d Sd ‘0’–‘9’ ‘.’ ‘0’–‘9’ ‘0’–‘9’ S d ,p,e ‘0’–‘9’ Fd ‘0’–‘9’ F d ,e ‘e’, ‘E’ ‘e’, ‘E’ E s,d ‘0’–‘9’ ‘+’, ‘-’ Ed ‘0’–‘9’ E d ,# ‘0’–‘9’ 23 Der Automat verwendet die folgenden Zustände, benannt nach d
  • 28. gibt. Dabei nennen wir für eine Gleitpunktzahl s. f · 10 : s den significand (oder Vorkomma-Anteil der Mantisse), f die fraction (oder Nachkomma-Anteil der Man- tisse), und e den exponent. Zustand Teil der Zahl Nachfolgerzeichen Beschreibung S s,d significand Ziffer (d ) oder Vorzeichen (s ) Anfangszustand, erkennt optionales Vor- zeichen Sd –”– Ziffer stellt sicher, dass zumindest eine Ziffer im significand vorkommt S d , f ,e –”– Ziffer, Punkt (p ) oder e erkennt beliebige Folgen von Ziffern, fährt mit Erkennung von fraction oder expo- nent fort, Endzustand Fd fraction Ziffer stellt sicher, dass zumindest eine Ziffer in fraction vorkommt F d ,e –”– Ziffer or e erkennt beliebige Folgen von Ziffern, fährt mit Erkennung von exponent fort, Endzu- stand E s,d exponent Ziffer oder Vorzeichen Ziffer oder Vorzeichen als Beginn des ex- ponent Ed –”– digit stellt sicher, dass zumindest eine Ziffer in exponent vorkommt Ed –”– digit erkennt beliebige Folgen von Ziffern, End- zustand 24
  • 29. Implementierung Endlicher Automaten Ansätze … Implicit state: wie Long.parseLong(); Zustand implizit Bereich im Programm identifiziert den aktuellen Zustand (PC) für einfach, im wesentlichen sequentielle Automaten geeignet Loop-and-switch: Schleife über Eingabe + goto/switch je nach akt. Zustand und Symbol effizient nur wenn Sprünge berechnet werden können typisch für komplexere Automaten mit oft wiederkehrenden Zuständen Loop-and-lookup: Schleife + Nachschlagen in Tabellenrepr. von δ Zeilen: Zustände, Spalten: Eingabesymbole, Zelleninhalt: Folgezustand Zeit-effizient auf Kosten von Speicher, nur bei kleinem Eingabealphabet z.B. reguläre Ausdrücke über Basispaarsequenzen (nur A, T, G, C). 25
  • 30. Implementierung Endlicher Automaten Umgebung für FP-Parser … FPParser: abstrakte Oberklasse für alle Floating-Point-Parser Attribute & Methoden zur Verwaltung & Berechnung der FP-Zahl FPPaser.FPNumberPart: hält ganzzahligen Anteil einer FP-Zahl significand (Vorkomma-Anteil), fraction (Nachkomma-Antail), exponent #parse(char): Transition & Berechnung des Automaten bei Eingabe eines einzelnen Zeichens #parse(String): Schleife über die Eingabe für jedes Zeichen wird #parse(char) aufgerufen 26
  • 31. Implementierung Endlicher Automaten Umgebung für FP-Parser … FPParser: abstrakte Oberklasse für alle Floating-Point-Parser Attribute & Methoden zur Verwaltung & Berechnung der FP-Zahl FPPaser.FPNumberPart: hält ganzzahligen Anteil einer FP-Zahl significand (Vorkomma-Anteil), fraction (Nachkomma-Antail), exponent #parse(char): Transition & Berechnung des Automaten bei Eingabe eines einzelnen Zeichens #parse(String): Schleife über die Eingabe für jedes Zeichen wird #parse(char) aufgerufen FPParser 26
  • 32. einer Ziffer bleiben wir im gleichen Zustand und fügen die Ziffer zur aktu- ellen Repräsentation des significand hinzu. Bei einem Punkt gehen wir in den Zustand F d , also erwarten die erste Ziffer der fraction (würden wir hier Implementierung Endlicher Automaten in F d ,e übergehen, wären auch Zahlen der Form 12.E10 erlaubt). Bei einem e oder E gehen wir in Zustand E s,d (STATE_Exponent). In den beiden letzten Loop-and-Switch … Fällen dienen die Zeichen nur als Trennzeichen und werden nicht zur aktu- ellen Repräsentation hinzugefügt. 1 case STATE_SignifDigit_Fraction_Exponent: if(Character.isDigit(c)) { 3 state = STATE_SignifDigit_Fraction_Exponent; significand.addDigit(c); 5 } else if(c == ’.’) { 7 state = STATE_FractionDigit; } 9 else if(c == ’e’ || c == ’E’) { state = STATE_Exponent; 11 } else state = STATE_Failure; 13 break; Loop-and-Lookup: realisiert in MatrixFPParser. Die Idee von loop-and-lookup Im- plementierungen ist, in der Schleife über die Eingabezeichen mit Hilfe ei- 27 ner (konstanten) Lookup-Tabelle den Folgezustand (und eventuelle Berech-
  • 33. einer Ziffer bleiben wir im gleichen Zustand und fügen die Ziffer zur aktu- ellen Repräsentation des significand hinzu. Bei einem Punkt gehen wir in den Zustand F d , also erwarten die erste Ziffer der fraction (würden wir hier Implementierung Endlicher Automaten in F d ,e übergehen, wären auch Zahlen der Form 12.E10 erlaubt). Bei einem e oder E gehen wir in Zustand E s,d (STATE_Exponent). In den beiden letzten Loop-and-Switch … Fällen dienen die Zeichen nur als Trennzeichen und werden nicht zur aktu- ellen Repräsentation hinzugefügt. 1 case STATE_SignifDigit_Fraction_Exponent: if(Character.isDigit(c)) { 3 state = STATE_SignifDigit_Fraction_Exponent; significand.addDigit(c); 5 } else if(c == ’.’) { 7 state = STATE_FractionDigit; } 9 else if(c == ’e’ || c == ’E’) { state = STATE_Exponent; 11 } else state = STATE_Failure; 13 break; PlainFPParser Loop-and-Lookup: realisiert in MatrixFPParser. Die Idee von loop-and-lookup Im- plementierungen ist, in der Schleife über die Eingabezeichen mit Hilfe ei- 27 ner (konstanten) Lookup-Tabelle den Folgezustand (und eventuelle Berech-
  • 34. 0 Implementierung Endlicher Automaten SIGNIF_DIGIT_FRACTION_EXPONENT { 2 Loop-and-Switch … State transition(char c, FPNumberPart nr){ if(Character.isDigit(c)) { 4 nr.addDigit(c); return SIGNIF_DIGIT_FRACTION_EXPONENT; 6 } else if(c == ’.’) { 8 return FRACTION_DIGIT; } 10 else if(c == ’e’ || c == ’E’) { return EXPONENT; 12 } else return FAILURE; 14 } FPNumberPart select(FPNumberPart s, FPNumberPart f, FPNumberPart← e){ return s; } 16 boolean isFinal(){ return true; } boolean isFailure(){ return false; } 18 }, 28 3.1 Tests
  • 35. 0 Implementierung Endlicher Automaten SIGNIF_DIGIT_FRACTION_EXPONENT { 2 Loop-and-Switch … State transition(char c, FPNumberPart nr){ if(Character.isDigit(c)) { 4 nr.addDigit(c); return SIGNIF_DIGIT_FRACTION_EXPONENT; 6 } else if(c == ’.’) { 8 return FRACTION_DIGIT; } 10 else if(c == ’e’ || c == ’E’) { return EXPONENT; 12 } else return FAILURE; 14 } FPNumberPart select(FPNumberPart s, FPNumberPart f, FPNumberPart← e){ return s; } 16 boolean isFinal(){ return true; } boolean isFailure(){ return false; } 18 }, EnumFPParser 28 3.1 Tests
  • 36. nungsschritte) zu spezifizieren. In der Lookup-Tabelle sind den Zuständen Zeilen, den Eingabezeichen Spalten zugeordnet. Implementierung Endlicher Automaten Die Lookup-Tabelle findet sich in MatrixFPParser#stateMatrix und ist eine ziemlich direkte Umsetzung der δ Übergangsfunktion des Automaten. Für Loop-and-Lookup … den gleichen Zustand wie oben ergibt sich z.B. folgender Eintrag in der Ma- trix: 1 // STATE_SignifDigit_Fraction_Exponent { // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Digit) 3 new DigitEffect(STATE_SignifDigit_Fraction_Exponent,← significand), // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Sign) 5 new Effect(STATE_Failure, significand), // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Expn) 7 new Effect(STATE_Exponent, significand), // (STATE_Initial, SCLASS_Period) 9 new Effect(STATE_FractionDigit, significand), // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Rest) 11 new Effect(STATE_Failure, significand) }, In jeder Zelle der Lookup-Tabelle findet sich ein Effect Objekt, dass den nächsten Zustand und die auszuführenden Berechnungsschritte enthält. Um die Berechnungsschritte zu paramerterisieren verwendet 29 MatrixFPParser Funktionsobjekte (wo Sprachen wie C++ Funktionspointer
  • 37. nungsschritte) zu spezifizieren. In der Lookup-Tabelle sind den Zuständen Zeilen, den Eingabezeichen Spalten zugeordnet. Implementierung Endlicher Automaten Die Lookup-Tabelle findet sich in MatrixFPParser#stateMatrix und ist eine ziemlich direkte Umsetzung der δ Übergangsfunktion des Automaten. Für Loop-and-Lookup … den gleichen Zustand wie oben ergibt sich z.B. folgender Eintrag in der Ma- trix: 1 // STATE_SignifDigit_Fraction_Exponent { // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Digit) 3 new DigitEffect(STATE_SignifDigit_Fraction_Exponent,← significand), // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Sign) 5 new Effect(STATE_Failure, significand), // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Expn) 7 new Effect(STATE_Exponent, significand), // (STATE_Initial, SCLASS_Period) 9 new Effect(STATE_FractionDigit, significand), // (STATE_SignifDigit_Fraction_Exponent, SCLASS_Rest) 11 new Effect(STATE_Failure, significand) }, In jeder Zelle der Lookup-Tabelle findet sich MatrixFPParser ein Effect Objekt, dass den nächsten Zustand und die auszuführenden Berechnungsschritte enthält. Um die Berechnungsschritte zu paramerterisieren verwendet 29 MatrixFPParser Funktionsobjekte (wo Sprachen wie C++ Funktionspointer
  • 38. Implementierung Endlicher Automaten Loop-and-Lookup … Ziffer Vorzeichen ‘e’, ‘E’ Punkt Initial SignifD_F_E SignifD Failure Failure SignifD SignifD Failure Failure Failure SignifD_F_E SignifD_F_E Failure Exponent FractionD FractionD FractionD_E Failure Failure Failure FractionD_E FractionD_E Failure Exponent Failure Exponent ExponentD_End ExponentD Failure Failure ExponentD ExponentD_End Failure Failure Failure ExponentD_End ExponentD_End Failure Failure Failure Failure Failure Failure Failure Failure 30
  • 39. $

java
‐jar
FPParser.jar
33E0
‐‐step
‐‐pEnum (INITIAL,
33E0)
 


|‐
(SIGNIF_DIGIT_FRACTION_EXPONENT,
3E0)
 


|‐
(SIGNIF_DIGIT_FRACTION_EXPONENT,
E0)
 


|‐
(EXPONENT,
0)
 


|‐
(EXPONENT_DIGIT_END,
<epsilon>)
 Success:



33.0
 ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
 Gleitpunktzahlen Parsen und Normalisieren mit Endlichem Automaten 31
  • 40. 32
  • 41. B Keller- Automaten Parser für kontextfreie Sprachen++ z.B. für arithmetische Ausdrücke und Erweiterungen 33
  • 43. 2 + 4 * 11 - 2 * 3 + 2 parsen, ausrechnen 35
  • 44. 2
+
4
*
11
‐
2
*
3
+
2 $

java
‐jar
ParserGenerators.jar
‐‐pIntExpr
‐‐file
plain‐intexpr <no
output>
(=
no
error) $

java
‐jar
ParserGenerators.jar
‐‐pIntExpr_Eval
‐‐file
plain‐intexpr Expression
in
line
1:
42
 $

java
‐jar
ParserGenerators.jar
‐‐pIntExpr_AST
‐‐file
plain‐intexpr (+
(‐
(+
2
(*
4
11))
(*
2
3))
2) Arithmetische Ausdrücke Parsen und Ausrechnen mit Kellerautomaten 36
  • 45. 37
  • 46. x
=
78 y
=
2 112
+
4
*
x
‐
2
*
y
+
z
*
2 5
+
3
‐
2 $

java
‐jar
ParserGenerators.jar
‐‐pIntExpr
‐‐file
var‐intexpr <no
output>
(=
no
error) $

java
‐jar
ParserGenerators.jar
‐‐pIntExpr_Var
‐‐file
var‐intexpr line
3:24
rule
atom
failed
predicate:
{
declaredVariables.contains($ID.text)
}? $

java
‐jar
ParserGenerators.jar
‐‐pIntExpr_Eval
‐‐file
var‐intexpr line
3:24
rule
atom
failed
predicate:
{undeclared
variable
z}? Expression
in
line
3:
420 Expression
in
line
4:
6 + Variablen Parsen und Ausrechnen mit Kellerautomaten 38
  • 47. 39
  • 48. 1 /*------------------------------------------------------------------ Arithmetik & Parsergeneratoren 3 * PARSER RULES *------------------------------------------------------------------*/ Grammatik prog: stat+ ; 5 stat: expr NEWLINE 7 |ID ’=’ expr NEWLINE |NEWLINE 9 ; 11 expr : multExpr ( (’+’ |’-’) multExpr )* 13 ; 15 multExpr : atom (’*’ atom )* 17 ; 19 atom : INT 21 |ID |’(’ expr ’)’ 23 ; 40 25 /*------------------------------------------------------------------
  • 49. 17 ; 19 atom Arithmetik & Parsergeneratoren : INT |ID Lexer-Regeln der Grammatik 21 |’(’ expr ’)’ 23 ; 25 /*------------------------------------------------------------------ * LEXER RULES 27 *------------------------------------------------------------------*/ 29 ID : (’a’..’z’|’A’..’Z’)+ ; INT : ’0’..’9’+ ; 31 NEWLINE:’r’? ’n’ ; WS : (’ ’|’t’)+ {skip();} ; Was ist die Aufgabe eines Lexers? Beispiel: -666.797E-14 Zum Ausprobieren der Parser einfach folgendem Rezept folgen: 41 • FPParser.jar herunterladen und mit
  • 50. direkte Ausgaben, Fehler Lexer Parser Character Token Abstract Strom Strom Syntax Tree (auch Scanner, Tokenizer) Struktur eines ANTLR-Parser Lexer, Parser, AST, Token vs. Character-Strom 42
  • 51. w i d t h = 2 0 0 ; n Characters ID = INT ; Tokens WS WS WS Von Characters zu Tokens Aufgabe des Lexers 43
  • 52. void multExpr() { try { atom(); while( <<next input symbol is '*' >> ) { match('*'); atom(); } } [... error handling] } void atom() { try { int alt=3; switch (<< next input symbol >>) { case INT: alt = 1; break; case ID: alt = 2; break; case '(': alt = 3; break; default: [error] } switch(alt){ case 1: match(INT); break; case 2: match(ID); break; case 3: match('('); expr(); match(')'); break; } Parser.java Was hinten herauskommt … } [... error handling] } 44
  • 53. 1 /*------------------------------------------------------------------ Arithmetik & Parsergeneratoren 3 * PARSER RULES *------------------------------------------------------------------*/ Grammatik prog: stat+ ; 5 { declaredVariables.add($ID.text); } stat: expr NEWLINE 7 |ID ’=’ expr NEWLINE |NEWLINE 9 ; 11 expr : multExpr ( (’+’ |’-’) multExpr )* 13 ; 15 multExpr : atom (’*’ atom )* 17 ; 19 atom : INT 21 |ID { declaredVariables.contains($ID.text) }? |’(’ expr ’)’ 23 ; 45 25 /*------------------------------------------------------------------
  • 54. 1 /*------------------------------------------------------------------ Arithmetik & Parsergeneratoren 3 * PARSER RULES *------------------------------------------------------------------*/ Grammatik prog: stat+ ; 5 { declaredVariables.add($ID.text); } stat: expr NEWLINE 7 |ID ’=’ expr NEWLINE |NEWLINE 9 ; 11 expr : multExpr ( (’+’ |’-’) multExpr )* 13 ; 15 multExpr : atom (’*’ atom )* 17 ; 19 atom : INT Test! 21 |ID { declaredVariables.contains($ID.text) }? |’(’ expr ’)’ 23 ; 45 25 /*------------------------------------------------------------------
  • 55. grammar IntExpr_Var; options { language = Java; superClass = RunnableParser; } @lexer::header{ package de.lmu.ifi.pms.parsergenerators; } @header{ package de.lmu.ifi.pms.parsergenerators; import java.util.Set; import java.util.HashSet; } @members { /** Set for maintaining already declared variables. */ Set declaredVariables = new HashSet(); public static RunnableParser getParserInstance(ANTLRStringStream stream){ [...] } public void run(ASTProcessor... processors){ try { Prolog prog(); } catch (Exception e) [...] } } 46
  • 56. prog: stat+ ; stat: // Semantic action for printing out the value returned by the evaluation of each expression expr NEWLINE { System.out.println(quot;Expression in line quot; + input.get(input.index()-1).getLine() + quot;: quot; + $expr.value);} // Semantic action for constructing the set of declared variables. | ID '=' expr NEWLINE { varValues.put($ID.text, new Integer($expr.value)); } | NEWLINE ; // All rules of the grammar get a return value, the computed value of their matching expression expr returns [int value] : e=multExpr {$value = $e.value;} // We need to distinguish addition and subtraction ( '+' e=multExpr {$value += $e.value;} | '-' e=multExpr {$value -= $e.value;} )* ; multExpr returns [int value] : e=atom {$value = $e.value;} ('*' e=atom {$value *= $e.value;})* ; atom returns [int value] : INT {$value = Integer.parseInt($INT.text);} | ID { Integer v = varValues.get($ID.text); if ( v!=null ) $value = v.intValue(); else throw new FailedPredicateException(input, quot;atomquot;, quot;undeclared variable quot;+$ID.text); } | '(' expr ')' {$value = $expr.value;} 47 ;
  • 57. prog: stat+ ; stat: // Semantic action for printing out the value returned by the evaluation of each expression expr NEWLINE { System.out.println(quot;Expression in line quot; + input.get(input.index()-1).getLine() + quot;: quot; + $expr.value);} // Semantic action for constructing the set of declared variables. | ID '=' expr NEWLINE { varValues.put($ID.text, new Integer($expr.value)); } | NEWLINE ; // All rules of the grammar get a return value, the computed value of their matching expression expr returns [int value] : e=multExpr {$value = $e.value;} // We need to distinguish addition and subtraction ( '+' e=multExpr {$value += $e.value;} | '-' e=multExpr {$value -= $e.value;} )* ; multExpr returns [int value] : e=atom {$value = $e.value;} ('*' e=atom {$value *= $e.value;})* ; atom returns [int value] : INT {$value = Integer.parseInt($INT.text);} | ID { Integer v = varValues.get($ID.text); if ( v!=null ) $value = v.intValue(); else throw new FailedPredicateException(input, quot;atomquot;, quot;undeclared variable quot;+$ID.text); } | '(' expr ')' {$value = $expr.value;} 47 ;
  • 58. public int expr() { int value = 0; // return value int e = 0; try { e = multExpr(); value = e; loop3: while(true) { int alt = 3; if (<<next input symbol is '+'>>) alt = 1; else if (<<next input symbol is '-'>>) alt = 2; switch(alt) { case 1: match('+'); e = multExpr(); value += e; break; case 2: [...] } } } } [...] Parser + Aktionen Was hinten herauskommt … 48
  • 59. 49
  • 60. Jenseits von Syntax Semantische Analyse Trennung syntaktische / semantische Analyse effiziente, kontext-freie Parser für syntaktische Analyse Semantische Analyse volle Programmiersprache mittels Traversierung/Transformation des AST aber: schwer, oft weitgehend unabhängig von Sprache, ineffizient Attribute Grammars (Attributgrammatiken), SDDs Formalismus zur Einbettung der semantischen in die syntaktische Analyse Anreicherung des ASTs durch “semantische” Attribute in der Praxis: oft auch Seiteneffekte 50
  • 61. Attribute Grammars Produktion Semantische Aktion 〈E〉 ::= 〈int〉 E.val = int.val | 〈E1 〉 ‘+’ 〈E2 〉 E.val = E1 .val + E2 .val | ‘(’ 〈E1 〉 ‘)’ E.val = E1 .val Beispiele 51
  • 62. Attribute Grammars Produktion Semantische Aktion 〈E〉 ::= 〈int〉 E.val = int.val | 〈E1 〉 ‘+’ 〈E2 〉 E.val = E1 .val + E2 .val | ‘(’ 〈E1 〉 ‘)’ E.val = E1 .val ).5&+$:'(!'$:2+#;(!+(4,&567.(012+$/3 Beispiele # M-+(&/U,,,,8,6,49,6,quot;5 # I%?*&'U,,,(&-8 @6A @4@ (&-9 @6A (&-quot; @5A *,V[R0; * L+%)C=-(%&',,,,,,,,,,,,,,,,,2^C0-(%&' R0;C*,40&),(', 2,,! 2! 6,29,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2[R0; O,2![R0;,6,29[R0 2! ! (&-8 2![R0;,O,(&-8[R0;,,O,8 'U 29 ! 4,2quot;5,,,,,,,,,,,,,,,,,,,,,,,,29[R0;,O,2quot;[R0; 2quot; ! 2H 6,28 2quot;[R0;,O,2H[R0;,6,28[R 2H ! (&-9 2H[R0;,O,(&-9[R0;,O,9 28 ! (&-quot; 28[R0;,O,(&-quot;[R0;,,O,quot; !Z Prof. Aiken CS 143 Lecture 6 51
  • 63. Attribute Grammars Produktion Semantische Aktion 〈E〉 ::= 〈int〉 E.val = int.val | 〈E1 〉 ‘+’ 〈E2 〉 E.val = E1 .val + E2 .val ).5&+$:'(!'$:2+#;(!+(4,&567.(012+$/3 | ‘(’ 〈E1 〉 ‘)’ E.val = E1 .val ).5&+$:'(!'$:2+#;(!+(4,&567.(012+$/3 Beispiele # M-+(&/U,,,,8,6,49,6,quot;5 # M-+(&/U,,,,8,6,49,6,quot;5 # I%?*&'U,,,(&-8 @6A @4@ (&-9 @6A (&-quot; @5A # I%?*&'U,,,(&-8 @6A @4@ (&-9 @6A (&-quot; @5A *,V[R0; * L+%)C=-(%&',,,,,,,,,,,,,,,,,2^C0-(%&' L+%)C=-(%&',,,,,,,,,,,,,,,,,2^C0-(%&' R0;C*,40&),(', 2,,! 2! 6,29,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2[R0; O,2![R0;,6,29[R0 2,,! 2! 6,29,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2[R0; O,2![R0;,6,29[R0; 2! ! (&-8 2!2! ! (&-88[R0;,,O,8 [R0;,O,(&- 2![R0;,O,(&-8[R0;,,O,8 'U 29 ! 4,2quot;5,,,,,,,,,,,,,,,,,,,,,,,,2929 ! 4,2[R0; [R0;,O,2quot; quot;5,,,,,,,,,,,,,,,,,,,,,,,,29[R0;,O,2quot;[R0; 2quot; ! 2H 6,28 2quot; ! 2 6,28 2quot;[R0;,O,2H [R0;,6,28[R0; 2quot;[R0;,O,2H[R0;,6,28[R H 2H ! (&-9 2H ! (&-9 2H[R0;,O,(&-9[R0;,O,9 2H[R0;,O,(&-9[R0;,O,9 28 ! (&-quot; 28 ! (&-quot; 28[R0;,O,(&-quot;[R0;,,O,quot; 28[R0;,O,(&-quot;[R0;,,O,quot; !Z Prof. Aiken CS 143 Lecture 6 Prof. Aiken CS 143 Lecture 6 !] 51
  • 64. /quot;0quot;%1quot;%(2)34$05 9 + # 9'+F,(-7%,8'D%8%7,9 F'.,-(%,.8-),0-6,)F%,>'8 9! A 9H '))6*D3)% # L-)%,)F%,7%/%(7%(+*%. *()B 5 J 9< + K 9@ A 9B *()H 2 *()< 3 Prof. Aiken CS 143 Lecture 6 HI 52
  • 65. /quot;0quot;%1quot;%(2)34$05 9 + # 9'+F,(-7%,8'D%8%7,9 F'.,-(%,.8-),0-6,)F%,>'8 9! A 9H '))6*D3)% # L-)%,)F%,7%/%(7%(+*%. *()B 5 J 9< + K /quot;0quot;%1quot;%(2)34$05 9@ A 9B 9 +-&/3)%7,'0)%6,'88,*)., 10 %(7%(+1,N6'/F,F'>%,D%%(, *() 2 H *()< 3 9! 5 A 9H 5 )6*D3)%.,+'(,D%,+-&/3)%7, Prof. Aiken CS 143 Lecture 6 HI *()B 5 J 9< 5 K QF%(,)F%6%,'6%,(-,+1+8%. 9@ 2 A 9B 3 D3)%.,'6%,(-),8%N'8 *()H 2 *()< 3 52 143 Lecture 6 H! Prof. Aiken CS 143 Lecture 6
  • 66. Jenseits von Syntax Attribute Grammars Attribute grammar := kontextfreie Grammatik mit Attributen und Regeln Attribute zu Symbolen, Regeln zu Produktionen S.a bezeichnet das Attribut ‘a’ des Symbols ‘S’ Synthetisiertes Attribut (“Rückgabewerte) a von S definiert nur unter Verwendung von Attributen von S und Kinder von S Vererbtes Attribut (“Parameter”) b von S definiert nur unter Verwendung von Attributen von S, des Vaters von S und der Geschwister von S 53
  • 67. Jenseits von Syntax Attribute Grammars Ergebnis: Gleichungssystem Auswertungsordnung ist nicht fixiert e.g., E3.val = E4.val + E5.val E4.val und E5.val nötig um E3.val zu berechnen (dependency) aber: ob erst E4.val oder E5.val berechnet wird ist offen Parser muß Auswertungsordnung festlegen Problem: zyklische Abhängigkeiten EXPTIME: für eine gegebene Grammatik feststellen, ob Abhängigkeiten für alle Parsebäume zyklenfrei sind. daher: Einschränkung von Attribute Grammars 54
  • 68. Jenseits von Syntax Attribute Grammars S-attributed attribute grammar entählt ausschließlich synthetisierte Attribute L-attributed attribute grammar: alle Attribute entweder synthetisiert oder vererbt, aber dann, für Regel A ::= X1 X2 … Xn Berechnung von Xi.a nur durch vererbte Attribute von A oder (synthetisierte oder vererbte) Attribute von Xj fuer j < i oder (synthetisierte oder vererbte) Attribute von Xi selbst falls nicht abhängig von a verwendet vor allem in Recursive Descent Parsern wie ANTLR 55
  • 69. | ‘(’ 〈E〉1 ‘)’ E.val = E1 .val bdigits2 .val 〈bnumeral〉 ::= 〈bdigits〉1 ‘.’ 〈bdigits〉2 bnumeral.val = bdigits1 .val + 2bdigits2 .len 〈bdigits〉 ::= 〈bdigits〉1 〈bit〉 bdigits.val = 2 · bdigits2 .val + bit.val bdigits.len = bdigits2 .len + 1 | 〈bit〉 bdigits.val = bit.val; bdigits.len = 1 〈bit〉 ::= ‘0’ bit.val = 0 | ‘1’ bit.val = 1 Beispiele 56
  • 70. | ‘(’ 〈E〉1 ‘)’ E.val = E1 .val Val (<bit>) ! 0 | 1 bdigits2 .val 〈bnumeral〉 ::= 〈bdigits〉1 ‘.’ 〈bdigits〉2 bnumeral.Val= bdigits1 .val + 2bdigits2 .len val (<bit>) ! 1 〈bdigits〉 ::= 〈bdigits〉1 〈bit〉 The derivation bdigits2 .val + bit.val illustrates the use of attributes that give the bdigits.val = 2 · tree in Figure 3.7 semantics for the binary numeral 1101.01 to be the real number 13.25. bdigits.len = bdigits .len + 1 2 | 〈bit〉 bdigits.val = bit.val; bdigits.len = 1 〈bit〉 ::= ‘0’ bit.val = 0 <binary numeral> | ‘1’ bit.val = 1 Val: 13 + 1/22 = 13.25 Beispiele <binary digits> <binary digits> Val : 13 Val : 1 Len : 4 Len : 2 <binary digits> <bit> <binary digits> <bit> Val : 6 Val : 1 Val : 0 Val : 1 Len : 3 Len : 1 1 1 <binary digits> <bit> <bit> Val : 3 Val : 0 Val : 0 Len : 2 0 0 <binary digits> <bit> Val : 1 Val : 1 Len : 1 1 <bit> Val : 1 1 56 Figure 3.7: Binary Numeral Semantics Using Synthesized Attributes
  • 71. D Fazit 57
  • 72. Zusammenfassung Parsergeneratoren 1. Implementierung von Endlichen Automaten loop-and-switch, loop-and-lookup, Lexer, Automatenbibliotheken manuelle Implementierung oft in Bibliotheken und bei zeitkritischem Parsing (Basispaarsequenzen) verwendet Lexer erlauben auch komplexe endliche Automaten ohne signifikanten Effizienzverlust Automatenbibliotheken ineffizienter als Lexer oder manuelle Implementierung aber: Konstruktion und Manipulation der Automaten zur Laufzeit möglich 58
  • 73. Zusammenfassung Parsergeneratoren 2. Implementierung von Kellerautomaten Parsergeneratoren manuelle Implementierung meist zu aufwendig Parsergeneratoren erzeugen Lexer und Parser Mehr als kontextfreie Sprachen dank semantischer Aktionen kontext-sensitive Eigenschaften “von Hand” programmieren Recursive-descent oder LL(k)/LL(*) Parser wie ANTLR einfach zu lesender Code, leichte manuelle Anpassung Andere verbreitete Ansätze: LR, LALR, Left-Corner, Earley 59
  • 74. Zusammenfassung Parsergeneratoren Beispielprogramme + Dokumentation im Laufe der Woche auf der Webseite Mehr Details zu Attributgrammatiken in den Übungen Kapitel 5, Drachenbuch (“Compilers …”, Aho et al., 2007) Selber ausprobieren! 60
  • 75. E Fragen 61