# Syntax- oder Semantikfehler?



## FelixII (16. Jan 2011)

Hallo,

handelt es sich bei folgender Zuweisung um einen Syntax- oder einen Semantikfehler?


```
int a;
float b = 5.0f;
a = b;
```

Kann man generell sagen, dass Compilerfehler immer Syntaxfehler sind und sich Semantikfehler ausschließlich zur Laufzeit (z.B. Exceptions, annormales Programmverhalten) bemerkbar machen?

Danke und Gruß

Felix


----------



## turing (16. Jan 2011)

Ich denke mal kurz: Ja. Sytnaxfehler können zwar auf Semantikfehlern beruhen (es ist syntaktisch verboten, weil es semnatisch falsch wäre), aber generell findet ein Compiler immer nur Syntaxfehler. Alles was der Compiler schluckt ist syntaktisch in Ordnung, während Semantikfehler erst zur Laufzeit sich bemerkbar machen. Sinnfehler dagegen merkt man erst bei der Evaluation...


----------



## whoopsie (16. Jan 2011)

Moin,

es handelt sich um einen Syntax-Fehler. Die Zuweisung einer Float in eine Integer ist für den Compiler ohne Typenumwandlung (Casting) nicht möglich. Er versteht das einfach nicht...

Ob eine einfache Typenumwandlung in deinem Beispiel z. B. durch


```
int a;
float b = 5.0f;
a = (int) b;
```

im Sinne der Programmausführung sinnvoll ist, bemerkt man erst zur Laufzeit.

Semantik ist eher das, was der Compiler unter z. B. einer syntaktisch korrekten Aussage (Befehl, Anweisung) versteht... diese stimmt hoffentlich immer mit der Interpretation des Entwicklers überein, d. h. Mensch und Maschine sprechen dieselbe Sprache 

Exceptions sind je nach Logik gewollt, darum gibt es ja die Möglichkeit diese abzufangen. Komisches Programmverhalten, wie z. B. ein Array-Überlauf oder ein Null-Pointer sind logische Fehler.

Ein nicht-akademischer Ansatz:
Syntax ist die Definition einer Sprache, wie eine strenge Grammatik - erst Prädikat, dann Subjekt, dann Objekt und anschließend ein Punkt, Frage- oder Ausrufezeichen, also ganz klare Regeln, wie etwas ausgedrückt werden kann. Semantik ist die Interpretation einer syntaktisch-korrekten Sprache. Man kann aber viel mit einer Sprache ausdrücken, aber nicht jede Aussage macht Sinn, auch wenn dessen Syntax bzw. Grammatik ok ist.

Gruß


----------



## FelixII (16. Jan 2011)

Super, danke für die ausführliche Erklärung. 

Gruß

Felix


----------



## Bierhumpen (16. Jan 2011)

Das [c]a = b;[/c] ist natürlich kein Syntaxfehler, sondern ein semantischer Fehler im Code. Die Syntax ist doch völlig korrekt.

Mit Exceptions oder Fehlverhalten haben semantische Fehler übrigens auch nichts zu tun, das sind dann Programmierfehler ;-)


----------



## FelixII (16. Jan 2011)

Ok und wer hat jetzt recht? ???:L


----------



## XHelp (16. Jan 2011)

Bierhumpen hat gesagt.:


> Das [c]a = b;[/c] ist natürlich kein Syntaxfehler, sondern ein semantischer Fehler im Code. Die Syntax ist doch völlig korrekt.


Nö? Der Compiler wird meckern, dass "possible loss of precision" und nicht kompilieren.


> Mit Exceptions oder Fehlverhalten haben semantische Fehler übrigens auch nichts zu tun, das sind dann Programmierfehler ;-)



Auf die Gefahr hin mich zu wiederholen: Nö? Das stimmt auch nicht


----------



## Gast2 (16. Jan 2011)

Bierhumpen hat gesagt.:


> Mit Exceptions oder Fehlverhalten haben semantische Fehler übrigens auch nichts zu tun, das sind dann Programmierfehler ;-)


