Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Jaccie-Beispiele Lothar Schmitz 1 [email protected] 20. Juli 2004

Startseite

JJ

II

J

I

Seite 1 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

1 gemeinsam

mit Teilnehmern an der Vorlesung ¨ uber Syntaxbasierte Programmierwerkzeuge an der Universit¨ at der Bundeswehr M¨ unchen im Wintertrimester 2004

Die Beispielsammlung umfasst zwei große und drei kleine Gruppen von Beispielen:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

• Die kleine Gruppe der Bin¨arzahlen-Beispiele geht zur¨uck auf ein Beispiel, mit dem Prof. D. E. Knuth, der Erfinder der Attributierten Grammatiken, seine neue Technik erl¨auterte. Hier demonstrieren wir insbesondere

Geschachtelte Rechtecke Scanner mit Aktionen

– dass sich bei einer Erweiterung der Syntax die Attributierung homogen“ erg¨anzen l¨asst; ” – das Zusammenspiel zwischen ererbten und synthetisierten Attributen; – die Modularisierung einer Attributierung in eine gleichwertige Sequenz von Attributierungen. • Die große Gruppe mit Beispielen zu arithmetischen Ausdr¨ucken zeigt exemplarisch die breite Palette unterschiedlicher Jaccie-Anwendungsm¨oglichkeiten: – – – – –

Ausdr¨ucke mit Variablen interaktiv auswerten; ¨ Ubersetzung in verschiedene Maschinensprachen (MI und Postscript); Erzeugung unterschiedlicher textueller und grafischer Darstellungen; Umwandlung in Postfix-Syntax und zur¨uck; diverse Spracherweiterungen.

• Die große Gruppe mit Beispielen zu geschachtelten Rechtecken zeigt – die schrittweise Berechnung verschiedener grafischer Formate; – geometrische Transformationen am Quelltext.

Startseite

JJ

II

J

I

• Die kleine Gruppe der Telegramme demonstriert die Vielseitigkeit von Scannern mit Aktionsbl¨ocken: – Man kann Telegramme aus Klartext in Morse-Code umwandeln und umgekehrt. – Die Kosten eines Telegramms lassen sich ebenfalls bestimmen. • Die kleine Gruppe der Spracherkennungs-Beispiele demonstriert die M¨achtigkeit von Scannern mit Aktionsbl¨ocken: – Typ-2-Sprachen wie Klammergebirge“ k¨onnen erkannt werden. ” – Typ-2-Sprachen wie {an bn | n ≥ 1} und sogar Typ-1-Sprachen wie {an bn an | n ≥ 1} lassen sich erkennen. Schon diese kleinen Beispiele belegen, welch unterschiedliche Aufgaben man mit unserem Compiler-Compiler Jaccie bearbeiten kann.

Seite 1 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

1. Bin¨ arzahlen

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

1.1. Ganzzahlige Bin¨ arzahlen auswerten

Geschachtelte Rechtecke Scanner mit Aktionen

Lexikalische und syntaktische Struktur festlegen Ganzzahlige Bin¨arzahlen sind Folgen von Nullen und Einsen. In Grammatiken, die attributiert werden sollen, d¨urfen als Tokenbezeichnungen nur Namen verwendet werden, die regul¨are Java-Bezeichner sind, weil in der Attributierung automatisch zu jedem Token namens X ein Pseudoattribut X_string abgeleitet wird. Als lexikalische Elemente verwenden wir hier die englischen Ziffernbezeichnungen (¨uberhaupt verwenden wir ausschließlich englische Bezeichnungen f¨ur Grammatiksymbole und Attribute): Tokendefinitionen: := $0 := $1

Von den folgenden Grammatikregeln dient die erste als Startregel“, in deren Kontext ererbte Attribute initialisiert ” werden k¨onnen: Grammatikregeln: Number -> Digits Digits -> Digits Digit Digits -> Digit Digit Digit

-> zero -> one

Startseite

JJ

II

J

I

Seite 2 von 100

Zur¨ uck

Attribute festlegen Der Wert einer Bin¨arzahl ergibt sich aus den Werten seiner Ziffern, wobei deren Stellengewichte in die Berechnung eingehen. Werte werden von den Bl¨attern zur Wurzel des Syntaxbaums hin berechnet (also in synthetisierten Attributen), Stellengewichte von der Wurzel in Richtung der Bl¨atter (also in ererbten Attributen). Da wir in einem Folgeschritt auch gebrochene Bin¨arzahlen behandeln wollen, verwenden wir den Java-Typ double f¨ur Werte und Gewichte.

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

Attribute und ihre Typen: >value : double Digits Digits_weight = 1; Number_value = Digits_value; Digits -> Digits Digit Digits2_weight = Digits1_weight * 2.0; Digit_weight = Digits1_weight; Digits1_value = Digits2_value + Digit_value; Digits -> Digit Digit_weight = Digits_weight; Digits_value = Digit_value; Digit -> zero Digit_value = 0; Digit -> one Digit_value = Digit_weight;

Startseite

JJ

II

J

I

Seite 3 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Ein Testlauf

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Wir verarbeiten die Ziffernfolge 10101.

Geschachtelte Rechtecke

Der Scanner macht daraus die Tokenfolge

Scanner mit Aktionen

one "1" zero "0" one "1" zero "0" one "1"

Der Parser baut aus der Tokenfolge den Syntaxbaum mit der textuellen Darstellung Number Digits Digits Digits Digit one - string: "1" Digit zero - string: "0" Digit one - string: "1"

Startseite

JJ

II

J

I

Seite 4 von 100

und der Evaluator verziert“ den Baum wie folgt mit Attributwerten ”

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

Number -value:5.0 Digits -weight:1.0 -value:5.0 Digits -weight:2.0 -value:4.0 Digits -weight:4.0 -value:4.0 Digit -weight:4.0 -value:4.0 one -string:1 Digit -weight:null -value:0.0 zero -string:0 Digit -weight:1.0 -value:1.0 one -string:1

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 5 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

1.2. Gebrochene Bin¨ arzahlen auswerten

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Erg¨ anzung der Syntax

Geschachtelte Rechtecke Scanner mit Aktionen

Bei gebrochenen Bin¨arzahlen kommt der Punkt als Token hinzu: := $.

Die Grammatik wird um eine weitere Startregel“erg¨anzt: ” Grammatikregeln: Number -> Digits point Digits

Ein neues Attribut Das Stellengewicht des Nachkommateils h¨angt ab von der L¨ange des Nachkommateils. L¨angen werden von den Bl¨attern zur Wurzel des Syntaxbaums hin berechnet (also in synthetisierten Attributen) und sind ganzzahlig, d.h. vom Java-Typ int. >length : int

L¨angen beziehen sich auf Ziffernfolgen. Daher ergibt sich insgesamt die folgende Zuordnung. Nonterminals und ihre Attribute: Number : value Digits : value weight length Digit : value weight

Startseite

JJ

II

J

I

Seite 6 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Zus¨ atzliche Attributauswertungsregeln

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Durch die neue Grammatikregel und das neue Attribut kommen ein paar Auswertungsregeln hinzu (man beachte, dass die fr¨uheren unver¨andert erhalten bleiben - Attributierungen k¨onnen im positiven Sinn modular aufgebaut sein!)

Geschachtelte Rechtecke Scanner mit Aktionen

Attributauswertungsregeln: Number -> Digits point Digits Digits1_weight = 1; Digits2_weight = 1.0 / exp(2.0, Digits2_length); Number_value = Digits1_value + Digits2_value; Number -> Digits Number_value = Digits_value; Digits -> Digits Digit Digits1_length = Digits2_length + 1; Digits -> Digit Digits_length = 1;

Zur Berechnung von Digits2_weight wird ein Exponentiationsoperator ben¨otigt, den es in Java standardm¨aßig nicht gibt und deshalb (im Unterbereich Evaluator - Definition - Actions - Java“) wie folgt implementiert wird: ” public static double exp (double b, int e) { double result = 1.0; while (e 0) { result = result * b; e = e - 1; } return result; }

Startseite

JJ

II

J

I

Seite 7 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Ein Testlauf Aus der Ziffernfolge 1.11 erhalten wir mit Scanner, Parser und Evaluator:

Beenden

Bin¨ arzahlen

Number -value:1.75 Digits -length:null -weight:1.0 -value:1.0 Digit -weight:1.0 -value:1.0 one -string:1 point -string:. Digits -length:2 -weight:0.25 -value:0.75 Digits -length:1 -weight:0.5 -value:0.5 Digit -weight:0.5 -value:0.5 one -string:1 Digit -weight:0.25 -value:0.25 one -string:1

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 8 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

1.3. Modularisierung der Attributierung

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Die bisher entwickelte Attributierung l¨asst sich bequem in drei Teilattributierungen aufteilen: • die erste Teilattributierung wertet nur das length-Attribut aus • die zweite Teilattributierung wertet nur das weight-Attribut aus • die dritte Teilattributierung wertet nur das value-Attribut aus

Geschachtelte Rechtecke Scanner mit Aktionen

Auf diese Weise lassen sich große Attributierungen in inhaltlich zusammengeh¨orige“ Teilattributierungen aufteilen ” und dadurch besser u¨berblicken. Außerdem k¨onnen Teilattributierungen evtl. wiederverwendet werden.

1.4. Eine g¨ unstigere Syntax Wir haben das Beispiel unn¨otig kompliziert behandelt (und damit missbraucht“), um Begriffe und Techniken zu ” demonstrieren. Wenn man die Syntax ein wenig anpasst, kommt man hier mit einen einzigen Attribut gut aus: Grammatik- und Attributauswertungsregeln: Number -> LeftDigits point RightDigits Number_value = LeftDigits_value + RightDigits_value; Number -> LeftDigits Number_value = LeftDigits_value; LeftDigits -> LeftDigits Digit LeftDigits1_value = LeftDigits2_value*2.0 + Digit_value; LeftDigits -> Digit LeftDigits_value = Digit_value;

Startseite

JJ

II

J

I

Seite 9 von 100

Zur¨ uck

RightDigits -> Digit RightDigits RightDigits1_value = (RightDigits2_value + Digit_value)/2.0; RightDigits -> Digit RightDigits_value = Digit_value/2.0; Digit -> bit Digit_value = (bit_string.equals("0") ? 0 : 1);

Vollbild ein/aus

Schließen

Beenden

2. Arithmetische Ausdru ¨ cke

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Die folgende Syntax ist Basis verschiedener, darauf aufbauender Attributierungen.

Geschachtelte Rechtecke Scanner mit Aktionen

2.1. Syntaxbeschreibung Lexikalische Ebene Neben der Angabe Standard bei Separators“ besteht die Scannerdefinition i.W. aus Tokendefinitionen, die auf ” folgenden regul¨ aren Hilfsausdr¨ ucken (benannten Patterns“) beruhen: ” Patterns:

:= := := := := := := :=

($+ | $-) ($* | $/) $( $) ({$a-$z}|{$A-$Z}) {$0-$9} ( | )[0-*] [1-*]

Namensmuster beginnen also mit einem Buchstaben, auf den beliebig viele Buchstaben und/oder Ziffern folgen. Ein Zahlmuster ist einfach eine nicht-leere Folge von Ziffern. Die folgenden Tokendefinitionen f¨uhren die Namen der Token ein, die in der kontextfreien Grammatik als terminale Zeichen erscheinen.

Startseite

JJ

II

J

I

Seite 10 von 100

Zur¨ uck

Tokens:

:= := := := := :=



Vollbild ein/aus

Schließen

Beenden

Kontextfreie Grammatik

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Die folgende kontextfreie Grammatik enth¨alt genau die oben eingef¨uhrten Token als terminale Zeichen. Es handelt sich um die aus der Literatur wohlbekannte Grammatik, welche die Pr¨azedenzen der Operatoren richtig und eindeutig wiedergibt. Das zus¨atzliche Startsymbol Arithmetic sowie die zugeh¨orige Startregel“ dienen als Aufh¨anger f¨ur die ” Initialisierung ererbter Attribute.

Geschachtelte Rechtecke Scanner mit Aktionen

Terminals: name number addOp multOp openingBracket closingBracket Nonterminals: Arithmetic Expression Term Factor

Startseite

Startsymbol: Arithmetic

JJ

II

Rules: Arithmetic -> Expression

J

I

Seite 11 von 100

Expression -> Expression addOp Term -> Term Term

-> Term multOp Factor -> Factor

Zur¨ uck

Vollbild ein/aus

Schließen

Factor

-> openingBracket Expression closingBracket -> number -> name

Beenden

2.2. Arithmetische Ausdr¨ ucke interaktiv auswerten

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Wir wollen arithmetische Ausdr¨ucke ohne Informationsverlust“ auswerten und das Ergebnis als gek¨urzten Bruch ” ausgeben. Da Java den ben¨otigten Typ nicht standardm¨aßig zur Verf¨ugung stellt, arbeiten wir mit der StringDarstellung von Zahlen und implementieren darauf die vier Grundrechnungsarten (und das K¨urzen) selbst. Die folgenden Methoden werden unter Evaluator - Definition - Java - Methods“ auszuprogrammieren sein (die vollst¨andigen ” Methodentexte findet man in der Datei ArithEvaluator.edef).

Geschachtelte Rechtecke Scanner mit Aktionen

static String addOp(String op, String left, String right); static String multOp(String op, String left, String right); static String kuerzen(int a, int b);

Die Zahlwerte von (Teil-)Ausdr¨ucken werden also in synthetisierten value-Attributen vom Typ String gehalten. Laut Syntax d¨urfen Ausdr¨ucke auch (Variablen-)Namen enthalten. Selbstverst¨andlich stehen gleiche Namen f¨ur gleiche Werte. Vor Auswertung des Ausdrucks m¨ussen die Variablen Werte erhalten. Wir sammeln dazu s¨amtliche im Ausdruck vorkommenden Namen u¨ber synthetisierte, mengenwertige Attribute variables vom Typ HashSet auf. F¨ur jeden im Gesamtbaum vorkommenden Namen erfragen wir vom Benutzer einen ganzzahligen Wert. Anschließend propagieren wir die so entstandene Menge von (Name, Wert)-Paaren u¨ber ererbte environment-Attribute vom Typ HashMap in den ganzen Baum, so dass die Werte f¨ur die Auswertung u¨berall verf¨ugbar sind. Wir haben also drei Arten von Attributen (> kennzeichnet ein synthetisiertes, < ein ererbtes Attribut). Attribute und ihre Typen: >value : String >variables : HashSet number Factor_variables = new HashSet();

Scanner mit Aktionen

Factor -> name Factor_variables = new HashSet(); Factor_variables.add(name_string);

Diese Mengen werden f¨ur zusammengesetzte Ausdr¨ucke vereinigt: Term1 -> Term2 multOp Factor Term1_variables = new HashSet(); Term1_variables.addAll(Term2_variables); Term1_variables.addAll(Factor_variables);

