9

Ich muss dazu übergehen, diese Programmiersprache zu schreiben, die ich schreiben wollte. Wie machen es die Kinder heutzutage? Ich bin seit über einem Jahrzehnt nicht mehr auf dem Laufenden. Machst du es jetzt anders als wir es in den Pre-Internet, Pre-Windows-Tagen getan haben? Weißt du, wann "echte" Codierer in C programmiert waren, die Befehlszeile verwendet haben und über welche Shell sich besser geäußert hat?Wie erstelle ich heute eine Sprache?

Nur um zu verdeutlichen, ich meine, nicht wie Sie eine Sprache entwerfen (die ich ziemlich leicht herausfinden kann), aber wie bauen Sie den Compiler und Standard-Bibliotheken und so weiter? Welche Werkzeuge benutzen Sie heutzutage?

+8

Für die Aufzeichnung verwenden wir "Kinder" immer noch die Befehlszeile und munkeln, welche Shell besser ist. Oder ich tue das zumindest. C ist aber tot. Ich muss jetzt vor den Programmierern von C fliehen, also werde ich dich sehen! –

+0

Welche Art von Sprache, interpretiert oder kompiliert? –

+0

interpretiert oder zusammengestellt? Hmmm gute Frage. Ich nehme an, es macht einen Unterschied, so dass ich sagen werde, nur um auf der sicheren Seite zu sein. – Mike

Antwort

2

Ich bin mir ziemlich sicher, dass Sie tun, was schon immer gemacht wurde.

Schreiben Sie einen Code und zeigen Sie Ihre Ergebnisse der Welt.

Im Vergleich zu den alten Zeiten gibt es einige Tools, um Ihre Arbeit zu erleichtern. Könnte ich vorschlagen, ANTLR für das Parsen Ihrer Sprachgrammatik?

0

Echte Codierer codieren immer noch in C. Nur dass es etwas schärfer ist.
Hmmm ... Sprachdesign? oder einen Compiler schreiben? Wenn Sie einen Compiler schreiben möchten, verwenden Sie Flex + Bison. (google)

+1

Wenn Sie einen guten Compiler schreiben möchten, werden Sie Ihre eigenen rekursiv Hand-Roll - Parser, wenn Sie einen mäßig komplexen Bison-Parser haben, werden Sie bald Probleme bekommen (wenn Sie die Sprache nicht zum Laufen bringen, sollten Sie den Compiler/Interpreter dazu bringen, Fehler zu melden). –

+0

+1 für die Art und Weise, wie Sie auf c verwiesen # – RCIX

+0

@chris Ja, vielleicht, aber nur für LISP (ASM, Scheme ...) Manuell schreiben einen richtigen Full-Blown-Compiler ist das letzte, was Sie tun wollen ... nur wegen die Komplexität. – aviraldg

2

Sie sollten Wimpy-Lösungen wie die Verwendung der neuesten Tools nicht akzeptieren. Sie sollten die Sprache starten, indem Sie einen minimalen Compiler in Visual Basic für Applikationen oder eine ähnliche Sprache schreiben. Schreiben Sie dann alle Kompilierungstools in Ihre neue Sprache und kompilieren Sie sie dann selbst, indem Sie nur die Sprache selbst verwenden.

Auch, was ist der vorgeschlagene Name der Sprache?

Ich denke, vor kurzem gab es keine Sprachen mit ALLEN GROSSBUCHSTABEN Namen wie COBOL und FORTRAN, also hoffe ich, dass Sie es so etwas wie MIKELANG mit allen Großbuchstaben nennen werden.

+1

BASIC? Ich hörte, dass jemand recherchierte, ob Schimpansen, die an einer Tastatur hämmerten, aufgeräumter waren als BASIC-Code auf Produktionsebene. Guess ... – aviraldg

+2

Coole Idee. Ich hatte vor einigen Jahren "Complicity" ausgewählt, aber mir gefällt die Idee einer ALLCAPS-Sprache! MIKTRAN, MOBOL, MIKEBASIC, MALEVOLENT, MALT, MARKV, MINGLE, MING, UNILANG ... – Mike

0

keine einfache Antwort, aber ..

