Wie werden Kommentare normalerweise analysiert?

31

Wie werden Kommentare generell in Programmiersprachen und Markups behandelt? Ich schreibe einen Parser für eine benutzerdefinierte Auszeichnungssprache und möchte dem Prinzip der geringsten Überraschung folgen , also versuche ich, die allgemeine Konvention zu bestimmen.

Soll beispielsweise ein in ein Token eingebetteter Kommentar das Token stören oder nicht? Im Allgemeinen ist so etwas wie:

Sys/* comment */tem.out.println()

gültig?

Wenn die Sprache für neue Zeilen empfindlich ist und der Kommentar die neue Zeile umfasst, sollte die neue Zeile berücksichtigt werden oder nicht?

stuff stuff /* this is comment
this is still comment */more stuff 

behandelt werden als

stuff stuff more stuff

oder

stuff stuff
more stuff

?

Ich weiß, was einige bestimmte Sprachen tun, und ich suche auch nach Meinungen, aber ich suche, ob es einen allgemeinen Konsens darüber gibt, was von einem Aufschlag in Bezug auf Token und neue Zeilen im Allgemeinen erwartet wird oder nicht.


Mein besonderer Kontext ist ein Wiki-ähnliches Markup.

Schlitten
quelle
Existiert die neue Zeile im Kommentar? Warum sollte es anders behandelt werden als jedes andere Zeichen im Kommentar?
1
@Snowman es gibt diese Perspektive, aber auf der anderen Seite, wenn Token 'x' eine besondere Bedeutung hat, wenn es das erste Token in der Zeile ist und es sowohl für die Person, die die Quelle als auch die Person betrachtet, das erste Token in der Zeile zu sein scheint Parser, der Zeile für Zeile liest. Scheint wie ein Dilemma, also stellte ich die Frage.
Schlitten
4
Ich musste dies vor einiger Zeit genau nach den Spezifikationen tun und fand, dass die Dokumente von gcc eine hervorragende Ressource sind. Es gibt einige seltsame Eckfälle, an die Sie vielleicht nicht gedacht haben.
Karl Bielefeldt

Antworten:

40

Normalerweise werden Kommentare als Teil des Tokenisierungsprozesses gescannt (und verworfen), jedoch vor dem Parsen. Ein Kommentar funktioniert wie ein Token-Trennzeichen, auch wenn kein Leerzeichen in der Nähe steht.

In der C-Spezifikation wird ausdrücklich darauf hingewiesen, dass Kommentare durch ein einzelnes Leerzeichen ersetzt werden. Es ist jedoch nur eine Spezifikationssprache, da ein Parser aus der realen Welt eigentlich nichts ersetzt, sondern einen Kommentar genauso scannt und verwirft, wie er Whitespace-Zeichen scannt und verwirft. Aber es erklärt auf einfache Weise, dass ein Kommentar Token genauso trennt wie ein Leerzeichen.

Der Inhalt von Kommentaren wird ignoriert, sodass Zeilenumbrüche in mehrzeiligen Kommentaren keine Auswirkungen haben. Sprachen, die empfindlich auf Zeilenumbrüche reagieren (Python und Visual Basic), enthalten normalerweise keine mehrzeiligen Kommentare, aber JavaScript ist eine Ausnahme. Beispielsweise:

return /*
       */ 17

Ist äquivalent zu

return 17

nicht

return
17

Einzeilige Kommentare erhalten den Zeilenumbruch

return // single line comment
    17

ist äquivalent zu

return
17

nicht

return 17

Da Kommentare gescannt, aber nicht analysiert werden, besteht die Tendenz, dass sie nicht verschachtelt werden. So

 /*  /* nested comment */ */

ist ein Syntaxfehler, da der Kommentar vom ersten geöffnet und vom ersten /*geschlossen wird*/