Analog bei der Regel Expression1 -> Expression2 addOp Term. Schließlich wird f¨ur jeden im obersten ExpressionKnoten angekommenen Namen vom Benutzer ein Wert erfragt und so das Attribut Expression_environment berechnet (dessen Wert dann unver¨andert nach unten propagiert wird): Arithmetic -> Expression Iterator variablesIterator = Expression_variables.iterator(); Expression_environment = new HashMap(); while (variablesIterator.hasNext()) { String variableName = (String) variablesIterator.next(); String inputValue = null; boolean ok = false; while (!ok) { inputValue = JOptionPane.showInputDialog( "Please input a value for " + variableName); try{Integer.parseInt(inputValue); ok=true;} catch (Exception e) {ok = false;} } Expression_environment.put(variableName, inputValue); }

Startseite

JJ

II

J

I

Seite 13 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Die Berechnung der Zahlwerte beginnt wieder im Kontext der zwei Factor-Regeln:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Factor -> number Factor_value = number_string;

Geschachtelte Rechtecke Scanner mit Aktionen

Factor -> name Factor_value = (String) Factor_environment.get(name_string);

Dann werden die Teilausdr¨ucke arithmetisch verkn¨upft: Expression -> Expression addOp Term Expression1_value = addOp(addOp_string, Expression2_value, Term_value); Term -> Term multOp Factor Term1_value = multOp(multOp_string, Term2_value, Factor_value);

und die Werte ansonsten bis zur Wurzel des Syntaxbaums durchgereicht. S¨amtliche Attributauswertungsregeln findet man in der Datei ArithEvaluator.edef.

Startseite

JJ

II

J

I

Seite 14 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

2.3. Textuelle Darstellungen

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Konversion in Pr¨ afix- und Postfix-Darstellung – Thomas G¨ otzinger

Geschachtelte Rechtecke Scanner mit Aktionen

Zum arithmetischen Ausdruck mit der Infix-Darstellung a*a - (a-2)*b + b*(b+1)

erh¨alt man die (klammerfreie!) Pr¨afix-Darstellung + - * a a * - a 2 b * b + b 1

und die Postfix-Darstellung (auch ohne Klammern!) a a * a 2 - b * - b b 1 + * +

Um die Struktur des Ergebnisses zu verdeutlichen, sollen • die Operatoren, Namen und Zahlen jeweils in eine eigene Zeile geschrieben werden; • Teilausdr¨ucke gegen¨uber ihren Operatoren jeweils eine Stufe (drei Blanks) weiter einger¨uckt werden. Das ergibt die Pr¨afix-Darstellung +

Startseite

* a a

JJ

II

J

I

* Seite 15 von 100

a 2

Zur¨ uck

b Vollbild ein/aus

* b +

Schließen

b 1

Beenden

und analog eine Postfix-Darstellung.

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

a a

Geschachtelte Rechtecke

*

Scanner mit Aktionen

a 2 b * b b 1 + * +

F¨ur die erste Attributierung, die zum Infix-Ausdruck den einger¨uckten Pr¨afix-Ausdruck aufbaut, ben¨otigen wir zwei Attribute: Den Pr¨ afix-Ausdruck bauen wir in einem Attribut prefix vom Typ String auf. Da die Berechnung von den Bl¨attern hin zur Wurzel erfolgen wird, handelt es sich um ein synthetisiertes Attribut. F¨ur das Einr¨ ucken verwenden wir ein zweites Attribut, indentation vom Typ String, in dem wir zu jedem Teilausdruck einen passenden Einr¨uckstring erzeugen. Der Einr¨uckstring des Gesamtausdrucks ist leer. Von einem Ausdruck zu seinen unmittelbaren Teilausdr¨ucken verl¨angert sich die Einr¨uckung um jeweils drei Leerzeichen. Da die Berechnung von der Wurzel in Richtung der Bl¨atter hin l¨auft, handelt es sich um ein ererbtes Attribut.

Startseite

JJ

II

J

I

Seite 16 von 100

Wir haben also f¨ur diesen Teil der Aufgabe zwei Attribute: >prefix : Expression Expression_identation = "";

Nach der Initialisierung erfolgt der weitere Aufbau nach verschiedenen Regeln: Wird ein Nonterminal nur auf ein weiteres Nonterminal abgebildet, ver¨andert sich der Einr¨uckstring nicht. Expression -> Term Term_identation = Expression_identation; Term -> Factor Factor_identation = Term_identation; Factor -> openingBracket Expression closingBracket Expression_identation = Factor_identation;

Wird der Ausdruck aus mehreren Teilausdr¨ucken gebildet, so wird der Einr¨uckstring der Teilausdr¨ucke aus dem aktuellen Einr¨uckstring konkateniert mit drei Blanks gebildet. Expression1 -> Expression2 addOp Term Expression2_identation = " " + Expression1_identation; Term_identation = " " + Expression1_identation; Term1 -> Term2 multOp Factor Term2_identation = " " + Term1_identation; Factor_identation = " " + Term1_identation;

Startseite

JJ

II

J

I

Seite 17 von 100

Zur¨ uck

Vollbild ein/aus

Nach dem der Aufbau des Einr¨uckstrings erl¨autert wurde, soll nun der Prefixterm erzeugt werden. Dies erfolgt von den Bl¨attern hin zur Wurzel. Die Zahlen und Variablen werden durch das Nonterminal Factor in den Prefixterm aufgenommen. Dabei wird jeweils der Einr¨uckstring vorangestellt.

Schließen

Beenden

Bin¨ arzahlen

Factor -> number Factor_prefix = Factor_identation + number_string;

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Factor -> name Factor_prefix = Factor_identation + name_string;

Wird ein Nonterminal nur auf ein weiteres Nonterminal abgebildet, ver¨andert sich der Prefix nicht. Factor ->openingBracket Expression closingBracket Factor_prefix = Expression_prefix; Term -> Factor Term_prefix = Factor_prefix; Expression -> Term Expression_prefix = Term_prefix; Arithmetic -> Expression Arithmetic_prefix = Expression_prefix;

Wird der Prefixausdruck eines Nonterminals aus mehreren Teilausdr¨ucken gebildet, so wird der Prefix des Nonterminals wie folgt zusammengesetzt (zum Verst¨andnis siehe auch Notation eines Prefix in der Aufgabenstellung): Expression1 -> Expression2 addOp Term Expression1_prefix = Expression1_identation + addOp_string + "\n" + Expression2_prefix + "\n" + Term_prefix; Term1 -> Term2 multOp Factor Term1_prefix = Term1_identation + multOp_string + "\n" + Term2_prefix + "\n" + Factor_prefix;

Startseite

JJ

II

J

I

Seite 18 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Nach der Beschreibung des Aufbaus der Attributierung von Infix zu Prefix ergibt sich die Postfixnotation v¨ollig analog: Man ben¨otigt ein zus¨atzliches Attribut postfix vom Typ String. Da dieses ebenfalls zu Wurzel hin ausgewertet wird, handelt es sich um ein synthetisiertes Attribut: >postfix

:

String

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Zu der im ersten Teil der Aufgabe angegebenen Zuordnung von Nonterminalen zu Attributen ergibt sich durch das Hinzuf¨ugen eines weiteren Attributes folgende Sicht: Arithmetic Expression Term Factor

: : : :

prefix postfix identation prefix postfix identation prefix postfix identation prefix postfix

An dem im ersten Teil der Aufgabe erl¨auterten Berechnung des Attribute identation ¨andert sich hier nichts. Der Aufbau des Postfixterms ist analog zum Prefixterm. Die ver¨anderte Reihenfolge ergibt aus folgenden Regeln: Expression1 -> Expression2 addOp Term Expression1_postfix = Expression2_postfix + "\n" + Term_postfix + "\n" + Expression1_identation + addOp_string; Term1 -> Term2 multOp Factor Term1_postfix = Term2_postfix + "\n" + Factor_postfix + "\n" + Term1_identation + multOp_string;

Startseite

JJ

II

J

I

Seite 19 von 100

Zur¨ uck

S¨amtliche Auswertungsregeln findet man auch in der Datei infix2prepostfix.edef. Vollbild ein/aus

Schließen

Beenden

Konversion von Pr¨ afix nach Infix – Roman Goltz

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Zur Syntax: Auf der lexikalischen Ebene unterscheidet sich die Pr¨afix-Form von der Infix-Form durch das Fehlen von Klammern. Es ist aber durchaus m¨oglich, einfach den Scanner f¨ur die Infix-Form zu verwenden.

Geschachtelte Rechtecke Scanner mit Aktionen

Die kontextfreie Grammatik ist aber deutlich einfacher, da nicht nur die Klammern fehlen, sondern auch die Bindungen der Operatoren durch ihre Reihenfolge komplett festgelegt sind. Die Regeln der Grammatik lauten: Rules: Prefix

-> PrefixExpression

PrefixExpression -> PrefixOperator PrefixExpression PrefixExpression -> PrefixFactor PrefixFactor

-> name -> number

PrefixOperator

-> addOP -> multOp

Der Grammatik-Check ergibt f¨ur alle Parser-Typen, dass die Grammatik deterministisch ist. ¨ Unser erstes Ziel ist die Ubersetzung eines Pr¨afix-Ausdrucks in einen vollst¨ andig geklammerten Infix-Ausdruck. F¨ur den Pr¨afix-Ausdruck

Startseite

JJ

II

J

I

Seite 20 von 100

+ - * a a * - a 2 b * b + b 1 Zur¨ uck

erg¨abe das die Infix-Darstellung Vollbild ein/aus

(((a * a) - ((a - 2) * b)) + (b * (b + 1))) Schließen

mit vielen u¨berfl¨ussigen Klammern. Beenden

Die Attributierung kommt mit einem einzigen synthetisierten Attribut infix vom Typ String aus, da Einr¨uckungen nicht erforderlich sind.

Diese Attributierung ist eigentlich sehr u¨berschaubar. Man f¨angt bei den Grundelementen an, in unserem Fall die Terminale name, number, addOp und multOp. Diese stammen alle vom PrefixFactor ab und geben dem PrefixFactor.infix jeweils ihren eigenen String Wert.

Bin¨ arzahlen

Nun muss man nur noch die PrefixFactoren zu Expressions zusammenf¨ugen.Ist der PrefixExpression nur ein Prefixfactor, wird der Infix-Wert nur eine Ebene h¨ohergereicht, ohne ver¨andert zu werden.

Scanner mit Aktionen

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

Am interessantesten sind zusammengestzte Prefixexpressions. Die Regel f¨ur deren infix-Wert ist: PrefixExpression1_infix = "(" + PrefixExpression2_infix + PrefixOperator_infix + PrefixExpression3_infix + ")";

Wenn man in der vollst¨andig geklammerten Infix-Darstellung (((a * a) - ((a - 2) * b)) + (b * (b + 1)))

die ¨außeren Klammern streicht und auch die Klammern um Teilausdr¨ucke, deren Operator eine h¨ohere Priorit¨at hat als der Operator des unmittelbar umgebenden Ausdrucks, dann erh¨alt man die reduzierte Infix-Darstellung (a * a - (a - 2) * b) + b * (b + 1)

die wir in einer zweiten Attributierung herstellen wollen. Dazu ordnen wir den Operatoren als level die Priorit¨aten • 1 (f¨ur den addOp +),

Startseite

JJ

II

J

I

Seite 21 von 100

Zur¨ uck

• 2 (f¨ur den addOp -), • 3 (f¨ur den multOp *) und • 4 (f¨ur den multOp /) zu. Die Ausdr¨ucke erhalten als enclosingLevel die Priorit¨aten ihrer umgebenden Ausdr¨ucke:

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

Prefix -> PrefixExpression PrefixExpression_enclosingLevel = 0; PrefixOperator -> addOP PrefixOperator_level = (addOp_string.equals("+")?1:2);

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

PrefixOperator -> multOp PrefixOperator_level = (multOp_string.equals("*")?3:4); PrefixExpression -> PrefixOperator PrefixExpression PrefixExpression PrefixExpression2_enclosingLevel = PrefixOperator_level; PrefixExpression3_enclosingLevel = PrefixOperator_level;

Man beachte, dass bei dieser Zuordnung assoziative Operatoren eine ungerade Priorit¨at haben. Und: Die nichtassoziativen Operatoren der gleichen Tokenklasse haben eine um eins h¨ohere Priorit¨at. Nach dieser Vorarbeit ist der letzte Schritt nicht mehr schwer: Der Knackpunkt ist die Berechnung des Attributs infix im Zusammenhang mit der letzten Grammatikregel. Hier muss man die Wertigkeiten der verschiedenen Prefixoperatoren nach den vorgegebenen Regeln einarbeiten. Dies geschieht im folgenden Anweisungsblock, der entscheidet, ob die Klammern ben¨otigt werden oder nicht: PrefixExpression -> PrefixOperator PrefixExpression PrefixExpression boolean lessThan = ( PrefixExpression1_enclosingLevel < PrefixOperator_level ); boolean isEqual = ( PrefixExpression1_enclosingLevel == PrefixOperator_level ); boolean isAssoc = ( PrefixOperator_level % 2 == 1 ); boolean omit = ( lessThan || ( isEqual && isAssoc ) ); PrefixExpression1_infix = ( omit ? "" : "(" ) + PrefixExpression2_infix + PrefixOperator_infix + PrefixExpression3_infix + ( omit ? "" : ")" );

Startseite

JJ

II

J

I

Seite 22 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Klammern k¨onnen genau dann weggelassen werden, wenn der umgebende Ausdruck ein geringeres Pr¨azedenzniveau hat als der betrachtete oder wenn beide das gleiche Pr¨azedenzniveau haben und der aktuelle Operator assoziativ ist.

Dazu als Beispiel die Eingabezeichenreihe:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

- * 10 + 1 2 * * a 50 - a b

Geschachtelte Rechtecke Scanner mit Aktionen

Auswertung ergibt: Prefix -infix:10*(1+2)-a*50*(a-b)

Startseite

JJ

II

J

I

Seite 23 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Konversion Infix nach MathML – Alexander Loechel

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Jetzt wollen wir eine Konversion von arithmetischen Ausdr¨ucken in den XML Subset MathML betrachten.

Geschachtelte Rechtecke Scanner mit Aktionen

MathML 2.0 ist eine W3C Recommendation vom 21. Februar 2001. Sie wurde f¨ur die Pr¨asentation und Beschreibung mathematischer Ausdr¨ucke entwickelt. F¨ur die Arithmetischen Ausdr¨ucke ben¨otigen wir die MathML-Tags: • + : • - : • * : • / : Die Syntax von MathML wird in Polnischer Notation geschrieben. In MathML wird jede Anwendung eines Operators im (durch Einr¨uckungen hervorgehobene) Format: Startseite



kenntlich gemacht. Zahlkonstanten werden in Tag-Paare ... eingeschlossen, Variablen-Namen in TagPaare .... Ein Beispiel zeigt uns, wie die MathMl-Form zu einem arithmetischen Ausdruck gebildet wird: (a + 2) ∗ (a − 2) 2∗b lautet in MathML-Form

JJ

II

J

I

Seite 24 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

a 2 a 2 2 b

In diesem Fall k¨onnen wir die bereits beschriebenen Scanner und Parser f¨ur arithmetische Ausdr¨ucke weiterverwenden und m¨ussen nur einen neuen Evaluator erzeugen. Den MathML-Code k¨onnen wir durch Baumtransformation am Ergebnis des Parser erzeugen. In Jaccie wird dies durch Attributierung getan. Den MathML-Code bauen wir in einem Attribut mathML vom Typ String auf. Da die Berechnung von den Bl¨attern hin zur Wurzel erfolgen wird, handelt es sich um ein synthetisiertes Attribut.

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 25 von 100

