2012-07-01 7 views
5

Ich versuche, eine Sprache zu analysieren, in der die Operatoren über den Menhir-Parser (ähnlich wie Ocamlyacc) dynamische Attribute (Priorität und Priorität) haben. Während der Lexing-Phase füllen alle Operatoren einen OP:string Token (so wird "+" zu (OP "+") usw.).Angeben einer dynamischen Priorität und Rangfolge für einen Operator in Menhir/Ocamlyacc

Die Operatorattribute werden zur Analysezeit bestimmt und füllen eine Tabelle, die Operatoren und ihre Attribute zuordnet. Wie kann ich Menhir anweisen, die Priorität der Regel, die die Operatoren analysiert, anhand der Daten dieser Tabelle dynamisch zu ändern?

Danke, CharlieP.

Antwort

10

Es tut mir leid, dass ich mit einem Kommentar "du machst es falsch" geantwortet hast. Ich habe drei Einwände Ich hoffe sind konstruktiv, nach Relevanz geordnet in abnehm:

  1. Menhir ist nicht für dynamische Grammatik Updates gemeint; Wenn Sie darauf bestehen, Ihre Grammatik während der Analyse zu ändern, sollten Sie ein Werkzeug verwenden, das diese Funktion bietet, wie den GLR-Parser Dypgen. Das Dypgen-Handbuch erwähnt die Möglichkeit, Operatorprioritäten dynamisch zu aktualisieren (es scheint, dass Sie neue Operatoren und entsprechende Prioritäten hinzufügen können, aber die Priorität bestehender nicht ändern), die Ihren Anforderungen entsprechen oder nicht entsprechen können. Siehe Abschnitt 6.6 der Dypgen manual (PDF), Seite ... 42.

  2. Das dynamische Aktualisieren einer CFG-Grammatik ist meiner Meinung nach nicht der beste Weg, um benutzerdefinierte Operator-Präzedenzfälle zu behandeln. Agda hat sehr allgemeine benutzerdefinierte mixfix-Operatoren, und ihre Lösung ist ungefähr die folgende: Verwenden Sie Ihren CFG-Parser, um die statisch bekannte grammatische Struktur zu analysieren, aber für Ausdrücke, die fiktive Präzedenzfälle und Assoziativitäten verwenden, parsen Sie sie einfach in eine Liste von Token. Zum Beispiel würde let x = if foo then x + y * z else bar in etwas wie Let(x, If(foo, Expr(x, +, y, *, z), bar) geparst werden. Ein späterer spezialisierter Durchlauf kann die erforderlichen Informationen sammeln, um diese nach Expr Knoten in ihre spezialisierte Struktur zu posten. Verwenden Sie Parser-Generatoren für das, wofür sie gut sind (statisch bekannte Rich-CFGs), und verwenden Sie einen Post-Processing-Pass für das komplexe, schlecht definierte, dynamische Zeug. Die Agda Jungs haben einige Literatur zu diesem Thema, zum Beispiel Parsing Mixfix Operators, Danielsson und Norell, 2009.

    Aus einem Design-Sicht, ich fordere Sie dringend, trennen Sie Ihre lexing und Parsing in mehreren verschiedenen Durchgängen, jeder von ihnen gut -definiert und verwendet nur Informationen aus der vorherigen Struktur, anstatt zu versuchen, sein eigenes Verhalten dynamisch zu ändern. Sie werden etwas viel einfacheres und viel robuster haben.

  3. Dynamische oder benutzerdefinierte Priorität und Prioritäten sind meiner Meinung nach ein bisschen böse. OCaml hat ein anderes System, bei dem Prioritäten für Operatorenprioritäten durch ihre ersten Zeichen bestimmt werden (z. B. @, @@ und sind alle rechtsassoziativ). Es ist ein wenig restriktiv für die Leute, die einen Infix-Operator wählen, aber macht Code Leser lebt viel bequemer, da sie nur einen Satz von Grammatikregeln zu lernen haben, anstatt ihre Augen dynamisch an jedes neue Stück Code anpassen zu müssen . Wenn Sie wilde, fremde Codeteile mit einer völlig anderen Syntax einfügen möchten, sind Zitationsmechanismen (z. B. camlp4 <:foo<...>>) viel robuster als das Herumspielen mit Assoziativitäten und Prioritäten auf Operatorebene und auch viel einfacher zu parsen.

    Das sagte, Projekte haben unterschiedliche Bedürfnisse und ich würde völlig verstehen, wenn Sie darauf bestanden haben, Operatoren Präzedenzfall und Assoziativität für einige Anwendungen, die ich nicht weiß dynamisch ändern.Bedenken Sie, dass es nicht der einzige Weg ist, und manchmal sind Konsistenz und Einfachheit besser als absolute Flexibilität.

Verwandte Themen