1

Ich schreibe einen Compiler für eine Javascript-ähnliche Sprache zum Spaß. alias ich lerne über das Rad, also mache ich eins für mich und versuche, alles herauszufinden, aber jetzt bin ich steckengeblieben.Wie konvertiert man Methodenaufrufe in Postfix-Notation?

Ich weiß, dass Shunting Yard-Algorithmus ist eine nette, wenn einfache Infix Ausdrücke zu analysieren. Ich konnte herausfinden, wie man diesen Algorithmus auch auf Präfix- und Postfixoperatoren ausdehnt und auch einfache Funktionen parsen kann.

Zum Beispiel: 2+3*a(3,5)+b(3,5) verwandelt sich in 2 3 <G> 3 5 a() * + <G> 3 5 b() +

(<G> ein Wächter-Token ist, der auf den Stapel geschoben wird, wird es die Rückkehradressen usw. () wird der Anruf-Befehl, der die Funktion auf der Oberseite des Stapels ruft die

Wenn der Funktionsname nur ein Token ist, kann ich es einfach als Funktionssymbol markieren, wenn direkt von einer Klammer gefolgt wird. Wenn ich während des Prozesses auf ein Funktionssymbol stoße, schiebe ich es auf den Operator-Stack und öffne es, wenn ich mit der Konvertierung der Parameter fertig bin.

Dies funktioniert so weit.

Aber wenn ich die Option hinzufügen, um Elementfunktionen zu haben, der Operator .. Die Dinge werden komplizierter. Zum Beispiel möchte ich die a.b.c(12)+d.e.f(34) konvertieren Ich kann nicht c und f als Funktionen markieren, weil a.b.c und d.e.f Funktionen sind. Wenn ich meinen Parser auf einem Ausdruck wie diesem starte, wird das Ergebnis a b . <G> 12 c() . d e . <G> 34 f() . sein, was offensichtlich falsch ist. Ich möchte, dass es <G> 12 a b . c .() <G> 34 d e . f.() ist, die korrekt erscheint. Aber des Fluches kann ich die Dinge komplizierter machen, wenn ich einige Klammern hinzufüge: (a.b.c)(). Oder ich mache eine Funktion, die eine Funktion zurückgibt, die ich noch einmal anrufe: f(a,b)(c,d).

Gibt es einen einfachen Weg, diese heiklen Situationen zu bewältigen?

Antwort

0

Ein Problem Ihrer Vorgehensweise besteht darin, dass Sie Objekt und sein Element als zwei separate Token behandeln, die durch . getrennt sind. Klassischer Rangierbahnhofalgorithmus weiß nichts über OOP und beruht auf einem einzelnen Token für Funktionsaufruf. Der erste Weg, Ihr Problem zu lösen, besteht also darin, ein Token für einen Aufruf eines Objektelements zu verwenden - d. H. Das gesamte a.b.c muss ein einzelnes Token sein.

Sie können auch auf automatische Parser-Generatoren für eine andere Lösung Ihres Problems verweisen. Sie ermöglichen es, komplette Grammatik Ihrer Zielsprache (JavaScript) als eine Reihe von formalen Regeln zu definieren und Parser automatisch zu generieren. Liste der beliebtesten Tools enthält Tools, die Parser in verschiedenen Programmiersprachen generiert: ANTLR, Bison + Lex, Lemon + Ragel.


--artem

+1

'.' ist so viel von einem einzelnen Token ein Operator wie' + '. – delnan

+0

@ Delnan hat Recht. Wir sollten Punkt genau wie ein normaler Operator behandeln. – mahdix

0

(Ich sah diese Frage noch am Leben ist. Ich die Lösung für es selbst gefunden.)

Zuerst habe ich Bedrohung die (...) und [...] Ausdrücke wie ein Token und erweitern sie (rekursiv) bei Bedarf. Dann erkenne ich die Funktionsaufrufe und Array-Indizes. Wenn es vor einem eingeklammerten Token keinen Infix-Operator gibt, dann ist das ein Funktionsaufruf oder ein Array-Index, also füge ich dort eine spezielle Call-Funktion oder einen Zugriffsoperator ein. Mit dieser Modifikation funktioniert es wie Charme.

Verwandte Themen