Zur¨ uck

Vollbild ein/aus

F¨ur das Einr¨ ucken verwenden wir ein zweites Attribut, indentation vom Typ String, in dem wir zu jedem Teilausdruck einen passenden Einr¨uckstring erzeugen. Der Einr¨uckstring des Gesamtausdrucks ist leer. Von einem Ausdruck zu seinen unmittelbaren Teilausdr¨ucken verl¨angert sich die Einr¨uckung um jeweils drei Leerzeichen. Da die Berechnung von der Wurzel in Richtung der Bl¨atter hin l¨auft, handelt es sich um ein ererbtes Attribut.

Schließen

Beenden

Zur Startregel

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Arithmetik -> Expression

Geschachtelte Rechtecke Scanner mit Aktionen

sind die entsprechenden Attributauswertungsregeln: Arithmetic_mathML = "" + "\n" + "" + "\n" + "" + "\n" + Expression_mathML + "\n" + ""; Expression_indentation = "";

Wie oben besprochen wird hier das indentation Attribut mit "" initialisiert. Das MathML-Code Attribut mathML von Arithmetik wird hier ausf¨uhrlich und komplett mit dem XML-Header erzeugt. Die kurze Form Startseite

Arithmetic_mathML = "" + "\n" + Expression_mathML + "\n" + "";

w¨urde zwar gen¨ugen, um das Resultat in andere XML Dokumente einzubetten, so ist es aber schon selber ein vollst¨andiges Dokument, welches getestet werden kann.

JJ

II

J

I

Seite 26 von 100

Zur¨ uck

Sehr interessant sind bei der Konversion von arithmetischen Ausdr¨ucken die zwei Regeln, in denen Operatoren vorkommen.

Vollbild ein/aus

Bei Schließen

Term -> Term multOp Factor

Beenden

sind drei Attribute gem¨aß folgenden Attributauswertungsregeln zu berechnen:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Term2_indentation = Term1_indentation + "

";

Geschachtelte Rechtecke Scanner mit Aktionen

Factor_indentation = Term1_indentation + "

";

String opM = multOp_string.equals("*")?"":""; Term1_mathML = Term1_indentation + "" + "\n" + Term2_indentation + opM + "\n" + Term2_mathML + "\n" + Factor_mathML + "\n" + Term1_indentation + "";

Interessant ist vor allem die dritte Auswertungsregel, die mit der Berechnung der Hilfsvariablen op beginnt. op enth¨alt , wenn der Operator im eingegebenen arithmetischen Ausdruck ein * war, sonst . In der Zuweisung an Term1_mathML wird jede aufgebaute Zeile mit dem Zeilenendestring "\n" abgeschlossen. Den Zeilen mit den Apply-Tags wird der passende Einr¨uckstring vorangestellt. Die eingef¨ugten Teilausdr¨ucke (Term2_mathML und Factor_mathML) bringen ihre Einr¨uckungen (und interne Zeilenwechsel) selber mit. Analog dazu die folgenden Regeln:

Startseite

Expression1 -> Expression2 addOp Term Expression2_indentation = Expression1_indentation + " Term_indentation = Expression1_indentation + "

";

";

String op = addOp_string.equals("+")?"":""; Expression1_mathML = Expression1_indentation + "" + "\n" + Expression2_indentation + op + "\n" + Expression2_mathML + "\n" + Term_mathML + "\n" + Expression1_indentation + "";

JJ

II

J

I

Seite 27 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

¨ was einer direkten Ubertragung der Regeln f¨ur den multOp entspricht.

Abschliessend m¨ussen nur noch die Blattelemente des Syntaxbaums mit Attributregeln versehen werden, wobei nur die f¨ur MathML gew¨unschte Kennzeichnung umschliessend hinzugef¨ugt wird:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

Factor -> number Factor_mathML = Factor_indentation + "" + number_string + "";

Scanner mit Aktionen

Factor -> name Factor_mathML = Factor_indentation + "" + name_string + "";

Die restlichen Attributauswertungsregeln sind Transfer“-Regeln, die Attributwerte unver¨andert weiterreichen (das ” einzig beachtenswerte hierbei ist, dass Klammern ignoriert werden k¨onnen, da MathML ja die Polnische Notation benutzt). Mit diesem Regelsatz kann jetzt jeder beliebige arithmetische Ausdruck in ein MathML Dokument transfomiert werden, diese Dokumente k¨onnen jetzt mit modernen Browsern bzw. mit gewissen PlugIn versehenen Tools angesehen werden.

Startseite

JJ

II

J

I

Seite 28 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Konversion MathML nach Infix– Andreas Jaehmlich

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Der MathML-Scanner muss die Tags der MathML-Darstellung als Token erkennen. Dazu die folgenden Tokendefinitionen:

Geschachtelte Rechtecke Scanner mit Aktionen

Hier erst einmal die Pattern, die dann den Token zugewiesen werden:

:= := := := := := := := := := := :=

"" "" "" "" "" "" "" | "" " | "" ({a-z}|{A-Z}) {0-9} ( | )[0-*] (1-*) Startseite

Nun die Token:

:= := := := := := := :=



JJ

II

J

I

Seite 29 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Als MathML-Parser-Definition wird eine Grammatik mit folgenden Regeln verwendet:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

MathML

-> Expression

Geschachtelte Rechtecke Scanner mit Aktionen

MathMLExpression -> applyBegin MathMLOperator MathMLExpression MathMLExpression applyEnd -> MathMLFactor MathMLFactor

-> ciBegin name ciEnd -> cnBegin number cnEnd

MathMLOperator

-> plusOp -> multOp

Die Attributierung kommt mit einem einzigen synthetisierten Attribut aus, da Einr¨uckungen nicht erforderlich sind und weil wir der Einfachheit halber den Infix-Ausdruck vollst¨andig geklammert erzeugen. Das schon erw¨ahnte einzige Attribut ist das synthetisiertes Attribut Ausdruck vom Typ String. Synthetisiert, weil wir an den Wurzeln beginnend den gesamten Ausdruck zusammensetzen. Jedem Nonterminal ist das Attribut Ausdruck genau einmal zugewiesen: MathMl : >Ausdruck Expression : >Ausdruck Operator : >Ausdruck Factor : >Ausdruck

Startseite

JJ

II

J

I

Seite 30 von 100

Zur¨ uck

Vollbild ein/aus

Attributauswertungsregeln sind eigentlich nur an einer Stelle interessant, n¨amlich bei der Regel: Schließen

Expression -> applyBegin Operator Expression Expression applyEnd Beenden

wo sie die Reihenfolge von Prefix (MathMl) auf Infix umstellen.

Das leistet die folgende Auswertungsregel

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Expression1_Ausdruck = "(" + Expression2_Ausdruck + Operator_Ausdruck + Expression3_Ausdruck + ")";

Geschachtelte Rechtecke Scanner mit Aktionen

Die Reihenfolge wird “gedreht“und f¨ur und werden ¨offnende bzw. schließende Klammern gesetzt. Nur noch bei einer Regel wird etwas ausgewertet, n¨amlich die Operatoren selbst. z.B.: Operator -> multOp

Hier ist zu entscheiden ob multipliziert oder dividiert werden soll. Dazu wird in einem If-Konstrukt das Operationszeichen in einen Zwischen- String gelesen, der dann an den Operator_Ausdruck u¨bergeben wird: String op = plusOp_string.equals("")?"+":"-"; Operator_Ausdruck = op;

An anderer Stelle wird der Wert nur “durchgeschleift“, aber ¨andert sich nicht. R¨uck¨ubersetzung der im letzen Abschnitt erzeugten MathML-Formel ergibt

Startseite

JJ

II

J

I

(((a+2)*(a-2))/(2*b)) Seite 31 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Kantorovic-Baum – von Richard Schack und Thorsten Urban

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Der folgende arithmetische Ausdruck a*a - 2*a*b + b*b

Geschachtelte Rechtecke Scanner mit Aktionen

hat die Kantorovic-Baum-Darstellung + |\ | * | |\ | | b | | | b | |\ | * | |\ | | b | | | * | |\ | | a | | | 2 | * |\ | a | a

Beachte: Der linke Operand steht jeweils weiter unten als der rechte!

Startseite

JJ

II

J

I

Seite 32 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Bei der Erzeugung des Kantorovic-Baums entsteht die String-Darstellung des kompletten Baums aus den Textdarstellungen der Teilb¨aume. Dabei gilt es genau aufzupassen: Der linke Teilbaum folgt jeweils am unteren Ende(!) nach dem rechten Teilbaum, der rechte zwei Zeilen nach dem Operator-Symbol. Der Darstellung des rechten Teilbaums geht links jeweils ein St¨uck des senkrechten Strichs voran, der zum linken Teilbaum f¨uhrt.

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Wegen der rekursiven Schachtelung von Teilausdr¨ucken empfiehlt es sich, zwei Arten von Attributen zu verwenden: text-Attribute vom Typ String zum Aufbau der Texte der Teilb¨aume und prefix-Attribute vom Typ String, in denen die (korrekt einger¨uckten) Strichfolgen stehen, die zu weiter unten folgenden, linken Teilausdr¨ucken f¨uhren. Die text-Attribute ordnen wir allen nichtterminalen Symbolen zu, die prefix-Attribute nur den Symbolen f¨ur (einzur¨uckende) Teilausdr¨ucke. Die text-Attribute werden wie die Attribute der ersten Attributierung von den Bl¨attern zur Wurzel hin“ berechnet, ” sind also synthetisiert. Die prefix-Attribute dagegen werden von der Wurzel zu den Bl¨attern hin“ aufgebaut, sind ” also ererbt. Insgesamt erhalten wir (> kennzeichnet ein synthetisiertes, < ein ererbtes Attribut): Nonterminals: Expression Term Factor S

>text text text text

Startseite

Die Regeln zu Factor sind praktisch selbsterkl¨arend:

JJ

II

Factor -> number Factor_text = Factor_prefix + number_string;

J

I

Seite 33 von 100

Factor -> name Factor_text = Factor_prefix + name_string; Factor -> openingBracket Expression closingBracket Factor_text = Expression_text; Expression_prefix = Factor_prefix;

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Besonders interessant sind die Auswertungsregeln zur ersten Grammatikregel zu E:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Expression -> Expression addOp Term Expression1_text = Expression1_prefix + addOp_string + "\n" + Expression1_prefix + "|" + "\\" + "\n" + Term_text + "\n" + Expression1_prefix + "|" + "\n" + Expression2_text; Expression2_prefix = Expression1_prefix; Term_prefix = Expression1_prefix + "| ";

Geschachtelte Rechtecke Scanner mit Aktionen

Die Textdarstellung des Expression1-Ausdrucks beginnt in der ersten Zeile mit dem Operatorsymbol, dem die Linienst¨ucke noch auf Expression1 folgender Ausdr¨ucke vorangestellt sind. In der zweiten Zeile folgt hinter dem gemeinsamen Pr¨afix (von Expression1) die Gabelung zwischen den beiden Teilausdr¨ucken. In den n¨achsten Zeilen folgt der rechte Teilausdruck Term, dem zus¨atzlich zum gemeinsamen Pr¨afix die senkrechten Striche hin zu Expression2 vorangehen (das entnimmt man der Auswertungsregel zu Term.prefix). In der vorletzten Zeile von Expression1.text folgt das letzte St¨uck des Strichs zum Teilausdruck Expression2, der ganz unten angef¨ugt wird. Die Auswertungsregel zu Expression2.prefix zeigt, dass Expression2 gleich weit einger¨uckt ist wie Expression1. Startseite

Die Auswertungsregeln zur zweiten Grammatikregel zu Expression besteht aus Transferregeln“, die Informationen ” in beide Richtungen unver¨andert weiterreichen: Expression -> Term Expression_text = Term_text; Term_prefix = Expression_prefix;

JJ

II

J

I

Seite 34 von 100

Zur¨ uck

Die Regeln zu Term sind vollst¨andig analog.

Vollbild ein/aus

Schließen

Beenden

2.4. Code-Erzeugung

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

MI-Code-Generierung – Andreas H¨ anel

Geschachtelte Rechtecke Scanner mit Aktionen

Der folgende arithmetische Ausdruck a*a - 2*a*b + b*b

l¨asst sich durch Ausf¨uhrung des folgenden MI-Codes auswerten b: DD 17 a: DD 4 MOVE MOVE MULT MOVE MOVE MULT MOVE MULT SUB MOVE MOVE MULT ADD

W W W W W W W W W W W W W

a , -!SP a , -!SP !SP+, !SP+, I 2 , -!SP a , -!SP !SP+, !SP+, b , -!SP !SP+, !SP+, !SP+, !SP+, b , -!SP b , -!SP !SP+, !SP+, !SP+, !SP+,

-!SP

-!SP -!SP -!SP

-!SP -!SP

Startseite

JJ

II

J

I

Seite 35 von 100

Die ersten vier Zeilen reservieren Speicherplatz f¨ur die beiden Variablen und initialisieren sie. Die Variablen-Werte (17 f¨ur b und 4 f¨ur a) werden – ¨ahnlich wie beim Auswerter – vom Benutzer erfragt, nachdem die Menge der im Ausdruck vorkommenden Variablen bestimmt wurde und bevor die eigentliche Code-Generierung beginnt.

Zur¨ uck

Vollbild ein/aus

Ein MOVE-Befehl schiebt den Wert einer Variablen oder die direkt angegebene Zahlkonstante 2 in den Keller.

Schließen

Die arithmetischen Befehle (ADD, SUB, MULT) entnehmen die Operanden dem Keller und ersetzen sie dort durch das Operationsergebnis.

Beenden

¨ Bei der Ubersetzung in Maschinensprache entsteht das komplette Programm aus Code-St¨ucken. Wir verwenden daher code-Attribute vom Typ String und ordnen diese allen nichtterminalen Symbolen der Grammatik zu. StringKonstanten werden mit doppelten Hochkommata geschrieben. Unsere Ausdr¨ucke enthalten Variablen, f¨ur die zu Beginn der Code-Sequenz Speicherplatz beschafft werden soll – f¨ur jede Variable genau ein Speicherwort. Um alle Variablen, die im Ausdruck vorkommen aufzusammeln, verwenden wir ein Attribut variables vom Typ Set of String (es handelt sich um Mengen von Namen). Beide Attribute werden von den Bl¨attern zur Wurzel hin“ ” berechnet, sind also beide synthetisiert.

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Insgesamt erhalten wir also ( kennzeichnet ein synthetisiertes Attribut): Nonterminals: E code variables T code variables F code variables S code