Sie wollen im Wesentlichen eine Reihe von Regeln in Text (Tokens) und dann einige Parser geschrieben definieren, die diese Regeln überprüft und fügt sie in Fragmente.

http://www.mactech.com/articles/mactech/Vol.16/16.07/UsingFlexandBison/

Menschen Jahren dafür aufwenden können, die oben Artikel spricht über die Verwendung von zwei Werkzeugen (Flex und Bison), die verwendet werden, um Text in Code wenden Sie sich an einen Compiler einspeisen kann.

2

Sprechen als jemand, der nur eine sehr einfache Assembly wie Sprache und Interpreter baute, würde ich mit dem .NET-Framework oder ähnliches beginnen. Nichts kann die mächtige Syntax von C# und die Unterstützung der gesamten .NET-Gemeinschaft schlagen, wenn versucht wird, die meisten Dinge zu schreiben. Von hier entwarf ich ein einfaches Bytecode-Format und eine Assembler-Syntax und verarbeitete meinen Interpreter + Assembler. Wie gesagt, es war ein sehr einfache Sprache.

+0

leistungsfähige Syntax? C#? du veräppelst mich. Aber das .net-Framework und die Community sind nett. –

7

Eine Überlegung, die seit der Ära der Lochkarten neu ist, ist die Existenz virtueller Maschinen, die bereits reichlich mit "Standard-Bibliotheken" ausgestattet sind. Das Targeting der JVM oder der .NET CLR anstelle des alten "Sprache ummauerten Gartens" erspart Ihnen eine Menge Bootstrapping. Wenn Sie eine kompilierte Sprache erstellen, finden Sie möglicherweise auch Java-Bytecode oder MSIL, ein leichteres Kompilierziel als Maschinencode (natürlich, wenn Sie aus Spaß daran arbeiten, einen engen optimierenden Compiler zu erstellen, dann werden Sie das sehen als Fehler und nicht als Feature).

Auf der negativen Seite, die Idiome der JVM oder CLR möglicherweise nicht, was Sie für Ihre Sprache wollen. So können Sie am Ende immer noch "Standard-Bibliotheken" erstellen, nur um idiomatische Schnittstellen über die Plattform zur Verfügung zu stellen. (Ein Beispiel ist, dass jede Sprache und ihr Hund anscheinend eine eigene Methode zum Schreiben in die Konsole bereitstellen, anstatt Benutzern den manuellen Aufruf von System.out.println oder Console.WriteLine zu überlassen.) Dennoch ermöglicht es eine inkrementelle Entwicklung des idiomatischen Systems Bibliotheken, und bedeutet, dass die obskuren Bibliotheken, für die man nie zu idiomatischen Interfaces kommt, immer noch zugänglich sind, auch wenn es in einer hässlichen Art und Weise geschieht.

Wenn Sie eine interpretierte Sprache in Betracht ziehen, unterstützt .NET auch die effiziente Interpretation über die Dynamic Language Runtime (DLR). (Ich weiß nicht, ob es ein Äquivalent für die JVM gibt.) Dies sollte Ihnen helfen, sich auf das Sprachdesign zu konzentrieren, ohne sich um die Optimierung des Interpreters kümmern zu müssen.

+1

VMs wie JVM und .NET sind eine evolutionäre Sackgasse. –

+1

Nicht wahr! Da die Bibliotheken für die JVM- und .NET-Plattformen sich nicht um Eigenheiten der Plattformen kümmern müssen, auf denen sie sich befinden, können sie die API-Designaspekte erforschen, die ansonsten nicht verändert würden. – RCIX

+1

VMs wie JVM und .NET sind eine evolutionäre Sackgasse. –

0

Zuerst verbrachte ich ungefähr ein Jahr, um darüber nachzudenken, wie die Sprache aussehen sollte. Zur gleichen Zeit half ich bei der Entwicklung von Ioke (www.ioke.org), um sprachliche Interna zu lernen.

Ich habe Objective-C als Implementierungsplattform gewählt, da es schnell (genug), einfach und reichhaltig ist. Es bietet auch Test-Framework so agilen Ansatz ist ein Go. Es hat auch eine umfangreiche Standardbibliothek, auf der ich aufbauen kann.