JacquesB
quelle
3
In den meisten Sprachen werden Inline-Kommentare ( /* like this */) als ein Leerzeichen und Kommentare mit EOL-Abschluss ( // like this) als eine Leerzeile betrachtet.
9000
@JacquesB Ich denke also daran, Kommentare als vollständig aus der Quelle ersetzte Kommentare als Leerzeichen ohne Breite zu behandeln , das scheint dem zu entsprechen, was Sie vorschlagen.
Schlitten
1
@artb ein gewöhnlicher Raum sollte gut funktionieren und liegt in der ASCII-Codepage.
John Dvorak
@JanDvorak Ein Leerzeichen bewirkt das Erscheinen und beseitigt das Verständnis und kommt der Semantik von "Ein Kommentar ist nicht wirklich da" näher. Die primäre Rendering-Ausgabe ist HTML. In meinem Fall ist ASCII nicht so problematisch, da Browser Unicode unterstützen. Ich glaube jedoch, dass der C-Standard vorschreibt, dass Kommentare durch ein einzelnes Leerzeichen ersetzt werden.
Schlitten
1
Einige Sprachen, insbesondere Racket, enthalten verschachtelte mehrzeilige Kommentare: (define x #| this is #| a sub-comment |# the main comment |# 3) xErträge 3.
wchargin
9

Um die Frage zu beantworten:

Gibt es einen allgemeinen Konsens darüber, was im Allgemeinen von einem Aufschlag erwartet wird?

Ich würde sagen, keiner würde erwarten, dass ein in ein Token eingebetteter Kommentar legal ist.

Als Faustregel gilt, dass Kommentare wie Leerzeichen behandelt werden sollten. Jeder Ort, an dem Leerzeichen zulässig wären, sollte auch einen eingebetteten Kommentar enthalten. Die einzige Ausnahme wären Strings:

trace("Hello /*world*/") // should print Hello /*world*/

Es wäre ziemlich seltsam, Kommentare in Zeichenfolgen zu unterstützen, und würde es mühsam machen, sie zu umgehen!

Connor Clark
quelle
2
Ich habe nie über Saiten nachgedacht, das ist ein guter Randfall. Mein aktueller Gedanke war, einen einfachen Ausdruck zwischen Kommentaranfang und -ende zu erstellen und ihn durch ein einzelnes Leerzeichen zu ersetzen. Das hätte Ihren Fall ausgelöst.
Schlitten
3
+1 für das bisschen über das Entkommen von Zeichenfolgen. Obwohl ich in Ihrem Beispiel generell davon ausgehen würde, dass es gedruckt wird, Hello /* world*/!anstatt die Kommentarbegrenzer zu unterdrücken. Willkommen auch bei Programmierern!
8bittree
1
Vielen Dank 8bittree! Und genau das habe ich gemeint. Lustigerweise muss ich auch dem ** in meiner Antwort entkommen ...
Connor Clark
2
@ArtB im Allgemeinen: "Parsen durch Ersetzen" wird in der Zukunft mit Randfällen und der Interaktion mit anderen Funktionen sehr schwierig und wird am besten von Anfang an vermieden.
Hobbs
7

In whitespace-unempfindlichen Sprachen werden Token durch ignorierte Zeichen (dh Leerzeichen oder solche, die Teil eines Kommentars sind) begrenzt.

So sind zum Beispiel Sys temzwei Token, während Systemeiner ist. Die Nützlichkeit dieser Funktion wird möglicherweise deutlicher, wenn Sie einen Vergleich anstellen new Foo()und newFoo()einer davon eine Instanz von erstellt, Foowährend der andere aufruft newFoo.

Kommentare können die gleiche Rolle spielen wie eine Folge von Leerzeichen, zB new/**/Foo()wie new Foo(). Dies kann natürlich komplexer sein, z new /**/ /**/ Foo(). B. oder so.

Technisch sollte es möglich sein, Kommentare innerhalb von Bezeichnern zuzulassen, aber ich bezweifle, dass dies besonders praktisch ist.

Was ist nun mit weißraumsensiblen Sprachen?

Python fällt mir ein und hat eine sehr einfache Antwort: Keine Blockkommentare. Sie beginnen einen Kommentar mit #und dann funktioniert der Parser genau so, als ob der Rest der Zeile nicht existiert hätte, sondern nur eine neue Zeile wäre.

Im Gegensatz dazu erlaubt Jade Blockkommentare , bei denen der Block endet, wenn Sie zur gleichen Einrückungsstufe zurückkehren. Beispiel:

body
  //-
    As much text as you want
    can go here.
  p this is no longer part of the comment

In diesem Bereich würde ich nicht sagen, dass man sagen kann, wie die Dinge normalerweise gehandhabt werden. Es scheint eine Gemeinsamkeit zu sein, dass ein Kommentar immer mit einem Zeilenende endet, dh, alle Kommentare verhalten sich genauso wie neue Zeilen.

back2dos
quelle
Hmm, der Zeilenvorschub ist das eigentliche Problem, da wir HTML \ XML-Syntax für Kommentare verwenden, sodass er mehrzeilig sein wird.
Schlitten
3
@ArtB Wenn Sie HTML / XML-Syntax verwenden, ist es möglicherweise ratsam, einfach deren Verhalten zu verwenden.
8bittree
1
@ 8bittree macht Sinn, hätte darüber nachdenken sollen. Ich werde die Frage so lassen, wie sie ist, da sie auf diese Weise nützlicher ist.
Schlitten
3

In der Vergangenheit habe ich Kommentare als Teil der lexikalischen Analyse zu einem einzigen Token gemacht. Gleiches gilt für Streicher. Von dort aus ist das Leben einfach.

Im speziellen Fall des letzten von mir erstellten Parsers wird eine Escape-Regel an die Analyseroutine der obersten Ebene übergeben. Die Escape-Regel wird verwendet, um Token wie Kommentartoken in Übereinstimmung mit der Kerngrammatik zu verarbeiten. Im Allgemeinen wurden diese Token verworfen.

Dies hat zur Folge, dass in dem Beispiel, das Sie mit einem Kommentar in der Mitte eines Bezeichners gepostet haben, der Bezeichner kein einzelner Bezeichner ist - dies ist das erwartete Verhalten in allen Sprachen (aus dem Speicher), mit denen ich gearbeitet habe .

Der Fall eines Kommentars innerhalb eines Strings sollte implizit von der lexikalischen Analyse behandelt werden. Die Regeln für den Umgang mit einer Zeichenfolge haben kein Interesse an Kommentaren. Daher wird der Kommentar als Inhalt der Zeichenfolge behandelt. Dasselbe gilt für eine Zeichenfolge (oder ein Literal in Anführungszeichen) innerhalb eines Kommentars. Die Zeichenfolge ist Teil eines Kommentars, bei dem es sich explizit um ein einzelnes Token handelt. Die Regeln für die Bearbeitung eines Kommentars haben kein Interesse an Strings.

Ich hoffe das macht Sinn / hilft.

user202190
quelle
Wenn Sie also Code haben, wie z. B. console.log(/*a comment containing "quotes" is possible*/ "and a string containing /*slash-star, star-slash*/ is possible")Anführungszeichen in einem Kommentar und Kommentarsyntax in einer Zeichenfolge, woher sollte der Lexer wissen, ob er den Code korrekt token kann? Können Sie bitte Ihre Antwort mit einer allgemeinen Beschreibung dieser Fälle bearbeiten?
Chharvey
1

Es hängt davon ab, welchen Zweck Ihr Parser hat. Wenn Sie einen Parser schreiben, um einen Analysebaum zum Kompilieren zu erstellen, hat ein Kommentar keinen semantischen Wert neben den potenziellen Trennzeichen (z. B. method / comment / (/ comment /)). In diesem Fall werden sie wie Leerzeichen behandelt.

Wenn Ihr Parser Teil eines Transpilers ist, der eine Quellensprache in eine andere Quellensprache übersetzt, oder wenn Ihr Parser ein Präprozessor ist, der eine Kompilierungseinheit in einer Quellensprache analysiert, sie modifiziert und die modifizierte Version in dieselbe Quellensprache zurückschreibt, kommentiert wie alles andere wird sehr wichtig.

Auch wenn Sie Metainformationen in Kommentaren haben und sich besonders für Kommentare interessieren, wie dies bei der Erstellung von API-Dokumentationen wie in JavaDoc der Fall ist, sind Kommentare plötzlich sehr wichtig.

Hier werden Kommentare häufig an die Tokens selbst angehängt. Wenn Sie einen Kommentar finden, fügen Sie ihn als Kommentar eines Tokens hinzu. Da ein Token davor und danach mehrere Token haben kann, ist es wiederum zweckabhängig, wie mit diesen Kommentaren umgegangen wird.

Die Idee, Nichtkommentar-Token mit Kommentaren zu versehen, besteht darin, Kommentare vollständig aus der Grammatik zu entfernen.

Sobald Sie den Analysebaum haben, beginnen einige AST, Kommentare zu entpacken, die jedes Token durch ein eigenes AST-Element darstellen, aber an ein anderes AST-Element neben der üblichen Contain-Beziehung angehängt werden. Eine gute Idee ist es, alle Parser / AST-Implementierungen auf Quellsprachen zu überprüfen, die in Open-Source-IDE verfügbar sind.

Eine sehr gute Implementierung ist die Eclipse-Compiler-Infrastruktur für die Java-Sprache. Sie behalten Kommentare während der Tokenisierung bei und repräsentieren Kommentare innerhalb des AST - soweit ich mich erinnere. Diese Parser / AST-Implementierung behält auch die Formatierung bei.

Martin Kersten
quelle