In den folgenden Attributauswertungsregeln bezeichnet codeE2 das code-Attribut des zweiten Vorkommens der syntaktischen Variablen E in der Grammatikregel, variablesF das variables-Attribut des einzigen Vorkommens der syntaktischen Variablen F in der Grammatikregel, usw. Im Kontext der ersten Grammatikregel zu E erhalten wir folgende Attributauswertungsregeln (Der Code zu E1 besteht aus dem Code zu E2, gefolgt vom Code zu T, gefolgt vom richtigen“ Befehl. Wenn man die Variablen in E2 und T ” vereinigt, dann erh¨alt man die von E1.): E -> E addOp T if (addOp_string.charAt(0)==’+’){ Expression1_code=Expression2_code+"\n"+Term_code+"\n else { Expression1_code=Expression2_code+"\n"+Term_code+"\n Expression1_variables = new HashSet(); Expression1_variables.addAll(Expression2_variables); Expression1_variables.addAll(Term_variables);

Die Attributauswertungsregeln zu E -> T sind trivial, die zu T v¨ollig analog. E -> T Expression_code=Term_code; Expression_variables=Term_variables;

Startseite

JJ

II

J

I

ADD W !SP+, !SP+, -!SP"; } Seite 36 von 100

SUB W !SP+, !SP+, -!SP"; } Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Die interessanteren der Attributauswertungsregeln zu F lauten:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

F -> variable Factor_code=" MOVE W "+name_string+" ,-!SP"; Factor_variables = new HashSet(); Factor_variables.add(name_string);

Geschachtelte Rechtecke Scanner mit Aktionen

F -> number Factor_code=" MOVE W I "+number_string+" ,-!SP"; Factor_variables = new HashSet();

Im Kontext der hinzugef¨ugten Startregel wird f¨ur jede der in variablesE aufgesammelten Variablen eine (zweizeilige) Speicherplatzreservierung erzeugt. Dann werden die Speicherplatzreservierungen vor den Auswertungscode gestellt: S -> E [String h = new String(); String inputValue = new String(); Iterator it = Expression_variables.iterator(); while (it.hasNext()){ String cv = (String)it.next(); boolean ok = false; while (!ok) { inputValue = JOptionPane.showInputDialog("Please input a value for " + cv); try {Integer.parseInt(inputValue); ok=true;} catch (Exception e) {ok = false;} } h=cv+":\n"+" DD "+inputValue+"\n"+h; } h="\n"+h; Arithmetic_code=h+Expression_code;]

Da S nur ein Attribut hat, braucht man auch nur eine Attributauswertungsregel.

Startseite

JJ

II

J

I

Seite 37 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Postscript-Code-Generierung– Martin Fuchs

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Das weitverbreitete Postscript-Format ist nicht nur eine Seitenbeschreibungssprache f¨ur die Bildschirm- und Druckausgabe, sondern kann auch als Programmiersprache genutzt werden. Postscript ist eine Stack-basierte Sprache in Reverse Polish Notation (RPN), der arithmetische Ausdruck

Geschachtelte Rechtecke Scanner mit Aktionen

a*a - 2*a*b + b*b

l¨asst sich in einem Postscript-Interpreter durch Ausf¨uhrung des folgenden Postscript-Codes auswerten: /a 4 def /b 17 def a a mul 2 a mul b mul sub b b mul add ==

¨ Dabei wurden die im Ausdruck vorkommenden Variablen mit 17 bzw 4 initialisiert (Zeile 1 bis 6) und der Ubersichtlichkeit halber eine Darstellung gew¨ahlt, bei der jeder Befehl in einer neuen Zeile steht, grunds¨atzlich ist auch eine Eingabe des kompletten Programmes in einer einzigen Zeile m¨oglich. F¨ur die Umsetzung einfacher arithmetischer Ausdr¨ucke werden nur Bezeichner (Variablen), Ganzzahlen, die Operatoren add, sub, mul, idiv und der Befehl == f¨ur die Programmausf¨uhrung ben¨otigt.

Startseite

JJ

II

J

I

Seite 38 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Zur Erzeugung eines Postscript-Code-Generators mit Jaccie muss nur der Evaluator ge¨andert werden, Scanner und Parser k¨onnen unver¨andert (siehe Syntaxbeschreibung) u¨bernommen werden.

Bin¨ arzahlen

F¨ur die Nonterminale wurde folgende Attributierung gew¨ahlt:

Geschachtelte Rechtecke

Arithmetische Ausdr¨ ucke

Scanner mit Aktionen

Nonterminals: Arithmetic Expression Term Factor

postscript postscript postscript postscript 

variables variables variables variables 



environment

Alle verwendeten Attribute sind synthesized; sie haben die folgende Bedeutung: • variables ist eine Datenstruktur, in der alle im zugeordneten Knoten und dessen direkten und indirekten Nachkommen vorkommenden Variablen enthalten sind. variables wird als Set vereinbart, in der eigentlichen Realisierung wird eine HashSet verwendet, ein Austausch gegen eine andere Datenstruktur, die das Set-Interface implementiert, ist leicht m¨oglich. • environment ist eine als Map vereinbarte und als HashMap realisierte Datenstruktur, die Variablen auf ihre vom Benutzer eingegebenen Belegungen abbildet. Startseite

• postscript ist ein String, der den Postscript-Code des Unterbaums mit dem entsprechenden Knoten als Wurzel darstellt. Berechnung der Attribute Die Berechnung der Attribute variables und environment erfolgt wie in der allerersten Attributierung zu den arithmetischen Ausdr¨ucken. Das environment-Attribut wird hier aber nicht nach unten propagiert.

JJ

II

J

I

Seite 39 von 100

Zur¨ uck

Das Attribut postscript wird wie folgt berechnet: Vollbild ein/aus

Factor -> number Factor_postscript = number_string + " ";

Schließen

Beenden

Factor -> name Factor_postscript = name_string + " ";

Wie oben wird stets ein Zwischenraum als Trenner nach einem Postscript-Token angef¨ugt. Da der Wert einer Variablen erst zur Laufzeit des Postscript-Interpreters beschafft wird, reicht es aus, Namen wie Zahlkonstanten direkt ” hinzuschreiben“.

Bin¨ arzahlen

Hier sieht man, wie Operator-Ausdr¨ucke in Postscriptform gebracht werden:

Scanner mit Aktionen

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

Expression -> Expression addOp Term Expression1_postscript = Expression2_postscript + Term_postscript + (addOp_string.equals("+")?"add ":"sub "); Term -> Term multOp Factor Term1_postscript = Term2_postscript + Factor_postscript + (multOp_string.equals("*")?"mul ":"idiv ");

Bei der Startregel Startseite

Arithmetic -> Expression Arithmetic_postscript = ""; for (Iterator it2 = Arithmetic_variables.iterator();it2.hasNext();) { String current = (String) it2.next(); String value = (String) (Arithmetic_environment.get(current)); Arithmetic_postscript = (Arithmetic_postscript + "/ " + current + " " + value + " def "); } Arithmetic_postscript += Expression_postscript;

wird f¨ur jede Variable eine Postscript-Definition mit dem vom Benutzer (beim Anlegen des Environments) erfragten Wert erzeugt.

JJ

II

J

I

Seite 40 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Alle nicht explizit gezeigten Attributauswertungsregeln sind Transferregeln, die Attributwerte unver¨andert weiterreichen.

Ein Beispiel

Bin¨ arzahlen

F¨ur den arithmetischen Ausdruck a*a-2*a*b+b*b ergibt sich die eingangs gezeigte Postscript-Sequenz (nur ohne Zeilenumbr¨uche). Unten wird der attributierte Syntaxbaum des kleineren arithmetischen Ausdrucks a*17+4 gezeigt, der sich ergibt, wenn der Variablen a der Wert 11 zugeordnet wird:

Arithmetische Ausdr¨ ucke

Arithmetic -postscript:/ a 11 def a 17 mul 4 add -variables:[a] -environment:{a=11} Expression -postscript:a 17 mul 4 add -variables:[a] Expression -postscript:a 17 mul -variables:[a] Term -postscript:a 17 mul -variables:[a] Term -postscript:a -variables:[a] Factor -postscript:a -variables:[a] name -string:a multOp -string:* Factor -postscript:17 -variables:[] number -string:17 addOp -string:+

Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 41 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

Term -postscript:4 -variables:[] Factor -postscript:4 -variables:[] number -string:4

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 42 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

2.5. Grafische Darstellung

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Syntax-Baum als Postscript-Grafik – Ansatz von Peter Pangerl & Co. u ¨berarbeitet

Geschachtelte Rechtecke Scanner mit Aktionen

Der folgende arithmetische Ausdruck 2 * alpha - 3

hat die Syntaxbaum-Darstellung

Arithmetic Expression Expression

addOp -

Term Term

multOp *

Factor

Term Factor

Factor

number 3

name alpha

number 2

Die Grafik stellt die gew¨unschten Proportionen dar: Startseite

1. Knotenbeschriftungen (wie Arithmetic, Expression, addOp, alpha und andere) stehen stets zentriert in einem Feld der L¨ange 10 (bei ungerader L¨ange wird vor dem Zentrieren auf gerade L¨ange aufgerundet). 2. Die rechten Seiten der Grammatik der arithmetischen Ausdr¨ucke haben alle eine ungerade L¨ange und damit stets ein mittleres Symbol. Dieses mittlere Symbol steht zentriert unter dem Vaterknoten.

JJ

II

J

I

Seite 43 von 100

3. Denken wir uns die Knotenbeschriftungen in der Maximall¨ange 10, dann gilt f¨ur Produktionsregeln der L¨ange 3, dass der linke und der rechte Teilbaum von der mittleren S¨aule durch Streifen von je einem Zeichen Breite getrennt sind. Die genauen horizontalen Positionen der Wurzeln des linken und rechten Teilbaums ergeben sich durch rekursive Anwendung dieser Vorschrift auf alle Teilb¨aume.

Zur¨ uck

Vollbild ein/aus

4. Die vertikalen Abst¨ande sind fest gew¨ahlt (in etwa so wie oben).

Schließen

5. Die senkrechten Linien sollen in der Mitte der S¨aule laufen, die schr¨agen Linien von der S¨aulenmitte des Vaterknotens zur S¨aulenmitte des Sohnknotens.

Beenden

Zur L¨ osung:

Bin¨ arzahlen

Zun¨achst werden wie vorgeschlagen folgende Hilfsklassen eingef¨ugt: MyLine und MyNode. MyLine hat vier Attribute: x1,y1, x2, y2, die die Koordinaten des Anfangs- und Endpunktes der Linie definieren. Neben dem Konstruktor besitzt MyLine noch die Methoden getX1(), getY1(),getX2() und getY2() sowie toString():

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

public class MyLine{ private int x1,x2,y1,y2; public public public public

int int int int

getX1(){ getY1(){ getX2(){ getY2(){

return return return return

x1;} y1;} x2;} y2;}

public MyLine(int x1, int y1, int x2, int y2){ this.x1=x1; this.y1=y1; this.x2=x2; this.y2=y2; } public String toString(){ return "\nMyLine(x1:"+x1+", y1:"+y1+", x2:"+x2+", y2:"+y2+")"; } }

Die Klasse MyNode ist analog aufgebaut und wird daher nicht eigens gezeigt. Sie besitzt f¨ur die grafische Darstellung von beschrifteten Knoten drei Attribute: x1, y1, contents, wobei contents die Knotenbeschriftung enth¨alt, x1,y1 die Koordinaten der Beschriftung. Analog zu MyLine hat MyNode die Methoden getX1(), getY1(), getContents() und toString(). Wir ben¨otigen folgende Konstanten:

Startseite

JJ

II

J

I

Seite 44 von 100

Zur¨ uck

Vollbild ein/aus

public public public public public

static static static static static

int int int int int

xDist yTop yInk xGap fontsize

= 36; = 736; = -12; = 1; = 12;

// // // // //

halbe Saeule (in Pixel) oberer Seitenrand (in Pixel) ein Zeilenabstand ein horizontaler Minimalabstand die Fontgroesse

Schließen

Beenden

Zum Einf¨ugen f¨uhrender Blanks (Auff¨ullen auf Spaltenbreite) verwenden wir:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

public static String padded(String s){ String result = s; int blanks = (10-s.length()+1)/2; for (int i = 0; i < blanks; i++) s = " " + s; return s; }

Geschachtelte Rechtecke Scanner mit Aktionen

Wie vorgegeben wurden folgende Attribute f¨ur die graphische Darstellung verwendet: • Ein ererbtes Attribut y mit der vertikalen Koordinate der linken, oberen Ecke eines Knotenfelds (der L¨ange 10 Zeichenbreiten). Ererbt ist dieses Attribut, weil die Berechnung von der Wurzel in Richtung der Bl¨atter l¨auft: Wurzel ganz oben, n¨achste Schicht in festem Abstand darunter, u.s.w. • Ein synthetisiertes Attribut width mit der Breite des Teilbaums, dessen Wurzel der Knoten ist. • Ein ererbtes Attribute left mit der x-Koordinate des linken Teilbaums, dessen Wurzel der Knoten ist. • Ein synthetisiertes Attribut x mit der horizontalen Koordinate der linken, oberen Ecke eines Knotenfelds. • Ein synthetisiertes Attribut nodes enth¨alt die Menge aller MyNode-Informationen zu allen Knoten im durch den Knoten bestimmten Teilbaum (bei Factor-Knoten sind das zwei MyNodes!) • Ein synthetisiertes Attribut lines enth¨alt die Menge aller MyLine-Informationen zu allen Kanten im durch den Knoten bestimmten Teilbaum (bei Factor-Knoten ist das eine MyLine!) • Der Wurzelknoten hat ein synthetisiertes Attribut postscript mit der aus den Mengen der MyLine-und MyNode-Informationen berechneten Postscript-Darstellung des Baums.

Startseite

JJ

II

J

I

Seite 45 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Diese Attribute werden wie folgt berechnet (stellvertretend f¨ur alle Attributauswertungsregeln betrachten wir hier nur die zur Startregel und die zur Regel, die Addition modelliert - Erl¨auterungen in Form von Kommentaren eingestreut):

Beenden

Bin¨ arzahlen

Arithmetic -> Expression

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

Arithmetic_width = Expression_width; // Transfer rule

Scanner mit Aktionen

Arithmetic_x = Expression_x; // Transfer rule Expression_y = yTop + 2 * yInk; // Arithmetic is at top margin on paper Expression_left = 5; // left margin on paper chosen arbitrarily // Set of nodes of Arithmetic ... Arithmetic_nodes = new ArrayList(); // contains all nodes from Expression ... Arithmetic_nodes.addAll(Expression_nodes); // plus the Arithmetic node itself: Arithmetic_nodes.add(new MyNode(Arithmetic_x, yTop, "Arithmetic")); // Set of lines of Arithmetic ... Arithmetic_lines = new ArrayList(); // contains all lines below Expression ... Arithmetic_lines.addAll(Expression_lines); // plus the line from Arithmetic to Expression: Arithmetic_lines.add(new MyLine(Arithmetic_x + xDist, yTop - 2, Arithmetic_x + xDist, yTop + yInk));

Startseite

JJ

II

J

I

Seite 46 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

// This page shows the *one* valuation rule that computes // the Postscript code for the whole tree:

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

// generated Postscript code starts with three fixed lines: Arithmetic_postscript = "\n/fntsize " + fontsize + " def\n" + "/Courier findfont " + fontsize + " scalefont setfont\n" + "newpath "; // then for each node its Postscript code is produced: Iterator n_iterator = Arithmetic_nodes.iterator(); while(n_iterator.hasNext()) { MyNode n = (MyNode)n_iterator.next(); Arithmetic_postscript = Arithmetic_postscript + "\n " + n.getX1() + " " + n.getY1() + " moveto " + " (" + n.getContents() + ") show "; }; // and similarly the Postscript code for each line: Iterator l_iterator = Arithmetic_lines.iterator(); while(l_iterator.hasNext()) { MyLine l = (MyLine)l_iterator.next(); Arithmetic_postscript = Arithmetic_postscript + "\n " + l.getX1() + " " + l.getY1() + " moveto" + " " + l.getX2() + " " + l.getY2() + " lineto"; };

Startseite

JJ

II

J

I

Seite 47 von 100

Zur¨ uck

// finally, two more fixed lines are appended: Arithmetic_postscript = Arithmetic_postscript + "\nstroke" + "\n" + "showpage";

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

Expression -> Expression addOp Term

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

Expression1_width = Expression2_width + 2 * (xGap + xDist) + Term_width; // 2*xDist is the with of the middle column which has 2 gaps around it

Scanner mit Aktionen

Expression1_x = Expression1_left + Expression2_width + xGap; // beetween the left margin of the Expression1 tree and its horizontal // root position there is the complete left hand subtree and one gap Expression2_y = Expression1_y + 2*yInk; // Expression2 is two fontsizes below Expression1 Term_y = Expression1_y + 2 * yInk; // Term is two fontsizes below Expression1, too Term_left = Expression1_left + Expression2_width + 2 * (xGap + xDist); // beetween the left margin of the Expression1 tree and the left margin // of its Term subtree there is the complete Expression2 subtree // plus the width 2*xDist of the middle column plus two gaps Startseite

// The nodes of the Expression1 tree ... Expression1_nodes = new ArrayList(); // are those from the Expression2 subtree ... Expression1_nodes.addAll(Expression2_nodes); // plus those from the Term subtree ... Expression1_nodes.addAll(Term_nodes); // plus directly generated nodes for left hand side (Expression1) // and for token "addOp" and the token string below it: Expression1_nodes.add(new MyNode(Expression1_x, Expression1_y, "Expression")); Expression1_nodes.add(new MyNode(Expression1_x, Expression1_y + 2 * yInk, " addOp")); Expression1_nodes.add(new MyNode(Expression1_x, Expression1_y + 3 * yInk, " "+addOp_string));

JJ

II

J

I

Seite 48 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

// The lines of the Expression1 tree ... Expression1_lines = new ArrayList(); // are those from the Expression2 subtree ... Expression1_lines.addAll(Expression2_lines); // plus those from the Term subtree ... Expression1_lines.addAll(Term_lines); // plus a line towards leftmost operand (Expression2): Expression1_lines.add(new MyLine(Expression1_x + xDist, Expression1_y - 2, Expression2_x + xDist, Expression2_y - yInk)); // plus a line towards rightmost operand (Term): Expression1_lines.add(new MyLine(Expression1_x + xDist, Expression1_y - 2, Term_x + xDist, Term_y - yInk)); // plus a vertical line towards addOp: Expression1_lines.add(new MyLine(Expression1_x + xDist, Expression1_y - 2, Expression1_x + xDist, Expression2_y - yInk)); Expression2_left = Expression1_left; // Transfer rule

F¨ur das Eingangsbeispiel ergeben sich (stark gek¨urzt) die Knoten und Linien ... -nodes:[ MyNode(x1:5, y1:616, string: Factor), MyNode(x1:5, y1:592, string: number), MyNode(x1:5, y1:580, string: 2), ... MyNode(x1:224, y1:736, string:Arithmetic)] -lines:[ MyLine(x1:41, y1:614, x2:41, y2:604), MyLine(x1:41, y1:638, x2:41, y2:628), ... MyLine(x1:260, y1:734, x2:260, y2:724)]

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 49 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

... sowie der (ebenfalls gek¨urzte) Postscript-Code zu der eingangs gezeigten Grafik:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

/fntsize 12 def /Courier findfont 12 scalefont setfont newpath 5 616 moveto ( Factor) show 5 592 moveto ( number) show 5 580 moveto ( 2) show 5 640 moveto ( Term) show 151 640 moveto ( Factor) show 151 616 moveto ( name) show 151 604 moveto ( alpha) show 78 664 moveto ( Term) show 78 640 moveto ( multOp) show 78 628 moveto ( *) show ... 297 688 moveto ( Term) show 224 712 moveto (Expression) show 224 688 moveto ( addOp) show 224 676 moveto ( -) show 224 736 moveto (Arithmetic) show 41 614 moveto 41 604 lineto 41 638 moveto 41 628 lineto 187 638 moveto 187 628 lineto 114 662 moveto 41 652 lineto 114 662 moveto 114 652 lineto .... 260 710 moveto 114 700 lineto 260 710 moveto 333 700 lineto 260 710 moveto 260 700 lineto 260 734 moveto 260 724 lineto stroke showpage

Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 50 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

2.6. Spracherweiterungen

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Vektor-Ausdru ¨ cke – Marc Akkermann und Matthias Ru ¨cker Wir fassen die Werte arithmetischer Ausdr¨ucke nun auf als die Koordinaten von 2-dimensionalen Vektoren in der kartesischen Zeichenebene. Der Operator @ verbindet zwei Koordinaten zu einem Vektor, welcher in Klammern geschrieben wird (z.B. (3@4) ). Solche Vektoren lassen sich addieren (+) bzw. subtrahieren (-) und von rechts her mit einem Skalar multiplizieren (*) (bzw. dividieren (/) ). Von Vektoren kann man den Betrag bilden, indem man den Vektor zwischen senkrechte Striche setzt. Und schließlich kann man von zwei Vektoren das Skalarprodukt (#) bilden. Ein paar Beispiele: (3@4) + (4@(0-3))

ergibt dasselbe wie (7@1)

|(3@4)|

ergibt ebenso wie |(4@(0-3))| den Wert 5

|(3@4) / |(3@4)||

ergibt 1 (den Betrag eines durch seinen Betrag geteilten Vektors)

(3@4) # (3@4)

ergibt nach Definition des Skalarprodukts den Wert 25

(3@4) # (4@(0-3))

Skalarprodukt senkrecht auf einander stehender Vektoren ergibt den Wert 0

Da arithmetische Ausdr¨ucke auch Variablen enthalten d¨urfen, deren konkrete Werte zur Auswertungszeit vom Benutzer erfragt werden, k¨onnen wir abstraktere“ Formeln formulieren – hier zwei Formeln, die sich auf die x- und ” y-Koordinaten von drei Punkten (A, B und C) beziehen: ((xB@yB) - (xA@yA)) + ((xC@yC) - (xB@yB)) + ((xA@yA) - (xC@yC)) eine geschlossene Vektorkette, ergibt dasselbe wie (0@0)

Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 51 von 100

((xA@yA)-(xB@yB))/|(xA@yA)-(xB@yB)| + ((xC@yC)-(xB@yB))/|(xC@yC)-(xB@yB)| winkelhalbierender Vektor zum Winkel ABC (als Summe der Einheitsvektoren zu BA und BC)

Zur¨ uck

Vollbild ein/aus

Wir betrachten die zugeh¨origen Grammatikerg¨ anzungen: Schließen

(1) Factor -> bar VectorExpression bar (2) Factor -> VectorFactor vecMultOp VectorFactor

(1) Der Betrag eines Vektors geht als Factorin einen arithmetischen Ausdruck ein. (2) Das Skalarprodukt ebenfalls.

Beenden

Bei den Vektor-wertigen Ausdr¨ucken haben wir drei Pr¨azedenzebenen (normale Vektoraddition (+) und -subtraktion (-); Produkt mit Skalar (*); Bildung Vektor aus Koordinaten ( (Koord@Koord) ): VectorExpression -> VectorExpression addOp VectorTerm VectorExpression -> VectorTerm

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

VectorTerm -> VectorTerm multOp Factor VectorTerm -> VectorFactor VectorFactor -> openingBracket Factor ampersand Factor closingBracket VectorFactor -> openingBracket VectorExpression closingBracket

Außerdem ist die Startregel zu erg¨anzen mit: Arithmetic -> VectorExpression

¨ In der Realisierung dieser Anderungen ergeben sich f¨ur (3@4) # (3@4)

folgende Zwischen- und Endergebnisse in Jaccie:

Startseite

a) Scanner-Ergebnis:

JJ

II

openingBracket number "3" ampersand "@" number "4" closingBracket vecMultOp "#" openingBracket number "3" ampersand "@" number "4" closingBracket

J

I

"("

Seite 52 von 100

")"

Zur¨ uck

"("

Vollbild ein/aus

Schließen

")"

Beenden

Bin¨ arzahlen

b) Parser-Ergebnis:

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

Arithmetic VectorExpression VectorExpression VectorTerm VectorFactor openingBracket - string: "(" Factor number - string: "3" ampersand - string: "@" Factor number - string: "4" closingBracket - string: ")" addOp - string: "+" VectorTerm VectorFactor openingBracket - string: "(" Factor number - string: "4" ampersand - string: "@" Factor openingBracket - string: "(" Expression Expression Term Factor number - string: "0" addOp - string: "-" Term Factor number - string: "3" closingBracket - string: ")" closingBracket - string: ")"

Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 53 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

c) Endergebnis :

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

