State Machine Compiler fĂźr 8-bit AVRs?

Hi Johannes,

Am 22.09.19 um 17:23 schrieb Johannes Bauer:
On 22.09.19 12:48, Andreas Weber wrote:

Dann hast du bis jetzt vielleicht keine komplizierte Grammatik gehabt.

Eine komplizierte Grammatik ist in jedem Fall kompliziert, egal welche
Werkzeuge man nutzt.

Warum versuchen mich hier Leute davon zu Ăźberzeugen KEIN Werkzeug dafĂźr
einzusetzen?

Kann ich dir nicht beantworten.

Was genau stĂśrt dich denn an der Ragel-Syntax bzw. was fĂźr Features
hättest du gerne, die im Moment fehlen?

Ich bin bisher mit Ragel wirklich voll und ganz zufrieden und kann
bisher alles damit abbilden was ich mĂśchte. Wollte eigentlich nur
wissen, was andere so verwenden. Dass das in so eine "angeregte
Diskussion" ausufert, hätte ich nicht gedacht.

Danke, Gruß Andy
 
Am 23.09.2019 um 14:31 schrieb Johannes Bauer:
On 23.09.19 14:15, Gerhard Hoffmann wrote:
Und er muss dir auch nichts liefern, du hast nichts bei ihm gekauft.

Wenn jemand groß Sprüche klopft, wie einfach das doch alles von Hand
sei, Lexer/Parser fĂźr komplexe Grammatiken zu schreiben (zum Beispiel
der von C), und dann in der Praxis halt schon bei simpelsten Beispielen
voll auf die Nase fliegt, dann ist das ja schon ein interessantes Ergebnis.

Ich warte ja auf das Gegenbeispiel, also: deinen C-Parser.

aber die wichtigen
Compiler, die jeder hernimmt, wie gcc oder clang benutzen rekursiven
Abstieg.

Das ist *professionelle* Software. Mit hunderttausenden Personenstunden,
die da reingeflossen sind, sowohl in clang als auch in gcc. Und ich habe
ausfĂźhrlich beschrieben, warum die das so machen -- sowohl clang als
auch gcc parsen eben auch C++, fĂźr das es keine ausdefinierte Grammatik
gibt

*Das* ist Geschwätz. Selbstverständlich hat C++ eine Grammatik. Zu
finden im Standard-Dokument unter "Annex A" sowie in Fragmenten in den
einzelnen Kapiteln. Sie ist halt nur nicht LL(1).

Ohne Not schreibt *niemand* einen Parser von Hand, auch nicht gcc und
clang. Und wenn man sich dazu entscheidet, ist das *weitaus*
schwieriger, als einen Parsergenerator zu nehmen.

Nein. Sage ich als einer, der routinemäßig Parser per Hand baut.

Pascal nimmt auch rekursiven Abstieg. Und da sind BĂśsartigkeiten
wie das with-statement drinnen:

with record_variablenliste do begin ... end

(Das ist Ăźbrigens parserseitig vĂśllig trivial. FĂźr Pascal musst du nicht
wissen, was das Wort 'x' bedeutet, um aus 'x(y)' einen AST bauen zu kĂśnnen.)

und zwischen begin & end sind die Komponenten der records plĂśtzlich
keine rec.a und rec.b mehr, sondern einfach nur noch a und b.
Wenn's zufällig globale a und b gab, dann gibt's die eben vorrßbergehend
nicht mehr. Bring das mal einem Parsergenerator nahe, wenn Variablen-
namen eben zwischendurch fĂźr etwas vĂśllig anderes mit mĂśglicherweise
einem anderen Typ stehen.

Ich weiß echt nicht, wieso du ständig mit Pascal anfängst, das hat mit
dem Thema Ăźberhaupt nichts zu tun. Ich habe nie bestritten, dass
Recursive Descent ein ordentliches oder geeignetes Parsing-Verfahren
ist. Ich sage lediglich, dass das Schreiben eines Parsers von Hand
RICHTIG viel schwieriger ist, als einen Parsergenerator zu nehmen und
dass man deswegen dafĂźr einen RICHTIG guten Grund (und viel, viel mehr
Zeit) braucht. Und bin extrem skeptisch wenn sich jemand hinstellt und
sagt "das hab ich schon gemacht, war ganz einfach". Weil >40000 Zeilen
Code zu schreiben, nur fĂźrs Parsing, ist eben NICHT einfach.

