Registriert seit: 3. Jan 2006
509 Beiträge
Delphi 7 Enterprise
|
Parser: Überladene Operatoren
1. Mai 2013, 22:32
Hallo!
Ich programmiere gerade an einem Parser und ich stehe bei den überladenen Operatoren ziemlich auf dem Schlauch. Zum Beispiel der Operator "-" ist ja normalerweise überladen: Sowohl "a-b" als auch "a*(-b)" ist möglich. Beim ersten hab ich Argumente auf beiden Seiten und beim zweiten nur eins auf der rechten Seite. Ein anderes Beispiel wäre "x!" und "!x" (Fakultät und Subfakultät). Theoretisch sind also überladene Operatoren möglich, die alle drei Möglichkeiten ausschöpfen: Argument links, rechts und auch auf beiden Seiten.
Dazu kommt noch dass Operatoren wegen dem Datentyp überladen sein können, zB "True and False = False" und "1 and 3 = 1".
Und dann können bestimmte Datentypen noch implizit in andere umgewandelt werden. Das bedeutet, wenn ich ein Gleitkommazahl-Plus definiere: 1,2 + 3,4 = 4,6 dann kann ich dieses + auch für Ganzzahlen benutzen: 1 + 2 wird dank impliziter Datentypumwandlung zu 1,0 + 2,0 = 3,0.
Das bedeutet wenn ich z.B 5 Datentypen habe könnte ein einziger Operator aus 5 + 5 + 5^2 = 35 Überladungen bestehen! Und jede Überladung könnte ihren eigenen Rang haben (mit Rang meine ich die Rangfolge von Operatoren wie z.B "Punkt vor Strich").
Angenommen ich habe nur solche Psycho-Operatoren (davon muss ich ja ausgehen wenn ich ein fehlerfreies Programm haben möchte), wie soll ich dann vorgehen???
1 Op Op Op 1 = (((1 Op) Op) Op 1) oder (1 Op (Op (Op 1))) oder ((1 Op) Op (Op 1))
Und dummerweise entstehen auch Möglichkeiten wie:
(1 Op) (Op (Op 1)) die dann zu einem Fehler führen
Ich habe mir überlegt, dass zur Auswahl des Operators in erster Linie der Datentyp entscheiden sollte (und nicht der Rang). Angenommen ich definiere String-Plus (String + String = String) und ein Int-Plus (Int + Int = Int) wobei das String-Plus einen höheren Rang hat als das Int-Plus. Dann würde wenn der Rang entscheidet sobald das +Zeichen auftaucht immer das String-Plus verwendet werden und z.B 1+2 würde zu einem Fehler führen.
Und genau das macht das ganze so schwer (bzw. unmöglich?).
Meine Grundvoraussetzung ist eine klammerlose Reihe von Operatoren und Zahlen (alles andere wurde im Schritt zuvor zu Zahlen reduziert).
Also z.B: Op Op Op 1 Op Op Op 2 Op Op Op (das ist zwar kein praktikables Beispiel aber durchaus ein korrektes, selbst wenn Op immer für denselben Operator steht)
Ein großes Problem hier ist, dass ein Operator nicht zwingend nur einen Typ benutzt. Es ist z.B auch ein solcher Operator möglich: Int Op Boolean = String.
Das bedeutet wenn ich folgenden Ausdruck habe
Op 1 Op
habe ich schon ein Problem.
angenommen Op 1 ist definiert als Op Int = Float und 1 Op als Int Op = Int. Dann wäre es von den Datentypen her sinnvoller ich rechne Op (1 Op) statt (Op 1) Op.
Und erst richtig unüberschaubar wird es bei vorherigem Beispiel Op Op Op 1 Op Op Op 2 Op Op Op.
Mein einziger Ansatz um die passendsten Datentypen herauszufinden ist es alle Möglichkeiten auszuprobieren. Aber das kann ich wegen der Effizienz nicht machen. Allein bei der Rechnung 1+2+3+4+5+6+7+8+9+0+1 würde ich hier ordentliche Probleme bekommen, da das Plus alleine schon 7 Überladungen hat und bei 10 Plus macht das 7^10 = 282.475.249 Möglichkeiten. Das bedeutet mit dieser Möglichkeit könnte man nicht einmal 11 Zahlen addieren!
Nochmal zusammengefasst:
Ich habe einen Audruck wie "Op Op Op 1 Op Op Op 2 Op Op Op". Ein Operator kann beliebig überladen werden mit beliebigen Rängen. Und ich habe keine Ahnung wie ich hierbei vorgehen soll.
Ich würde mich wirklich über jede Idee freuen!
Grüße
blablab
Noch etwas: Der Parser hat den Delphi-Parser zum Vorbild. Das bedeutet, sobald eine Entscheidungsmöglichkeit entsteht möchte ich es möglichst gleich wie der Delphi-Parser behandeln.
|