Expression (arithmetische Ausdrücke)

Werbung
Expression (arithmetische Ausdrücke)
Beispiel
$ CLASSPATH=. java Expression2
2+3*4
BinaryAdd
2
BinaryMul
3
4
14.0
Grammatikregeln -- Backus-Naur-Form (BNF)
Formal besteht eine Grammatik aus einer Menge von Eingabesymbolen, einer Menge von
Grammatikbegriffen, daraus einem Startbegriff, und einer Menge von Regeln, das heißt,
bestimmten Paaren von Folgen von Grammatikbegriffen und Eingabesymbolen; alle Mengen
und Folgen müssen endlich sein.
Typischerweise schreibt man nur die Regeln auf und verlangt bei kontextfreien Grammatiken,
daß die linke Seite einer Regel immer ein Grammatikbegriff sein muß. Nach Konvention steht
der Startbegriff auf der linken Seite der ersten Regel und man faßt rechte Seiten zum gleichen
Grammatikbegriff als Alternativen zusammen. Die Wiederholungen der Syntaxgraphen muß man
durch rekursive Verweise modellieren. Für arithmetische Ausdrücke sieht das etwa so aus:
sum : product | sum ’+’ product | sum ’-’ product ;
product : term | product ’*’ term | product ’/’ term | product ’%’ term ;
term : ’+’ term | ’-’ term | ’(’ sum ’)’ | Number ;
trennt linke und rechte Seite, | trennt Alternativen, ; steht nach allen rechten Seiten zum
gleichen Grammatikbegriff. Eingabesymbole werden mit einfachen Anführungszeichen zitiert.
Da Number nicht links vorkommt, muß Number (implizit) eine Klasse von Eingabesymbolen
repräsentieren. Man könnte auch folgende Regeln hinzufügen:
:
Number : digit | Number digit ;
digit : ’0’ | ’1’ | ’2’ | ’3’ | ’4’ | ’5’ | ’6’ | ’7’ | ’8’ | ’9’ ;
Grammatikregeln -- Erweiterte Backus-Naur-Form (EBNF)
Syntaxgraphen korrespondieren wesentlich intuitiver zu Grammatikregeln, wenn man sich auf
Schreibweisen für Wiederholungen und relativ standardisierte Graphen einigt, zum Beispiel
one
alt
two
alt : ( one | two ) ;
( )
|
zur Zusammenfassung
für Alternativen
{ }
einmal oder mehrfach
[ ]
höchstens einmal
some
body
some : { body } ;
opt
body
opt : [ body ] ;
many
body
many : [{ body }] ;
kombiniert: beliebig oft
EBNF ist als Schreibweise für Wiederholungen eine verkürzende Schreibweise für BNF. Für die
meisten Menschen ist EBNF intuitiver als BNF. Die traditionelle Schreibweise für Wiederholungen
in EBNF hat Probleme bei 1-n Wiederholungen. Hier muß man Teile der Grammatik verdoppeln.
konventionelle Schreibweise:
{...}
0-n mal wiederholen
[...]
0 oder 1 mal erkennen
unsere Schreibweise:
{...}
1-n mal wiederholen
[...]
0 oder 1 mal erkennen
Analog zu den folgenden Syntaxgraphen sehen arithmetische Ausdrücke dann etwa so aus:
sum : product [{ (’+’|’-’) product }];
product : term [{ (’*’|’/’|’%’) term }];
term : [{’+’|’-’}] ( Number | ’(’ sum ’)’ ) ;
Rekursiver Abstieg
Idee: Pro Graph wird eine Funktion implementiert, die diesen Teil der Grammatik erkennt. Die
Funktionen rufen sich gegenseitig (auch rekursiv) auf. Man steigt so in Richtung der Blätter
(auch rekursiv) in der Erkennung ab. Hat die Funktion einen Teil erkannt, führt sie
entsprechende Aktionen aus. Im Expression-Beispiel könnte das Ergebnis des Teilausdrucks
sofort berechnet werden, oder es wird wie in der Vorlesung ein Baum gebaut, der die erkannte
Informationen repräsentiert. Wenn alle Knoten und Blätter im Baum Unterklassen von
java.lang.Number sind, kann der Wert des arithmetischen Ausdrucks über die Methoden der
Number-Klasse in verschiedenen Typen berechnet werden.
Bäume für arithmetische Ausdrücke
Hier zwei Beispiel für Bäume, die einen arithm. Ausdruck speichern. Das Programm gibt nun
auch den Baum textuell aus.
• 5-6*8:
-
5
*
6
8
$ pwd; make stdin
..../lab2/addon/expr
$ CLASSPATH=.. java expr.Expression2
5-6*8
tree:
BinarySub
5
BinaryMul
6
8
-43.0
• 9-+-9*-(-3*(3-2))
9
*
-
-
9
*
3
3
2
$ CLASSPATH=.. java expr.Expression2
5-6*8
BinarySub
9
BinaryMul
UnaryMinus
9
UnaryMinus
BinaryMul
UnaryMinus
3
BinarySub
3
2
36.0
Herunterladen