Das, was du beim Schreiben der Grammatik sparst - wenn Ăźberhaupt was -
zahlst du beim Debuggen drauf. Wo muss ich jetzt die Aktionen
platzieren? Wie bekomme ich das Speicherleck-frei? Wie bekomme ich
gescheite Fehlermeldungen außer "parse error"? Wie erhole ich mich am
besten von einem Parser-Fehler? (Nächstes Semikolon suchen? Oder doch
lieber geschweifte Klammern? Oder 'END'-SchlĂźsselwort?)

Und - und das ist einer der GrĂźnde, einen C-Parser per Hand zu machen -
in einem händischen Parser ist es trivial, Feedback zu geben, was fßr
ein Ding 'x' in 'x*y[3]' ist, denn abhängig davon wird der Rest
geparsed. Mit einem generierten Parser muss man damit durch ein paar
Ebenen Generat (yacc, lex) durch und dabei Annahmen treffen, wie der
generierte Code sich benimmt.


Stefan
 
On 24.09.19 19:18, Stefan Reuther wrote:

Wenn jemand groß Sprüche klopft, wie einfach das doch alles von Hand
sei, Lexer/Parser fĂźr komplexe Grammatiken zu schreiben (zum Beispiel
der von C), und dann in der Praxis halt schon bei simpelsten Beispielen
voll auf die Nase fliegt, dann ist das ja schon ein interessantes Ergebnis.

Ich warte ja auf das Gegenbeispiel, also: deinen C-Parser.

Nur weil einen Parser von Hand schreiben schwer ist, heißt das noch
lange nicht, dass einen Parser mit Generator schreiben leicht ist.

Aber wenn ich ein Beispiel liefern wĂźrde, dann kann ich dir immerhin
versichern, dass das nicht so grütze-mäßig Segfaulten würde wie DoDis
Beispiel. Denn DAS ist Pfusch, vĂśllig egal wie man parst.

auch gcc parsen eben auch C++, fĂźr das es keine ausdefinierte Grammatik
gibt

*Das* ist Geschwätz. Selbstverständlich hat C++ eine Grammatik. Zu
finden im Standard-Dokument unter "Annex A"

Du kannst offenbar keine Standards lesen. Denn da steht ganz klar
zuerstmal: Annex A (informative) -- muss ich dir jetzt den Unterschied
zwischen informative und normative erklären?

Und dann nochmal Ăźberdeutlich: "This summary of C ++ syntax is intended
to be an aid to comprehension. It is not an exact statement of the
language."

sowie in Fragmenten in den
einzelnen Kapiteln.

Genau, verteilt Ăźber ~1300 Seiten, aber eben nicht ausdefiniert (und
genau das habe ich geschrieben, keine ausdefinierte Grammatik).

> Sie ist halt nur nicht LL(1).

Hat auch nie irgendjemand behauptet, vĂślliges Strohmann-Argument.

Ohne Not schreibt *niemand* einen Parser von Hand, auch nicht gcc und
clang. Und wenn man sich dazu entscheidet, ist das *weitaus*
schwieriger, als einen Parsergenerator zu nehmen.

Nein. Sage ich als einer, der routinemäßig Parser per Hand baut.

Puh, naja, das ist jetzt Aussage gegen Aussage. Du findest das Schreiben
von Hand einfach, ich habe gerne UnterstĂźtzung von Werkzeugen.

Das, was du beim Schreiben der Grammatik sparst - wenn Ăźberhaupt was -
zahlst du beim Debuggen drauf. Wo muss ich jetzt die Aktionen
platzieren? Wie bekomme ich das Speicherleck-frei? Wie bekomme ich
gescheite Fehlermeldungen außer "parse error"? Wie erhole ich mich am
besten von einem Parser-Fehler? (Nächstes Semikolon suchen? Oder doch
lieber geschweifte Klammern? Oder 'END'-SchlĂźsselwort?)