Arithmetic -result:([email protected])

Scanner mit Aktionen

F¨ur den Winkelhalbierenden-Ausdruck (s.o.) ((xA@yA)-(xB@yB))/|(xA@yA)-(xB@yB)| + ((xC@yC)-(xB@yB))/|(xC@yC)-(xB@yB)|

ergeben sich bei verschiedenen Variablenbelegungen folgende Endergebnisse in Jaccie: Endergebnis f¨ ur [xA,yA,xB,yB,xC,yC] = [0,6,0,0,3,0] : Arithmetic -result:([email protected])

Endergebnis f¨ ur [xA,yA,xB,yB,xC,yC] = [1,8,6,2,5,3] : Startseite

Arithmetic -result:([email protected])

Die Attributierung enth¨alt ¨ahnliche Attribute zum Aufsammeln der vorkommenden Variablen und zum Propagieren der Name-Wert-Paare in den Syntaxbaum wie die Attributierung zur Auswertung einfacher arithmetischer Ausdr¨ucke.

JJ

II

J

I

Seite 54 von 100

Zur¨ uck

Anders als dort rechnen wir hier nicht mit gek¨urzten Br¨uchen (die als Strings gespeichert werden), sondern mit Javadouble-Werten (die zum Speichern in HashMaps in Double-Objekte verpackt“werden m¨ ussen, weil Java-Collections ” nur echte Objekte aufnehmen k¨onnen und keine einfachen double-Werte). F¨ur double-Werte steht uns die ganze Palette von arithmetischen Operationen aus Java zur Verf¨ugung, insbesondere auch die sqrt, die zur Ermittlung des Betrags eines Vektors ben¨otigt wird.

Vollbild ein/aus

Schließen

Beenden

Eine typische Attributierungsregeln ist dann auch die zur Ermittlung des Betrags eines Vektors:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Factor -> bar VectorExpression bar // erst zwei Hilfsvariablen ... double x = java.lang.Math.abs(VectorExpression_vecValX); double y = java.lang.Math.abs(VectorExpression_vecValY); // ... und dann die Berechnung des Attributwerts: Factor_value = java.lang.Math.sqrt((x*x)+(y*y));

Geschachtelte Rechtecke Scanner mit Aktionen

Andere typische Attributierungsregeln implementieren die Vektor-Addition koordinatenweise (getrennt f¨ur x und y): VectorExpression1 -> VectorExpression2 addOp VectorTerm // die x-Koordinaten ... if (addOp_string.equals("+")) { VectorExpression1_vecValX = VectorExpression2_vecValX + VectorTerm_vecValX; else { VectorExpression1_vecValX = VectorExpression2_vecValX - VectorTerm_vecValX; // ... und die y-Koordinaten: if (addOp_string.equals("+")) { VectorExpression1_vecValY = VectorExpression2_vecValY + VectorTerm_vecValY; else { VectorExpression1_vecValY = VectorExpression2_vecValY - VectorTerm_vecValY;

}

}

}

Startseite

JJ

II

J

I

Seite 55 von 100

} Zur¨ uck

Die Fallunterscheidungen sind notwendig, weil ein addOp ja auch ein - sein kann.

Vollbild ein/aus

Schließen

Beenden

Bedingte Ausdru ¨ cke – Dennis Koch und Maximilian Winkler

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Hier soll die zuletzt um Vektor-Ausdr¨ucke erweiterte Syntax arithmetischer Ausdr¨ucke nochmals erweitert werden um

Geschachtelte Rechtecke Scanner mit Aktionen

• Einf¨uhrung von initialisierten Variablen (im mathematischen Sinn) mit geschachtelten G¨ultigkeitsbereichen in einem let-Konstrukt • Boolesche Ausdr¨ucke und Vergleichsausdr¨ucke • Bedingte Audr¨ucke in C-/Java-Syntax • Rekursive Verwebung dieser Teilausdr¨ucke Was damit genau gemeint ist, wird am schnellsten an der zugeh¨origen Grammatikerg¨ anzung klar: Factor -> let name becomes Expression in Expression end BooleExpression -> BooleExpression orOp BooleTerm BooleExpression -> BooleTerm BooleTerm -> BooleTerm andOp BooleFactor BooleTerm -> BooleFactor BooleFactor -> notOp BooleFactor BooleFactor -> Expression relOP Expression

Startseite

JJ

II

J

I

Seite 56 von 100

Expression -> openingBracket BooleExpression questionMark Expression colon Expression closingBracket

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Diese Grammatikerg¨anzung erfordert eine Erweiterung der Scanner-Definition um folgende Patterns und Token:

Bin¨ arzahlen

Patterns:

Tokens:

:= := := := := := := := := :=

Arithmetische Ausdr¨ ucke

:= := := := := := := := := := := := := := :=

$>$= $ $< $!$= $? $: $i$n $l$e$t $e$n$d $&$& $~ ( | | | | | )



Es ist darauf zu achten, dass in, let und end vor der name-Token-Definition eingetragen werden m¨ussen, weil wir vorrangig Schl¨usselw¨orter erkennen wollen.

Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 57 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Zu den so erweiterten Ausdr¨ucken soll – aufbauend auf der Auswerter-Attributierung aus 2.2 – ein interaktiver Auswerter erstellt werden, der auf das Erfragen von Variablenwerten verzichtet, sofern sie in let-Konstrukten ihren Wert erhalten. F¨ur Vergleichsausdr¨ucke und Boolsche Ausdr¨ucke verwenden wir ein Attribut boolValue:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Attributes: boolValue : boolean boolValue ist ein synthetisiertes Attribut und dient zur Wertermittlung in booleschen Ausdr¨ ucken wie z.B. in folgender

Regel, in der der Wert eines bedingten Ausdrucks berechnet wird: Expression1 -> openingBracket BooleExpression questionMark Expression2 colon Expression3 closingBracket if (BooleExpression_boolValue) Expression1_value = Expression2_value; else Expression1_value = Expression3_value;

Im Attribut variables werden nur diejenigen Namen gesammelt, die noch nicht durch let-Konstrukte gebunden wurden: Factor -> let name becomes Expression1 in Expression2 end Iterator variablesIterator = Expression2_variables.iterator(); while (variablesIterator.hasNext()) { String name = new String(name_string); if (name.equals(variablesIterator.next())) { variablesIterator.remove(); break; } }

