von automaten zu programmen–parsergeneratoren und attributgrammatiken

75
Von Automaten zu Programmen 1 Tim Furche Compilerbau, Wintersemester 2008/09, Prof. F. Bry Manuelle und automatische Entwicklung von Parsern

Upload: tim-furche

Post on 17-Jul-2015

1.027 views

Category:

Education


0 download

TRANSCRIPT

Von Automaten zu Programmen

1

Tim Furche

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

Manuelle und automatische Entwicklung von Parsern

2

Beispiele aus der Praxis

Formale Sprachen:

3

Nicht nur in Compilern!

Formale Sprachen:

Browser

4

5

6

URIs

HTML

Google Anfrage

CSS

JavaScript

Browser: Formale Sprachen

Spreadsheets: Excel/Numbers/OpenCalc

7

8

9

Formeln

Format Felder

Macros

Parser für Reguläre Sprachenz.B.: URIs, Datumsangaben, Gleitpunktzahlen

10

AEndliche

Automaten

Beispiel:Gleitpunktzahlen

11

12

-666.797E-14

parsen, normalisieren

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

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

14

15

Wie?

z.B. in Java

16

17

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

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’

21

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

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

32

Parser für kontextfreie Sprachen++z.B. für arithmetische Ausdrücke und Erweiterungen

33

BKeller-

Automaten

34

Beispiel: Arithmetischer Ausdruck

35

2 + 4 * 11 - 2 * 3 + 2

parsen, ausrechnen

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)

37

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

39

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: [...] } } } [...] }

49

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

57

FazitD

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

61

FragenE