Das ist wohl richtig, eine ordentliche Grammatik zu schreiben ist auch
alles andere als leicht. Und tatsächlich ist Debugging von Grammatiken
elendige Arbeit.

Und - und das ist einer der GrĂźnde, einen C-Parser per Hand zu machen -
in einem händischen Parser ist es trivial, Feedback zu geben, was fßr
ein Ding 'x' in 'x*y[3]' ist, denn abhängig davon wird der Rest
geparsed. Mit einem generierten Parser muss man damit durch ein paar
Ebenen Generat (yacc, lex) durch und dabei Annahmen treffen, wie der
generierte Code sich benimmt.

Einen Tod muss man sterben. Vermutlich ist dann wohl ausschlaggebend,
womit man am meisten Erfahrung hat.

Viele Grüße,
Johannes

--
"Performance ist nicht das Problem, es läuft ja nachher beides auf der
selben Hardware." -- Hans-Peter Diettrich in d.s.e.
 
Am 24.09.2019 um 20:47 schrieb Johannes Bauer:
On 24.09.19 19:18, Stefan Reuther wrote:
Wenn jemand groß Sprüche klopft, wie einfach das doch alles von Hand
sei, Lexer/Parser fĂźr komplexe Grammatiken zu schreiben (zum Beispiel
der von C), und dann in der Praxis halt schon bei simpelsten Beispielen
voll auf die Nase fliegt, dann ist das ja schon ein interessantes Ergebnis.

Ich warte ja auf das Gegenbeispiel, also: deinen C-Parser.

Nur weil einen Parser von Hand schreiben schwer ist, heißt das noch
lange nicht, dass einen Parser mit Generator schreiben leicht ist.

Aber wenn ich ein Beispiel liefern wĂźrde, dann kann ich dir immerhin
versichern, dass das nicht so grütze-mäßig Segfaulten würde wie DoDis
Beispiel.

Da wäre ich mir nicht so sicher, denn Ressourcenmanagement zumindest mit
yacc ist nicht einfach. Wer gackert muss auch legen.