Startseite

JJ

II

J

I

Seite 58 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Im Kontext der gleichen Grammatikregel wird von dem ererbten environment eine Kopie gezogen und vor dem Weiterreichen nach unten“ ein neuer Eintrag f¨ur den gerade gebundenen Namen erzeugt: ” Factor -> let name becomes Expression1 in Expression2 end Expression2_environment = new HashMap(Factor_environment); Expression2_environment.put(name_string, Expression1_value);

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Beispiele f¨ ur solche Ausdr¨ ucke: 17 + 4 = ergibt wie immer 21 let a := 3 in let b := 4 in a*a + b*b end end => ergibt 25 Startseite

let a := 3 in a*a end + let b := 4 in b*b end => ergibt ebenfalls 25 let a := 5 in let b := 2*a in let c := 2*(a-b) in ( a < c ? a : ( c < b ? c : b)) end end end => ergibt -10, weil a=5, b=10, c=-10 und weil davon das Minimum bestimmt wird

JJ

II

J

I

Seite 59 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

let a := 5 in let b := 2*a in let b := (0-2)*a in let c := 2*(a-b) in let a := (0-8) in ( a < c ? a : ( c < b ? c : b)) end end end end end => ergibt -8

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

G¨ultigkeitsbereiche kann man in syntaktisch korrekter, aber inhaltlich unsinniger Weise verwenden: let a := 3 in let b := 4 in 17 + 4 end end => ergibt immer noch 21 let b := 3 in a*a end + let a := 4 in b*b end => ergibt keinesfalls 25!!

Startseite

JJ

II

J

I

Seite 60 von 100

let a := b in let b := a in a + b end end => ergibt ?!?

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

In einer weiteren Attributierung ließe sich pr¨ufen, ob solche inhaltlichen Fehler vorliegen.

3. Geschachtelte Rechtecke

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Im Buch Syntaxbasierte Programmierwerkzeuge“ wird ab S. 14 ein Beispiel beschrieben, bei dem es um die Er” zeugung von Grafiken aus textuellen Beschreibungen geht. Konkret handelt es sich um Bilder aus achsenparallelen Rechtecken, sogenannten Boxen:

Geschachtelte Rechtecke Scanner mit Aktionen

• Eine Box hat eine frei bestimmbare Breite und H¨ohe. • Eine Box kann ein Teilbild umrahmen. • Teilbilder und Boxen k¨onnen senkrecht angeordnet werden. Dann werden sie – unter Wahrung des Mindestabstands – von oben nach unten um eine senkrechte Mittelachse zentriert angeordnet. • Teilbilder und Boxen k¨onnen waagerecht angeordnet werden. Dann werden sie – unter Wahrung des Mindestabstands – von links nach rechts um eine waagerechte Mittelachse zentriert angeordnet. Der Mindestabstand wird f¨ur die gesamte Zeichnung global festgelegt. Im Buch findet man dazu i.W. folgende Syntax: Token definitions:

Startseite

JJ

II

J

I



:= $( := $)



:= $[ := $]



