Wenn Leute sagen "X komponiert nicht", bedeutet "komponieren" eigentlich nur "zusammensetzen", und was und wie man sie zusammensetzt, kann sehr unterschiedlich sein, je nachdem, was genau "X" ist.
Wenn sie "nicht komponieren" sagen, können sie auch ein paar leicht unterschiedliche Dinge bedeuten:
- Sie können nicht zwei Xs zusammen, Punkt.
- Sie können zwei Xs zusammenfügen, aber das Ergebnis ist möglicherweise kein X (IOW: X ist unter Komposition nicht geschlossen .)
- Sie können zwei Xs zusammenfügen, aber das resultierende X funktioniert möglicherweise nicht so, wie Sie es erwarten.
Ein Beispiel für # 1 sind Parser mit Scannern / Lexern. Möglicherweise hören Sie den Satz "Scanner / Lexer komponieren nicht". Das stimmt eigentlich nicht. Was sie bedeuten, ist "Parser, die eine separate Lexing-Stufe verwenden, komponieren nicht".
Warum sollten Sie Parser erstellen? Stellen Sie sich vor, Sie sind ein IDE-Anbieter wie JetBrains, die Eclipse Foundation, Microsoft oder Embarcadero und möchten eine IDE für ein Webframework erstellen. In der typischen Webentwicklung mischen wir oft Sprachen. Sie haben HTML-Dateien mit <script>
Elementen, die ECMAScript und enthalten<style>
Elemente, die CSS enthalten. Sie haben Vorlagendateien, die HTML, eine Programmiersprache und eine Metasyntax für Vorlagensprachen enthalten. Sie möchten keine unterschiedlichen Syntaxmarker für "Python", "In eine Vorlage eingebettetes Python", "CSS", "CSS in HTML", "ECMASCript", "ECMAScript in HTML", "HTML", "HTML in" schreiben eine Vorlage ", und so weiter und so fort. Sie möchten einen Syntax-Textmarker für Python, einen für HTML und einen für die Vorlagensprache schreiben und die drei dann zu einem Syntax-Textmarker für eine Vorlagendatei zusammensetzen.
Ein Lexer parst jedoch die gesamte Datei in einen Strom von Token, was nur für diese eine Sprache Sinn macht. Der Parser für die andere Sprache kann nicht mit den Tokens arbeiten, die der Lexer übergibt. Beispielsweise werden Python-Parser in der Regel so geschrieben, dass der Lexer die Einrückung nachverfolgt und Fälschungen INDENT
und DEDENT
Token in den Token-Stream einfügt, sodass der Parser kontextfrei ist, obwohl Pythons Syntax dies nicht ist. Ein HTML-Lexer ignoriert jedoch Whitespace vollständig, da es in HTML keine Bedeutung hat.
Ein scannerloser Parser, der lediglich Zeichen liest, kann den Zeichenstrom an einen anderen Parser weiterleiten, der ihn dann zurückgibt und so die Komposition erheblich vereinfacht.
Ein Beispiel für # 2 sind Zeichenfolgen mit darin enthaltenen SQL-Abfragen. Sie können zwei Zeichenfolgen verwenden, in denen jeweils eine syntaktisch korrekte SQL-Abfrage enthalten ist. Wenn Sie die beiden Zeichenfolgen jedoch verketten, ist das Ergebnis möglicherweise keine syntaktisch korrekte SQL-Abfrage. Deshalb haben wir Abfrage algebras wie ARel
, was tun compose.
Schlösser sind ein Beispiel für # 3. Wenn Sie zwei Programme mit Sperren haben und diese zu einem einzigen Programm kombinieren, haben Sie immer noch ein Programm mit Sperren, aber selbst wenn die beiden ursprünglichen Programme völlig korrekt und frei von Deadlocks und Rennen waren, muss das resultierende Programm dies nicht unbedingt haben Eigentum. Die korrekte Verwendung von Sperren ist eine globale Eigenschaft des gesamten Programms und wird beim Erstellen von Programmen nicht beibehalten. Dies unterscheidet sich von zum Beispiel Transaktionen, die tun compose. Ein Programm, das Transaktionen korrekt verwendet, kann mit einem anderen solchen Programm zusammengesetzt werden und ergibt ein kombiniertes Programm, das Transaktionen korrekt verwendet.