(Mein zweites größeres Parserprojekt war vor >20 Jahren bei "Jugend
Forscht", ist also nicht so, dass ich nicht legen kĂśnnte.)

auch gcc parsen eben auch C++, fĂźr das es keine ausdefinierte Grammatik
gibt

*Das* ist Geschwätz. Selbstverständlich hat C++ eine Grammatik. Zu
finden im Standard-Dokument unter "Annex A"

Du kannst offenbar keine Standards lesen. Denn da steht ganz klar
zuerstmal: Annex A (informative) -- muss ich dir jetzt den Unterschied
zwischen informative und normative erklären?

Danke, sehr freundlich. (Mein ca. fünftes größeres Parserprojekt war
Teil eines C++-Compilers fĂźr das VFiasco-Projekt. C++-Standard kenn ich.)

Und dann nochmal Ăźberdeutlich: "This summary of C ++ syntax is intended
to be an aid to comprehension. It is not an exact statement of the
language."

Das ist die Zusammenfassung der Fragmente. Nicht normativ, weil die
normativen Teile nebst der semantischen Bedingungen in den anderen
Kapiteln stehen, und weil dir niemand zusichert, in dem Anhang nichts
vergessen zu haben.

sowie in Fragmenten in den
einzelnen Kapiteln.

Genau, verteilt Ăźber ~1300 Seiten, aber eben nicht ausdefiniert (und
genau das habe ich geschrieben, keine ausdefinierte Grammatik).

Was wäre denn eine "ausdefinierte Grammatik"?

Die ernsthafte Schwäche, die diese Grammatik hat, ist, dass sie zwischen
den Ebenen "lexikalische Analyse", "Präprozessor" und "syntaktische
Analyse" nicht sauber trennt. Jedem Praktiker ist das egal. Regeln wie
"maximum munch" (also dass 'inti' ein Wort ist und nicht das gleiche wie
'int i') werden quasi immer in Prosa angegeben, nicht in der Grammatik.


Stefan
 
On 25.09.19 17:51, Stefan Reuther wrote:

Nur weil einen Parser von Hand schreiben schwer ist, heißt das noch
lange nicht, dass einen Parser mit Generator schreiben leicht ist.

Aber wenn ich ein Beispiel liefern wĂźrde, dann kann ich dir immerhin
versichern, dass das nicht so grütze-mäßig Segfaulten würde wie DoDis
Beispiel.

Da wäre ich mir nicht so sicher, denn Ressourcenmanagement zumindest mit
yacc ist nicht einfach. Wer gackert muss auch legen.

Du vergisst die Messlatte: DoDi's Programm stĂźrzt schon ab, wenn man es
lediglich STARTET.

Ich bin mir extrem sicher, dass ich ein Programm hinkriege, dass nicht
beim Start abstĂźrzt. Eines, das nicht "F:\DoDi\..." als hardgecodete
Pfade enthält.

Und einen Parser kann man auch in einer Programmiersprache schreiben,
die Ressourcenmanagement Ăźbernimmt, ich bevorzuge Python wenn
Performance nicht kritisch ist.

(Mein zweites größeres Parserprojekt war vor >20 Jahren bei "Jugend
Forscht", ist also nicht so, dass ich nicht legen kĂśnnte.)

Joa und ich habe produktiven, sicherheitskritsichen Kernelcode
geschrieben, der jahrelang unterbrechungsfrei laufen muss. Da kann man
sich keine Ressourcenleaks erlauben, nicht mal die Kleinsten.

*Das* ist Geschwätz. Selbstverständlich hat C++ eine Grammatik. Zu
finden im Standard-Dokument unter "Annex A"

Du kannst offenbar keine Standards lesen. Denn da steht ganz klar
zuerstmal: Annex A (informative) -- muss ich dir jetzt den Unterschied
zwischen informative und normative erklären?

Danke, sehr freundlich.

Na du musst dich schon entscheiden. Entweder du unterstellst mir
Geschwätz, kannst das ordentlich belegen und ich halte meine Schnauze.
Oder du unterstellst mir Geschwätz, lieferst unzureichende Belege und
bekommst eine entsprechend unfreundliche Antwort. Beides geht nicht.

(Mein ca. fünftes größeres Parserprojekt war
Teil eines C++-Compilers fĂźr das VFiasco-Projekt. C++-Standard kenn ich.)

Mag ja sein, trotzdem hast du einen INFORMATIVEN Teil als "Beleg"
angefĂźhrt. Einen Teil, der also als Beleg vĂśllig untauglich ist, weil er
formal eben NICHT Teil der Spezifikation ist. Und selbst wenn er es wäre
ganz klar drin steht, dass es eben nicht den Sprachumfang abdeckt.

Und dann nochmal Ăźberdeutlich: "This summary of C ++ syntax is intended
to be an aid to comprehension. It is not an exact statement of the
language."

Das ist die Zusammenfassung der Fragmente. Nicht normativ, weil die
normativen Teile nebst der semantischen Bedingungen in den anderen
Kapiteln stehen, und weil dir niemand zusichert, in dem Anhang nichts
vergessen zu haben.

Und selbst die Fragmente sind horrend unvollständig. Ich nehme mir ein
beliebiges Beispiel raus: "14.2. Names of template specializations".
Eine popelige Grammatik, evtl 15 Zeilen lang. Gefolgt von 1 1/2 Seiten
Prosa, die dann genau sagt wie die zu interpretieren ist.

Das ist keine formale Beschreibung einer Sprache. Das ist Prosa.

sowie in Fragmenten in den
einzelnen Kapiteln.

Genau, verteilt Ăźber ~1300 Seiten, aber eben nicht ausdefiniert (und
genau das habe ich geschrieben, keine ausdefinierte Grammatik).

Was wäre denn eine "ausdefinierte Grammatik"?

Eine formale Beschreibung, die man im idealfall direkt einem Parser
vorlegen kann, also maschinenlesbar ist. C++ ist aber als Sprache so
kompliziert, dass ich vermute, dass das wohl nicht (mehr?) machbar ist.
Deswegen nutzt man eben viel Prosa und Beispiele, um zu verdeutlichen,
was gemeint ist.

Die ernsthafte Schwäche, die diese Grammatik hat, ist, dass sie zwischen
den Ebenen "lexikalische Analyse", "Präprozessor" und "syntaktische
Analyse" nicht sauber trennt. Jedem Praktiker ist das egal. Regeln wie
"maximum munch" (also dass 'inti' ein Wort ist und nicht das gleiche wie
'int i') werden quasi immer in Prosa angegeben, nicht in der Grammatik.

Ich wßrde sagen, die ernsthafteste Schwäche sind die extrem
komplizierten Disambiguation Regeln. Die wirklich korrekt zu
implementieren ist (auch aufgrund der mangelhaften Definition als
textuelle Repräsentation) extrem schwierig und das zeigt sich auch immer
wieder bei Beispielen, die von einem Compiler gefressen werden und von
einem anderen nicht.

C++ ist halt Stückelwerk. Außerdem sind ihnen offenbar irgendwann die
Tokens ausgegangen, sonst hätten wir nicht jahrelang elendige Probleme
gehabt mir trivialsten Mist wie

std::vector<std::vector<std::string>>

bzw eben der frĂźher notwendigen Variante

std::vector<std::vector<std::string> >

Wenn mich meiner Errinerung nicht täuscht, sind die ntowendigen
Disambiguation Regeln dafĂźr erst mit C++11 dazugekommen. Das ist einfach
nur gruselig.

Gruß,
Johannes

--
"Performance ist nicht das Problem, es läuft ja nachher beides auf der
selben Hardware." -- Hans-Peter Diettrich in d.s.e.
 
Am 27.09.2019 um 10:37 schrieb Johannes Bauer:
Und dann nochmal Ăźberdeutlich: "This summary of C ++ syntax is intended
to be an aid to comprehension. It is not an exact statement of the
language."

Das ist die Zusammenfassung der Fragmente. Nicht normativ, weil die
normativen Teile nebst der semantischen Bedingungen in den anderen
Kapiteln stehen, und weil dir niemand zusichert, in dem Anhang nichts
vergessen zu haben.

Und selbst die Fragmente sind horrend unvollständig. Ich nehme mir ein
beliebiges Beispiel raus: "14.2. Names of template specializations".
Eine popelige Grammatik, evtl 15 Zeilen lang. Gefolgt von 1 1/2 Seiten
Prosa, die dann genau sagt wie die zu interpretieren ist.

Das nennt sich - ich wiederhole mich - semantische Bedingungen. Von
Trivialitäten wie Brainfuck abgesehen kommt kaum eine Sprache ohne aus.

sowie in Fragmenten in den
einzelnen Kapiteln.

Genau, verteilt Ăźber ~1300 Seiten, aber eben nicht ausdefiniert (und
genau das habe ich geschrieben, keine ausdefinierte Grammatik).

Was wäre denn eine "ausdefinierte Grammatik"?

Eine formale Beschreibung, die man im idealfall direkt einem Parser
vorlegen kann, also maschinenlesbar ist. C++ ist aber als Sprache so
kompliziert, dass ich vermute, dass das wohl nicht (mehr?) machbar ist.
Deswegen nutzt man eben viel Prosa und Beispiele, um zu verdeutlichen,
was gemeint ist.

Du kannst die Grammatik einem ausreichend fähigen Parsergenerator
vorlegen. Der wird dann halt *mehr* erkennen als nur gĂźltige
C++-Programme, da die semantischen Bedingungen die gĂźltigen Programme
*einschränken* ("eine Variable muss vor der Verwendung deklariert sein"
usw.).

Die ernsthafte Schwäche, die diese Grammatik hat, ist, dass sie zwischen
den Ebenen "lexikalische Analyse", "Präprozessor" und "syntaktische
Analyse" nicht sauber trennt. Jedem Praktiker ist das egal. Regeln wie
"maximum munch" (also dass 'inti' ein Wort ist und nicht das gleiche wie
'int i') werden quasi immer in Prosa angegeben, nicht in der Grammatik.

Ich wßrde sagen, die ernsthafteste Schwäche sind die extrem
komplizierten Disambiguation Regeln. Die wirklich korrekt zu
implementieren ist (auch aufgrund der mangelhaften Definition als
textuelle Repräsentation) extrem schwierig und das zeigt sich auch immer
wieder bei Beispielen, die von einem Compiler gefressen werden und von
einem anderen nicht.

Diese Disambiguierungsregeln hat es zum Teil von C geerbt. 'a * b;' ist
ein expression-statement oder eine Deklaration.

C++ ist halt Stückelwerk. Außerdem sind ihnen offenbar irgendwann die
Tokens ausgegangen, sonst hätten wir nicht jahrelang elendige Probleme
gehabt mir trivialsten Mist wie

std::vector<std::vector<std::string

bzw eben der frĂźher notwendigen Variante

std::vector<std::vector<std::string

Wenn mich meiner Errinerung nicht täuscht, sind die ntowendigen
Disambiguation Regeln dafĂźr erst mit C++11 dazugekommen. Das ist einfach
nur gruselig.

Das hat nichts mit schwammiger Disambiguierung zu tun, das ist ein ganz
normaler "maximum munch" Lexer, der, wenn man ihm keinen Tipp gibt, '>>'
als ein Token parsed.

Solche Effekte gibt es in vielen Sprachen. Pascal:

a := sqrt(.5);

(parsed nicht, weil '(.' als '[' interpretiert wird.)

In C++ hat man halt eine Sonderbehandlung fĂźr diesen einen Fall eingebaut.


Stefan
 
Am 27.09.2019 um 17:42 schrieb Stefan Reuther:

Das hat nichts mit schwammiger Disambiguierung zu tun, das ist ein ganz
normaler "maximum munch" Lexer, der, wenn man ihm keinen Tipp gibt, '>>'
als ein Token parsed.

Schon K&R hat >>, ==, ++ usw. als eigenständige Tokens definiert. Selbst
fĂźr +++ wurde geregelt, welche Tokens das ergibt. Und wenn wir schon
dabei sind, das "dangling else" wird auch weit einfacher in der
semantischen PrĂźfung des Parsers aufgelĂśst als in der Grammatik.

Mich stĂśrt da mehr das "long long", das eine eigene Bedeutung erhalten
hat, nicht aber "short short". Ist eigentlich heutzutage auch "long
signed long" ein gĂźltiger Typ, und wenn ja welcher?

Solche Effekte gibt es in vielen Sprachen. Pascal:

a := sqrt(.5);

(parsed nicht, weil '(.' als '[' interpretiert wird.)

Sofern man Digraphen als Option eingeschaltet hat. Heutige Compiler
kennen mĂśglicherweise garkeine Di-/Trigraphen mehr, oder ignorieren sie
per Default. Delphi unterscheidet inzwischen sogar Kommentare in { } und
(* *), die eigentlich gleich interpretiert werden müßten. So kann man
ganze CodeblĂścke mit Kommentaren ggf. nochmal mit der anderen
Schreibweise auskommentieren.

DoDi
 
Am 27.09.2019 um 21:22 schrieb Hans-Peter Diettrich:
Am 27.09.2019 um 17:42 schrieb Stefan Reuther:
Das hat nichts mit schwammiger Disambiguierung zu tun, das ist ein ganz
normaler "maximum munch" Lexer, der, wenn man ihm keinen Tipp gibt, '>>'
als ein Token parsed.

Schon K&R hat >>, ==, ++ usw. als eigenständige Tokens definiert. Selbst
fĂźr +++ wurde geregelt, welche Tokens das ergibt. Und wenn wir schon
dabei sind, das "dangling else" wird auch weit einfacher in der
semantischen PrĂźfung des Parsers aufgelĂśst als in der Grammatik.

Mich stĂśrt da mehr das "long long", das eine eigene Bedeutung erhalten
hat, nicht aber "short short". Ist eigentlich heutzutage auch "long
signed long" ein gĂźltiger Typ, und wenn ja welcher?

"long signed long" ist das gleiche wie "long long".

DafĂźr gibt es wenigstens einen Compiler, der "long short" fĂźr einen
24-Bit-Typen kennt (MPLAB C18). Was sollte denn "short short" sein? Bei
den üblichen Größen mit "char" = 8 Bit, "short" = 16 Bit bliebe ja nur
ein 12-Bit-Typ Ăźbrig. HardwareunterstĂźtzung dafĂźr dĂźrfte dann doch eher
selten in freier Natur anzutreffen sein. Einfach, weil sich der
Programmierer von der Straße nichts ohne 8-Bit-Bytes mehr vorstellen kann.

Solche Effekte gibt es in vielen Sprachen. Pascal:

a := sqrt(.5);

(parsed nicht, weil '(.' als '[' interpretiert wird.)

Sofern man Digraphen als Option eingeschaltet hat. Heutige Compiler
kennen mĂśglicherweise garkeine Di-/Trigraphen mehr, oder ignorieren sie
per Default.

Zumindest die Turbo-Pascal-Compiler hatten keine mir bekannte
MĂśglichkeit, das auszuschalten.

Delphi unterscheidet inzwischen sogar Kommentare in { } und
(* *), die eigentlich gleich interpretiert werden müßten. So kann man
ganze CodeblĂścke mit Kommentaren ggf. nochmal mit der anderen
Schreibweise auskommentieren.

Das wiederum hatte Turbo Pascal auch.


Stefan
 
On 27.09.19 17:42, Stefan Reuther wrote:

Das ist die Zusammenfassung der Fragmente. Nicht normativ, weil die
normativen Teile nebst der semantischen Bedingungen in den anderen
Kapiteln stehen, und weil dir niemand zusichert, in dem Anhang nichts
vergessen zu haben.

Und selbst die Fragmente sind horrend unvollständig. Ich nehme mir ein
beliebiges Beispiel raus: "14.2. Names of template specializations".
Eine popelige Grammatik, evtl 15 Zeilen lang. Gefolgt von 1 1/2 Seiten
Prosa, die dann genau sagt wie die zu interpretieren ist.

Das nennt sich - ich wiederhole mich - semantische Bedingungen. Von
Trivialitäten wie Brainfuck abgesehen kommt kaum eine Sprache ohne aus.

Klar, aber die Komplexität der in Prosa geschriebenen semantischen
Bedingungen Ăźbersteigt die der Grammatik eben bei Weitem. Der Effekt ist
bei C++ eben wirklich ausgeprägt.

Eine formale Beschreibung, die man im idealfall direkt einem Parser
vorlegen kann, also maschinenlesbar ist. C++ ist aber als Sprache so
kompliziert, dass ich vermute, dass das wohl nicht (mehr?) machbar ist.
Deswegen nutzt man eben viel Prosa und Beispiele, um zu verdeutlichen,
was gemeint ist.

Du kannst die Grammatik einem ausreichend fähigen Parsergenerator
vorlegen. Der wird dann halt *mehr* erkennen als nur gĂźltige
C++-Programme, da die semantischen Bedingungen die gĂźltigen Programme
*einschränken* ("eine Variable muss vor der Verwendung deklariert sein"
usw.).

Umso mehr Bedingungen es gibt, die diese Programme einschränken, umso
nutzloser ist die reine formale Grammatik. Weil dann kann ich
prinzipiell fĂźr jede Sprache eine allgemeingĂźltige Grammatik angeben:

PROGRAM := chr(0..255)*

Supereinfach, und korrekt dazu. Parst jedes gĂźltige C++-Programm. Und
halt noch mehr, als semantische Bedingung gebe ich an muss zusätzlich
den C++-Standard erfĂźllen. Feddich ist der Lack.

Ist aber halt super nutzlos, so eine Grammatik.

Diese Disambiguierungsregeln hat es zum Teil von C geerbt. 'a * b;' ist
ein expression-statement oder eine Deklaration.

C ist im Vergleich zu C++ absoluter Kinderkram. Die Komplexität von C++
würde ich, bauchgefühlsmäßig, als mindestens Faktor 10 höher einschätzen.

Wenn mich meiner Errinerung nicht täuscht, sind die ntowendigen
Disambiguation Regeln dafĂźr erst mit C++11 dazugekommen. Das ist einfach
nur gruselig.

Das hat nichts mit schwammiger Disambiguierung zu tun, das ist ein ganz
normaler "maximum munch" Lexer, der, wenn man ihm keinen Tipp gibt, '>>'
als ein Token parsed.

Schon klar. Aber es geht nicht darum, wieso der Parser das so parst,
sondern was per Definition die *korrekte* Art des Parsens ist. Und, wenn
mich meine Errinerung nicht täuscht, war eben

std::vector<std:vector<std::string>>

Formal gesehen vor C++x ein Syntaxfehler. Ich glaube mich daran zu
errinern, dass sowohl der MS C++-Compiler als auch der icc trotzdem das
geparst haben, was "gemeint" war, und nur der gcc sich daran
verschluckte. Und meiner Errinerung nach war gcc eben formal "korrekt".
Aber das ist alles jetzt schon ewig her, bin mir in den Details nicht
mehr ganz sicher.

Das verdeutlicht aber genau das Problem, das ich anspreche: Jemand, der
einen Compiler schreibt, versucht das "richtige" zu machen, weil die
formale Definition eben unvollständig oder klobig ist. Da wackelt der
Schwanz mit dem Hund.

Gruß,
Johannes

--
"Performance ist nicht das Problem, es läuft ja nachher beides auf der
selben Hardware." -- Hans-Peter Diettrich in d.s.e.
 
Am 28.09.2019 um 11:58 schrieb Stefan Reuther:
Am 27.09.2019 um 21:22 schrieb Hans-Peter Diettrich:
Am 27.09.2019 um 17:42 schrieb Stefan Reuther:
Das hat nichts mit schwammiger Disambiguierung zu tun, das ist ein ganz
normaler "maximum munch" Lexer, der, wenn man ihm keinen Tipp gibt, '>>'
als ein Token parsed.

Schon K&R hat >>, ==, ++ usw. als eigenständige Tokens definiert. Selbst
fĂźr +++ wurde geregelt, welche Tokens das ergibt. Und wenn wir schon
dabei sind, das "dangling else" wird auch weit einfacher in der
semantischen PrĂźfung des Parsers aufgelĂśst als in der Grammatik.

Mich stĂśrt da mehr das "long long", das eine eigene Bedeutung erhalten
hat, nicht aber "short short". Ist eigentlich heutzutage auch "long
signed long" ein gĂźltiger Typ, und wenn ja welcher?

"long signed long" ist das gleiche wie "long long".

Warum? Ich hätte auf "signed long" getippt.

DafĂźr gibt es wenigstens einen Compiler, der "long short" fĂźr einen
24-Bit-Typen kennt (MPLAB C18). Was sollte denn "short short" sein? Bei
den üblichen Größen mit "char" = 8 Bit, "short" = 16 Bit bliebe ja nur
ein 12-Bit-Typ Ăźbrig. HardwareunterstĂźtzung dafĂźr dĂźrfte dann doch eher
selten in freier Natur anzutreffen sein. Einfach, weil sich der
Programmierer von der Straße nichts ohne 8-Bit-Bytes mehr vorstellen kann.

Das hat dann aber nichts mit einem C Standard zu tun, sondern ist eine
compilerspezifische Erweiterung.

Solche Effekte gibt es in vielen Sprachen. Pascal:

a := sqrt(.5);

(parsed nicht, weil '(.' als '[' interpretiert wird.)

Sofern man Digraphen als Option eingeschaltet hat. Heutige Compiler
kennen mĂśglicherweise garkeine Di-/Trigraphen mehr, oder ignorieren sie
per Default.

Zumindest die Turbo-Pascal-Compiler hatten keine mir bekannte
MĂśglichkeit, das auszuschalten.

Deshalb schrieb ich ja "heutige" Compiler :-]

DoDi
 

Welcome to EDABoard.com

Sponsor

Back
Top