:= ({$0-$9}[1-*]



:= $> := $V

Schließen

:= $@

Beenden

Seite 61 von 100

Zur¨ uck

Vollbild ein/aus

(Der @-Operator wird erst sp¨ater ben¨otigt.)

Bin¨ arzahlen

Grammar rules: Drawing -> Picture

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Picture Picture Picture Picture

-> -> -> ->

Box Picture right Box Picture down Box openB Picture closeB

Box Box

-> openB Width Height closeB -> openP Picture closeP

Width

-> number

Height

-> number

Das zus¨atzliche Startsymbol Drawing und seine zugeh¨orige Startregel wurden wie u¨blich als Aufh¨anger von Wurzelattributen und Ort der Initialisierung von ererbten Attributen hinzugef¨ugt. Die anderen Regeln spiegeln die vorher beschriebenen Bildungsgesetze wider (man interpretiere eckige Klammerpaare als Rahmen von Rechtecken). Nur die zweite Regel zu Box folgt nicht direkt: Sie ist zum Gruppieren von Teilbildern notwendig. Bei dieser Syntax d¨urfen – ¨ahnlich wie bei arithmetischen Ausdr¨ucken – u¨berfl¨ussige runde Klammerpaare fast nach Belieben eingef¨ugt werden. Die Enden einer vertikalen oder einer horizontalen Folge werden in der Eingabe nicht durch Klammerung hervorgehoben. Wir verwenden daher in der Jaccie-Implementierung parallel zur alten Grammatik eine neue Grammatik, die zwar umfangreicher ist, aber die genannten Nachteile behebt.

Startseite

JJ

II

J

I

Seite 62 von 100

Zur¨ uck

Alte Syntax und Attribute portieren – Dominik Oesterreich Vollbild ein/aus

Eine unter Evaluator – Definition – Java – Methods“ angelegte Hilfsklasse MyRectangle hat vier Attribute vom Typ ” int, die ein achsenparalleles Rechteck komplett beschreiben: top und left bestimmen die linke obere Ecke, bottom und right die gegen¨uberliegende. MyRectangle hat einen Konstruktor mit vier Parametern (die Attributwerte in der oben angegebenen Reihenfolge), eine toString()-Methode sowie vier Methoden zum Erfragen der Attributwerte: int top() u.s.w.

Schließen

Beenden

Bin¨ arzahlen

public class MyRectangle { protected int top; protected int left; protected int bottom; protected int right; MyRectangle (int t, int l, int b, int r) { top = t; left = l; bottom = b; right = r; } public public public public

int int int int

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

top() { return top; } left() { return left; } right() { return right; } bottom() { return bottom; }

public String toString() { return "\n[top="+top+", left="+left+", right="+right+", bottom="+bottom+"]"; } }

Dort ist auch eine globale Variable mit dem Mindestabstand zwischen Boxen (als Attribut der Scanner-Klasse) vereinbart und initialisiert: int gap = 2;

Von den folgenden Attributen entsprechen left und top zusammen dem position-Attribut aus dem Buch (genauer entspricht left dem Wert position.x und top dem Wert position.y).

Startseite

JJ

II

J

I

Seite 63 von 100

Zur¨ uck

Vollbild ein/aus

Attribute und ihre Typen: >width : int >height : int Picture Drawing_rectangles = Picture_rectangles; Picture_left = 0; Picture_top = 0; Picture -> Picture right Box Picture1_rectangles = Picture2_rectangles; Picture1_rectangles.addAll(Box_rectangles); Picture1_width = Picture2_width + gap + Box_width; Picture1_height = Math.max (Picture2_height, Box_height); int yPos = Picture1_top; int yDiff = Box_height - Picture2_height; Picture2_top = yPos; if (yDiff > 0) {Picture2_top = Picture2_top + yDiff/2;};

Startseite

JJ

II

J

I

Seite 64 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

Box_left = Picture1_left + gap + Picture2_width;

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

int yPos = Picture1_top; int yDiff = Picture2_height - Box_height; if (yDiff > 0) {yPos = yPos + (yDiff/2);}; Box_top = yPos;

Scanner mit Aktionen

Picture -> Picture down Box Picture1_rectangles = Picture2_rectangles; Picture1_rectangles.addAll(Box_rectangles); Picture1_width = Math.max(Picture2_width, Box_width); Picture1_height = Picture2_height + gap + Box_height; int xPos = Picture1_left; int xDiff = Box_width - Picture2_width; if (xDiff > 0) {xPos = xPos + xDiff/2;}; Picture2_left = xPos; Startseite

int xPos = Picture1_left; int xDiff = Picture2_width - Box_width; if (xDiff > 0) {xPos = xPos + xDiff/2;}; Box_left = xPos;

JJ

II

J

I

Seite 65 von 100

Box_top = Picture1_top + gap + Picture2_height; Zur¨ uck

Picture -> openB Picture closeB Picture1_rectangles = Picture2_rectangles; Picture1_rectangles.add(new MyRectangle (Picture1_top, Picture1_left, Picture1_top + Picture1_height, Picture1_left + Picture1_width));

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

Picture1_width = 2*gap + Picture2_width;

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

Picture1_height = 2*gap + Picture2_height;

Scanner mit Aktionen

Picture2_left = Picture1_left + gap; Picture2_top = Picture1_top + gap; Box -> openB Width Height closeB Box_rectangles = new HashSet(); Box_rectangles.add(new MyRectangle (Box_top, Box_left, Box_top + Box_height, Box_left + Box_width)); Width -> number Width_width = (new Integer(number_string)).intValue(); Height -> number Height_height = (new Integer(number_string)).intValue();

Wir wenden unseren Compiler an auf die Eingabezeichenreihe

Startseite

JJ

II

J

I

Seite 66 von 100

[5 11] > ( [15 15] v [40 10] ) Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Der Scanner macht daraus die Tokenfolge

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

openB "[" number "5" number "11" closeB "]" right ">" openP "(" openB "[" number "15" number "15" closeB "]" down "v" openB "[" number "40" number "10" closeB "]" closeP ")"

Der Parser baut aus der Tokenfolge den Syntaxbaum mit der textuellen Darstellung Drawing Picture Picture Box openB - string: "[" Width number - string: "5" Height number - string: "11" closeB - string: "]" right - string: ">"

Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 67 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

Box openP - string: "(" Picture Picture Box openB - string: "[" Width number - string: "15" Height number - string: "15" closeB - string: "]" down - string: "v" Box openB - string: "[" Width number - string: "40" Height number - string: "10" closeB - string: "]" closeP - string: ")"

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

und der Evaluator berechnet daraus das Wurzel-Attribut Drawing -rectangles:[ [top=8, left=0, right=5, bottom=19], [top=17, left=7, right=47, bottom=27], [top=0, left=19, right=34, bottom=15]]

Seite 68 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Grafische Darstellungen – Sebastian Bergatt und Stefan Keil

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Hier geht es darum, die im Attribut Drawing_rectangles aufgesammelten Rechtecke grafisch anzuzeigen, und zwar

Geschachtelte Rechtecke Scanner mit Aktionen

• Teilattributierung Java“: in einem Java-Grafik-Fenster; ” • Teilattributierung Postscript“: als druckbares Postscript-File. ” Jede der beiden Teilattributierungen umfasst genau ein Attribut, das nur dem Startsymbol der Grammatik zugeordnet ist und daher auch nur im Kontext der Startregel ausgewertet wird. Daher enth¨alt jede Teilattributierungen auch nur eine einzige Attributauswertungsregel. Zun¨achst die formalen Teile: Attribute und ihre Typen: >window : int >postscript : String

¨ W¨ahrend das window ein reines Dummy-Attribut ist – wichtig ist nur der Nebeneffekt: das Offnen eines Java-Fensters mit der Grafik –, wird im Attribut postscript tats¨achlich der Postscript-Text erzeugt, den der Drucker entsprechend ausgeben kann.

Startseite

Die Attributauswertungsregel f¨ur window lautet:

JJ

II

Drawing_window = 1; // irrelevanter Attributwert

J

I

// Das Ausgabefenster, in dem die Rechtecke gezeichnet werden, // ¨ ubernimmt ein DrawRectangle-Objekt, welches alle Rechtecke // (HashSet) und den Titel des Ausgabefensters enth¨ alt: JFrame window = new DrawRectangle(Drawing_rectangles, "Boxes");

Seite 69 von 100

Zur¨ uck

Vollbild ein/aus

// Bestimmem der Gr¨ oße des Ausgabefensters: window.setSize(Picture_width+10, Picture_height+30); // Anzeigen des Ausgabefensters: window.setVisible(true);

Schließen

Beenden

Die eigentliche Zeichenarbeit“ erledigt die ausf¨uhrlich kommentierte Methode paint() der folgenden Hilfsklasse, ” die in Jaccie unter Evaluator - Definition - Actions - Java“ definiert wird: ” import java.awt.*; import java.awt.geom.*; import javax.swing.*;

// viele der 2D-Klassen sind hier untergebracht // wird f¨ ur das JFrame ben¨ otigt

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

public class DrawRectangle extends JFrame { HashSet rect; public DrawRectangle(HashSet r, String title) { super(title); rect = r; } public void paint (Graphics g) { super.paint(g); /* grafische Objekte werden gezeichnet, indem f¨ ur alle Komponenten die paint()-Methode mit passendem Grafikkontext aufgerufen wird. Der Grafikkontext wurde mit der Klasse Graphics2D erweitert.. deshalb wird hier von Graphics auf Graphics2D gecastet, um die erweiterte Funktionalit¨ at nutzen zu k¨ onen. Graphics2D ist Unterklasse von Graphics. */

Startseite

JJ

II

J

I

Graphics2D g2 = (Graphics2D) g; Seite 70 von 100

/* Da die Ausgabe normalerweise nicht gegl¨ attet wird, schalten wir Antialiasing an, nun werden alle Grafikobjekte weichgezeichnet: */ g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

/* Anlegen eines Iterators, um alle Rechtecke zu erfassen: */ Iterator r_iterator = rect.iterator(); while(r_iterator.hasNext()) { MyRectangle r = (MyRectangle)r_iterator.next();

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

/* Die draw-Methode aus der Graphics2D-Klasse nimmt Shape-Objecte und zeichnet diese. Shape-Objecte sind z.B. Rectangle, Polygon, Line2D ... Point: der Startpunkt, von dem gezeichnet wird (beim Rechteck die linke obere Ecke) Er wird aus techn. Gr¨ unden noch um 5 nach rechts und 25 nach unten verschoben, da das Objekt sonst direkt auf dem Rand des Ausgabefensters beginnen w¨ urde. Diese Verschiebunghat ausschließlich optische Gr¨ unde. */ g2.draw(new Rectangle(new Point(r.left()+5,r.top()+25), new Dimension(r.right()-r.left(),r.bottom()-r.top()))); } } } Startseite

JJ

II

J

I

Seite 71 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Die Attributauswertungsregel f¨ur postscript lautet:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Drawing_postscript = "\n" + "/box {" + "\n" + " /bwidth exch def" + "\n" + " /bheight exch def" + "\n" + " 0 bwidth rlineto" + "\n" + " bheight 0 rlineto" + "\n" + " 0 bwidth neg rlineto" + "\n" + " closepath" + "\n" + "} def" + "\n" + "newpath" + "\n"; // erzeugt den immer gleichen Vorspann, in // dem die Zeichenprozedur box(width,height) // definiert wird (beim Aufruf kommen erst // die Parameter, dann der Prozedurname "box") Iterator r_iterator = Drawing_rectangles.iterator(); // erzeugt einen Iterator der den Inhalt von // Drawing_rectangles durchl¨ auft while(r_iterator.hasNext()) { MyRectangle r = (MyRectangle)r_iterator.next(); // nun wird f¨ ur jedes gefundene MyRectangle-Objekt // eine Zeile der Form : // " moveto box" // erzeugt und an den String Drawing_postscript angeh¨ angt Drawing_postscript = Drawing_postscript + (" " + (r.left() + " " + r.top() + " moveto " + (r.right()-r.left()) + " " + (r.bottom()-r.top()) + " box" + "\n")); }

Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 72 von 100

Zur¨ uck

Vollbild ein/aus

Drawing_postscript = Drawing_postscript + "stroke" + "\n" + "showpage"; // erzeugt den immer gleichen Nachspann

Schließen

Beenden

Die Beispieldaten

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

[([[50 60]] > [30 100] > ([[50 60]])) v [200 25]]

ergeben das Auswertungsergebnis (zwecks Lesbarkeit von Hand einger¨uckt): Drawing -rectangles:[ , , , , , ,

Geschachtelte Rechtecke Scanner mit Aktionen

[top=0, left=0, right=210, bottom=139] [top=20, left=26, right=86, bottom=90] [top=20, left=124, right=184, bottom=90] [top=5, left=90, right=120, bottom=105] [top=109, left=5, right=205, bottom=134] [top=25, left=31, right=81, bottom=85] [top=25, left=129, right=179, bottom=85]

] -postscript: /box { /bwidth exch def /bheight exch def 0 bwidth rlineto bheight 0 rlineto 0 bwidth neg rlineto closepath } def newpath 90 5 moveto 30 100 box 0 0 moveto 210 139 box 124 20 moveto 60 70 box 31 25 moveto 50 60 box 129 25 moveto 50 60 box 26 20 moveto 60 70 box 5 109 moveto 200 25 box stroke showpage -window:1

Startseite

JJ

II

J

I

Seite 73 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

und das Fenster

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 74 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Neue Syntax attributieren – Marc Kru ¨ger und Alexander Schmitz

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Die neue Grammatik lautet (Startsymbol ist Drawing):

Geschachtelte Rechtecke Scanner mit Aktionen

Drawing

-> Picture

Picture Picture

-> openP Directed closeP -> Undirected

Undirected -> number ampersand number Undirected -> openB Picture closeB Directed Directed

-> Horizontal right HorPart -> Vertical down VerPart

Horizontal -> Horizontal right HorPart Horizontal -> HorPart HorPart HorPart

-> openP Vertical down VerPart closeP -> Undirected

Vertical Vertical

-> Vertical down VerPart -> VerPart

VerPart VerPart

-> openP Horizontal right HorPart closeP -> Undirected

Die neue Grammatik wird mit den gleichen Attributen wie bisher versehen.

Startseite

JJ

II

J

I

Seite 75 von 100

Zur¨ uck

Vollbild ein/aus

Attribute und ihre Typen: >width : int >height : int oldSyntax : String >topDown : String >turned90 : String

Erzeugung der alten Syntax: Da die alte Syntax weniger standardisiert“ ist als die neue, kann man neue Syntax besser in alte Syntax u¨bertragen ” als umgekehrt. Hierbei liegt der wesentliche Arbeitsaufwand darin, Ausdr¨ucke der Form number1 ampersand number2 so umzuwandeln, dass das @ in der alten Syntax nicht auftaucht. In allen anderen F¨allen, wird daS Attribut von unten nach oben durchgereicht, wobei hier jeweils die Ausdr¨ucke in Strings umgewandelt werden m¨ussen. Nachfolgend die Attributauswertungsregeln in ihrem jeweilen Kontext (dabei sind die einfachen Transfer“-Regeln, die Attributwerte ” unver¨andert weiterreichen nebst ihren Kontexten weggelassen worden): Picture -> openP Directed closeP Picture_oldSyntax = openP_string + Directed_oldSyntax + closeP_string;

Startseite

JJ

II

J

I

Seite 80 von 100

Zur¨ uck

Vollbild ein/aus

Undirected -> number ampersand number Undirected_oldSyntax = "[ " + Number1_oldSyntax + " " + Number2_oldSyntax + " ]"; Undirected -> openB Picture closeB Undirected_oldSyntax = openB_string + Picture_oldSyntax + closeB_string;

Schließen

Beenden

Bin¨ arzahlen

Directed -> Horizontal right HorPart Directed_oldSyntax = Horizontal_oldSyntax + right_string + HorPart_oldSyntax;

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Directed -> Vertical down VerPart Directed_oldSyntax = Vertical_oldSyntax + down_string + VerPart_oldSyntax; Horizontal -> Horizontal right HorPart Horizontal1_oldSyntax = Horizontal2_oldSyntax + right_string + HorPart_oldSyntax; Vertical -> Vertical down VerPart Vertical1_oldSyntax = Vertical2_oldSyntax + down_string + VerPart_oldSyntax; HorPart -> openP Vertical down VerPart closeP HorPart_oldSyntax = openP_string + Vertical_oldSyntax + down_string + VerPart_oldSyntax + closeP_string; VerPart -> openP Horizontal right HorPart closeP VerPart_oldSyntax = openP_string + Horizontal_oldSyntax + right_string + HorPart_oldSyntax + closeP_string; Startseite

Angewandt auf die Eingabe (in neuer Syntax) ( ( [ 10 @ 10 ] > 10 @ 50 >

JJ

II

J

I

[ 10 @ 10 ] ) V 120 @ 20 ) Seite 81 von 100

ergibt sich die alte Syntax: (([[ 10 10 ]]>[ 10 50 ]>[[ 10 10 ]])V[ 120 20 ])

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Vertikale Spiegelung:

Bin¨ arzahlen

Offenbar ver¨andert die TopDown-Attributierung nur die Vertikalen und l¨asst die Horizontalen unver¨andert. Im folgenden ist nur der Kontext aufgef¨uhrt, in dem die eigentliche Arbeit passiert.

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Directed -> Vertical down VerPart Directed_topDown = VerPart_topDown + down_string + Vertical_topDown; Vertical -> Vertical down VerPart Vertical1_topDown = VerPart_topDown + down_string + Vertical2_topDown;

Angewandt auf die Eingabe ( ( [ 10 @ 10 ] > 10 @ 50 >

[ 10 @ 10 ] ) V 120 @ 20 )

ergibt sich die auf den Kopf gestellte“ Eingabe: ” (120@20V([10@10]>10@50>[10@10])) Startseite

Angewandt auf die Eingabe (120@20V([10@10]>10@50>[10@10]))

ergibt sich die nochmals auf den Kopf gestellte“ Eingabe: ”

JJ

II

J

I

Seite 82 von 100

Zur¨ uck

(([10@10]>10@50>[10@10])V120@20) Vollbild ein/aus

d.h. die urspr¨ungliche Eingabe (ohne Zwischenr¨aume)! Schließen

Bemerkung: Auch die in der n¨achsten Attributierung erzeugte Drehung um 90 Grad l¨asst sich in dieser Weise iterieren und f¨uhrt nach viermaliger Anwendung zur urspr¨unglichen Zeichenreihe zur¨uck.

Beenden

Drehung um 90 Grad:

Bin¨ arzahlen

Bei der Turned90-Attributierung tauschen die Vertikalen und die Horizontalen ihre Rollen. W¨ahrend die Elemente einer Horizontalen in der Vertikalen in genau der gleichen Reihenfolge erscheinen, kehrt sich die Reihenfolge der Elemente in Vertikalen, die zu Horizontalen werden, genau um. Dabei ist darauf zu achten, dass bei einer gedrehten Box die Gr¨oße und Breite vertauscht ist.

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Undirected -> Number ampersand Number Undirected_turned90 = number2_string + ampersand_string + number1_string; Directed -> Horizontal right HorPart Directed_turned90 = Horizontal_turned90 + "V" + HorPart_turned90; Directed -> Vertical down VerPart Directed_turned90 = VerPart_turned90 + ">" + Vertical_turned90; Horizontal -> Horizontal right HorPart Horizontal1_turned90 = Horizontal2_turned90 + "V" + HorPart_turned90; Vertical -> Vertical down VerPart Vertical1_turned90 = VerPart_turned90 + ">" + Vertical2_turned90; Startseite

HorPart -> openP Vertical down VerPart closeP HorPart_turned90 = openP_string + VerPart_turned90 + ">" + Vertical_turned90 + closeP_string; VerPart -> openP Horizontal right HorPart closeP VerPart_turned90 = openP_string + Horizontal_turned90 + "V" + HorPart_turned90 + closeP_string;

Angewandt auf die Eingabe ( ( [ 10 @ 10 ] > 10 @ 50 >

JJ

II

J

I

Seite 83 von 100

Zur¨ uck

[ 10 @ 10 ] ) V 120 @ 20 )

ergibt sich die um 90 Grad gedrehte“ Eingabe: ”

Vollbild ein/aus

Schließen

Beenden

(20@120>([10@10]V50@10V[10@10]))

Compiler erstellen – Ein Bearbeiter

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 84 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Aufgabe: Erstellen Sie entweder zur alten oder zur neuen Syntax aus allen entwickelten Komponenten einen lauff¨ ahigen Compiler in Form eines ausf¨uhrbaren jar-Files. Der Compiler soll

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

• eine textuelle Beschreibung einer Boxen-Grafik aus einer Datei XXX.sinp einlesen (Name XXX dazu erfragen),

Scanner mit Aktionen

• die Grafik in einem Fenster anzeigen und • eine Datei XXX.ps mit der Postscript-Form der Grafik erzeugen (bzw. u¨berschreiben). Bitte alle Schritte ausf¨uhrlich am Beispiel darstellen! (Dieser Inhalt soll sp¨ater ins Jaccie-Handbuch eingearbeitet werden.)

Startseite

JJ

II

J

I

Seite 85 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

4. Scanner mit Aktionen

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

4.1. Telegramme

Scanner mit Aktionen

Unsere Telegrammverschl¨usselung basiert auf den drei Grundzeichen: Punkt ( .“), Strich ( -“) und Zwischenraum ” ” ( “ oder ). ” Die verschl¨ usselten Symbole sind Buchstaben, Ziffern oder Sonderzeichen. Der Morse-Code ist gegeben durch: a a ¨ b c ch d e f g h i j k l m

..-.-... -.-. ----.. . ..-. --. .... .. .---..-.. --

n o o ¨ p q r s t u u ¨ v w x y z

-. -----. .--. --..-. ... ....-....--..-.---..

0 1 2 3 4 5 6 7 8 9

----.---..--...-......... -.... --... ---.. ----.

. , ? EOM

.-.-.--..-..--.. .-.-.

Startseite

JJ

II

J

I

Seite 86 von 100

In der Verschl¨usselung trennt ein Zwischenraum je zwei Symbole, zwei Zwischenr¨aume trennen W¨orter von einander.

Zur¨ uck

Jede verschl¨usselte Nachricht endet mit dem End-of-Message-Sonderzeichen, das im Klartext als EOM wiedergegeben wird.

Vollbild ein/aus

Schließen

Beenden

Klartext in Morse-Code umwandeln - Philipp Appelhoff

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Inhalt dieser Aufgabe ist es, einen Verschl¨usseler zu erstellen, der Texte ins Morsealphabet u¨bersetzt. Zwei Symbole werden durch ein Leerzeichen getrennt. Zwei Leerzeichen stellen damit die Trennung zweier Worte dar. Jede Nachricht ¨ endet mit dem End-of-Message-Sonderzeichen, das im Klartext als EOM dargestellt wird. Neben der Ubersetzung von Klartext in Morse-Code sollen auch die Kosten f¨ur eine Nachricht berechnet werden:

Geschachtelte Rechtecke Scanner mit Aktionen

• W¨orter kosten 2ct pro Zeichen • Die ersten 3 Zeichen pro Wort sind frei • Jeder Satz kostet pauschal 5ct Um die Aufgabe nur mit einem Scanners zu l¨osen, wird ein Token f¨ur jedes Zeichen, also a bis z, 0 bis 9, die Satzzeichen , . und ?, das Leerzeichen und die Endmarke ben¨otigt. Die Token der Zeichen ch, a-z, 0-9 und der Umlaute sind nach folgendem Muster erstellt worden. Man beachte, dass nach dem Morsealphabet auch ch als ein Zeichen interpretiert wird. := "z" Action: telegramm = telegramm + [Morsecode als String]; payChar(); add(scannerService.getString()); [\]

Diese Definition bedient sich einiger Besonderheiten. Zum einen wird den Token eine Aktion zugewiesen. Dabei wird der Variable telegramm der Morsecode des Zeichens angeh¨angt. Zudem werden zwei Methoden aufgerufen, um die Kosten zu berechnen und den Eingabestring in einer weiteren variable zusammenzusetzen. Die Variablen sind genau wie die aufgerufenen Methoden im Punkt Global declarations“ von Jaccie eingetragen. Folgende Deklarationen sind ” darin enthalten:

Startseite

JJ

II

J

I

Seite 87 von 100

Zur¨ uck

Vollbild ein/aus

String telegramm = ""; String origin = ""; int n = 0; int cost = 0;

Schließen

Beenden

Bin¨ arzahlen

public void payChar() { if (n2) cost = cost + 2; n++; }

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

public void paySentence() { % cost = cost + 5; n = 0; } public void add(String s) { origin = origin + s; }

Neben der Variablendeklaration sind hier auch drei Methoden definiert: Die Methode payChar() addiert 2ct f¨ur den Buchstaben, falls bereits mehr als 3 Buchstaben im Wort sind. Gleichzeitig wird der Z¨ahler n hochgesetzt. Dementsprechend muß der Token eines Leerzeichens n wieder auf Null setzen. Die Methode paySentence() nutzen wir beim Vorkommen eines Punkts oder Fragezeichen. Die Token f¨ur . und ? sind daher: := "z" Action: telegramm = telegramm + ; paySentence(); add(scannerService.getString()); [\]

Wie schon erw¨ahnt, wird der Buchstabenz¨ahler beim Leerzeichen zur¨uckgesetzt und dem Morsecode ein Leerzeichen hinzugef¨ugt. Dadurch ergeben sich als Worttrenner zwei Leerzeichen. := " " Action: telegramm = telegramm + " "; n = 0; // Ein Leerzeichen setzt den Buchstabenz¨ ahler auf Null [\]

Startseite

JJ

II

J

I

Seite 88 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Damit unser Ergebnis aber auch ausgegeben wird, muss beim letzten Token der u¨bersetzte Text ausgegeben werden. Er ist wie folgt definiert:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

:= "EOM" Action: telegramm = telegramm + ".-.-."; String[] out = { telegramm, origin, new String("Message costs: ").concat(cost+"ct") }; JOptionPane.showMessageDialog(null,out,"Entschluessler", JOptionPane.INFORMATION_MESSAGE); telegramm = ""; [\]

Scanner mit Aktionen

Der Test ergibt:

Startseite

JJ

II

J

I

Seite 89 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Morse-Code in Klartext umwandeln - Axel Betschinski

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

F¨ur die Scannerdefinition ben¨otigen wir ein Token f¨ur jedes im Morse-Code darstellbare Symbol. Wenn ein Symbol vom Scanner erkannt wurde, f¨ugen wir das entsprechende Zeichen einem String hinzu und generieren so den Ausgabetext.

Geschachtelte Rechtecke Scanner mit Aktionen

Tokens: := ".- " Action: telegramm = telegramm + "a"; eingabe = eingabe + ".- "; := "-... " Action: telegramm = telegramm + "¨ a"; eingabe = eingabe + "-... "; := "-... " Action: telegramm = telegramm + "b"; eingabe = eingabe + "-... "; := "-.-. " Action: telegramm = telegramm + "c"; eingabe = eingabe + "-.-. "; := "---- " Action: telegramm = telegramm + "ch"; eingabe = eingabe + "---- "; := "-.. " Action: telegramm = telegramm + "d"; eingabe = eingabe + "-.. ";

Analog zu diesen Symbolen definieren wir die Token f¨ur die restlichen Symbole.

Startseite

JJ

II

J

I

Seite 90 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Nach Abarbeitung der Eingabe enth¨alt der String telegramm den entschl¨usselten Telegrammtext; der String eingabe enth¨alt die Eingabe im Morse-Code.

Bin¨ arzahlen

Jetzt wollen wir zus¨atzlich eine Kostenberechnung nach folgender Vorschrift hinzuf¨ugen:

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

• Jeder Punkt und jeder Strich kosten einen Cent.

Scanner mit Aktionen

• W¨orter kosten zus¨atzlich 10 Cents. • Sonderzeichen (einschließlich des obligaten EOM) kosten pauschal 5 Cents. Daf¨ur ben¨otigen wir eine Variable vom Typ Float. Wir addieren f¨ur jedes Zeichen den entsprechenden Betrag hinzu und dividieren die Summe vor der Ausgabe durch 100. := "---- " Action: telegramm = telegramm + "ch"; eingabe = eingabe + "---- "; kosten = kosten + 4; [\] := "-.. " Action: telegramm = telegramm + "d"; eingabe = eingabe + "-.. "; kosten = kosten + 3; [\] := ". " Action: telegramm = telegramm + "e"; eingabe = eingabe + ". "; kosten = kosten + 1; [\]

Startseite

JJ

II

J

I

Seite 91 von 100

...

Zur¨ uck

Vollbild ein/aus

:= ".---- " Action: telegramm = telegramm + "1"; eingabe = eingabe + ".---- "; kosten = kosten + 5; [\]

Schließen

Beenden

Bin¨ arzahlen

:= "..--- " Action: telegramm = telegramm + "2"; eingabe = eingabe + "..--- "; kosten = kosten + 5; [\]

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

... := "--..-- " Action: telegramm = telegramm + ","; eingabe = eingabe + "--..-- "; kosten = kosten + 5; [\] := "..--.. " Action: telegramm = telegramm + "?"; eingabe = eingabe + "..--.. "; kosten = kosten + 5; [\] := " " Action: telegramm = telegramm + " "; eingabe = eingabe + " "; kosten = kosten + 10; [\] := ".-.-." Action: telegramm = telegramm + "EOM"; eingabe = eingabe + ".-.-."; kosten = kosten + 5;

Startseite

JJ

II

J

I

Seite 92 von 100

Zur¨ uck

Float ko = new Float(kosten/100); preis = "Kosten: " + ko.toString() + "EUR";

Vollbild ein/aus

Schließen

Beenden

Nach Abarbeitung der Eingabe haben wir also die Preisinformation im String preis abgelegt. Die Ausgabe erfolgt u¨ber ein JOptionPane, welches ein Array aus den Strings telegramm, eingabe und preis enth¨alt:

Bin¨ arzahlen Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

sa = new String[3]; sa[0]=telegramm; sa[1]=eingabe; sa[2]=preis; JOptionPane.showMessageDialog(null,sa,"Entschluessler", JOptionPane.INFORMATION_MESSAGE);

Scanner mit Aktionen

Zum Test codieren wir per Hand den Satz quidquid agas, age prudenter et respice finem.“ in Morse-Code und ” verwenden diesen als Eingabe f¨ur den Scanner. --.- ..- .. -.. --.- ..- .. -.. .- --. .- ... --..-- .- --. . .--. .-. ..- -.. . -. - . .-. . - .-. . ... .--. .. -.-. . ..-. .. -. . -- .-.-.- .-.-.

Das Resultat des Scannerdurchlaufs ist folgende Ausgabe: q "--.- " u "..- " i ".. " d "-.. " q "--.- " u "..- " i ".. " d "-.. " worttrenner " " a ".- " g "--. " a ".- " s "... " , "--..-- " worttrenner " "

Startseite

JJ

II

J

I

Seite 93 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

...

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke

worttrenner " " f "..-. " i ".. " n "-. " e ". " m "-- " . ".-.-.- " worttrenner " " schluss ".-.-."

Scanner mit Aktionen

Startseite

JJ

II

J

I

Seite 94 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

4.2. Spracherkennung

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Klammergebirge & Co – Alexander Talaska

Geschachtelte Rechtecke Scanner mit Aktionen

Ein Klammergebirge“ ist die Folge aus ¨offnenden und schließenden Klammern, die u¨brigbleibt, wenn man aus ” einem beliebigen arithmetischen Ausdruck alle Zeichen außer den Klammern streicht. Die Menge aller m¨oglichen Klammergebirge ist die formale Sprache der Klammergebirge. Wie im Beispielband beispieleScreen.pdf erw¨ahnt, l¨asst sich diese Sprache z.B. durch eine kontextfreie Grammatik mit nur zwei Regeln beschreiben: S → (S)S |  Die Sprache der Klammergebirge ist eine Teilmenge der Sprache der balancierten Klammerfolgen, die definiert ist durch (die Notation w : a bezeichnet die Anzahl der as in w): { w ∈ {(, )}∗ | w : ( = w :) } Die Sprache der balancierten Klammerfolgen wiederum ist offenbar eine Teilmenge der Sprache aller Klammerfolgen, die definiert ist durch {(, )}∗ . Von den drei Sprachen ist die umfangreichste (d.h. gr¨obste“), die Sprache aller Klammerfolgen, eine Typ-3-Sprache ” und damit von einem endlichen Automaten zu erkennen. Die beiden anderen sind Typ-2-, aber nicht Typ-3 und damit prinzipiell nicht von endlichen Automaten erkennbar. W¨ahrend Jaccie-Scanner im Prinzip auf endlichen Automaten beruhen, werden sie durch die M¨oglichkeit, beim Erkennen eines Tokens eine Aktion, d.h. ein beliebiges Java-Programmst¨uck, auszuf¨uhren, sehr viel m¨achtiger als endliche Automaten. Wir demonstrieren das mit einem Jaccie-Scanner, der Klammerfolgen verarbeitet und nach jedem gelesenen Token (also nach jedem Klammersymbol) in einem Dialogfenster meldet, ob das bisher gelesene Anfangsst¨uck der Folge

Startseite

JJ

II

J

I

Seite 95 von 100

Zur¨ uck

1. gerade balanciert ist 2. Anfangsst¨uck eines Klammergebirges ist Das zweite Kriterium ist erf¨ullt, wenn im Anfangsst¨uck (und in jedem seiner Anfangsst¨ucke) die Anzahl der schließenden Klammern nicht gr¨oßer ist als die Anzahl der o¨ffnenden Klammern.

Vollbild ein/aus

Schließen

Beenden

Um die Eigenschaften des Terms korrekt zu bestimmen ist es notwendig, Informationen u¨ber den bereits abgearbeiteten Abschnitt zu behalten. Dazu f¨uhrt man Variablen ein:

Bin¨ arzahlen

In der ganzzahlige Variablen openB wird die Differenz der ¨offnenden und schließenden Klammern gehalten. Sie erh¨oht bzw. erniedrigt sich mit jeder gelesenen ¨offnenden bzw. schließenden Klammer um 1 .

Geschachtelte Rechtecke

Arithmetische Ausdr¨ ucke

Scanner mit Aktionen

Die Bedingung 1. ist also genau dann erf¨ullt, wenn die Differenz Null ist. Bedingung 2. ist solange erf¨ullt, bis die Differenz einen negativen Wert annimmt, denn dann ist die Anzahl der schließenden Klammern gr¨osser als die der ¨offnenden. Ausserdem folgt aus der Forderung, dass f¨ur ein Anfangsst¨uck eines Klammergebirges die Bedingung 2. auch f¨ur s¨amtliche Pr¨afixe gelten soll. Also kann ein Ausdruck, in dem die Bedingung einmal veletzt wurde, nicht mehr Anfangsst¨uck eines Klammergebirges werden. Diese Information wird hier in dem String sgeb gespeichert. Da dieser auch f¨ur die Ausgabe verwendet wird, nimmt er bei negativer Differenz den Wert "kein " an, sonst ist er leer. In gleicher Weise nutzt man den String sbal, der bei Balanciertheit leer ist und sonst den Wert "nicht " annimmt. Der String kExpr zeichnet den bisher abgearbeiteten Teilausdruck auf. Er erscheint im Titel des Dialogs, der die Eigenschaften des Teilausdrucks angibt. Die Information u¨ber den Teilausdruck ist folgendermaßen zusammengesetzt: "Der Teilausdruck ist " + sbal + "balanciert und " + sgeb + "Anfang eines Klammergebirges."

Der Ablauf an einem Beispiel: Beispiel: --------1.

Ausdruck = ())(

| V ())( openB = 1 = sbal = "nicht ", sgeb = "" Also: "Der Teilausdruck ist nicht balanciert und Anfang eines Klammergebirges."

Startseite

JJ

II

J

I

Seite 96 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Bin¨ arzahlen

2.

| V ())(

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

openB = 0 = sbal = "", sgeb = "" Also: "Der Teilausdruck ist balanciert und Anfang eines Klammergebirges."

3.

| V ())( openB = -1 = sbal = "nicht ", sgeb = "kein " Also: "Der Teilausdruck ist nicht balanciert und kein Anfang eines Klammergebirges." Startseite

4.

| V ())( openB = 0 = sbal = "", sgeb = "kein " Also: "Der Teilausdruck ist balanciert und kein Anfang eines Klammergebirges."

JJ

II

J

I

Seite 97 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden

Typ-2 und Typ-1 erkennen – Stefan Harwarth

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Ein bekanntes Beispiel f¨ur eine Typ-2-Sprache, die nicht Typ-3 ist: {an bn | n ≥ 1}

Geschachtelte Rechtecke Scanner mit Aktionen

n n n

Ein ebenso bekanntes Beispiel f¨ur eine Typ-1-Sprache, die nicht Typ-2 ist: {a b a | n ≥ 1} Der Sachverhalt ¨andert sich nicht, wenn man an jedes Wort der beiden genannten Sprachen ein Endezeichen (#) anh¨angt. F¨ur unser Vorhaben ist es aber n¨utzlich, da wir so ein Token haben, bei dem die Abrechnung gemacht“ ” werden kann. W¨ahrend Jaccie-Scanner im Prinzip auf endlichen Automaten beruhen, also Typ-3-Sprachen erkennen, werden sie durch die M¨oglichkeit, beim Erkennen eines Tokens eine Aktion, d.h. ein beliebiges Java-Programmst¨uck, auszuf¨uhren, sehr viel m¨achtiger als endliche Automaten. Wir demonstrieren das mit zwei Jaccie-Scannern, die jeweils Folgen von as und bs mit Endesymbol # verarbeiten und beim Erkennen des Endesymbols in einem Dialogfenster melden, ob das Wort zur Sprache {an bn | n ≥ 1} (bzw. zur Sprache {an bn an | n ≥ 1}) geh¨ort. L¨ osung: Bei der Aufgabe ist zu beachten, dass hier nur ein Scanner entwickelt werden soll, der bereits in der Lage ist, die beiden angegebenen Sprachen zu erkennen. Beide Sprachen sind Teilmengen von {a | b} ∗ #. Die beiden Scanner sind bis auf eine Codezeile identisch, daher nun zun¨achst der gemeinsame Teil:

Startseite

Definiert sind als Token des Scanners:

JJ

II

:= $a Action: a1++; [\]

J

I

Seite 98 von 100

:= $b Action: b++; [\]

Zur¨ uck

Vollbild ein/aus

:= $a Start: (b > 0); [\] Action: a2++; [\]

Schließen

Beenden

:= $# Action: (siehe unten)

In der Action des endToken, die weiter unten gezeigt wird, liegt der Unterschied der beiden Scanner.

Bin¨ arzahlen

Jedem Token der Scanner ist eine Action zugeordnet. Das ist ein beliebiges Java-Codest¨uck (bei dem jede Codezeile mit [\] abgeschlossen ist), das bei Erreichen des Tokens ausgef¨uhrt wird und damit die endlichen Automaten des Jaccie-Scanners viel m¨achtiger macht. In den Actions der Token wird nichts weiter gemacht, als 3 Variablen zu inkrementieren, die jeweils die Anzahl der a vor dem ersten b, die nach dem ersten b und die Anzahl der b wiederspiegelt.

Arithmetische Ausdr¨ ucke Geschachtelte Rechtecke Scanner mit Aktionen

Daneben hat das aNachB-Token eine Start-Bedingung, die als Vorbedingung f¨ur das Erreichen dieses Tokens erf¨ullt sein muss. Der aufmerksame Beobachter hat schon gesehen, dass sich aToken und aNachB nur in dieser Bedingung unterscheiden. Das heisst, Jaccie pr¨uft bei der Ausf¨uhrung die Bedingung von aNachB und matcht - falls erf¨ullt dieses Token, oder - falls nicht erf¨ullt - das Token aToken. F¨ur die Action Codest¨ucke ist es n¨otig, die verwendeten Variablen zu deklarieren und initialisieren. Dies geschieht im Abschnitt Global Declarations: Global Declarations: int a1 = 0; int a2 = 0; int b = 0; Startseite

Ferner ist es n¨otig f¨ur die unten gezeigte Ausgabe der Benachrichtigung an den Benutzer einige Teile des JavaFramework einzubinden, was im Import-Abschnitt geschieht: Import: import java.util.*; import javax.swing.*;

JJ

II

J

I

Seite 99 von 100

Zur¨ uck

Abschließend nun die beiden endToken, in denen die Variablen ausgewertet und anhand ihrer Werte der Typ der Sprache ermittelt wird. Wichtig ist hier auch die Pr¨ufung, ob u¨berhaupt Zeichen gez¨ahlt wurden, da die beiden Sprachen eine L¨ange n ≥ 1 erwarten. Die abschließende R¨ucksetzung der Variablen ist n¨otig, da sonst der Scanner vor jedem Lauf neu kompiliert werden m¨usste - it’s not a bug, it’s a feature?

Vollbild ein/aus

Schließen

Beenden

Typ-2-Sprache

Bin¨ arzahlen Arithmetische Ausdr¨ ucke

Action: String s = "Nicht in der Sprache: a^n b^n | n >= 1"; if ((a1 >= 1) && (a1 == b) && (a2 == 0)) s = "Wort der Sprache: a^n b^n | n >= 1"; JOptionPane.showMessageDialog(null, s, "Scanner", JOptionPane.INFORMATION_MESSAGE); a1 = a2 = b = 0; [\]

Geschachtelte Rechtecke Scanner mit Aktionen

Typ-1-Sprache Action: String s = "Nicht in der Sprache: a^n b^n a^n | n >= 1"; if ((a1 >= 1) && (a1 == b) && (a2 == a1)) s = "Wort der Sprache: a^n b^n a^n | n >= 1"; JOptionPane.showMessageDialog(null, s, "Scanner", JOptionPane.INFORMATION_MESSAGE); a1 = a2 = b = 0; [\]

Bei Eingabe von aaabbbaaa#

Startseite

JJ

II

J

I

ergibt sich erwartungsgem¨aß: Seite 100 von 100

Zur¨ uck

Vollbild ein/aus

Schließen

Beenden