weil der Benutzer mit meinem Programm eine Datei schreiben wozu er kein Recht hat, ist es also mein Programmierfehler das ich die IOException abfange ... immer mache ich alles falsch - ;(

hand, mogel


----------



## Bierhumpen (16. Jan 2011)

XHelp hat gesagt.:


> Nö? Der Compiler wird meckern, dass "possible loss of precision" und nicht kompilieren.


Richtig, weil es ein semantischer Fehler im Code ist...



> Auf die Gefahr hin mich zu wiederholen: Nö? Das stimmt auch nicht


 Doch


----------



## Marco13 (16. Jan 2011)

<halbwissen>

Rein syntaktisch ist es richtig. Laut The Java Language Specification Expressions ist die syntaktische Struktur einer Zuweisung

```
[b]Assignment:[/b]
	[b]LeftHandSide AssignmentOperator AssignmentExpression[/b]
[b]LeftHandSide:[/b]
	[b]ExpressionName[/b]
	FieldAccess
	ArrayAccess
AssignmentOperator: one of
	[b]=[/b] *= /= %= += -= <<= >>= >>>= &= ^= |=

[b]ExpressionName:[/b]
	[b]Identifier[/b]
...
[b]Identifier:[/b]
	[b]IdentifierChars[/b] but not a Keyword or BooleanLiteral or NullLiteral

[b]IdentifierChars:[/b]
	[b]JavaLetter[/b]
...
[b]JavaLetter:[/b]
	[b]any Unicode character that is a Java letter (see below)[/b]
...
```

Der sematische Fehler resultiert daraus, dass es keine assignment conversion von float nach int gibt, laut The Java Language Specification Conversions and Promotions

</halbwissen>

EDIT: AssignmentExpression fehlte noch - *Kaffeesauf*, ja, es ist kompiziert...


----------



## whoopsie (16. Jan 2011)

Moin,

der Zuweisungsoperator ist syntaktisch korrekt, links steht eine Variable, auch korrekt, die Variablennamen sind alle korrekt, der Typ der Zuweisung entspricht dem Typ der Variable... ehm, nein.

Ein semantischer Fehler wäre sowas... ich hoffe den Fehler des synataktisch korrekten und lauffähigen Programms findet jemand 


```
int a = 10;
System.out.println("a="+a);
int b = 10;
System.out.println("b="+b);
int c = a + a;
System.out.println("a+b=c="+c);
```



> Nö? Der Compiler wird meckern, dass "possible loss of precision" und nicht kompilieren.
> Richtig, weil es ein semantischer Fehler im Code ist...



Das ist ja mal ein Statement... ich wusste gar nicht, dass der Compiler den Source-Code auf semantische Korrektheit prüft, sogar noch vor dem Komplieren :bahnhof: Was wär die Softwareentwicklung einfach...

Exceptions sind nicht mal im weitesten Sinne mit Semantik in Verbindung zu bringen. Exceptions sind ein Spezialfall einer einfachen Abfrage, reine Programmlogik und dementsprechend bei Auslösung gewollt und fangen "logische", vorher durchdachte Fehler ab.

Gruß


----------



## Bierhumpen (16. Jan 2011)

whoopsie hat gesagt.:


> Ein semantischer Fehler wäre sowas...


Nein das ist ein Programmier(er)fehler



> Das ist ja mal ein Statement... ich wusste gar nicht, dass der Compiler den Source-Code auf semantische Korrektheit prüft, sogar noch vor dem Komplieren


Richtig, genau das tut er. Und wenn er Fehler findet, gibt er dir einen Error aus, wie z.B. "possible loss of precision". Nicht logisch?


----------



## XHelp (16. Jan 2011)

Bierhumpen hat gesagt.:


> Nein das ist ein Programmier(er)fehler


In deiner Vorstellung gibt es scheinbar nur Programmiererfehler. Syntax falsch - Programmiererfehler, Semantik falsch - Programmiererfehler... :bahnhof:


> Richtig, genau das tut er. Und wenn er Fehler findet, gibt er dir einen Error aus, wie z.B. "possible loss of precision". Nicht logisch?


Dass der Compiler VOR dem kompilieren erkennt, was der Coder damit wohl meinen könnte und es meldet? Ja, das ist nicht logisch.


----------



## Bierhumpen (16. Jan 2011)

XHelp hat gesagt.:


> In deiner Vorstellung gibt es scheinbar nur Programmiererfehler. Syntax falsch - Programmiererfehler, Semantik falsch - Programmiererfehler... :bahnhof:


Am Ende ist jeder Fehler ein Fehler des Programmierers, richtig, was willst du uns damit sagen :bahnhof:



> Dass der Compiler VOR dem kompilieren erkennt, was der Coder damit wohl meinen könnte und es meldet? Ja, das ist nicht logisch.


Was hat das irgendwas damit zu tun was der Coder "meint"?
Es gibt Syntaxfehler und es gibt Semantikfehler. Wenn ein Code entweder das eine oder das andere enthält kompiliert der Compiler nicht. Wenn der Code kompiliert muss er zwar noch immer nicht "richtig" sein, aber dann ist es ein Denkfehler und beim Programmierer zu suchen. Und der Fehler in der Ausgangsfrage ist ganz offensichtlich ein Semantikfehler. Was gibt's jetzt darin noch nicht zu verstehen? :bahnhof:


----------



## whoopsie (16. Jan 2011)

Also ich bleib dabei... es handelt ich bei dem Beispiel um einen semantischen (logischen) Fehler... evtl. meinst du genau das mit dem Begriff "Programmier(er)fehler"...


```
int a = 10;
System.out.println("a="+a);
int b = 10;
System.out.println("b="+b);
int c = a + a;
System.out.println("a+b=c="+c);
```

Das andere Beispiel ist ein syntaktischer Fehler, da dort nicht alle Regeln zu der Sprache eingehalten worden sind... Zuweisungstyp passt nicht zur Variable. Automatisches Casting gibt es vllt in Java 10.9. Wenn genau dieser Fehler ein semantischer Fehler wäre, dann wäre das Programm lauffähig, da die Anweisungen offensichtlich der Sprache genügen.


```
int a;
float b = 5.0f;
a = b;
```

Semantische Fehler sind nicht zu erkennen, da sie syntaktisch i. O. sind und der Compiler nicht der Bordcomputer von Deep Space 9 ist und genau versteht, was man mit den Befehlen und Anweisungen in deinem Quellcode eigentlich bezwecken will... es gibt im Bereich des Software Engineering Tools, Tests und Algorithmen, die anhand von Kennzahlen einen Quellcode auf "Verständlichkeit" oder "Fehlerpotential" prüfen können, und es gibt dort semantische Prüfung für ganz kleine Teilprobleme, z. B. für sowas (ein semantischer Fehler):


```
...
int a = 10;
a = 9;
a = 7;
...
```

Ein Compiler macht keine semantische (logische) Prüfung... die Menge der programmierbaren Programme ist, ich sag es mal, unendlich.

Gruß


----------



## Bierhumpen (16. Jan 2011)

whoopsie, dein Verständnis von den Begriffen ist halt einfach falsch, mehr kann man dazu nicht sagen.
[c]a = b;[/c] ist syntaktisch vollkommen korrekt (vorausgesetzt es steht an der richtigen Stelle im Code...)
genauso wie [c]System.bierhumpen();[/c] syntaktisch völlig korrekt ist. Kompiliert es deswegen? Nein.


----------



## whoopsie (16. Jan 2011)

> whoopsie, dein Verständnis von den Begriffen ist halt einfach falsch, mehr kann man dazu nicht sagen.



Möglich ist alles... gib bitte mal deine Definition von Syntax und Semantik an... mein Studium ist zugegebenermaßen schon etwas her... und das war ja irgendwo in den ersten Semestern


----------



## XHelp (16. Jan 2011)

Bierhumpen hat gesagt.:


> Am Ende ist jeder Fehler ein Fehler des Programmierers, richtig, was willst du uns damit sagen :bahnhof:


Darum geht es aber nicht bei der Einordnung von Fehlern. In der Medizin kannst du auch nicht sagen "hm, ist das jetzt ein Gendefekt oder eine Viruserkrankung? Ach, ist egal, ist eh alles ein Patzer vom Gott"


> Es gibt Syntaxfehler und es gibt Semantikfehler. Wenn ein Code entweder das eine oder das andere enthält kompiliert der Compiler nicht. Wenn der Code kompiliert muss er zwar noch immer nicht "richtig" sein, aber dann ist es ein Denkfehler und beim Programmierer zu suchen. Und der Fehler in der Ausgangsfrage ist ganz offensichtlich ein Semantikfehler. Was gibt's jetzt darin noch nicht zu verstehen? :bahnhof:



Der Compiler kann nur bedingt die Semantik überprüfen. Woher soll er auch wissen, was du damit ausdrücken willst? Marco hat zwar logische Argumente für Sematik gebracht, aber ich würde dennoch weiterhin darauf tippen, dass das ein syntaktischer Fehler ist. Fürs erste ohne Beweise, aber da denke ich noch drüber nach, wenn ich Zeit habe.


----------



## Bierhumpen (16. Jan 2011)

@FelixII & interessierte:
hier hast du noch 2 Methoden um heruaszufinden ob ein Fehler ein syntaxfehler oder ein semantischer Fehler ist, wenn du es nicht direkt siehst:
1. Herleiten:
Dein a = b; funktioniert nicht, weil a und b inkompatible Typen sind. Während der syntaktischen Analyse ist der Compiler sich noch gar nicht bewusst von welchen Typen a und b sind oder welche Methoden eine Klasse hat. Daher können a = b; oder System.bierhumpen(); schonmal keine Syntaxerrors sein.
2. Ausprobieren:
Versuch mal eine Testklasse zu kompilieren mit diesem Code:

```
int i = 123;
i = 1f;
System.bierhumpen();
```
Und dann entfern mal das Semikolon hinter der ersten Anweisung. Die beiden semantischen Fehler in Zeile 2 und 3 werden dir vom Compiler nicht mehr gemeldet, weil er schon nach der syntaktischen Analyse aussteigt und sich bei dir mit dem Semikolon-Error verabschiedet.


----------



## planetenkiller (16. Jan 2011)

Siehe auch bei Wikipedia:
Compiler ? Wikipedia


----------



## whoopsie (16. Jan 2011)

Ich brauche noch eine Differenzierung zwischen Syntax und "statischer Semantik" :applaus:

Nun, statische Semantik bedeutet, das Konsistenzen zwischen den syntaktischen Objekten festgelegt sind. Ein Compiler führt eine semantische Analyse (keine Interpretation oder gar logische Fehlersuche) durch und prüft dabei eben diese Konsistenzen auf Wahrheitsgehalt, z. B. Bindung von Typen an Bezeichner.

Wenn man nun die dritte Zeile


```
int a;
float b = 5.0f;
a = b;
```

als Verletzung der statischen Semantik ansieht, ist es kein semantischer Fehler, sondern eine semantische Inkonsistenz, welche der Compiler anmeckert. Sei es drum... es handelt sich um eine semantische Inkonsistenz der statischen Semantik, welcher der Compiler im Rahmen einer semantischen Analyse bemerkt und meldet.

Es ändert nichts daran, dass sowas ein semantischer Fehler ist... :bae:


```
...
int a = 10;
a = 9;
a = 7;
...
```

Ein Programmierfehler ist das nicht, wenn a den Wert 7 haben soll.

Gruß


----------



## FelixII (16. Jan 2011)

Gut, also kann man abschließend sagen, dass es ein Semantik- und KEIN Syntaxfehler ist oder? Zu welchem Teil der Semantik das Problem nun gehört ist für meine Bedürfnisse unwichtig.

Danke jedenfalls an alle für eure Hilfe!

Gruß

Felix


----------



## whoopsie (16. Jan 2011)

Man kann alles sagen, man muss es nur gut begründen können :autsch:

Der Fehler geht wohl tatsächlich eher in Richtung Semantik... mir fällt die Abgrenzung etwas schwer zwischen Syntax und statischer Semantik ;( ...alles auf so abstraktem Niveau 

Ciao


----------



## Antoras (16. Jan 2011)

Die Grenzen zwischen Syntax und Semantik können sehr stark verschwimmen, mal ein Beispiel anhand von Zeitangaben im 24-Stunden-Format:

Wenn 
	
	
	
	





```
\d
```
 eine Ganzzahl ist, dass wäre die Definition für eine Zeit als regulärer Ausdruck wohl 
	
	
	
	





```
\d\d:\d\d
```
. Dieser RegEx ist aber zu allgemein, denn Angaben wie 
	
	
	
	





```
37:71
```
 wären möglich obwohl sie dies keine gültige Uhrzeit wäre. Um zu überprüfen ob diese Uhrzeit korrekt wäre müsste der Compiler nach dem Parsen der Uhrzeit eine Nachbearbeitung vornehmen um die Semantik zu überprüfen. Wenn die Uhrzeitensyntax aber so definiert wäre, dass die Zahlenwerte eingeschränkt wären, z.B. mit dem RegEx 
	
	
	
	





```
([01]\d)|(2[0-3]):([0-5]\d)
```
, dann könnte der Parser schon eine gültige Zeitangaben erfassen und es müsste keine semantische Überprüfen mehr stattfinden, da sich die Nachbearbeitung darauf verlassen kann, dass der Parser bei einer falschen Uhrzeitenangabe den Fehler entdecken und den weiteren Dienst quittieren würde.

Der Idealfall ist, dass die Syntax eindeutig ist, was dazu führen würde, dass keine semantische Nachbearbeitung mehr nötig wäre. Das ist aber nicht immer möglich. Die RegEx für beispielsweise Datumsangaben wäre schon deutlich komplizierter, wenn auch noch beschreibbar. Allerdings wäre es nicht mehr sinnvoll, da z.B. beim Monat Februar die RegEx nicht entscheiden könnte ob die Tagangabe 29 stimmt - es kann schließlich ein Schaltjahr vorliegen. Woher soll die Syntax dies wissen? Dafür bräuchte sie Rechenfähigkeiten, was der Punkt ist, der die Syntax von der Semantik unterscheidet.

Die Syntax ist ein Teil der Sprachdefinition, die gültige Zeichenfolgen mit einem Formalismus erkennt, der keine Rechenfähigkeiten besitzt - sie ist also nicht Turing-Vollständig. Erst die Semantik kann Berechnungen übernehmen, die dann mit einem Formalismus beschrieben ist, der die Turing-Vollständigkeit gewährleisten kann.


Im Beispiel vom TO legt die JLS ganz klar fest, dass einem Integerwert keine Fließkommazahl zugewiesen werden darf, weshalb das Beispiel 
	
	
	
	





```
int a = 5.0f
```
 wie auch 
	
	
	
	





```
a = b
```
 also syntaktisch falsch wären wenn a ein Integerwert und b eine Fließkommazahl ist.


----------



## Bierhumpen (16. Jan 2011)

Antoras hat gesagt.:


> Im Beispiel vom TO legt die JLS ganz klar fest, dass einem Integerwert keine Fließkommazahl zugewiesen werden darf, weshalb das Beispiel
> 
> 
> 
> ...



Die Schlussfolgerung kann gar nicht stimmen, da beide deine Ausdrücke die syntaktische Analyse des Compilers ohne Probleme durchlaufen, wie du selbst ausprobieren kannst.
Davon abgesehen ist "syntaktisch falsch wären wenn a ein Integerwert und b eine Fließkommazahl ist" völliger Mumpitz, da synatktische Korrektheit von soetwas gar nicht abhängig ist, da die syntaktische Analyse gar keine Typen _kennt_.


----------



## Marco13 (16. Jan 2011)

Bierhumpen hat gesagt.:


> Davon abgesehen ist "syntaktisch falsch wären wenn a ein Integerwert und b eine Fließkommazahl ist" völliger Mumpitz, da synatktische Korrektheit von soetwas gar nicht abhängig ist, da die syntaktische Analyse gar keine Typen _kennt_.



Mumpitz. :noe: Naja. Zumindest stimme ich Antoras dahingehend zu, dass (zumindest für mich, mit meinem Halbwissen) die Grenzen verschwimmen. Sowas wie

```
int a = 1.2;
```
wäre so gesehen ja schon "wegen der Typen" falsch, aber dann doch syntaktisch fehlerhaft, weil ein Integer-Literal eben keinen "." enthalten darf. Die Zuweisung 
a = b;
ist syntaktisch richtig, im Gegensatz zu einer Zuweisung wie
a := b;
oder
a = 4b;
die syntaktisch falsch sind. Dass die erste im konkreten Fall NICHT angenommen wird, hängt mit Dingen zusammen, die nichts mit der _Grammatik _ der Sprache zu tun haben.

Aber ich betone nochmal: Ich "weiß" das alles nicht, sondern nuckle mir das nur aus meiner Informatischen Allgemeinbildung zusammen.


----------



## Bierhumpen (16. Jan 2011)

Marco13 hat gesagt.:


> wäre so gesehen ja schon "wegen der Typen" falsch, aber dann doch syntaktisch fehlerhaft, weil ein Integer-Literal eben keinen "." enthalten darf.


Das 1.2 ist zwar kein Integer Literal, aber in der JLS steht auch nirgends geschrieben, dass eine Integer Deklaration genau so lauten muss: [c]int <Name> = <Integer Literal>;[/c]
Daher ist [c]int i = 1.2;[/c] genauso _viel oder wenig_ falsch wie [c]List l = "keine List";[/c], aber syntaktisch trotzdem völlig in Ordnung. Und nochmal: wenn man nicht sicher ist einfach ausprobieren. Die Antwort von javac ist definitiv.


----------



## Antoras (17. Jan 2011)

Bierhumpen hat gesagt.:


> Die Schlussfolgerung kann gar nicht stimmen, da beide deine Ausdrücke die syntaktische Analyse des Compilers ohne Probleme durchlaufen, wie du selbst ausprobieren kannst.


Und wie? Ich hab keine Option bei javac gefunden mit der man nur einen Syntaxcheck aktivieren kann. Ich hab über Google zwar die Option -nowrite gefunden, die nimmt die neueste Version von javac aber nicht an.


Bierhumpen hat gesagt.:


> Davon abgesehen ist "syntaktisch falsch wären wenn a ein Integerwert und b eine Fließkommazahl ist" völliger Mumpitz, da synatktische Korrektheit von soetwas gar nicht abhängig ist, da die syntaktische Analyse gar keine Typen _kennt_.


Hast du dafür einen Beweis? Ich würde nach wie vor sagen, dass das von der Grammatik abhängig ist ob die syntaktische Analyse den Fehler findet oder nicht. Wobei die Grammatik von Java wahrscheinlich komplex genug ist, damit die syntaktische Analyse dafür wirklich nicht mehr ausreicht.


----------



## Bierhumpen (18. Jan 2011)

Wie man das prüfen kann habe ich auf der letzten Seite schon gezeigt...
Ansonsten kann ich zu dir nur sagen, dass wenn man so wenig Ahnung von etwas hat dass man nach dem posten noch in einem anderen Forum nachfragen muss ob's richtig ist , kann man sich das posten auch gleich sparen. Ansonsten verweis ich dich zum Thema auf die anderen Antworten die du auf C++ bekommen hast.


----------



## Antoras (18. Jan 2011)

Bierhumpen hat gesagt.:


> Wie man das prüfen kann habe ich auf der letzten Seite schon gezeigt...


Ok, den Beitrag muss ich wohl überlesen haben.


Bierhumpen hat gesagt.:


> Ansonsten kann ich zu dir nur sagen, dass wenn man so wenig Ahnung von etwas hat dass man nach dem posten noch in einem anderen Forum nachfragen muss ob's richtig ist , kann man sich das posten auch gleich sparen. Ansonsten verweis ich dich zum Thema auf die anderen Antworten die du auf C++ bekommen hast.


Da ging es mir mehr um einen von der Programmiersprache unabhängigen Beweis ob man einen solchen Fehler immer der Syntax oder der Semantik zuordnen kann. Die Antwort dort war mehr oder weniger eindeutig: es gibt keinen. Es hängt stattdessen von der Grammatik der Programmiersprache ab.


----------

