Damit eine Sprache programmierbar ist, muss sie auf einer kontextfreien Grammatik basieren

23

Ist es für eine Sprache, die schließlich in Anweisungen auf Systemebene kompiliert / umgewandelt werden kann, praktisch erforderlich, dass es sich um eine kontextfreie Grammatik handelt?

Beispiel: Sind alle Programmier- / Skriptsprachen kontextfrei? Java basiert auf CFGs, aber ist es tatsächlich so, dass alle Programmiersprachen auf CFGs basieren?

Es scheint nicht obligatorisch, aber es gibt Lücken in meinem Verständnis.

Einiger Kontext für die Frage: Ich war auf der Suche auf Java - Sprachspezifikation, die auch die Grammatik liefert Regeln . Das hat mich über diese Frage nachdenken lassen.

sandeepkunkunuru
quelle
1
Im Allgemeinen denke ich, dass das Kompilierungsproblem nur berechenbar sein soll, und das Parsen von CFGs ist nett und einfach. Obwohl ich einige Behauptungen gehört habe, dass zum Beispiel das Erkennen gültiger Perl-Programme tatsächlich ein nicht berechenbares Problem ist.
Janne H. Korhonen
2
Eigentlich ist alles, was Sie wirklich brauchen, eine entscheidbare Syntax (die alle CFGs sind). Sie könnten auch könnte eine Programmiersprache , die deren Syntax machen ist nicht Turing-entscheidbar, aber wenn man ein Tippfehler - Compiler machen könnte nie stoppen , während es versucht , zu entscheiden , ob es eine gültige Syntax ist. das ist nicht wirklich nützlich
ratschenfreak 30.11.11
@ratchet, gehen Sie davon aus, dass die Syntax rekursiv aufzählbar sein muss?
David Harris
4
@JanneKorhonen: Insbesondere kann Perl nicht statisch analysiert werden, das heißt, es kann nicht analysiert werden, ohne auch ausgeführt zu werden. da diese Ausführung nicht beendet werden könnte, würde das statische Parsen von Perl das Beheben des Halteproblems bedeuten.
Jon Purdy
@janne Ich meine, nach der Vorverarbeitung, die Probleme mit sich bringen kann, die möglicherweise nicht berechenbar sind, ist es im Allgemeinen so, dass die endgültige Grammatik, anhand derer das Programm validiert wird, kontextfrei ist. Um genauer zu sein, müssen wir nach der Vorverarbeitung zur Identifizierung einer Regel, die zu einer Sequenz von Token passt, andere Token untersuchen, die die Sequenz umgeben. Ich weiß nicht, ob ich einen Sinn habe, tut mir leid. Eigentlich bin ich ein bisschen verwirrt.
Sandeepkunkunuru

Antworten:

20

Zweimal nein.

Erstens sind die meisten HPLs nicht kontextfrei. Während sie normalerweise eine Syntax haben, die auf einer CFG basiert, haben sie auch eine sogenannte statische Semantik (die auch häufig in der Begriffssyntax enthalten ist). Dies kann Namen und Typen beinhalten, die auf ein korrektes Programm überprüft werden müssen. Zum Beispiel,

class A {
  String a = "a";
  int b = a + d;
}

ist ein syntaktisch korrektes Java-Programm, wird jedoch nicht kompiliert, da des nicht definiert ist und akeinen passenden Typ hat.

Zweitens Sie können Sprachen analysieren , die nicht kontextfrei sind (wie offensichtlich durch die Existenz von Compilern bewiesen). Es ist nur so, dass CFGs effizient analysiert werden können, während CSGs dies im Allgemeinen nicht können. Sie können jedoch bestimmte nicht kontextfreie Funktionen hinzufügen, ohne die Effizienz zu beeinträchtigen.

Compiler werden häufig in Phasen ausgeführt: zuerst Tokenisierung (regulär), dann kontextfreies Parsen, dann Namens- und Typanalyse (kontextsensitiv, manchmal sogar schwieriger). Sie können dieses Verhalten anhand der Art der Fehlermeldungen beobachten, die Sie erhalten.

Raphael
quelle
3
Vergiss das nicht public class Program { public static void main(String[] args) { ... } }... Java wird dich nicht so leicht davonkommen lassen. :-)
Roy Tinker
Technisch gesehen class A { ... }ist dies völlig ausreichend, da javackompilierte Dateien auch nicht ausgeführt werden können (da kein Einstiegspunkt vorhanden ist). Aber ja.
Raphael
20

Das Parsen von Perl ist unentscheidbar.

http://www.jeffreykegler.com/Home/perl-and-und-undecidability/perl-and-undecidability-files/TPR3.pdf?attredirects=0

http://www.perlmonks.org/?node_id=663393

