@ Edel
Ich habe gestern meinen Parser vom letzten Jahr nochmal ausgepackt. Es war ein Projekt was ich mit jemanden zusammen aus der Community angefangen und später alleine weitergeführt habe, da derjenige keine Zeit mehr hatte.
Lag alles noch auf meiner Platte, fehlte nur noch die Unterstützung von Polymorphismus, denn das sollte absolut vorhanden sein, andernfalls ists imho kein OOP, sondern lediglich ObjektBasiert. Aber das habe ich am gestrigen Abend noch ergänzt.
Ich werde dir heute Mittag den vorliegenden Code zusenden, damit du mal drüberschaust (bitte deine Email via PM). Ich würde das Projekt dann wenn es steht (wie hier auch angedacht) gerne öffentlich machen, damit -wenn vorhanden- schneller Bugs beseitigt werden, können, bzw. Optimierungen sich ebenso von anderen gut einbauen lassen.
Folgendes wird unterstützt:
- Parsing via Remis' Lexer
-
Vererbung inkl.! Überladung/Polymorphismus
- Automatische Erkennung von Attribute und Methodenaufrufen der selben Klasse innerhalb von Methoden.
- Konstruktoren werden autom. Erkannt und beim Erstellen der Ojekte aufgerufen (sind aber nicht pflicht).
- Der ausgegebene Code des Parsers ist Debugger nativ, bedeutet, die Zeilen sind nicht vom Inhalt her verschoben o.ä.
Es sind momentan mehrere Arten von Objekt Initialisierern und This Zugriffen unterstützt, am Ende sollte aber EINE Syntax stehen.
-
New, Delete
-
->attribute, *this->attribute, \attribute, .attribute
-
->methode(), *this-> methode(), \ methode(), . methode()
-
Extends (also Vererbung)
-
Virtual (bei Überladung!)
Man kann sich später festlegen, ob man C++ like wie z.B. New, Delete, -> und Virtual verwendet, oder diese Begriffe PureBasic like anwendet, also Create, Free, \attribute, \methode().
der Zugriff auf den *this Zeiger innerhalb einer Methode gefällt mir mit
\attribute am ehesten, da diese Art von PB's
With bekannt ist.
Machen solche Dinge wie "Declare" innerhalb einer Classe wirklich Sinn??? Bei Interfaces oder Strukturen in PB ist dies auch nicht der Fall, bzw. nicht von Nöten.
Was mir aber an deinem Beispiel weiter oben sehr gefiel und PB like ist, war die Methodendefinition als "CLASSE.Methode()".
Bei folgendem Code:
Code: Alles auswählen
Class OTHERCLASS
OTHERCLASS()
Release()
get.s()
Value.s
EndClass
Class THECLASS Extends OTHERCLASS
THECLASS()
Release()
Virtual get.s()
Set(string.s, long.l)
append(string.s)
string.s
long.l
EndClass
Procedure OTHERCLASS.OTHERCLASS()
Debug "Constructor from OTHERCLASS called"
\Value = "Here is a string from OTHERCLASS"
EndProcedure
Procedure OTHERCLASS.Release()
Debug "The destructor of OTHERCLASS called"
EndProcedure
Procedure.s OTHERCLASS.get()
ProcedureReturn \Value
EndProcedure
Procedure THECLASS.THECLASS()
Debug "Constructor from THECLASS called"
EndProcedure
Procedure THECLASS.Release()
Debug "The destructor of THECLASS has been called"
EndProcedure
Procedure.s THECLASS.get()
ProcedureReturn \string + " from THECLASS! "
EndProcedure
Procedure THECLASS.Set(string.s, long.l)
*this\string = Str(long) + " " + string
*this->long = long
EndProcedure
Procedure THECLASS.Append(string.s)
For i = 0 To \long -1
Debug Str(i) + " " + \string
Next
For i = 0 To .long -1
Debug Str(i) + " " + ->string
Next
For i = 0 To ->long -1
Debug Str(i) + " " + ->get()
Next
EndProcedure
*object.THECLASS = New THECLASS
*object\Set("A nice word", 10)
Debug *object\get()
Du kannst hier am Beispiel sehen, dass neben der Vererbung eine Überladung stattfindet, via "Virtual" wird aber get() der geerbten Klasse genutzt, daher ist der Ansatz der Polymorphie vorhanden.
Wenn ich also eine Helferklasse z.B. cWINDOW habe, kann ich somit definieren, dass ich die Methode \Create via einer eigenen \Create() Methode überladen lasse. So macht OOP erst richtig spaß
Ich habe im o.g. Code auch noch etwas mit den Möglichkeiten der *this Zeiger Optionen innerhalb der Methoden gearbeitet.
Und dieser Code kommt dann raus:
Code: Alles auswählen
Declare.l ConstructOTHERCLASS() : Interface OTHERCLASS
OTHERCLASS ( )
Release ( )
get . s ( )
EndInterface : Structure sOTHERCLASS : *vt : Value . s
EndStructure
Declare.l ConstructTHECLASS() : Interface THECLASS Extends OTHERCLASS
THECLASS ( )
_overloaded_Release ( )
_overloaded_get . s ( )
Set ( string . s , long . l )
append ( string . s )
EndInterface : Structure sTHECLASS Extends sOTHERCLASS : string . s
long . l
EndStructure
Procedure OTHERCLASS_OTHERCLASS (*this.sOTHERCLASS ) : *thisM.OTHERCLASS = *this
Debug "Constructor from OTHERCLASS called"
*this\ Value = "Here is a string from OTHERCLASS"
EndProcedure
Procedure OTHERCLASS_Release (*this.sOTHERCLASS ) : *thisM.OTHERCLASS = *this
Debug "The destructor of OTHERCLASS called"
EndProcedure
Procedure . s OTHERCLASS_get (*this.sOTHERCLASS ) : *thisM.OTHERCLASS = *this
ProcedureReturn *this\ Value
EndProcedure
Procedure THECLASS_THECLASS (*this.sTHECLASS ) : *thisM.THECLASS = *this
Debug "Constructor from THECLASS called"
EndProcedure
Procedure THECLASS_Release (*this.sTHECLASS ) : *thisM.THECLASS = *this
Debug "The destructor of THECLASS has been called"
EndProcedure
Procedure . s THECLASS_get (*this.sTHECLASS ) : *thisM.THECLASS = *this
ProcedureReturn *this\ string + " from THECLASS! "
EndProcedure
Procedure THECLASS_Set (*this.sTHECLASS, string . s , long . l ) : *thisM.THECLASS = *this
*this \ string = Str ( long ) + " " + string
*this \ long = long
EndProcedure
Procedure THECLASS_Append (*this.sTHECLASS, string . s ) : *thisM.THECLASS = *this
For i = 0 To *this\ long - 1
Debug Str ( i ) + " " + *this\ string
Next
For i = 0 To *this\ long - 1
Debug Str ( i ) + " " + *this \ string
Next
For i = 0 To *this \ long - 1
Debug Str ( i ) + " " + *thisM \ get ( )
Next
EndProcedure
*object . THECLASS = ConstructTHECLASS()
*object \ Set ( "A nice word" , 10 )
Debug *object \ get ( )
*object \ append ( " comes here" )
*object\Release() : FreeMemory(PeekL(*object)) : FreeMemory(*object)
; jaPBe Version=3.7.7.653
; Build=0
; Language=0x0000 Language Neutral
; FirstLine=0
; CursorPosition=7
; ExecutableFormat=Windows
; DontSaveDeclare
; EOF
; ------------------------------- OOP Constructors, etc. -------------------------------
Procedure ConstructOTHERCLASS()
Protected *this.sOTHERCLASS = AllocateMemory(SizeOf(sOTHERCLASS))
Protected *thisM.OTHERCLASS = *this
If Not *this : ProcedureReturn #False : EndIf
Global _VT_OTHERCLASS = AllocateMemory(SizeOf(OTHERCLASS))
*this\vt = _VT_OTHERCLASS
PokeL(_VT_OTHERCLASS + OffsetOf(OTHERCLASS\OTHERCLASS()), @OTHERCLASS_OTHERCLASS() )
PokeL(_VT_OTHERCLASS + OffsetOf(OTHERCLASS\Release()), @OTHERCLASS_Release() )
PokeL(_VT_OTHERCLASS + OffsetOf(OTHERCLASS\get()), @OTHERCLASS_get() )
CompilerIf Defined(OTHERCLASS_OTHERCLASS, #PB_Procedure) = #True
*thisM\OTHERCLASS()
CompilerEndIf
ProcedureReturn *this
EndProcedure
Procedure ConstructTHECLASS()
Protected *this.sTHECLASS = AllocateMemory(SizeOf(sTHECLASS))
Protected *thisM.THECLASS = *this
If Not *this : ProcedureReturn #False : EndIf
Global _VT_THECLASS = AllocateMemory(SizeOf(THECLASS))
*this\vt = _VT_THECLASS
PokeL(_VT_THECLASS + OffsetOf(THECLASS\OTHERCLASS()), @OTHERCLASS_OTHERCLASS() )
PokeL(_VT_THECLASS + OffsetOf(THECLASS\Release()), @OTHERCLASS_Release() )
PokeL(_VT_THECLASS + OffsetOf(THECLASS\get()), @OTHERCLASS_get() )
PokeL(_VT_THECLASS + OffsetOf(THECLASS\THECLASS()), @THECLASS_THECLASS() )
PokeL(_VT_THECLASS + OffsetOf(THECLASS\Release()), @THECLASS_Release() )
PokeL(_VT_THECLASS + OffsetOf(THECLASS\get()), @OTHERCLASS_get() )
PokeL(_VT_THECLASS + OffsetOf(THECLASS\Set()), @THECLASS_Set() )
PokeL(_VT_THECLASS + OffsetOf(THECLASS\append()), @THECLASS_Append() )
CompilerIf Defined(OTHERCLASS_OTHERCLASS, #PB_Procedure) = #True
*thisM\OTHERCLASS()
CompilerEndIf
CompilerIf Defined(THECLASS_THECLASS, #PB_Procedure) = #True
*thisM\THECLASS()
CompilerEndIf
ProcedureReturn *this
EndProcedure
Die Zeilenstruktur ist komplett zwecks Debugging erhalten da die OOP spez. Dingen via ":" im Code angehangen und die Konstruktoren etc. am Ende angefügt sind.