Da meine Sprache einfach auf syntaktischer Ebene ist (keine Schlüsselwörter, nur Literale, Operatoren und Nachrichten), könnte ich mit Ragel (http://www.complang.org/ragel/) zum Aufbau von Scanner gehen. Es ist schnell und einfach zu bedienen.

Jetzt habe ich ein funktionierendes Objektmodell, Scanner und einfachen Operator Shuffling plus Standard-Bibliothek Bootstrap-Code. Ich kann sogar ein einfaches Programm laufen lassen - solange sie in eine Datei passen :)

6

Ich habe jetzt zwei Compiler in Haskell für kleine domänenspezifische Sprachen geschrieben und habe festgestellt, dass es eine unglaublich produktive Erfahrung ist . Die Bibliothek parsec macht das Spielen mit Syntax einfach, und Interpreter lassen sich sehr einfach über eine Haskell-Datenstruktur schreiben. Es gibt eine Beschreibung von writing a Lisp interpreter in Haskell, die ich hilfreich fand. Wenn Sie an einem leistungsstarken Backend interessiert sind, empfehle ich LLVM. Es hat einen prägnanten und eleganten Byte-Code und das beste x86/amd64 erzeugende Backend, das Sie finden können. Es gibt einen optionalen Garbage Collector und einige experimentelle Backends, die target the JVM and CLR.

Sie können einen Compiler in jeder Sprache schreiben, die LLVM-Bytecode erzeugt. Wenn Sie abenteuerlich genug sind, Haskell zu lernen, aber LLVM wollen, gibt es eine Reihe von Haskell-LLVM Bindungen.

2

Nicht so sehr eine Implementierung, sondern eine Designentscheidung, die die Implementierung beeinflusst - wenn Sie jede Aussage Ihrer Sprache einen einzigartigen Syntaxbaum ohne Kontext haben, erhalten Sie etwas, das einen Parser leicht handkodiert erfordert keine große Menge an Arbeit, um Syntax-Hervorhebung für bereitzustellen. Ähnlich einfache Dinge wie die Verwendung eines anderen Symbols für Modul-Namespaces und Objekt-Namespaces bedeutet im Gegensatz zu Java, das . sowohl für Paket- als auch Klassen-Namespaces verwendet, dass Sie den Code analysieren können, ohne jedes Modul zu laden.

Standardbibliotheken - enthalten das Äquivalent von allem in C99-Standardbibliotheken außer setjmp. Fügen Sie alles hinzu, was Sie für Ihre Domain benötigen. Erarbeiten Sie einen einfachen Weg, um dies zu tun, entweder SWIG oder ein Inline-FFI wie Ruby's (kann sich nicht an Modulnamen erinnern) und Pythons Ctypes.

Gebäude so viel von der Sprache in der Sprache ist eine Option, aber Projekte, die dabei beginnen entweder aufgeben (rubinius bewegten C++ für Teile seiner Standardbibliothek zu verwenden) oder nur für Forschungszwecke (Mozilla Narcissus)

1

Ich bin eigentlich ein Kind, haha. Ich habe noch nie einen eigentlichen Compiler geschrieben oder eine Sprache entworfen, aber ich habe das Red Dragon Book fertiggestellt, also nehme ich an, dass ich etwas von einer Idee habe (hoffe ich).

Es hängt erstens von der Grammatik ab. Wenn es LR oder LALR ist, nehme ich an, dass Werkzeuge wie Bison/Flex gut funktionieren würden. Wenn es mehr LL ist, würde ich Spirit verwenden, die eine Komponente von Boost ist. Es ermöglicht Ihnen, die Grammatik der Sprache in C++ in einer EBNF-artigen Syntax zu schreiben, so dass Sie sich nicht mit Code-Generatoren herumschlagen müssen; Der C++ - Compiler kompiliert die Grammatik für Sie. Wenn eine dieser Methoden fehlschlägt, schreibe ich eine EBNF-Grammatik auf Papier und führe dann eine schwere rekursive Abstiegsanalyse durch, die zu funktionieren scheint; Wenn C++ mit RDP ziemlich gut geparst werden kann (wie GCC es tut), dann nehme ich an, dass mit genügend Unit-Tests und Geduld ganze Compiler mit RDP geschrieben werden können.

