Präzedenregeln in Java sagen, dass +expr und -expr vor + von Addition und - von Addition stehen, warum wird dann z. B. a+b als eine Addition ausgeführ

Kelsjb7

Mitglied
Wenn man dieser Tabelle folgt, dann wird z. B. der AUsdruck:

a*-b so interpretiert (a*(-b)). Weil das - vor dem * steht, wird das für das b genutzt. Wenn das so ist, müsste bei einer Addition z. B. a+b, das + nicht zum b gezählt werden, also als a(+b) interpretiert werden und nicht als Addition a+b? Da dürfte ja dann eigentlich keine Addition stattfinden oder?


istso.png
 
Beste Antwort
Aber im Falle von a+-b wird das - zu b zugeordnet, hier würde ich dei Begründung mit den Parametern noch akzeptieren.
Für den Ausdruck "a+-b" kannst du auch wieder versuchen, einen Syntaxbaum mit Hilfe der Präzedenztabelle aufzubauen.
Starten wir mal wieder bei dem "a". Das kann ja die linke Seite für zumindest noch binäre Operatoren werden. Also gehen wir weiter.
"a+". Das erste Plus ist hier wieder die (11), also der binäre Additionsoperator. Also suchen wir jetzt die Bedeutung des rechten Operanden.
Wir müssen hier wieder ab mindestens der Präzedenz des Operators starten, dessen rechten Operanden wir finden wollen, also mindestens bei 11.
Hier sehen wir jetzt das "-" Minus. Da wir noch keinen linken Operanden für einen...
Nein, das wäre kein valider ausdruck. a+b ist ein Operator mit 2 Parametern, kein unaray Operator mit nur einem.

Ansonsten würde da ja ab rauskommen, was kein valider java Ausdruck wäre
 
Ausdrücke werden immer startend mit den Grammatikregeln für Operatoren mit geringer Priorität hin zu Operatoren mit hoher Priorität ausgewertet/geprased.
Wenn der Parser also den Tokenstream "a+b" sieht, dann geht er erstmal die Grammatikregeln für einen Ausdruck/Expression durch, beginnend mit Operatoren niedriger Priorität. Der erste Operator, der in einer Grammatikregel vorkommt, wäre dann der binäre Additionsoperator (11). Der Parser kann also schonmal annehmen, dass es sich hier um eine Addition zweier Zahlen handelt. Jetzt schaut sich der Parser den Ausdruck nach dem '+' Zeichen für den rechten Operanden an. Da die Assoziativität bei '+' links-nach-rechts ist, entsteht bei solchen binären Operatoren ein rechtslastiger Syntax-Baum.
Du kannst also selbst im Kopf einen Syntaxbaum "aufbauen", wenn du die Operator Precedence Tabelle von unten nach oben durchgehst für einen Ausdruck.
 
Nein, das wäre kein valider ausdruck. a+b ist ein Operator mit 2 Parametern, kein unaray Operator mit nur einem.

Ansonsten würde da ja ab rauskommen, was kein valider java Ausdruck wäre
Korrekt, wenn man das so argumentieren will mit den Parametern!

Aber im Falle von a+-b wird das - zu b zugeordnet, hier würde ich dei Begründung mit den Parametern noch akzeptieren.

Aber warum wird bei a++-b+k das minus zwischen a++ und b als unaray gewertet? Habe doch hier nur einen Operator und zwar b das a++ zählt ja eig. nicht mehr oder?
 
