von automaten zu programmen–parsergeneratoren und attributgrammatiken
TRANSCRIPT
Von Automaten zu Programmen
1
Tim Furche
Compilerbau, Wintersemester 2008/09, Prof. F. Bry
Manuelle und automatische Entwicklung von Parsern
13
Parsen und Normalisieren mit Endlichem Automaten
Gleitpunktzahlen
$java‐jarFPParser.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
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
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
Ganzzahlen in JavaEndlicher Automat für den Ganzzahlparser in Long.parseLong
18
5
1 public static long parseLong(String s, int radix) throws NumberFormatException{
3 if (s == null) throw new NumberFormatException("null");[...]
5 int max = s.length();[...]
7 // State 1: Treat the signif (s.charAt(0) == ’-’) {
9 negative = true;limit = Long.MIN_VALUE;
11 i++;} else
13 limit = -Long.MAX_VALUE;
15 // State 2: Treat first digitif (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 digits25 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 "-" */37 throw NumberFormatException.forInputString(s);
} else39 return -result;
41 }
Istart F R
‘-’
‘0’–‘9’
‘0’–‘9’
‘0’–‘9’
19
5
1 public static long parseLong(String s, int radix) throws NumberFormatException{
3 if (s == null) throw new NumberFormatException("null");[...]
5 int max = s.length();[...]
7 // State 1: Treat the signif (s.charAt(0) == ’-’) {
9 negative = true;limit = Long.MIN_VALUE;
11 i++;} else
13 limit = -Long.MAX_VALUE;
15 // State 2: Treat first digitif (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 digits25 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 "-" */37 throw NumberFormatException.forInputString(s);
} else39 return -result;
41 }
2 Von der Spezifikation zum Parser
Kurz gesagt entwickelt man einen Parser für Werte (i.e., Worte) einer regulärenSprache wie folgt:
• Spezifikation der Sprache durch regulären Ausdruck oder Automat.
20
5
1 public static long parseLong(String s, int radix) throws NumberFormatException{
3 if (s == null) throw new NumberFormatException("null");[...]
5 int max = s.length();[...]
7 // State 1: Treat the signif (s.charAt(0) == ’-’) {
9 negative = true;limit = Long.MIN_VALUE;
11 i++;} else
13 limit = -Long.MAX_VALUE;
15 // State 2: Treat first digitif (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 digits25 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 "-" */37 throw NumberFormatException.forInputString(s);
} else39 return -result;
41 }
Istart F R
‘-’
‘0’–‘9’
‘0’–‘9’
‘0’–‘9’
Gleitpunktzahlen in JavaSpezifikation: Regulärer Ausdruck
22
6
2 Von der Spezifikation zum Parser
Kurz gesagt entwickelt man einen Parser für Werte (i.e., Worte) einer regulärenSprache wie folgt:
• Spezifikation der Sprache durch regulären Ausdruck oder Automat.
• Auswahl einer Implementierungstechnik.
• Anwendung des Musters der Implementierungstechnik.
Solange es nur um das Wortproblem geht, also die Erkennung, ob ein Wert teilder Sprache ist (eine String eine URI sein könnte), geht das rein mechanisch. So-bald jedoch auch Berechnungen auszuführen sind, z.B., das Berechnen der Gleit-punktzahl, ist es nötig den generischen Ansatz an die jeweilige Aufgabe anzupas-sen.
2.1 Regulärer Ausdruck für Gleitpunktzahlen
Für unser Beispiel beginnen wir mit einem regulären Ausdruck für die Art vonGleitpunktzahlen, die unser Parser erkennen soll:
(‘+’|‘-’)? digit+ (‘.’ digit+)? ((‘e’|‘E’) digit+)?
digit := ‘0’ | ‘1’ | ‘2’ | ‘3’ | ‘4’ | ‘5’ | ‘6’ | ‘7’ | ‘8’ | ‘9’digit+ := digit digit*
Die Spezifikation ist fast wie in den Übungen behandelt, allerdings erlauben wirdass der Nachkomma-Anteil wegfallen kann (wie der Exponent).
2.2 Endlicher Automat für Gleitpunktzahlen
Die gleiche Sprache können wir durch folgenden Automaten beschreiben:
6
2 Von der Spezifikation zum Parser
Kurz gesagt entwickelt man einen Parser für Werte (i.e., Worte) einer regulärenSprache wie folgt:
• Spezifikation der Sprache durch regulären Ausdruck oder Automat.
• Auswahl einer Implementierungstechnik.
• Anwendung des Musters der Implementierungstechnik.
Solange es nur um das Wortproblem geht, also die Erkennung, ob ein Wert teilder Sprache ist (eine String eine URI sein könnte), geht das rein mechanisch. So-bald jedoch auch Berechnungen auszuführen sind, z.B., das Berechnen der Gleit-punktzahl, ist es nötig den generischen Ansatz an die jeweilige Aufgabe anzupas-sen.
2.1 Regulärer Ausdruck für Gleitpunktzahlen
Für unser Beispiel beginnen wir mit einem regulären Ausdruck für die Art vonGleitpunktzahlen, die unser Parser erkennen soll:
(‘+’|‘-’)? digit+ (‘.’ digit+)? ((‘e’|‘E’) digit+)?
digit := ‘0’ | ‘1’ | ‘2’ | ‘3’ | ‘4’ | ‘5’ | ‘6’ | ‘7’ | ‘8’ | ‘9’digit+ := digit digit*
Die Spezifikation ist fast wie in den Übungen behandelt, allerdings erlauben wirdass der Nachkomma-Anteil wegfallen kann (wie der Exponent).
2.2 Endlicher Automat für Gleitpunktzahlen
Die gleiche Sprache können wir durch folgenden Automaten beschreiben:
23
7
Ss,dstart Sd
Sd ,p,e Fd Fd ,e
Es,d
Ed Ed ,#
‘+’, ‘-’
‘0’–‘9’‘0’–‘9’
‘0’–‘9’
‘.’
‘e’, ‘E’
‘0’–‘9’
‘0’–‘9’
‘e’, ‘E’
‘0’–‘9’
‘+’, ‘-’
‘0’–‘9’
‘0’–‘9’
Der Automat verwendet die folgenden Zustände, benannt nach denjenigenSymbolen des Alphabets, für die es einen Übergang in einen Nicht-Fehlerzustandgibt. Dabei nennen wir für eine Gleitpunktzahl s. f · 10e : s den significand (oderVorkomma-Anteil der Mantisse), f die fraction (oder Nachkomma-Anteil der Man-tisse), und e den exponent.
state part of number follow characters description
Ss,d significand digit (d ) or sign (s) initial state, recognizes optional sign
Sd –”– digit ensures at least one digit in the non-fraction part of the significand
Sd , f ,e –”– digit, or period (p) or e recognizes any number of digits and tran-sitions to fraction or exponent, final state
Fd fraction digit ensures at least one digit in fraction
Fd ,e –”– digit or e recognizes any number of digits and tran-sitions to exponent, final state
Es,d exponent digit or sign sign or digit as start of exponent
Ed –”– digit ensures at least one digit in exponent
Ed –”– digit recognizes any number of digits, finalstate
24
7
Ss,dstart Sd
Sd ,p,e Fd Fd ,e
Es,d
Ed Ed ,#
‘+’, ‘-’
‘0’–‘9’‘0’–‘9’
‘0’–‘9’
‘.’
‘e’, ‘E’
‘0’–‘9’
‘0’–‘9’
‘e’, ‘E’
‘0’–‘9’
‘+’, ‘-’
‘0’–‘9’
‘0’–‘9’
Der Automat verwendet die folgenden Zustände, benannt nach denjenigenSymbolen des Alphabets, für die es einen Übergang in einen Nicht-Fehlerzustandgibt. Dabei nennen wir für eine Gleitpunktzahl s. f · 10e : s den significand (oderVorkomma-Anteil der Mantisse), f die fraction (oder Nachkomma-Anteil der Man-tisse), und e den exponent.
Zustand Teil der Zahl Nachfolgerzeichen Beschreibung
Ss,d significand Ziffer (d ) oder Vorzeichen (s) Anfangszustand, erkennt optionales Vor-zeichen
Sd –”– Ziffer stellt sicher, dass zumindest eine Ziffer imsignificand vorkommt
Sd , f ,e –”– Ziffer, Punkt (p) oder e erkennt beliebige Folgen von Ziffern, fährtmit Erkennung von fraction oder expo-nent fort, Endzustand
Fd fraction Ziffer stellt sicher, dass zumindest eine Ziffer infraction vorkommt
Fd ,e –”– Ziffer or e erkennt beliebige Folgen von Ziffern, fährtmit Erkennung von exponent fort, Endzu-stand
Es,d exponent Ziffer oder Vorzeichen Ziffer oder Vorzeichen als Beginn des ex-ponent
Ed –”– digit stellt sicher, dass zumindest eine Ziffer inexponent vorkommt
Ed –”– digit erkennt beliebige Folgen von Ziffern, End-zustand
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
Ansätze …
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
26
Implementierung Endlicher Automaten
Umgebung für FP-Parser …
FPParser
27
Implementierung Endlicher Automaten
Loop-and-Switch …
8
3 Diskussion der Implementierungsansätze
Diesen Automaten können wir auf unterschiedliche Weise implementieren. InFPParser.jar finden sich drei gebräuchliche Varianten. Alle varianten haben ge-meinsam, dass sie über alle Zeichen der Eingabe iterieren (daher der loop-Anteilim Nahmen). Für bestimmte Parsing-Probleme (z.B. mit eingeschränkteren Spra-chen wie dem Suchen von Vorkommen eines Strings in einem Text) gibt es Par-ser, die nicht alle Zeichen der Eingabe betrachten müßen. Diese werden hier abernicht weiter betrachtet.
Loop-and-Switch: realisiert in PlainFPParser. Die Idee von loop-and-switch Im-plementierungen ist, in der Schleife über die Eingabezeichen mit Hilfe vonBedingungen oder Switch-Ausdrücken für alle relevanten Kombinationenaus Zustand und Eingabezeichen den Folgezustand (und eventuelle Berech-nungsschritte) zu spezifizieren.
Dies ist illustriert in PlainFPParser#parse(char). Das folgende Programm-frament illustriert beispielsweise die Übergangsfunktion für den ZustandSd , f ,e (im Code expandiert zu STATE_SignifDigit_Fraction_Exponent): beieiner Ziffer bleiben wir im gleichen Zustand und fügen die Ziffer zur aktu-ellen Repräsentation des significand hinzu. Bei einem Punkt gehen wir inden Zustand Fd , also erwarten die erste Ziffer der fraction (würden wir hierin Fd ,e übergehen, wären auch Zahlen der Form 12.E10 erlaubt). Bei eineme oder E gehen wir in Zustand Es,d (STATE_Exponent). In den beiden letztenFä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-ner (konstanten) Lookup-Tabelle den Folgezustand (und eventuelle Berech-
27
Implementierung Endlicher Automaten
Loop-and-Switch …
8
3 Diskussion der Implementierungsansätze
Diesen Automaten können wir auf unterschiedliche Weise implementieren. InFPParser.jar finden sich drei gebräuchliche Varianten. Alle varianten haben ge-meinsam, dass sie über alle Zeichen der Eingabe iterieren (daher der loop-Anteilim Nahmen). Für bestimmte Parsing-Probleme (z.B. mit eingeschränkteren Spra-chen wie dem Suchen von Vorkommen eines Strings in einem Text) gibt es Par-ser, die nicht alle Zeichen der Eingabe betrachten müßen. Diese werden hier abernicht weiter betrachtet.
Loop-and-Switch: realisiert in PlainFPParser. Die Idee von loop-and-switch Im-plementierungen ist, in der Schleife über die Eingabezeichen mit Hilfe vonBedingungen oder Switch-Ausdrücken für alle relevanten Kombinationenaus Zustand und Eingabezeichen den Folgezustand (und eventuelle Berech-nungsschritte) zu spezifizieren.
Dies ist illustriert in PlainFPParser#parse(char). Das folgende Programm-frament illustriert beispielsweise die Übergangsfunktion für den ZustandSd , f ,e (im Code expandiert zu STATE_SignifDigit_Fraction_Exponent): beieiner Ziffer bleiben wir im gleichen Zustand und fügen die Ziffer zur aktu-ellen Repräsentation des significand hinzu. Bei einem Punkt gehen wir inden Zustand Fd , also erwarten die erste Ziffer der fraction (würden wir hierin Fd ,e übergehen, wären auch Zahlen der Form 12.E10 erlaubt). Bei eineme oder E gehen wir in Zustand Es,d (STATE_Exponent). In den beiden letztenFä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-ner (konstanten) Lookup-Tabelle den Folgezustand (und eventuelle Berech-
PlainFPParser
28
Implementierung Endlicher Automaten
Loop-and-Switch …
10
SIGNIF_DIGIT_FRACTION_EXPONENT {2 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 },
3.1 Tests
Um sich zu vergewissern, dass die Implementierungen weitgehend korrekt sind,steht das Kommandozeilen-Interface in FPParserCLI zur Verfügung. Daneben gibtes auch einen JUnit 4 Testcase in FPParserTestCase der gleich eine ganze Rei-he von kanonischen Eingaben testet. Zur Ausführung wird JUnit 4 benötigt, siehehttp://www.junit.org/.
28
Implementierung Endlicher Automaten
Loop-and-Switch …
10
SIGNIF_DIGIT_FRACTION_EXPONENT {2 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 },
3.1 Tests
Um sich zu vergewissern, dass die Implementierungen weitgehend korrekt sind,steht das Kommandozeilen-Interface in FPParserCLI zur Verfügung. Daneben gibtes auch einen JUnit 4 Testcase in FPParserTestCase der gleich eine ganze Rei-he von kanonischen Eingaben testet. Zur Ausführung wird JUnit 4 benötigt, siehehttp://www.junit.org/.
EnumFPParser
29
Implementierung Endlicher Automaten
Loop-and-Lookup …
9
nungsschritte) zu spezifizieren. In der Lookup-Tabelle sind den ZuständenZeilen, den Eingabezeichen Spalten zugeordnet.
Die Lookup-Tabelle findet sich in MatrixFPParser#stateMatrix und ist eineziemlich direkte Umsetzung der ! Übergangsfunktion des Automaten. Fürden 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, dassden nächsten Zustand und die auszuführenden Berechnungsschritteenthält. Um die Berechnungsschritte zu paramerterisieren verwendetMatrixFPParser Funktionsobjekte (wo Sprachen wie C++ Funktionspointerverwenden würden), siehe DigitEffect und SignEffect.
Loop-and-Switch mit Zustandsobjekten: realisiert in EnumFPParser. Eine elegantereRealisierung des loop-and-switch Ansatzes, die Zustandsobjekte, eine enumKlasse und anonyme Klassen für die Spezialisierung abstrakter enum Klassenverwendet, um alle Informationen über einen Zustand zu kapseln.
Die Spezifikation eines Zustandes, wie im folgenden gezeigt, enthält hier al-le relevanten Information, so dass man direkt sehen kann, ob es sich z.B. umeinen Endzustand handelt. Auch die Übergangsfunktion ist so klar partitio-niert:
SIGNIF_DIGIT_FRACTION_EXPONENT {2 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;
}
29
Implementierung Endlicher Automaten
Loop-and-Lookup …
MatrixFPParser
9
nungsschritte) zu spezifizieren. In der Lookup-Tabelle sind den ZuständenZeilen, den Eingabezeichen Spalten zugeordnet.
Die Lookup-Tabelle findet sich in MatrixFPParser#stateMatrix und ist eineziemlich direkte Umsetzung der ! Übergangsfunktion des Automaten. Fürden 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, dassden nächsten Zustand und die auszuführenden Berechnungsschritteenthält. Um die Berechnungsschritte zu paramerterisieren verwendetMatrixFPParser Funktionsobjekte (wo Sprachen wie C++ Funktionspointerverwenden würden), siehe DigitEffect und SignEffect.
Loop-and-Switch mit Zustandsobjekten: realisiert in EnumFPParser. Eine elegantereRealisierung des loop-and-switch Ansatzes, die Zustandsobjekte, eine enumKlasse und anonyme Klassen für die Spezialisierung abstrakter enum Klassenverwendet, um alle Informationen über einen Zustand zu kapseln.
Die Spezifikation eines Zustandes, wie im folgenden gezeigt, enthält hier al-le relevanten Information, so dass man direkt sehen kann, ob es sich z.B. umeinen Endzustand handelt. Auch die Übergangsfunktion ist so klar partitio-niert:
SIGNIF_DIGIT_FRACTION_EXPONENT {2 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;
}
30
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
31
Parsen und Normalisieren mit Endlichem Automaten
Gleitpunktzahlen
$java‐jarFPParser.jar33E0‐‐step‐‐pEnum
(INITIAL,33E0)
|‐(SIGNIF_DIGIT_FRACTION_EXPONENT,3E0)
|‐(SIGNIF_DIGIT_FRACTION_EXPONENT,E0)
|‐(EXPONENT,0)
|‐(EXPONENT_DIGIT_END,<epsilon>)
Success:33.0
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
Parser für kontextfreie Sprachen++z.B. für arithmetische Ausdrücke und Erweiterungen
33
BKeller-
Automaten
36
Parsen und Ausrechnen mit Kellerautomaten
Arithmetische Ausdrücke
$java‐jarParserGenerators.jar‐‐pIntExpr_Eval‐‐fileplain‐intexpr
Expressioninline1:42
2+4*11‐2*3+2
$java‐jarParserGenerators.jar‐‐pIntExpr_AST‐‐fileplain‐intexpr
(+(‐(+2(*411))(*23))2)
$java‐jarParserGenerators.jar‐‐pIntExpr‐‐fileplain‐intexpr
<nooutput>(=noerror)
38
Parsen und Ausrechnen mit Kellerautomaten
+ Variablen
$java‐jarParserGenerators.jar‐‐pIntExpr_Var‐‐filevar‐intexpr
line3:24ruleatomfailedpredicate:{declaredVariables.contains($ID.text)}?
$java‐jarParserGenerators.jar‐‐pIntExpr_Eval‐‐filevar‐intexpr
line3:24ruleatomfailedpredicate:{undeclaredvariablez}?
Expressioninline3:420
Expressioninline4:6
$java‐jarParserGenerators.jar‐‐pIntExpr‐‐filevar‐intexpr
<nooutput>(=noerror)
x=78
y=2
112+4*x‐2*y+z*2
5+3‐2
Arithmetik & Parsergeneratoren
Grammatik
40
3
1 /*------------------------------------------------------------------
* PARSER RULES3 *------------------------------------------------------------------*/prog: stat+ ;
5
stat: expr NEWLINE7 |ID ’=’ expr NEWLINE
|NEWLINE9 ;
11 expr: multExpr ( (’+’ |’-’) multExpr )*
13 ;
15 multExpr: atom (’*’ atom )*
17 ;
19 atom: INT
21 |ID|’(’ expr ’)’
23 ;
25 /*------------------------------------------------------------------
* LEXER RULES27 *------------------------------------------------------------------*/
29 ID : (’a’..’z’|’A’..’Z’)+ ;INT : ’0’..’9’+ ;
31 NEWLINE:’\r’? ’\n’ ;WS : (’ ’|’\t’)+ {skip();} ;
Beispiel: -666.797E-14
Zum Ausprobieren der Parser einfach folgendem Rezept folgen:
• FPParser.jar herunterladen und mit
$ java -jar FPParser.jar
testen, ob alle Abhängigkeiten vorhanden sind (Java >= 1.5, nur für Testcasesauch JUnit 4).
• Wenn das klappt, einfach Gleitpunktzahl als Parameter übergeben:
Arithmetik & Parsergeneratoren
Lexer-Regeln der Grammatik
41
3
1 /*------------------------------------------------------------------
* PARSER RULES3 *------------------------------------------------------------------*/prog: stat+ ;
5
stat: expr NEWLINE7 |ID ’=’ expr NEWLINE
|NEWLINE9 ;
11 expr: multExpr ( (’+’ |’-’) multExpr )*
13 ;
15 multExpr: atom (’*’ atom )*
17 ;
19 atom: INT
21 |ID|’(’ expr ’)’
23 ;
25 /*------------------------------------------------------------------
* LEXER RULES27 *------------------------------------------------------------------*/
29 ID : (’a’..’z’|’A’..’Z’)+ ;INT : ’0’..’9’+ ;
31 NEWLINE:’\r’? ’\n’ ;WS : (’ ’|’\t’)+ {skip();} ;
Beispiel: -666.797E-14
Zum Ausprobieren der Parser einfach folgendem Rezept folgen:
• FPParser.jar herunterladen und mit
$ java -jar FPParser.jar
testen, ob alle Abhängigkeiten vorhanden sind (Java >= 1.5, nur für Testcasesauch JUnit 4).
• Wenn das klappt, einfach Gleitpunktzahl als Parameter übergeben:
Was ist die Aufgabe eines Lexers?
Struktur eines ANTLR-ParserLexer, Parser, AST, Token vs. Character-Strom
42
Lexer ParserTokenStrom
Abstract Syntax Tree
(auch Scanner, Tokenizer)
CharacterStrom
direkte Ausgaben, Fehler
Von Characters zu TokensAufgabe des Lexers
43
WS
w i d t h = 2 0 0 ; \n
ID
Characters
WS= INT ;
WSTokens
Parser.javaWas hinten herauskommt …
44
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; } } [... error handling] }
Arithmetik & Parsergeneratoren
Grammatik
45
3
1 /*------------------------------------------------------------------
* PARSER RULES3 *------------------------------------------------------------------*/prog: stat+ ;
5
stat: expr NEWLINE7 |ID ’=’ expr NEWLINE
|NEWLINE9 ;
11 expr: multExpr ( (’+’ |’-’) multExpr )*
13 ;
15 multExpr: atom (’*’ atom )*
17 ;
19 atom: INT
21 |ID|’(’ expr ’)’
23 ;
25 /*------------------------------------------------------------------
* LEXER RULES27 *------------------------------------------------------------------*/
29 ID : (’a’..’z’|’A’..’Z’)+ ;INT : ’0’..’9’+ ;
31 NEWLINE:’\r’? ’\n’ ;WS : (’ ’|’\t’)+ {skip();} ;
Beispiel: -666.797E-14
Zum Ausprobieren der Parser einfach folgendem Rezept folgen:
• FPParser.jar herunterladen und mit
$ java -jar FPParser.jar
testen, ob alle Abhängigkeiten vorhanden sind (Java >= 1.5, nur für Testcasesauch JUnit 4).
• Wenn das klappt, einfach Gleitpunktzahl als Parameter übergeben:
{ declaredVariables.add($ID.text); }
{ declaredVariables.contains($ID.text) }?
Arithmetik & Parsergeneratoren
Grammatik
45
3
1 /*------------------------------------------------------------------
* PARSER RULES3 *------------------------------------------------------------------*/prog: stat+ ;
5
stat: expr NEWLINE7 |ID ’=’ expr NEWLINE
|NEWLINE9 ;
11 expr: multExpr ( (’+’ |’-’) multExpr )*
13 ;
15 multExpr: atom (’*’ atom )*
17 ;
19 atom: INT
21 |ID|’(’ expr ’)’
23 ;
25 /*------------------------------------------------------------------
* LEXER RULES27 *------------------------------------------------------------------*/
29 ID : (’a’..’z’|’A’..’Z’)+ ;INT : ’0’..’9’+ ;
31 NEWLINE:’\r’? ’\n’ ;WS : (’ ’|’\t’)+ {skip();} ;
Beispiel: -666.797E-14
Zum Ausprobieren der Parser einfach folgendem Rezept folgen:
• FPParser.jar herunterladen und mit
$ java -jar FPParser.jar
testen, ob alle Abhängigkeiten vorhanden sind (Java >= 1.5, nur für Testcasesauch JUnit 4).
• Wenn das klappt, einfach Gleitpunktzahl als Parameter übergeben:
{ declaredVariables.add($ID.text); }
{ declaredVariables.contains($ID.text) }?Test!
46
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 { prog(); } catch (Exception e) [...] }}
Prolog
47
prog: stat+ ; stat: // Semantic action for printing out the value returned by the evaluation of each expression expr NEWLINE { System.out.println("Expression in line " + input.get(input.index()-1).getLine() + ": " + $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 expressionexpr 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, "atom", "undeclared variable "+$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("Expression in line " + input.get(input.index()-1).getLine() + ": " + $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 expressionexpr 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, "atom", "undeclared variable "+$ID.text); } | '(' expr ')' {$value = $expr.value;} ;
Parser + AktionenWas hinten herauskommt …
48
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: [...] } } } [...] }
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
Jenseits von Syntax
Semantische Analyse
51
2
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
2
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
3
Prof. Aiken CS 143 Lecture 6 !"
!"#$%&'$()*+$&,(-%../(012+$/3
# $%&'()*+,-.*,/+0110+2,! (&- 3,4,2,5,3,2,6,2,
# 7&),-.*,'-+(&/8,6,49,6,"5
# 7:-*+,;*<(=0;,0&0;>'(',40,;('-,%:,-%?*&'5(&-8 @6A @4@ (&-9 @6A (&-" @5A
# BC+(&/,D0+'(&/,E*,FC(;),0,D0+'*,-+**,G
Prof. Aiken CS 143 Lecture 6 !H
4,&567.(28(9&%#.(-%..
2
2 2
4 2 5
6
2 6
(&-8
(&-9
2
(&-"
# I+0=*',-.*,%D*+0-(%&,%:,-.*,D0+'*+
# B%*',=0D-C+*,-.*,&*'-(&/,'-+C=-C+*
# JC-,-%%,1C=.,(&:%K L0+*&-.*'*'K M(&/;*N'C==*''%+,
&%)*'
Prof. Aiken CS 143 Lecture 6 !8
4,&567.(28(!"#$%&'$()*+$&,(-%..
# 7;'%,=0D-C+*',-.*,&*'-(&/,'-+C=-C+*
# JC-,0F'-+0=-' :+%1,-.*,=%&=+*-*,'>&-0<OP,1%+*,=%1D0=-,0&),*0'(*+,-%,C'*
# 7&,(1D%+-0&-,)0-0,'-+C=-C+*,(&,0,=%1D(;*+
PLUS
PLUS
25 3
Prof. Aiken CS 143 Lecture 6 !Q
).5&+$:'(!'$:2+#
# I.(',(',E.0-,E*A;;,C'*,-%,=%&'-+C=-,7MI'
# 20=.,/+0110+,'>1F%;,10>,.0R*,0--+(FC-*'K S%+,-*+1(&0;,'>1F%;',4;*<(=0;,-%?*&'5,0--+(FC-*',=0&,F*,=0;=C;0-*),F>,-.*,;*<*+
# 20=.,D+%)C=-(%&,10>,.0R*,0&,0=-(%&K T+(--*&,0'U,,,, V,! W! G W& X,0=-(%&,Y
K I.0-,=0&,+*:*+,-%,%+,=%1DC-*,'>1F%;,0--+(FC-*'
Prof. Aiken CS 143 Lecture 6 !Z
).5&+$:'(!'$:2+#;(!+(4,&567.
# $%&'()*+,-.*,/+0110+2,! (&- 3,2,6,2,3,4,2,5
# S%+,*0=.,'>1F%;,V )*:(&*,0&,0--+(FC-*,V[R0;K S%+,-*+1(&0;'\,R0; (',-.*,0''%=(0-*),;*<*1*K S%+,&%&N-*+1(&0;'\,R0; (',-.*,*<D+*''(%&A',R0;C*,40&),(',
=%1DC-*),:+%1,R0;C*',%:,'CF*<D+*''(%&'5
# T*,0&&%-0-*,-.*,/+0110+,E(-.,0=-(%&'U2,! (&- X,2[R0; O,(&-[R0; Y
3,2! 6,29 X,2[R0; O,2![R0;,6,29[R0;,Y3,4,2! 5,,,,,,,,,,,,,,,X,2[R0; O,2![R0;,Y
Prof. Aiken CS 143 Lecture 6 !]
).5&+$:'(!'$:2+#;(!+(4,&567.(012+$/3
L+%)C=-(%&',,,,,,,,,,,,,,,,,2^C0-(%&'2,,! 2! 6,29,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2[R0; O,2![R0;,6,29[R0;
2! ! (&-8 2![R0;,O,(&-8[R0;,,O,8
29 ! 4,2"5,,,,,,,,,,,,,,,,,,,,,,,,29[R0;,O,2"[R0;
2" ! 2H 6,28 2"[R0;,O,2H[R0;,6,28[R0;
2H ! (&-9 2H[R0;,O,(&-9[R0;,O,9
28 ! (&-" 28[R0;,O,(&-"[R0;,,O,"
# M-+(&/U,,,,8,6,49,6,"5
# I%?*&'U,,,(&-8 @6A @4@ (&-9 @6A (&-" @5A
51
2
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
3
Prof. Aiken CS 143 Lecture 6 !"
!"#$%&'$()*+$&,(-%../(012+$/3
# $%&'()*+,-.*,/+0110+2,! (&- 3,4,2,5,3,2,6,2,
# 7&),-.*,'-+(&/8,6,49,6,"5
# 7:-*+,;*<(=0;,0&0;>'(',40,;('-,%:,-%?*&'5(&-8 @6A @4@ (&-9 @6A (&-" @5A
# BC+(&/,D0+'(&/,E*,FC(;),0,D0+'*,-+**,G
Prof. Aiken CS 143 Lecture 6 !H
4,&567.(28(9&%#.(-%..
2
2 2
4 2 5
6
2 6
(&-8
(&-9
2
(&-"
# I+0=*',-.*,%D*+0-(%&,%:,-.*,D0+'*+
# B%*',=0D-C+*,-.*,&*'-(&/,'-+C=-C+*
# JC-,-%%,1C=.,(&:%K L0+*&-.*'*'K M(&/;*N'C==*''%+,
&%)*'
Prof. Aiken CS 143 Lecture 6 !8
4,&567.(28(!"#$%&'$()*+$&,(-%..
# 7;'%,=0D-C+*',-.*,&*'-(&/,'-+C=-C+*
# JC-,0F'-+0=-' :+%1,-.*,=%&=+*-*,'>&-0<OP,1%+*,=%1D0=-,0&),*0'(*+,-%,C'*
# 7&,(1D%+-0&-,)0-0,'-+C=-C+*,(&,0,=%1D(;*+
PLUS
PLUS
25 3
Prof. Aiken CS 143 Lecture 6 !Q
).5&+$:'(!'$:2+#
# I.(',(',E.0-,E*A;;,C'*,-%,=%&'-+C=-,7MI'
# 20=.,/+0110+,'>1F%;,10>,.0R*,0--+(FC-*'K S%+,-*+1(&0;,'>1F%;',4;*<(=0;,-%?*&'5,0--+(FC-*',=0&,F*,=0;=C;0-*),F>,-.*,;*<*+
# 20=.,D+%)C=-(%&,10>,.0R*,0&,0=-(%&K T+(--*&,0'U,,,, V,! W! G W& X,0=-(%&,Y
K I.0-,=0&,+*:*+,-%,%+,=%1DC-*,'>1F%;,0--+(FC-*'
Prof. Aiken CS 143 Lecture 6 !Z
).5&+$:'(!'$:2+#;(!+(4,&567.
# $%&'()*+,-.*,/+0110+2,! (&- 3,2,6,2,3,4,2,5
# S%+,*0=.,'>1F%;,V )*:(&*,0&,0--+(FC-*,V[R0;K S%+,-*+1(&0;'\,R0; (',-.*,0''%=(0-*),;*<*1*K S%+,&%&N-*+1(&0;'\,R0; (',-.*,*<D+*''(%&A',R0;C*,40&),(',
=%1DC-*),:+%1,R0;C*',%:,'CF*<D+*''(%&'5
# T*,0&&%-0-*,-.*,/+0110+,E(-.,0=-(%&'U2,! (&- X,2[R0; O,(&-[R0; Y
3,2! 6,29 X,2[R0; O,2![R0;,6,29[R0;,Y3,4,2! 5,,,,,,,,,,,,,,,X,2[R0; O,2![R0;,Y
Prof. Aiken CS 143 Lecture 6 !]
).5&+$:'(!'$:2+#;(!+(4,&567.(012+$/3
L+%)C=-(%&',,,,,,,,,,,,,,,,,2^C0-(%&'2,,! 2! 6,29,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2[R0; O,2![R0;,6,29[R0;
2! ! (&-8 2![R0;,O,(&-8[R0;,,O,8
29 ! 4,2"5,,,,,,,,,,,,,,,,,,,,,,,,29[R0;,O,2"[R0;
2" ! 2H 6,28 2"[R0;,O,2H[R0;,6,28[R0;
2H ! (&-9 2H[R0;,O,(&-9[R0;,O,9
28 ! (&-" 28[R0;,O,(&-"[R0;,,O,"
# M-+(&/U,,,,8,6,49,6,"5
# I%?*&'U,,,(&-8 @6A @4@ (&-9 @6A (&-" @5A
3
Prof. Aiken CS 143 Lecture 6 !"
!"#$%&'$()*+$&,(-%../(012+$/3
# $%&'()*+,-.*,/+0110+2,! (&- 3,4,2,5,3,2,6,2,
# 7&),-.*,'-+(&/8,6,49,6,"5
# 7:-*+,;*<(=0;,0&0;>'(',40,;('-,%:,-%?*&'5(&-8 @6A @4@ (&-9 @6A (&-" @5A
# BC+(&/,D0+'(&/,E*,FC(;),0,D0+'*,-+**,G
Prof. Aiken CS 143 Lecture 6 !H
4,&567.(28(9&%#.(-%..
2
2 2
4 2 5
6
2 6
(&-8
(&-9
2
(&-"
# I+0=*',-.*,%D*+0-(%&,%:,-.*,D0+'*+
# B%*',=0D-C+*,-.*,&*'-(&/,'-+C=-C+*
# JC-,-%%,1C=.,(&:%K L0+*&-.*'*'K M(&/;*N'C==*''%+,
&%)*'
Prof. Aiken CS 143 Lecture 6 !8
4,&567.(28(!"#$%&'$()*+$&,(-%..
# 7;'%,=0D-C+*',-.*,&*'-(&/,'-+C=-C+*
# JC-,0F'-+0=-' :+%1,-.*,=%&=+*-*,'>&-0<OP,1%+*,=%1D0=-,0&),*0'(*+,-%,C'*
# 7&,(1D%+-0&-,)0-0,'-+C=-C+*,(&,0,=%1D(;*+
PLUS
PLUS
25 3
Prof. Aiken CS 143 Lecture 6 !Q
).5&+$:'(!'$:2+#
# I.(',(',E.0-,E*A;;,C'*,-%,=%&'-+C=-,7MI'
# 20=.,/+0110+,'>1F%;,10>,.0R*,0--+(FC-*'K S%+,-*+1(&0;,'>1F%;',4;*<(=0;,-%?*&'5,0--+(FC-*',=0&,F*,=0;=C;0-*),F>,-.*,;*<*+
# 20=.,D+%)C=-(%&,10>,.0R*,0&,0=-(%&K T+(--*&,0'U,,,, V,! W! G W& X,0=-(%&,Y
K I.0-,=0&,+*:*+,-%,%+,=%1DC-*,'>1F%;,0--+(FC-*'
Prof. Aiken CS 143 Lecture 6 !Z
).5&+$:'(!'$:2+#;(!+(4,&567.
# $%&'()*+,-.*,/+0110+2,! (&- 3,2,6,2,3,4,2,5
# S%+,*0=.,'>1F%;,V )*:(&*,0&,0--+(FC-*,V[R0;K S%+,-*+1(&0;'\,R0; (',-.*,0''%=(0-*),;*<*1*K S%+,&%&N-*+1(&0;'\,R0; (',-.*,*<D+*''(%&A',R0;C*,40&),(',
=%1DC-*),:+%1,R0;C*',%:,'CF*<D+*''(%&'5
# T*,0&&%-0-*,-.*,/+0110+,E(-.,0=-(%&'U2,! (&- X,2[R0; O,(&-[R0; Y
3,2! 6,29 X,2[R0; O,2![R0;,6,29[R0;,Y3,4,2! 5,,,,,,,,,,,,,,,X,2[R0; O,2![R0;,Y
Prof. Aiken CS 143 Lecture 6 !]
).5&+$:'(!'$:2+#;(!+(4,&567.(012+$/3
L+%)C=-(%&',,,,,,,,,,,,,,,,,2^C0-(%&'2,,! 2! 6,29,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2[R0; O,2![R0;,6,29[R0;
2! ! (&-8 2![R0;,O,(&-8[R0;,,O,8
29 ! 4,2"5,,,,,,,,,,,,,,,,,,,,,,,,29[R0;,O,2"[R0;
2" ! 2H 6,28 2"[R0;,O,2H[R0;,6,28[R0;
2H ! (&-9 2H[R0;,O,(&-9[R0;,O,9
28 ! (&-" 28[R0;,O,(&-"[R0;,,O,"
# M-+(&/U,,,,8,6,49,6,"5
# I%?*&'U,,,(&-8 @6A @4@ (&-9 @6A (&-" @5A
52
4
Prof. Aiken CS 143 Lecture 6 !"
!"#$%&'()*(&'+%,-).+&",
# $%&'()*+,'+)*-(.,./%+*01,',.1.)%&,-0,%23')*-(.4 567%6,-0,6%.-83)*-(,*.,(-),./%+*0*%7
# 9:'&/8%;9<=>'8,?,9@=>'8,A,9B=>'8
4 C3.),+-&/3)% 9@=>'8 '(7,9B=>'8 D%0-6%,9<=>'84 E%,.'1,)F') 9<=>'8 7%/%(7.,-(,9@=>'8 '(7,9B=>'8
# GF%,/'6.%6,&3.),0*(7,)F%,-67%6,-0,%>'83')*-(
Prof. Aiken CS 143 Lecture 6 HI
/"0"%1"%(2)34$05
9
9! 9H
J 9< K
A
9@A
*()B
*()H
9B
*()<
+
+
2
5
# 9'+F,(-7%,8'D%8%7,9F'.,-(%,.8-),0-6,)F%,>'8'))6*D3)%
# L-)%,)F%,7%/%(7%(+*%.
3
Prof. Aiken CS 143 Lecture 6 H!
67$89$&'%:)*&&4';9&",
# M(,'))6*D3)%,&3.),D%,+-&/3)%7,'0)%6,'88,*).,.3++%..-6.,*(,)F%,7%/%(7%(+1,N6'/F,F'>%,D%%(,+-&/3)%7,4 O(,/6%>*-3.,%:'&/8%,'))6*D3)%.,+'(,D%,+-&/3)%7,D-))-&P3/
# $3+F,'(,-67%6,%:*.).,QF%(,)F%6%,'6%,(-,+1+8%.4 R1+8*+'881,7%0*(%7,'))6*D3)%.,'6%,(-),8%N'8
Prof. Aiken CS 143 Lecture 6 HH
/"0"%1"%(2)34$05
9
9! 9H
J 9< K
A
9@A
*()B
*()H
9B
*()<
10
5
5 5
32
2
5
3
Prof. Aiken CS 143 Lecture 6 H<
!"#$%&'()*(&'+%,-).+&",)<=+%&>?
# $1()F%.*S%7 '))6*D3)%.4 R'8+38')%7,06-&,'))6*D3)%.,-0,7%.+%(7%().,*(,)F%,/'6.%,)6%%
4 9=>'8 *.,',.1()F%.*S%7,'))6*D3)%
4 R'(,'8Q'1.,D%,+'8+38')%7,*(,',D-))-&P3/,-67%6
# T6'&&'6.,Q*)F,-(81,.1()F%.*S%7,'))6*D3)%.,'6%,+'88%7,$P'))6*D3)%7 N6'&&'6.4 C-.),+-&&-(,+'.%
Prof. Aiken CS 143 Lecture 6 H@
@%5"4'&"1)*&&4';9&",
# M(-)F%6,U*(7,-0,'))6*D3)%
# R'8+38')%7,06-&,'))6*D3)%.,-0,/'6%(),'(7V-6,.*D8*(N.,*(,)F%,/'6.%,)6%%
# 9:'&/8%;,',8*(%,+'8+38')-6
52
4
Prof. Aiken CS 143 Lecture 6 !"
!"#$%&'()*(&'+%,-).+&",
# $%&'()*+,'+)*-(.,./%+*01,',.1.)%&,-0,%23')*-(.4 567%6,-0,6%.-83)*-(,*.,(-),./%+*0*%7
# 9:'&/8%;9<=>'8,?,9@=>'8,A,9B=>'8
4 C3.),+-&/3)% 9@=>'8 '(7,9B=>'8 D%0-6%,9<=>'84 E%,.'1,)F') 9<=>'8 7%/%(7.,-(,9@=>'8 '(7,9B=>'8
# GF%,/'6.%6,&3.),0*(7,)F%,-67%6,-0,%>'83')*-(
Prof. Aiken CS 143 Lecture 6 HI
/"0"%1"%(2)34$05
9
9! 9H
J 9< K
A
9@A
*()B
*()H
9B
*()<
+
+
2
5
# 9'+F,(-7%,8'D%8%7,9F'.,-(%,.8-),0-6,)F%,>'8'))6*D3)%
# L-)%,)F%,7%/%(7%(+*%.
3
Prof. Aiken CS 143 Lecture 6 H!
67$89$&'%:)*&&4';9&",
# M(,'))6*D3)%,&3.),D%,+-&/3)%7,'0)%6,'88,*).,.3++%..-6.,*(,)F%,7%/%(7%(+1,N6'/F,F'>%,D%%(,+-&/3)%7,4 O(,/6%>*-3.,%:'&/8%,'))6*D3)%.,+'(,D%,+-&/3)%7,D-))-&P3/
# $3+F,'(,-67%6,%:*.).,QF%(,)F%6%,'6%,(-,+1+8%.4 R1+8*+'881,7%0*(%7,'))6*D3)%.,'6%,(-),8%N'8
Prof. Aiken CS 143 Lecture 6 HH
/"0"%1"%(2)34$05
9
9! 9H
J 9< K
A
9@A
*()B
*()H
9B
*()<
10
5
5 5
32
2
5
3
Prof. Aiken CS 143 Lecture 6 H<
!"#$%&'()*(&'+%,-).+&",)<=+%&>?
# $1()F%.*S%7 '))6*D3)%.4 R'8+38')%7,06-&,'))6*D3)%.,-0,7%.+%(7%().,*(,)F%,/'6.%,)6%%
4 9=>'8 *.,',.1()F%.*S%7,'))6*D3)%
4 R'(,'8Q'1.,D%,+'8+38')%7,*(,',D-))-&P3/,-67%6
# T6'&&'6.,Q*)F,-(81,.1()F%.*S%7,'))6*D3)%.,'6%,+'88%7,$P'))6*D3)%7 N6'&&'6.4 C-.),+-&&-(,+'.%
Prof. Aiken CS 143 Lecture 6 H@
@%5"4'&"1)*&&4';9&",
# M(-)F%6,U*(7,-0,'))6*D3)%
# R'8+38')%7,06-&,'))6*D3)%.,-0,/'6%(),'(7V-6,.*D8*(N.,*(,)F%,/'6.%,)6%%
# 9:'&/8%;,',8*(%,+'8+38')-6
4
Prof. Aiken CS 143 Lecture 6 !"
!"#$%&'()*(&'+%,-).+&",
# $%&'()*+,'+)*-(.,./%+*01,',.1.)%&,-0,%23')*-(.4 567%6,-0,6%.-83)*-(,*.,(-),./%+*0*%7
# 9:'&/8%;9<=>'8,?,9@=>'8,A,9B=>'8
4 C3.),+-&/3)% 9@=>'8 '(7,9B=>'8 D%0-6%,9<=>'84 E%,.'1,)F') 9<=>'8 7%/%(7.,-(,9@=>'8 '(7,9B=>'8
# GF%,/'6.%6,&3.),0*(7,)F%,-67%6,-0,%>'83')*-(
Prof. Aiken CS 143 Lecture 6 HI
/"0"%1"%(2)34$05
9
9! 9H
J 9< K
A
9@A
*()B
*()H
9B
*()<
+
+
2
5
# 9'+F,(-7%,8'D%8%7,9F'.,-(%,.8-),0-6,)F%,>'8'))6*D3)%
# L-)%,)F%,7%/%(7%(+*%.
3
Prof. Aiken CS 143 Lecture 6 H!
67$89$&'%:)*&&4';9&",
# M(,'))6*D3)%,&3.),D%,+-&/3)%7,'0)%6,'88,*).,.3++%..-6.,*(,)F%,7%/%(7%(+1,N6'/F,F'>%,D%%(,+-&/3)%7,4 O(,/6%>*-3.,%:'&/8%,'))6*D3)%.,+'(,D%,+-&/3)%7,D-))-&P3/
# $3+F,'(,-67%6,%:*.).,QF%(,)F%6%,'6%,(-,+1+8%.4 R1+8*+'881,7%0*(%7,'))6*D3)%.,'6%,(-),8%N'8
Prof. Aiken CS 143 Lecture 6 HH
/"0"%1"%(2)34$05
9
9! 9H
J 9< K
A
9@A
*()B
*()H
9B
*()<
10
5
5 5
32
2
5
3
Prof. Aiken CS 143 Lecture 6 H<
!"#$%&'()*(&'+%,-).+&",)<=+%&>?
# $1()F%.*S%7 '))6*D3)%.4 R'8+38')%7,06-&,'))6*D3)%.,-0,7%.+%(7%().,*(,)F%,/'6.%,)6%%
4 9=>'8 *.,',.1()F%.*S%7,'))6*D3)%
4 R'(,'8Q'1.,D%,+'8+38')%7,*(,',D-))-&P3/,-67%6
# T6'&&'6.,Q*)F,-(81,.1()F%.*S%7,'))6*D3)%.,'6%,+'88%7,$P'))6*D3)%7 N6'&&'6.4 C-.),+-&&-(,+'.%
Prof. Aiken CS 143 Lecture 6 H@
@%5"4'&"1)*&&4';9&",
# M(-)F%6,U*(7,-0,'))6*D3)%
# R'8+38')%7,06-&,'))6*D3)%.,-0,/'6%(),'(7V-6,.*D8*(N.,*(,)F%,/'6.%,)6%%
# 9:'&/8%;,',8*(%,+'8+38')-6
Jenseits von Syntax
Attribute GrammarsAttribute 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 GrammarsErgebnis: 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 GrammarsS-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
56
2
Attribute Grammars
Produktion Semantische Aktion
!E" ::= !int" E.val= int.val| !E"1 ‘+’ !E"2 E.val= E1.val+E2.val| ‘(’ !E"1 ‘)’ E.val= E1.val
!bnumeral" ::= !bdigits"1 ‘.’ !bdigits"2
!bnumeral.val= bdigits1.val+ bdigits2.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
2
Attribute Grammars
Produktion Semantische Aktion
!E" ::= !int" E.val= int.val| !E"1 ‘+’ !E"2 E.val= E1.val+E2.val| ‘(’ !E"1 ‘)’ E.val= E1.val
!bnumeral" ::= !bdigits"1 ‘.’ !bdigits"2
!bnumeral.val= bdigits1.val+ bdigits2.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
68 CHAPTER 3 ATTRIBUTE GRAMMARS
<bit> ::=
0Val (<bit>) ! 0
| 1Val (<bit>) ! 1
The derivation tree in Figure 3.7 illustrates the use of attributes that give thesemantics for the binary numeral 1101.01 to be the real number 13.25.
<binary numeral>Val: 13 + 1/22 = 13.25
<binary digits>Val : 13Len : 4
<binary digits>Val : 1 Len : 2
<binary digits>Val : 6 Len : 3
<binary digits>Val : 3 Len : 2
<binary digits>Val : 1 Len : 1
<bit>Val : 1
<binary digits>Val : 0 Len : 1
<bit>Val : 1
<bit>Val : 0
<bit>Val : 1
<bit>Val : 1
<bit>Val : 0
1
1
1 1
0 0
Figure 3.7: Binary Numeral Semantics Using Synthesized Attributes
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