Sobald ich einen Parser laufen habe und irgendeine Art von Zwischenrepräsentation, dann hängt es davon ab, wie es läuft. Wenn es sich um einen Bytecode- oder Native-Code-Compiler handelt, verwende ich LLVM oder libJIT, um es zu verarbeiten. LLVM eignet sich besser für die allgemeine Kompilierung, aber ich mag die libJIT API und Dokumentation besser. Alternativ, wenn ich wirklich faul bin, erzeuge ich C-Code und lasse GCC die eigentliche Kompilierung machen. Eine andere Alternative besteht darin, eine vorhandene VM wie Parrot oder die JVM oder die CLR zu targetieren. Parrot ist die VM, die für Perl entworfen wird. Wenn es nur ein Interpreter ist, gehe ich den Syntaxbaum durch.

Eine radikale Alternative ist die Verwendung von Prolog mit Syntaxfunktionen, die EBNF bemerkenswert simulieren. Ich habe jedoch keine Erfahrung damit, und wenn ich nicht falsch liege (was ich mit ziemlicher Sicherheit tun werde), wäre Prolog ziemlich langsam, wenn er schwere Programmiersprachen mit einer Menge von syntaktischen Konstrukten und Macken parsen würde (lies: C++ und Perl).

All dies werde ich in C++ tun, nur weil ich mehr daran gewöhnt bin, in C zu schreiben. Ich würde von Java/Python oder irgendetwas dieser Art für den eigentlichen Produktionscode (Compiler schreiben in C/C++ hilft dabei, es portabel zu machen), aber ich könnte sehen, dass ich sie als Prototyping-Sprache benutze, besonders Python, zu dem ich teilweise tendiere. Natürlich habe ich das vorher noch nie gemacht, also kann ich es nicht sagen.

3

Was hat sich stark verändert hat, aber noch nicht ist IDE-Unterstützung und Interoperabilität genannt:

Heute wir ziemlich viel erwarten Intellisense, Schritt-für-Schritt-Ausführung und Zustand Inspektion „direkt im Editor-Fenster“, neu Typen, die dem Debugger mitteilen, wie sie behandelt werden sollen, und eher hilfreiche Diagnosemeldungen. Die alte ausführbare Datei "compile .x -> .y" reicht nicht aus, um eine Sprache zu erstellen. Die Umwelt ist zunächst nichts, auf das man sich konzentrieren muss, sondern beeinflusst die Bereitschaft zu adoptieren.

Auch Bibliotheken sind viel mächtiger geworden, niemand möchte all das in einer anderen Sprache implementieren. Versuchen Sie zu borgen, machen Sie es einfach, bestehenden Code aufzurufen, und machen Sie es leicht, von anderem Code aufgerufen zu werden.

Das Targeting einer VM - wie es itulson vorgeschlagen hat - ist wahrscheinlich ein guter Einstieg. Wenn sich daraus ein Problem ergibt, kann es trotzdem durch native Compiler ersetzt werden.

+2

"die alte 'kompilieren .x -> .y' ausführbare Datei ist ziemlich tot" - hahahaha! Erzähl mir einen anderen. Na los, das war großartig! –

+0

alex: wie in "alles was du für eine neue sprache brauchst ist ...", sollte ich das wohl klarstellen. – peterchen

-1

Mike -

Wenn Sie in einem effizienten nativen Code-Erzeugungs Compiler für Windows interessiert sind, so dass Sie Ihre Lager bekommen - ohne alle waten durch die unnötigen Widgets, Gadgets und anderen Unsinn, dass Unordnung die heutigen Maschinen - Ich empfehle das Plain English Entwicklungssystem des Osmosianischen Ordens. Es enthält eine einzigartige Schnittstelle, einen vereinfachten Dateimanager, einen freundlichen Texteditor, einen handlichen hexadezimalen Dumper, den Compiler/Linker (natürlich) und eine wysiwyg Seitenlayout-Anwendung für die Dokumentation. Vollständig in Plain English geschrieben, ist es ein schneller Download (weniger als ein Megabyte), klein genug, um in kurzer Reihenfolge zu verstehen (ungefähr 25.000 Zeilen Plain English Code mit nur 4.000 im Compiler/Linker), aber mächtig genug, um sich zu reproduzieren auf einem unteren Dell in weniger als drei Sekunden. Wirklich: drei Sekunden. Und es ist kostenlos für alle, die schreiben und um eine Kopie bitten, einschließlich des Quellcodes und eines ziemlich humorvollen 100-seitigen Handbuchs. Siehe www.osmosian.com für Details, wie eine Kopie zu bekommen, oder schreiben Sie mir direkt mit Fragen oder Anmerkungen: [email protected]