Niall Murphy
quelle
6
Ich denke, das sollte die Pointe eines Perl-Witzes sein :)
Suresh Venkat
5
Suresh: Ich habe diesen Witz bereits gemacht, obwohl er sich nicht als sehr guter Witz herausstellte, in der Veröffentlichung "Über unlexible Programmiersprachen" in SIGBOVIK 2011 ( sigbovik.org/2011/proceedings.pdf - Seite 79- 82).
Rob Simmons
1
Hinweis: Der Perl-Interpreter ist noch nicht deterministisch, wenn das für irgendjemanden ein Trost ist :)
Roy Tinker
15

Ich glaube nicht, dass Pythons Grammatik kontextfrei ist. Das Erfordernis, dass Zeilen in demselben Codeblock den gleichen Einrückungsgrad aufweisen, ist nicht das, was kontextfreie Grammatiken gut handhaben.

Genauer gesagt scheint es einen Homomorphismus aus der Sprache der Python-Blöcke der Form zu geben

wenn zustand:
     Linie 1
     Zeile 2
     line3
sonst:
     line4

0n10n10n

David Eppstein
quelle
4
Streng genommen haben Sie recht, aber im Kontext von Programmiersprachen versuchen wir, die Sprache, die nach einem Vorverarbeitungsschritt namens Tokenisierung entsteht , kontextfrei zu machen . Ich denke, die Einrückung wird vorher geprüft.
Diego de Estrada
7
Ja, der Python-Lexer (Tokenizer) verfügt über einen Stapel von Einrückungstiefen. Der Token-Stream hat am Anfang jedes Blocks ein INDENT-Symbol und am Ende ein DEDENT-Symbol, das kontextfrei analysiert werden kann (INDENT und DEDENT verhalten sich ähnlich wie die geschweiften Klammern in C). C hat das Problem "Kann nicht sagen, ob Deklaration oder Ausdruck": Ist foo * bar;eine Deklaration fooein Zeiger auf baroder eine Multiplikation von fooZeiten bar?
Max
8
Ok, klar, aber dann verstecken Sie nur die gleiche Komplexität im Lexer, anstatt ihn zu einem Wandler mit endlichen Zuständen zu machen, wie sie es oft sind.
David Eppstein
1
@ DavidEppstein: Um fair zu sein, sagte Komplexität ist keineswegs groß.
Jon Purdy
1
Abgesehen von der Handhabung von INDENT / DEDENT im Lexer verfügt Python über eine sehr einfache LL (1) -Grammatik.
rmmh
13

Bodo Manthey und Martin Böhme zeigen, dass jeder C ++ - Compiler unbedingt vollständig ist, das heißt, dass er zur Kompilierungszeit jede teilweise rekursive Funktion berechnen kann . Es ist also viel schlimmer als nur kontextsensitiv.

http://wwwhome.math.utwente.nl/~mantheyb/journals/BotEATCS_BoehmeManthey_CompilingCPP.pdf

Markus Bläser
quelle
Ja, aber Compiler sind niemals nur kontextfreie Grammatiken. Sie sollten die Grammatik selbst diskutieren, nicht den Compiler.
Jeff Burdges
@ Jeff: "Kompilierzeit" in meiner Antwort bedeutet "Überprüfen, ob ein gegebener C + -Quellcode korrekt ist". Durch eine geringfügige Änderung der Konstruktion in dem Papier folgt, dass Sie jede entscheidbare Sprache auf die Menge aller korrekten C ++ - Programme reduzieren können.
Markus Bläser
7

Ich denke, dass die Deklaration vor der Verwendung von Variablen und der Funktionspolymorphismus der OOP-Sprachen andere Beispiele für Programmiersprachenspezifikationen sind, die von kontextfreien Grammatiken nicht verarbeitet werden können:

int myfun(int a) { ... }
int myfun(int a, int b) { ... }
int myfun(int a, int b, int c, ...) { ... }
...
int I_m_I_cfg = myfun(1,2);
...

Ich machte eine kleine Google-Suche und fand diesen Artikel: " Eine boolesche Grammatik für eine einfache boolesche Sprache " von A.Okhotin (2004); Seiner Meinung nach besteht das eigentliche Problem darin, eine Programmiersprache zu finden, die vollständig durch eine formale Grammatik beschrieben wird:

Es wird eine prozedurale Programmiersprache für Spielzeug definiert und eine boolesche Grammatik für die Menge wohlgeformter Programme in dieser Sprache erstellt. Dies ist anscheinend die erste Spezifikation einer Programmiersprache vollständig durch eine formale Grammatik.

Der Einleitungsteil des Artikels ist kurz, aber sehr klar.

Marzio De Biasi
quelle
6

