Es ist keine dumme Frage. Es ist eine ausgezeichnete Frage.
Wie bereits beantwortet, lautet die kurze Antwort "Eine andere Sprache".
Nun, das führt zu einigen interessanten Fragen? Was ist, wenn es die allererste Sprache ist, die für Ihre spezielle Hardware geschrieben wurde? Ein sehr reales Problem für Leute, die an eingebetteten Geräten arbeiten. Wie bereits geantwortet "eine Sprache auf einem anderen Computer". Tatsächlich erhalten einige eingebettete Geräte niemals einen Compiler, ihre Programme werden immer auf einem anderen Computer kompiliert.
Aber Sie können es noch weiter zurückschieben. Was ist mit den ersten Programmen, die jemals geschrieben wurden?
Nun, die ersten Compiler für "Hochsprachen" wären in der sogenannten "Assemblersprache" geschrieben worden. Assemblersprache ist eine Sprache, in der jeder Befehl in der Sprache einem einzelnen Befehl an die CPU entspricht. Es ist eine sehr niedrige Sprache und extrem ausführlich und sehr arbeitsintensiv zu schreiben.
Aber selbst das Schreiben von Assemblersprache erfordert ein Programm namens Assembler, um die Assemblersprache in "Maschinensprache" zu konvertieren. Wir gehen weiter zurück. Die allerersten Assembler wurden in "Maschinencode" geschrieben. Ein Programm, das ausschließlich aus Binärzahlen besteht, die eine direkte Eins-zu-Eins-Entsprechung mit der Rohsprache des Computers selbst darstellen.
Aber es hört immer noch nicht auf. Selbst eine Datei mit nur rohen Zahlen darin noch übersetzt werden. Sie müssen diese Rohzahlen noch in einer Datei auf den Computer übertragen.
Ob Sie es glauben oder nicht, die frühen Computer hatten eine Reihe von Schaltern an der Vorderseite. Sie haben die Schalter umgelegt, bis sie eine Binärzahl darstellen, dann haben Sie einen anderen Schalter umgelegt und diese einzelne Zahl in den Computerspeicher geladen. Dann schalteten Sie weiter um, bis Sie ein minimales Computerprogramm geladen hatten, das Programme von Datenträgerdateien oder Lochkarten lesen konnte. Sie haben einen anderen Schalter umgelegt und das Programm gestartet. Als ich in den 80er Jahren zur Universität ging, sah ich Computer, die diese Kapazität hatten, aber nie den Auftrag erhielten, ein Programm mit den Schaltern zu laden.
Und noch früher mussten Computerprogramme mit Steckdosen fest verdrahtet werden !
Die häufigste Antwort ist
C
. Die meisten Sprachen sind in C oder in einem Hybrid aus C mit Rückrufen und einem "Lexer" wie Flex und einem Parser-Generator wie YACC implementiert . Dies sind Sprachen, die für einen Zweck verwendet werden - um die Syntax einer anderen Sprache zu beschreiben. Wenn kompilierte Sprachen verwendet werden, werden sie manchmal zuerst in C implementiert. Dann wird die erste Version der Sprache verwendet, um eine neue Version zu erstellen, und so weiter. (Wie Haskell .)quelle
Viele Sprachen werden gebootet - das ist in sich selbst geschrieben . Warum Sie dies tun möchten, ist oft eine gute Idee, Ihr eigenes Hundefutter zu essen .
Der Wikipedia-Artikel, auf den ich mich beziehe, behandelt das Henne-Ei- Problem. Ich denke, Sie werden es ziemlich interessant finden.
quelle
So ziemlich jede Sprache, obwohl die Verwendung einer Sprache, die für die Arbeit mit Grafiken und anderen komplexen Datenstrukturen geeignet ist, viele Dinge einfacher macht. Produktionscompiler werden aus Leistungsgründen häufig in C oder C ++ geschrieben, aber Sprachen wie OCaml, SML, Prolog und Lisp eignen sich wahrscheinlich besser für das Prototyping der Sprache.
Es gibt auch mehrere "kleine Sprachen", die im Sprachdesign verwendet werden. Lex und yacc werden beispielsweise zum Festlegen von Syntax und Grammatik verwendet und zu C kompiliert. (Es gibt Ports für andere Sprachen wie ocamllex / ocamlyacc und viele andere ähnliche Tools.)
Als Sonderfall werden neue Lisp-Dialekte häufig auf vorhandenen Lisp-Implementierungen aufgebaut, da sie auf den meisten derselben Infrastruktur huckepack nehmen können. Das Schreiben eines Scheme-Interpreters kann in Scheme unter einer Codeseite erfolgen. An diesem Punkt können problemlos neue Funktionen hinzugefügt werden.
Grundsätzlich sind Compiler nur Programme, die etwas einlesen und in etwas anderes übersetzen - Konvertieren der LaTeX-Quelle in DVI, Konvertieren von C-Code in Assembler und dann in Maschinensprache, Konvertieren einer Grammatikspezifikation in C-Code für einen Parser usw. Der Designer gibt dies an die Struktur des Quellformats (Parsing), was diese Strukturen bedeuten, wie die Daten vereinfacht werden (Optimierung) und die Art der zu generierenden Ausgabe. Dolmetscher lesen die Quelle und führen sie direkt aus. (Dolmetscher sind normalerweise einfacher zu schreiben, aber viel langsamer.)
quelle
Eigentlich können Sie in fast jeder Sprache schreiben, die Sie möchten. Nichts hindert Sie daran, einen C-Compiler in Ruby zu schreiben. "Alles", was Sie tun müssen, ist das Programm zu analysieren und den entsprechenden Maschinencode auszugeben. Wenn Sie Dateien lesen / schreiben können, wird Ihre Programmiersprache wahrscheinlich ausreichen.
Wenn Sie auf einer neuen Plattform von vorne anfangen, können Sie Cross-Compiling durchführen: Schreiben Sie einen Compiler für Ihre neue Plattform, der in Java oder nativ auf x86 ausgeführt wird. Entwickeln Sie auf Ihrem PC und übertragen Sie das Programm dann auf Ihre neue Zielplattform.
Die grundlegendsten Compiler sind wahrscheinlich Assembler und C.
quelle
"Eine neue Programmiersprache schreiben" beinhaltet technisch gesehen keinen Code. Es wird lediglich eine Spezifikation erstellt, wie Ihre Sprache aussieht und wie sie funktioniert. Sobald Sie eine Vorstellung davon haben, wie Ihre Sprache ist, können Sie Übersetzer und Dolmetscher schreiben, damit Ihre Sprache tatsächlich "funktioniert".
Ein Übersetzer gibt ein Programm in einer Sprache ein und gibt ein gleichwertiges Programm in einer anderen Sprache aus. Ein Interpreter gibt ein Programm in einer bestimmten Sprache ein und führt es aus.
Beispielsweise übersetzt ein C-Compiler normalerweise C-Quellcode (die Eingabesprache) in ein Assembler-Programm (die Ausgabesprache). Der Assembler nimmt dann das Assemblersprachenprogramm und erzeugt die Maschinensprache. Sobald Sie Ihre Ausgabe haben, brauchen Sie die Übersetzer nicht mehr, um Ihr Programm auszuführen. Da Sie jetzt ein Maschinensprachenprogramm haben, fungiert die CPU als Interpreter.
Viele Sprachen sind unterschiedlich implementiert. Ist beispielsweise
javac
ein Übersetzer, der Java-Quellcode in JVM-Bytecode konvertiert. Die JVM ist ein Interpreter [1], der Java-Bytecode ausführt. Nachdem Sie ausgeführt habenjavac
und Bytecode erhalten haben, brauchen Sie nichtjavac
mehr. Wenn Sie jedoch Ihr Programm ausführen möchten, benötigen Sie die JVM.Die Tatsache, dass Übersetzer nicht in der Nähe gehalten werden müssen, um ein Programm auszuführen, ermöglicht es, Ihre Sprache zu "booten", ohne dass sie "über" Ebenen und Ebenen anderer Sprachen ausgeführt wird.
[1] Die meisten JVMs übersetzen hinter den Kulissen, aber sie sind keine wirklichen Übersetzer, da die Schnittstelle zur JVM nicht "Eingabesprache -> Ausgabesprache" ist.
quelle
Im Allgemeinen können Sie fast jede Sprache verwenden, die Sie mögen. PHP wurde zum Beispiel in C geschrieben. Wenn Sie überhaupt keinen Zugriff auf einen Compiler haben, müssen Sie Assemblersprache schreiben und diese manuell in Maschinencode kompilieren.
quelle
Viele Sprachen wurden zuerst in einer anderen verfügbaren Sprache geschrieben und dann in sich selbst neu implementiert und auf diese Weise gebootet (oder nur die Implementierung in der Fremdsprache beibehalten, wie PHP und Perl), aber einige Sprachen, wie der erste Assembler, wurden von Hand zu Maschinencode wie kompiliert Der erste C-Compiler wurde von Hand zur Montage kompiliert.
Ich habe mich für Bootstrapping interessiert, seit ich darüber gelesen habe. Um mehr zu erfahren, habe ich versucht, es selbst zu tun, indem ich meine eigene Obermenge von BF, die ich EBF nannte , selbst geschrieben habe. Die erste Version von EBF hatte 3 zusätzliche Grundelemente und ich habe die erste Binärdatei von Hand kompiliert. Dabei fand ich einen zweistufigen Rhythmus. Ich habe eine Funktion in der aktuellen Sprache in einer Version implementiert und hatte eine süße Version, in der ich den Code neu geschrieben habe, um die implementierte Funktion zu nutzen. Die Sprache war ausdrucksstark genug, um einen LISP-Interpreter zu erstellen .
Ich habe die handkompilierte Version zusammen mit der Quelle im ersten Release-Tag und der Code ist ziemlich klein. Die letzte Version ist 12-mal größer und der Code und ermöglicht kompakteren Code, sodass es schwierig ist, die aktuelle Version von Hand zu kompilieren.
Edmund Grimley Evans hat mit seiner HEX-Sprache etwas Ähnliches gemacht
Eines der interessanten Dinge dabei ist, dass Sie verstehen, warum manche Dinge so sind, wie sie sind. Mein Code war ein Produkt, wenn kleine inkrementelle Anpassungen vorgenommen wurden und es eher so aussieht, als ob es sich weiterentwickelt hat, als dass es von Grund auf neu entwickelt wurde. Ich denke daran, wenn ich heute Code lese, der meiner Meinung nach ein wenig anders aussieht.
quelle
Normalerweise mit einer für die Systementwicklung geeigneten allgemeinen Programmiersprache, z. B. C, Haskell, ML, Lisp usw., aber die Liste der Optionen ist lang. Außerdem normalerweise mit einigen domänenspezifischen Sprachen für die Sprachimplementierung, z. B. Parser- und lexikalischen Analysatorgeneratoren, Zwischensprachen wie LLVM usw. Und wahrscheinlich einigen Shell-Skripten, Testframeworks und einem Build-Konfigurationssystem, z. B. Autoconf.
quelle
Die meisten Compiler haben C- oder AC-ähnliche Programme geschrieben, wenn nicht C, dann ist Assembly Lang der richtige Weg. Wenn Sie jedoch eine neue Sprache von Grund auf neu schreiben und keine Makro-Bibliothek oder keinen Quellcode aus einer Prototypsprache haben, müssen Sie Ihre eigenen Funktionen definieren Jetzt in welcher Sprache? Sie können einfach eine Form "des Quellcodes mit dem Namen psedocode auf die Maschine schreiben, die wie eine BNF-Grammatik aus der objektorientierten strukturierten Lang-Spezifikation wie Fortran Basic Algo Lisp aussieht. Schreiben Sie also einen Cross-Code, der einer dieser Sprachsyntaxen ähnelt. Das ist Psedo-Code
quelle
Noch weitere Binär- oder Assemblyoperationen müssen in Funktionen übersetzt werden, dh in den Assembler- / Compiler-Job und dann in ein Objekt aus Daten und Funktionen, wenn Sie keine Quelldatei haben, um zu sehen, "wie diese Objektfunktionalität in Ihrer dargestellt werden soll." Sprachimplementierung, Dann müssen Sie die Implementierung "sehen" erkennen oder Ihre eigenen Funktionen, Prozeduren und Datenstrukturen definieren. Was viel Wissen erfordert, müssen Sie sich fragen, was eine Funktion ist. Ihr Verstand wird dann zur Sprachsimulation. Dies trennt einen Master-Programmierer vom Rest.
quelle
Auch ich hatte diese Frage vor einigen Monaten. Und ich habe nur wenige Artikel gelesen und mir einige Videos angesehen, die mir geholfen haben, meine eigene Sprache namens soft zu schreiben. Es ist noch nicht vollständig, aber ich habe viel von dieser Reise gelernt.
Grundlegende Dinge, die Sie wissen sollten, sind, wie der Compiler funktioniert, wenn er ein Code-Snippet ausführen muss. Der Compiler hat viele Phasen wie lexikalische Analyse, semantischer Analysator, AST (Abstract Syntax Tree) usw.
Was ich in meiner neuen Sprache getan habe, finden Sie hier - http://www.singhajit.com/writing-a-new-programming-language/
Wenn Sie zum ersten Mal eine Sprache schreiben, dann alles Gute und Sie haben noch einen langen Weg vor sich.
quelle
Was sind Programmiersprachen im Allgemeinen?
Programmiersprachen sind nur eine Möglichkeit, mit Computern zu sprechen. Zunächst grob gesagt, weil Computer nur Nullen und Einsen verstehen konnten (aufgrund der Tatsache, dass Computer aus Transistoren als Schalter bestehen, die nur zwei Zustände annehmen können, nennen wir diese beiden Zustände 0 und 1) und es schwierig war, mit 0,1 zu arbeiten Da wir Menschen Menschen sind, haben Informatiker beschlossen, eine Eins-zu-Eins-Zuordnung von jeder Anweisung in Binär (0,1) zu einer besser lesbaren Form vorzunehmen, die sie Assemblersprache nannten.
Zum Beispiel, wenn wir eine Anweisung hatten wie:
11001101
in der Montage würde es heißen:
LOAD_A 15
was bedeutet, dass der Inhalt von Register a in Speicherplatz 15 geladen wird. Wie gesagt, es war nur eine Konvention wie die Auswahl von 0 und 1 für zwei Zustände der Transistoren oder irgendetwas anderes im Computer. Auf diese Weise hat man ein Programm mit 50 Anweisungen. Das Erinnern an die Assemblersprache wäre einfacher. Der Benutzer würde also den Assembler-Code schreiben und ein Programm (in diesem Fall Assembler) würde die Codes in binäre Anweisungen oder Maschinensprache übersetzen, wie sie es nennen.
Aber dann, da die Computer jeden Tag verbessert wurden, gab es Platz für kompliziertere Programme mit mehr Anweisungen, sagen wir 10000.
In diesem Fall würde eine Eins-zu-Eins-Zuordnung wie Assembly nicht funktionieren, sodass andere Programmiersprachen auf hoher Ebene erstellt wurden. Sie sagten zum Beispiel, wenn für eine Beziehung mit E / A-Geräten zum Drucken von etwas auf dem vom Benutzer erstellten Bildschirm etwa 80 Anweisungen erforderlich sind, lassen Sie uns hier etwas tun, und wir könnten den gesamten Code in eine Bibliothek packen und ihn beispielsweise printf aufrufen und erstellen Sie auch ein anderes Programm, das diesen Ausdruck hier in den zugehörigen Assemblycode übersetzen könnte, und von dort aus würde die Assembly den Rest erledigen. Also nennen sie es Compiler.
Jetzt muss jeder Benutzer, der nur etwas auf dem Bildschirm drucken möchte, nicht alle Anweisungen in Binär- oder Assembly-Form schreiben. Er gibt nur printf ("etwas") ein, und alle Programme wie der Compiler und der Assembler erledigen den Rest. Jetzt später werden andere längere Codes auf die gleiche Weise verpackt, um nur die Arbeit anderer zu erleichtern, da Sie sehen, dass Sie einfach eine Tausend-Code-Zeile in einem Code in Python vereinfachen und für die Verwendung durch andere Personen packen können.
Nehmen wir also an, Sie haben viele verschiedene Codes in Python gepackt und ein Modul erstellt (libray, package oder irgendetwas, das Sie aufrufen möchten), und Sie nennen dieses Modul mgh (nur meinen Namen). Nehmen wir jetzt an, wir haben dieses mgh irgendwie erstellt, dass jeder, der sagt:
könnte leicht eine Verbindung zu einem Remote-Server mit der angegebenen IP- und Portnummer herstellen und die Daten anschließend senden (oder so ähnlich). Jetzt könnten die Leute alles mit einer einzigen Zeile machen, aber was passiert, ist, dass viele Codes ausgeführt werden, die aus der mgh-Datei abgerufen wurden. und das Verpacken diente nicht dazu, den Ausführungsprozess zu beschleunigen, sondern anderen Programmierern die Arbeit zu erleichtern. Wenn also hier jemand zuerst Ihren Code verwenden möchte, sollte er die Datei importieren, und dann erkennt der Python-Interpreter den gesamten darin enthaltenen Code und kann den Code interpretieren.
Wenn Sie nun eine Programmiersprache erstellen und ausführen möchten, muss zunächst eine Übersetzung erstellt werden. Nehmen wir beispielsweise an, Sie erstellen ein Programm, das die Syntax verstehen und in c konvertieren kann, in diesem Fall nach der Übersetzung bis c würde der Rest vom c-Compiler erledigt, dann vom Assembler, Linker, .... obwohl Sie den Preis dafür zahlen müssten, langsamer zu sein, da es zuerst in c konvertiert werden muss.
Jetzt können Sie auch ein Programm erstellen, das den gesamten Code in die entsprechende Assemblersprache übersetzt, genau wie dies bei c der Fall ist. In diesem Fall kann das Programm dies jedoch direkt tun, und von dort aus wird der Rest von der erledigt Linker. Wir wissen, dass dieses Programm Compiler heißt.
Ich spreche also davon, dass der einzige Code, den das System versteht, 0,1 ist. Sie sollten also irgendwie Ihre Syntax darauf umstellen, jetzt haben in unseren Betriebssystemen viele verschiedene Programme wie Assembler, Linker und ... wurde erstellt, um Ihnen mitzuteilen, dass Sie den Rest erledigen könnten, wenn Sie Ihren Code in Assembly konvertieren könnten, oder wie gesagt, Sie könnten sogar andere Programmiersprachen-Compiler verwenden, indem Sie Ihren Code in diese Sprache konvertieren.
quelle