0

Natürlich sind immer noch ältere Techniken üblich (z.B. unter Verwendung von Flex und Bison) viele neuere Sprachimplementierungen kombinieren die Lexing- und Parsing-Phase, indem sie einen Parser verwenden, der auf einer Parsing Expression Grammatik (PEG) basiert. Dies funktioniert für rekursive Abstiegs-Parser, die mit Kombinatoren erstellt wurden, oder Memorys von Packrat-Parsern. Viele Compiler werden ebenfalls mit dem Antlr-Framework erstellt.

1

Nur um zu klären, ich meine, nicht, wie man eine Sprache entwirft (die ich ziemlich leicht herausfinden kann)

nur einen Hinweis: zuerst bei einigen ziemlich verschiedenen Sprachen suchen, bevor Entwerfen einer neuen Sprache (dh Sprachen mit einer sehr unterschiedlichen Bewertungsstrategie). Haskell und Oz in den Sinn kommen. Obwohl Sie auch Prolog und Scheme kennen sollten. Vor einem Jahr war ich auch wie "hey, lass uns eine Sprache entwerfen, die sich genau so verhält wie ich will", aber glücklicherweise habe ich zuerst diese anderen Sprachen angeschaut (oder du könntest auch unglücklich sagen, weil ich jetzt nicht weiß wie ich möchte, dass sich eine Sprache mehr benimmt ...).

1

Bevor Sie eine Sprache Beginn der Erstellung sollten Sie dies lesen:

Hanspeter Moessenboeck, die Kunst von Niklaus Wirth

ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe00b.pdf

+0

Niklaus Wirth war schrecklich im Compiler-Design. Er verstößt gegen Einsteins Gesetz: Mach alles so einfach wie möglich, aber nicht einfacher. Seine Sprachen waren einfach zu produktiv. Übrigens mag ich Modula3, die nicht von ihm entworfen wurde. – Lothar

0

Verwenden Bison/flex, die die GNU-Version von yacc/lex ist. Dies book is extremely helpful.

Der Grund für die Verwendung von Bison ist, dass es Konflikte in der Sprache fängt. Ich benutzte es und es machte mein Leben viele Jahre leichter (ok, also bin ich in meinem zweiten Jahr, aber die ersten 6 Monate waren vor ein paar Jahren in C++ geschrieben und die Parsing/Konflikte/Ergebnisse waren schrecklich! :(.)

0

Es gibt eine große Abkürzung ist eine Sprache zu implementieren, die ich hier nicht in den anderen Antworten sehen. Wenn Sie eines von Lukasiewiczs "ungeprüften" Formularen benutzen (zB Forward Polish oder Reverse Polish), brauchen Sie überhaupt keinen Parser! Bei der umgekehrten Politur gehen die Abhängigkeiten von rechts nach links, so dass Sie einfach jedes Token ausführen, während es gescannt wird. Beim Vorwärts-Polieren ist das Gegenteil der Fall, also führen Sie das Programm "rückwärts" aus und vereinfachen Teilausdrücke bis zum Start-Token.

Um zu verstehen, warum das funktioniert, sollten Sie die 3 primären Baum-Traversal-Algorithmen untersuchen: Vorbestellung, In-Reihenfolge, Nach-Bestellung. Diese drei Durchläufe sind die Umkehrung der Parsing-Aufgabe, die ein Sprachleser (i. Parser) ausführen muss. Nur die In-Order-Notation "benötigt" einen rekursiven Decent, um den Ausdrucksbaum neu zu konstruieren. Mit den anderen beiden kannst du nur mit einem Stapel davonkommen.

Dies kann mehr „Denken‘ und weniger ‚erfordern Umsetzung‘.

BTW, wenn Sie bereits eine Antwort gefunden (diese Frage ein Jahr alt ist), können Sie die Post und akzeptieren es.