Ausdrücke werden immer startend mit den Grammatikregeln für Operatoren mit geringer Priorität hin zu Operatoren mit hoher Priorität ausgewertet/geprased.
Wenn der Parser also den Tokenstream "a+b" sieht, dann geht er erstmal die Grammatikregeln für einen Ausdruck/Expression durch, beginnend mit Operatoren niedriger Priorität. Der erste Operator, der in einer Grammatikregel vorkommt, wäre dann der binäre Additionsoperator (11). Der Parser kann also schonmal annehmen, dass es sich hier um eine Addition zweier Zahlen handelt. Jetzt schaut sich der Parser den Ausdruck nach dem '+' Zeichen für den rechten Operanden an. Da die Assoziativität bei '+' links-nach-rechts ist, entsteht bei solchen binären Operatoren ein rechtslastiger Syntax-Baum.
Du kannst also selbst im Kopf einen Syntaxbaum "aufbauen", wenn du die Operator Precedence Tabelle von unten nach oben durchgehst für einen Ausdruck.
Aber darf man das immer von unten nach oben arbeiten, führt das nicht zu Fehlern?
 
Aber im Falle von a+-b wird das - zu b zugeordnet, hier würde ich dei Begründung mit den Parametern noch akzeptieren.
Für den Ausdruck "a+-b" kannst du auch wieder versuchen, einen Syntaxbaum mit Hilfe der Präzedenztabelle aufzubauen.
Starten wir mal wieder bei dem "a". Das kann ja die linke Seite für zumindest noch binäre Operatoren werden. Also gehen wir weiter.
"a+". Das erste Plus ist hier wieder die (11), also der binäre Additionsoperator. Also suchen wir jetzt die Bedeutung des rechten Operanden.
Wir müssen hier wieder ab mindestens der Präzedenz des Operators starten, dessen rechten Operanden wir finden wollen, also mindestens bei 11.
Hier sehen wir jetzt das "-" Minus. Da wir noch keinen linken Operanden für einen solchen "-" Operator haben (wir suchen ja einen komplett neuen Ausdruck als rechten Operanden des ersten "+" Operator), muss es sich hierbei um das unäre Minus handeln. Also suchen wir jetzt noch den einzigen Operanden dafür (auch wieder gestartet bei mindestens der Präzedenz des unären Minus.

Aber warum wird bei a++-b+k das minus zwischen a++ und b als unaray gewertet? Habe doch hier nur einen Operator und zwar b das a++ zählt ja eig. nicht mehr oder?
Um das hier richtig zu parsen, müssen wir noch wissen, dass Operatoren vom Tokenizer/Lexer immer als längstmöglicher Match zum Parser ausgegeben werden. Das "++" hinter dem "a" ist also ein "++" und keine zweimal "+". Das heißt, hier ist es ein Postinkrement.
Explizit geklammert ist es also: ((a++) - b) + k
Das Minus zwischen a++ und b ist also _nicht_ der unäre "-" Operator, sondern der binäre.

EDIT: Übrigens, wenn du nach genau diesem Schema vorgehst, dann tust du das, was auch ein "recursive descent parser" tun würde. Da du dir im Falle von Javas arithmetischen Ausdrücken auch immer nur das nächste Zeichen anzuschauen brauchst, um zu entscheiden, welche Grammatikregel bzw. welcher Operator Anwendung findet, und den Inputstream von links nach rechts durchgehen kannst, ist das eine LL(1) Grammatik und recursive descent parser können LL(1) bzw. generell LL(k) Grammatiken erkennen. Das "Beheben" von rechts-nach-links Assoziativitäten einzelner Operatoren kann man in einem einfachen post-processing Schritt im Syntaxbaum beheben.
 
Zuletzt bearbeitet:
Beste Antwort
Bei (a++-b+c) kommt übrigens (a-b+c) raus, a wird erst hinterher um 1 erhöht.
Lustig wirds bei (a++-b+c+a). Hier kommt (a-b+c+a+1) raus.

Man kann sich jetzt lange damit beschäftigen, warum was passiert, oder einfach solche Operationen vermeiden 🙂
 
Ich finde die Nutzung des Postdekrement-Operators noch lustig, wenn man von z.B. 9 bis 0, also umgekehrt, iterieren möchte:
Java:
int i = 10;
while (i --> 0) {
    System.out.println(i);
}
Also i "gegen" 0.
Man darf den Quellcode nur nicht formatieren. 🙂
 

Zurück
Oben