Gibt es Programmierung (oder Scripting) Sprache (oder eine domänenspezifische Sprache) mit zwei binären Operatoren opl
und opr
der gleichen Priorität mit opl
Linksassoziativität werden und opr
rechtsassoziativ sein?
(Ich kann ein solches Beispiel nicht finden, aber ich versuche, einen Parser allgemein genug zu codieren, um diesen seltsamen Fall zu behandeln.)
Wie würden Ausdrücke der Form x opl
y opr
z oder x opr
y opl
z analysiert? Und allgemeiner mit noch mehr Operanden?
language-design
parsing
Basile Starynkevitch
quelle
quelle
x <@ y @> z
mit<@
gelassen werden assoziativ und@>
sein rechtsassoziativ, GHC gibt Ihnen einen „Präzedenz - Parsing - Fehler“: „kann nicht mischen‚<@
‘[infixl 0] und‚@>
‘[infixr 0] in dem gleichen Infix Ausdruck“ (wo ich definierte diese Operatoren auf Ebene 0 für das Beispiel).if_then_else_
oder[1;2;3]
definiert werden sollen?).Antworten:
Hier sind drei Sprachen, mit denen Sie Ihre eigenen Operatoren definieren können, die zweieinhalb verschiedene Dinge tun ! Haskell und Coq verbieten beide diese Art von Spielereien - aber unterschiedlich -, während Agda diese Art der Vermischung von Assoziativitäten zulässt.
Erstens dürfen Sie dies in Haskell einfach nicht tun. Sie können Ihre eigenen Operatoren definieren und ihnen den Vorrang (von 0 bis 9) und die Assoziativität Ihrer Wahl geben. Der Haskell-Bericht verbietet Ihnen jedoch, Assoziativitäten zu mischen :
Wenn wir also in GHC einen linksassoziativen (
infixl
) Operator<@
und einen rechtsassoziativen Operator@>
auf derselben Prioritätsstufe definieren - sagen wir 0 -,x <@ y @> z
ergibt die Auswertung den Fehler(Tatsächlich können Sie einen Operator auch als Infix deklarieren, aber nicht assoziativ
==
, so dass diesx == y == z
ein Syntaxfehler ist!)Auf der anderen Seite gibt es den abhängig typisierten Sprach- / Theorembeweiser Agda (der zugegebenermaßen wesentlich weniger Mainstream ist). Agda hat einige der formbarsten Syntax aller mir bekannten Sprachen und unterstützt Mixfix- Operatoren: Die Standardbibliothek enthält die Funktion
was, wenn es aufgerufen wird, geschrieben wird
mit den Argumenten, die die Unterstriche ausfüllen! Ich erwähne dies, weil dies bedeutet, dass es unglaublich flexibles Parsen unterstützen muss. Natürlich Agda hat auch fixity Erklärungen (obwohl seine Prioritätsebenen über beliebige natürliche Zahlen reichen, und sind in der Regel in 0-100), und Agda macht Sie erlauben Operatoren gleicher Priorität zu mischen , aber unterschiedliche fixities. Ich kann jedoch keine Informationen dazu in der Dokumentation finden, also musste ich experimentieren.
Lassen Sie uns unsere
<@
und@>
von oben wiederverwenden . In den beiden einfachen Fällen haben wirx <@ y @> z
Parsen alsx <@ (y @> z)
; undx @> y <@ z
Analyse als(x @> y) <@ z
.Ich denke, was Agda tut, ist, die Zeile in "linksassoziative" und "rechtsassoziative" Blöcke zu gruppieren, und - wenn ich nicht über falsche Dinge nachdenke - erhält der rechtsassoziative Block "Priorität" beim Ergreifen der benachbarten Argumente. Das gibt uns also
Analyse als
oder
Trotz meiner Experimente habe ich beim ersten Schreiben falsch geraten, was lehrreich sein könnte :-)
(Und Agda hat wie Haskell nicht assoziative Operatoren, die Analysefehler korrekt angeben, sodass gemischte Assoziativitäten auch zu einem Analysefehler führen können.)
Schließlich gibt es noch die Satzbeweis- / abhängig typisierte Sprache Coq , die eine noch flexiblere Syntax als Agda aufweist, da ihre Syntaxerweiterungen tatsächlich implementiert werden, indem Spezifikationen für die neuen syntaktischen Konstrukte angegeben und diese dann in die Kernsprache umgeschrieben werden (vage makroähnlich) , Schätze ich). In Coq ist die Listensyntax
[1; 2; 3]
ein optionaler Import aus der Standardbibliothek. Neue Syntaxen können sogar Variablen binden!Wiederum können wir in Coq unsere eigenen Infix-Operatoren definieren und ihnen Vorrangstufen (meistens von 0 bis 99) und Assoziativitäten zuweisen. In Coq kann jedoch jede Prioritätsstufe nur eine Assoziativität haben . Wenn wir also
<@
als linksassoziativ definieren und dann versuchen,@>
auf derselben Ebene - sagen wir 50 - als rechtsassoziativ zu definieren , erhalten wirDie meisten Operatoren in Coq befinden sich auf Ebenen, die durch 10 teilbar sind. Wenn ich Assoziativitätsprobleme hatte (diese Assoziativitäten sind global), habe ich die Ebene im Allgemeinen nur um eins in beide Richtungen erhöht (normalerweise nach oben).
quelle
graphviz
\ttfamily \Tree[.<@ [.<@ [.<@ a b ] [.@> c [.@> d [.@> e f ]]]] g ]
.Seit sie von Douglas Crockford populär gemacht wurden, sind Pratt Parsers (oder Top-Down Operator Precedence Parser) immer häufiger geworden. Diese Parser arbeiten anhand einer Tabelle mit Operatorrang und Assoziativität, anstatt die Regeln in eine feste Grammatik zu integrieren. Sie sind daher hilfreich für Sprachen, mit denen Benutzer ihre eigenen Operatoren definieren können.
Sie haben eine Analysefunktion, die funktioniert, indem zuerst der am weitesten links stehende Term eines Ausdrucks analysiert und dann rekursiv neue Operatoren und Begriffe für die rechte Hand gebunden werden, solange sie ordnungsgemäß binden. Linksassoziative Operatoren binden Begriffe der rechten Hand, die Vorrang bis einschließlich derselben Priorität haben, während rechtsassoziative Operatoren nur bis zu ihrer Vorrangstufe binden, diese jedoch nicht einschließen. Ich glaube, dies führt zu demselben Analysebaum wie für Agda, der oben zitiert wurde.
quelle