Ich glaube, dass Cs Grammatik nur technisch kontextfrei ist, da Parser immer nicht-kontextfreie Techniken verwenden, um Duffs Gerät zu unterstützen .

Einrückungsbasierte Sprachen sind natürlich auch nicht kontextfrei, wie David sagte, aber sie werden kontextfrei im Vergleich zu einem parametrisierten Einrückungs-Token.

Mit Haskell können Sie die Operatorrangfolge mit infix und infixl ändern. Perls striktes Pragma-Modul wird mit den lexikalischen Einstellungen $ ^ H und% ^ H implementiert, wodurch es nicht kontextfrei ist, wahrscheinlich auch mit anderen Einstellungen.

Es gibt Makro-Expander-Sprachen wie TeX, in denen afaik-Parsing ohne Ausführung keinen Sinn ergibt.

Es gibt wahrscheinlich sogar zwei kontextfreie Grammatiken, deren Schnittmenge nicht kontextfrei ist, aber dennoch eine Turing-Maschine beschreibt.

Java und Assembler sind wahrscheinlich beide von Natur aus kontextfrei.

Jeff Burdges
quelle
2
Macht die Mehrdeutigkeit von (a)-bC nicht kontextsensitiv? ( aDies kann eine Variable oder ein typedef sein. In einigen anderen Sprachen ist es aus diesem Grund nicht möglich, unäre Minus-Ausdrücke zu verwenden.)
Random832
Ich entschuldige mich für den sehr verspäteten Kommentar, aber Duffs Gerät enthält keine syntaktischen Abweichungen. Die Zahnspangen balancieren richtig. Die C-Funktion, die in Diskussionen darüber, ob C kontextfrei ist, am häufigsten ignoriert wird, ist der Präprozessor. Ich bin skeptisch, dass es eine wie auch immer informelle Interpretation von "kontextfrei" gibt, die es erlaubt, damit eine Sprache mit einem Makro-Prozessor zu beschreiben, selbst eine gut erzogene. Und der C-Präprozessor ist alles andere als brav.
rici
4

Nein, und viele praktische Sprachen sind nicht kontextfrei. Zum Beispiel ist C ++ - Grammatik keine, da in einigen Kontexten die Grammatikauflösung von der Eingabe von Informationen abhängt, die nicht kontextfrei sind.

antti.huima
quelle
4

Lassen Sie mich zunächst zwischen der Syntax einer Programmiersprache und der Sprache selbst unterscheiden.

Die Syntax vieler Sprachen basiert (zumindest auf) einer kontextfreien Grammatik (Context Free Grammar, CFG), da diese gut studiert sind und es Algorithmen gibt, die eine CFG effizient analysieren können und der Randfall, der von der CFG nicht gelöst werden kann, speziell behandelt werden kann

Tatsächlich sind jedoch viele Sprachen nicht kontextfrei (wenn vor der Verwendung deklarierte Symbole verwendet werden, z. B. in Java, C (++), D).

Unterhaltsame Tatsache: D hat eine Turing-vollständige Auswertung der Kompilierungszeitfunktion und eine Vorlagenerweiterung, die die Sprache selbst nicht von Turing entscheidbar macht. Der Schöpfer der Sprache unternahm jedoch große Anstrengungen, um die Syntax zu einer CFG zu machen.

Ratschenfreak
quelle
Die Namens- und Typanalyse führt normalerweise inhärent nicht-kontextfreie Aufgaben durch.
Raphael
Die Template-Metaprogrammierung in C ++ ist abgeschlossen.
Jeff Burdges
3

Was die "Sind alle Programmiersprachen / Skriptsprachen kontextfrei?" Teil betroffen ist, ist die Antwort ein klares Nein.

Betreff: Die Hauptfrage "für eine Sprache, die schließlich in Anweisungen auf Systemebene kompiliert / transformiert werden kann", ich weiß nicht, warum es notwendigerweise eine CFG sein muss. Es könnte jedoch bessere Erklärungen geben.

Kris
quelle
1
Kris, kannst du einige Beispiele für nicht-kontextfreie grammatikbasierte Programmiersprachen nennen? Ich meine, Nachbearbeitung, die Probleme mit sich bringen kann, die möglicherweise nicht berechenbar sind, die endgültige Grammatik, anhand derer das Programm validiert wird.
Sandeepkunkunuru
3

Eine Programmiersprache muss auf einer Art Grammatikformalismus basieren, wofür CFGs ein Beispiel sind. Während CFGs am häufigsten vorkommen (und in Compilerkursen an Universitäten üblich sind), gibt es andere Formalismen wie das Parsen von Ausdrucksgrammatiken, über die Sie hier mehr lesen können (pdf) oder auf Wikipedia, um mehr Informationen zu erhalten.

evilcandybag
quelle