Little Class Parser
Posted: Thu Jun 01, 2006 12:23 am
Code updated For 5.20+
Further down you find code for a little parser that takes code like this:
or this:
and creates a pb file that can be compiled with the pb compiler.
If somebody has ideas how to improve it please post it.
If you guys/gals want to make a community project out of it: why not.
In any case the generated code helps to understand how the oo portion works.
The Parser:
Hope there are enough comments to show what's going on.
Please keep the code simple.
Feedback welcome.

EDIT: Code above updated (examples and parser).
Uses Double Colon for the Method now.
THIS is a keyword.
THIS as the first method (procedure) parameter is not needed anymore.
(see examples)
EDIT: Code above updated (parser).
Fixed bug with comments on the NewObject line.
Comments on the parsed line should not criple the actual code.
EDIT: Code above updated (examples and parser).
NewObject now needs to be defined as Global, because of PureBasic compatibility (like Lists or Arrays).
Also a new Keyword is introduced: NewArray (as macro)
I have it since the first V4 beta. IMHO NewArray fits better with NewList, NewObject etc.
EDIT: Code above updated (parser).
Fixed bug when a Class name contained the name of another Class.
Also forgot to mention that the UBound Macro is needed too.
(it's in the parser code)
Got Multiple Inheritance to work
Further down you find code for a little parser that takes code like this:
Code: Select all
;oop example by fsw
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;- start main:
Class YourObject ;this is a comment
YourValueOfThat.l ;this is a comment
YourAnotherValue.s
YourThis(par.l) ;this is a comment
YourThat()
EndClass
Class MyObject
ValueOfThat.l
AnotherValue.s
myThis(par.l)
myThat()
EndClass
Global NewObject myThing.MyObject ;this is a comment
Global NewObject YourThing.YourObject
Global NewObject AnotherThing.MyObject
Global hello.s ; not used, just for testing purpose
AnotherThing\myThis(56)
With myThing
\myThis(347)
\myThat()
EndWith
With YourThing
\YourThis(123)
\YourThat()
EndWith
myThing\myThat()
YourThing\YourThat()
AnotherThing\myThat()
End
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; for now no constructor or destructor
Procedure YourObject::yourThis(par.l) ;this is a comment
*THIS\YourValueOfThat = par
EndProcedure
Procedure YourObject::yourThat()
*THIS\YourAnotherValue = " That: "
MessageRequester("YourObject", *THIS\YourAnotherValue + Str(*THIS\YourValueOfThat))
EndProcedure
Procedure MyObject::myThis(par.l)
*THIS\ValueOfThat = par
EndProcedure
Procedure MyObject::myThat()
*THIS\AnotherValue = " That: "
MessageRequester("MyObject", *THIS\AnotherValue + Str(*THIS\ValueOfThat))
EndProcedure
Code: Select all
;oop example by fsw
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;- start main:
Class YourObject ;this is a comment
YourValueOfThat.l ;this is a comment
YourAnotherValue.s
YourThis(par.l) ;this is a comment
YourThat()
EndClass ;this is a comment
Class MyObject Extends YourObject ;this is a comment
ValueOfThat.l
AnotherValue.s
myThis(par.l)
myThat()
EndClass
Global NewObject YourThing.YourObject ;this is a comment
Global NewObject myThing.MyObject
Global NewObject AnotherThing.MyObject
Global hello.s ; not used, just for testing purpose
With myThing
\myThis(347)
\myThat()
EndWith
With AnotherThing
\myThis(123)
\myThat()
EndWith
With YourThing
\YourThis(789)
\YourThat()
EndWith
myThing\YourThis(5)
AnotherThing\YourThis(6)
myThing\YourThat()
AnotherThing\YourThat()
YourThing\YourThat()
End
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; for now no constructor or destructor
Procedure YourObject::yourThis(par.l)
*THIS\YourValueOfThat = par
EndProcedure
Procedure YourObject::yourThat()
*THIS\YourAnotherValue = " That: "
MessageRequester("YourObject", *THIS\YourAnotherValue + Str(*THIS\YourValueOfThat))
EndProcedure
Procedure MyObject::myThis(par.l)
*THIS\ValueOfThat = par
EndProcedure
Procedure MyObject::myThat()
*THIS\AnotherValue = " That: "
MessageRequester("MyObject", *THIS\AnotherValue + Str(*THIS\ValueOfThat))
EndProcedure
If somebody has ideas how to improve it please post it.
If you guys/gals want to make a community project out of it: why not.
In any case the generated code helps to understand how the oo portion works.
The Parser:
Code: Select all
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; ; This is oop code that will be converted correctly:
; LPC - Little Class Parser ;
; ; Class YourObject ;this is a comment
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; YourValueOfThat.l ;this is a comment
; OOP parser - by FSW ; YourAnotherValue.s
; version 0.3 ; YourThis(par.l) ;this is a comment
; GPL Licence ; YourThat()
; June 2006 ; EndClass ;this is a comment
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;
; Features: ; Class MyObject Extends YourObject ;this is a comment
; ; myValueOfThat.l
; Double Colon for Class Methods ; myAnotherValue.s
; Data Encapsulation ; myThis(par.l)
; Multiple Inheritance ; myThat()
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; EndClass
; Keywords: ;
; ; Global NewObject YourThing.YourObject ;this is a comment
; Class ; Global NewObject myThing.MyObject
; EndClass ;
; NewObject ; With YourThing
; This ; \YourThis(789)
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; \YourThat()
; Notes: ; EndWith
; ;
; Extends is used for Inheritance ; myThing\YourThis(5)
; ; myThing\myThis(347)
; NewObject needs to be set as Global ; myThing\YourThat()
; because of PureBasic compatibility ; myThing\MyThat()
; (like NewList or Arrays) ;
; ; End
; Comments are now allowed on parsed ;
; lines ; Procedure YourObject::yourThis(par.l) ;this is a comment
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; *THIS\YourValueOfThat = par
; Special Notes About This Code: ; EndProcedure
; ;
; This code is NOT optimized for speed ; Procedure YourObject::yourThat()
; ; *THIS\YourAnotherValue = " That: "
; This code uses a dim Macro ; MessageRequester("YourObject", *THIS\YourAnotherValue + Str(*THIS\YourValueOfThat))
; Dim does look too weird... ; EndProcedure
; It also goes well with NewList... ;
; ;
; Macro dim ; Procedure MyObject::myThis(par.l)
; Dim ; *THIS\myValueOfThat = par
; EndMacro ; EndProcedure
; ;
; Uncomment this macro if you don't ; Procedure MyObject::myThat()
; have it in a res file already... ; *THIS\myAnotherValue = " That: "
; ; MessageRequester("MyObject", *THIS\myAnotherValue + Str(*THIS\myValueOfThat))
; BTW: it's also used in the generated ; EndProcedure
; code (dim instead of Dim) ;
; ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; ;
; Another Macro that it used is ArraySize ;
; The result is the amount of the ;
; elements of the array ;
; ;
; Macro ArraySize(array) ;
; (PeekL(@array - 8) - 1) ;
; EndMacro ;
; ;
; Uncomment this macro if you don't ;
; have it in a res file already... ;
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;
EnableExplicit
#File_In = 0
#File_Out = 1
Global RawLine$, Line$, RestOfLine$
Global ClassName$, InheritedClassName$, NextInheritedClassName$, MethodClassName$
Global MethodLine$, MethodName$, MethodParameter$, MethodComment$
Global ObjectName$, ObjectComment$
Global BracketPos.l, RightOne$, LookFor$
Global i.l, ii.l, si.l, ei.l, di.l, oi.l, ci.l ; these vars will be used while working with arrays
Global Dim StructureArray.s(0) ; we need to store the Structure parts of a class
Global Dim InterfaceArray.s(0) ; we need to store the Interface parts of a class
Global Dim DeclareMethodArray.s(0) ; we need to store the Declare Method parts of a class
Global Dim DataSectionArray.s(0) ; we need to store the DataSection Method names of a class
Global Dim ClassArray.s(0) ; we need to store the Names of the classes
Global Dim AllDataArray.s(0) ; we need to store all the DataSection Method names in one list for Inheritance
Global Dim ExtendsArray.s(0) ; we need to store the Inheritance of the classes (who inherits from whom)
;Result = OpenFile(#File_In, ".\try_normal.pbo")
;Result = OpenFile(#File_In, ".\try_extends.pbo")
;Result = OpenFile(#File_In, ".\try_double_extends.pbo")
;Result = OpenFile(#File_In, ".\try_triple_extends.pbo")
;Result = OpenFile(#File_In, ".\try_quad_extends.pbo")
OpenFile(#File_In, ProgramParameter(0))
CreateFile(#File_Out, ".\output.pb")
; Special note...
WriteStringN(#File_Out, "; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
WriteStringN(#File_Out, "; Special Notes About This Code:")
WriteStringN(#File_Out, "; ")
WriteStringN(#File_Out, "; This code uses a dim Macro")
WriteStringN(#File_Out, "; Dim does look too weird...")
WriteStringN(#File_Out, "; It also goes well with NewList...")
WriteStringN(#File_Out, ";")
WriteStringN(#File_Out, "; Macro dim")
WriteStringN(#File_Out, "; Dim")
WriteStringN(#File_Out, "; EndMacro")
WriteStringN(#File_Out, ";")
WriteStringN(#File_Out, "; Uncomment this macro if you don't")
WriteStringN(#File_Out, "; have it in a res file already...")
WriteStringN(#File_Out, "; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
; End Special note...
Repeat
; read the line from the file
RawLine$ = ReadString(#File_In)
; trim and upper case it
Line$ = UCase(Trim(RawLine$))
; set some settings to default values
InheritedClassName$ = ""
ii = 0
ReDim InterfaceArray.s(ii)
si = 0
ReDim StructureArray.s(si)
; Debug Line$
;this line needs to be parsed
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; looking out for CLASS
If Left(Line$, 5) = "CLASS"
; Debug "Class Begin Found"
; get class name
If FindString(Line$, "EXTENDS", 0)
InheritedClassName$ = StringField(Line$, 4, " ")
EndIf
; class name is the second word
ClassName$ = LTrim(StringField(Line$, 2, " "))
; Debug "ClassName: " + ClassName$
Repeat
; ReadNextLine and do some stuff with it
Line$ = Trim(ReadString(#File_In))
BracketPos.l = FindString(Line$, "(", 0)
; if there is a bracket then this is a Method -> goes into interface
If BracketPos
;start of methods...
; Debug ii
; Debug "Method found: " + Line$
If ii = 0
; first line of the interface
If Len(InheritedClassName$) > 0
; with inheritance
InterfaceArray.s(ii) = "Interface " + ClassName$ + "_Methods " + "EXTENDS " + InheritedClassName$ + "_Methods"
;store all inheritances
ExtendsArray.s(ei) = ClassName$ + " " + InheritedClassName$
; Debug "Extended= " + ExtendsArray.s(ei)
ei+1
ReDim ExtendsArray.s(ei)
Else
; NO inheritance
InterfaceArray.s(ii) = "Interface " + ClassName$ + "_Methods"
EndIf
; start of DataSection
DataSectionArray.s(ii) = "DataSection : " + ClassName$ + "_VTable:"
ii+1
; prepare the interface line array for writing the next lin
ReDim InterfaceArray.s(ii)
; prepare the declare line array for writing the next lin
ReDim DeclareMethodArray.s(ii)
; prepare the DataSection array for writing the next line
ReDim DataSectionArray.s(ii)
EndIf
; write the interface line to the array
InterfaceArray.s(ii) = " " + Line$
; prepare the parameters for the declare line
RestOfLine$ = Trim(Right(Line$, Len(Line$) - BracketPos))
; write the declare line to the array
If Len(RestOfLine$) > 1
; there are some parameters
DeclareMethodArray.s(ii) = "Declare " + ClassName$ + "_" + Left(Line$, BracketPos) + "*THIS." + ClassName$ + ", " + RestOfLine$
Else
; there are NO parameters
DeclareMethodArray.s(ii) = "Declare " + ClassName$ + "_" + Left(Line$, BracketPos) + "*THIS." + ClassName$ + RestOfLine$
EndIf
; End of writing Interface line
; start of DataSection
DataSectionArray.s(ii) = " Data.l @" + ClassName$ + "_" + Left(Line$, BracketPos) + ")"
;store all methods into an array, needed for inheritance
AllDataArray.s(di) = " Data.l @" + ClassName$ + "_" + Left(Line$, BracketPos) + ")"
; Call; Debugger
; redim the needed arrays
ii+1
ReDim InterfaceArray.s(ii)
ReDim DeclareMethodArray.s(ii)
ReDim DataSectionArray.s(ii)
di+1
ReDim AllDataArray.s(di)
;end of methods...
Else ; no bracket, this is a property -> goes into structure
; start of properties...
If FindString(Line$, ".", 0)
; Debug si
; Debug "Property found: " + Line$
;property found
If si = 0
; first line of the structure
; check for inheritance
If Len(InheritedClassName$) > 0
StructureArray.s(si) = "Structure " + ClassName$ + " Extends " + InheritedClassName$ ; + " : VTable.l"
Else
StructureArray.s(si) = "Structure " + ClassName$ + " : VTable.l"
EndIf
; prepare for the next line
si+1
ReDim StructureArray.s(si)
EndIf
; write the line of structure
StructureArray.s(si) = " " + Line$
; prepare for the next line
si+1
ReDim StructureArray.s(si)
EndIf
; end of properties...
EndIf
; and of line inside the class - goto next line inside the class
Until UCase(Left(Line$,8)) = "ENDCLASS"
; this class is done...
;finish up the arrays
StructureArray.s(si) = "EndStructure"
InterfaceArray.s(ii) = "EndInterface"
DataSectionArray.s(ii) = "EndDataSection : Global dim " + ClassName$ + "_Self." + ClassName$ + "(" + Str(oi) + ")"
; START writing a class
WriteStringN(#File_Out, "; Start of class")
; write the structure
For i = 0 To ArraySize(StructureArray.s())
WriteStringN(#File_Out, StructureArray.s(i))
Next
WriteStringN(#File_Out, "")
; write the interface
For i = 0 To ArraySize(InterfaceArray.s())
WriteStringN(#File_Out, InterfaceArray.s(i))
Next
WriteStringN(#File_Out, "")
; write the declares
For i = 0 To ArraySize(DeclareMethodArray.s())
WriteStringN(#File_Out, DeclareMethodArray.s(i))
Next
WriteStringN(#File_Out, "")
; write first DataSection line
WriteStringN(#File_Out, DataSectionArray.s(0))
; ----------------------------------------
; ----------------------------------------
; look for inheritance and write the lines
; ----------------------------------------
; start single inheritance - WORKS! ; but not used anymore...
; ---------------------------------
;If Len(InheritedClassName$) > 0
; ; single inheritance
; For i = 0 To ArraySize(AllDataArray.s())
; If FindString(AllDataArray.s(i), InheritedClassName$, 0)
; WriteStringN(#File_Out, AllDataArray.s(i))
; EndIf
; Next
;EndIf
; end single inheritance
; ----------------------
; start multiple inheritance - WORKS!
; -----------------------------------
If Len(InheritedClassName$) > 0
; now go down all the way and start from the first inherited class...
NextInheritedClassName$ = InheritedClassName$
Repeat
LookFor$ = ""
For i = 0 To ArraySize(ExtendsArray.s())
; ; Debug "ExtendsArray= " + ExtendsArray.s(i)
; this only works properly with StringField
If StringField(ExtendsArray.s(i), 1, " ") = NextInheritedClassName$
;this class has inherited methods
; Debug "ExtendsArray= " + ExtendsArray.s(i)
; this only works properly with StringField
LookFor$ = StringField(ExtendsArray.s(i), 2, " ")
; Debug "LookFor 1= " + LookFor$
NextInheritedClassName$ = LookFor$
EndIf
Next
Until Len(LookFor$) = 0
; now the NextInheritedClassName$ should have the first class of inheritance
; Debug "EXIT Repeat loop 1"
; Debug ""
Repeat
; write the Inherited Class Name
For i = 0 To ArraySize(AllDataArray.s())
If FindString(AllDataArray.s(i), "@" + NextInheritedClassName$ + "_", 0)
WriteStringN(#File_Out, AllDataArray.s(i))
EndIf
Next
InheritedClassName$ = NextInheritedClassName$
NextInheritedClassName$ = ""
; Call; Debugger
; look out for the next class in line...
For i = 0 To ArraySize(ExtendsArray.s())
; Debug "InheritedClassName= " + InheritedClassName$
; Debug "ExtendsArray= " + ExtendsArray.s(i)
; this only works properly with StringField
If StringField(ExtendsArray.s(i), 2, " ") = InheritedClassName$
; found the Inherited Class Name, get the Next Inherited Class Name
; Debug "WHAT= " + Trim(RemoveString(ExtendsArray.s(i), InheritedClassName$))
NextInheritedClassName$ = Trim(RemoveString(ExtendsArray.s(i), InheritedClassName$))
; look if Next Inherited ClassName = ClassName
If NextInheritedClassName$ = ClassName$
; stop here, don't write the methods of ClassName$
; they will be written later...
NextInheritedClassName$ = ""
EndIf
EndIf
Next
Until Len(NextInheritedClassName$) = 0
EndIf
; end multiple inheritance
; ------------------------
;write the methods of ClassName$, always!!!
For i = 1 To ArraySize(DataSectionArray.s())
WriteStringN(#File_Out, DataSectionArray.s(i))
Next
WriteStringN(#File_Out, "; End of class")
; END writing a class
WriteStringN(#File_Out, "")
WriteStringN(#File_Out, "")
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; looking out for NEWOBJECT
ElseIf Left(Line$, 6) = "GLOBAL" Or Left(Line$, 9) = "NEWOBJECT"
RightOne$ = ""
If Left(Line$, 6) = "GLOBAL"
; Debug "GLOBAL FOUND"
RightOne$ = Trim(StringField(Line$, 2, " "))
If RightOne$ = "NEWOBJECT"
Line$ = Trim(Right(Line$, Len(Line$) - 7))
EndIf
EndIf
If RightOne$ = "NEWOBJECT" Or Left(Line$, 9) = "NEWOBJECT"
; time to write the new object...
; get the object name without any comments
ObjectName$ = Trim(StringField(Right(Line$, Len(Line$) - 9), 1, ";"))
; get the class name without any comments
ClassName$ = Trim(StringField(Right(Line$, Len(Line$) - FindString(Line$, ".", 10)), 1, ";"))
; write class name into array - needed for inheritance
ClassArray.s(ci) = ClassName$
; get the comment
ObjectComment$ = ""
ObjectComment$ = Trim(StringField(Line$, 2, ";"))
; START writing an object
WriteStringN(#File_Out, "")
; check how many times this class is already used...
; and increase the number of the class array according to the amount of objects that use the class
; this way we don't waste memory
oi = -1
For i = 0 To ArraySize(ClassArray.s())
; only the exact class name is valid
If ClassArray.s(i) = ClassName$
oi+1
EndIf
Next
; start writing the object
WriteStringN(#File_Out, "; Define Object")
; write the object
If RightOne$ = "NEWOBJECT"
; global is used
WriteStringN(#File_Out, "ReDim " + ClassName$ + "_Self." + ClassName$ + "(" + Str(oi) + ") : " + ClassName$ + "_Self(" + Str(oi) + ")\VTable = ?" + ClassName$ + "_VTable" + " : Global " + ObjectName$ + "_Methods = " + ClassName$ + "_Self(" + Str(oi) + ")" + " ;" + ObjectComment$)
Else
;object is not defined as global
WriteStringN(#File_Out, "ReDim " + ClassName$ + "_Self." + ClassName$ + "(" + Str(oi) + ") : " + ClassName$ + "_Self(" + Str(oi) + ")\VTable = ?" + ClassName$ + "_VTable" + " : " + ObjectName$ + "_Methods = " + ClassName$ + "_Self(" + Str(oi) + ")" + " ;" + ObjectComment$)
EndIf
; prepare the array for the next round
ci+1
ReDim ClassArray.s(ci)
Else
; global variable or list, nothing to do...
WriteStringN(#File_Out, RawLine$)
EndIf
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; looking out for METHODS (Procedure)
ElseIf Left(Line$, 9) = "PROCEDURE"
; look out for methods...
If FindString(Line$, "::", 10)
; it's a method...
; Debug "Method for class found"
; remove "preocedure" for further process..
Line$ = Trim(RemoveString(Line$, "PROCEDURE"))
; Debug Line$
; Debug "analize line"
; get the class of the method
MethodClassName$ = Left(Line$, FindString(Line$, "::", 1) - 1)
; get the rest of the line
MethodLine$ = Right(Line$, Len(Line$) - FindString(Line$, "::", 1) - 1)
; extract the method name
MethodName$ = StringField(MethodLine$, 1, "(")
; get the method parameters
MethodParameter$ = Trim(StringField( StringField(MethodLine$, 2, "("), 1, ";"))
; delete old comments
MethodComment$ = ""
; get new comment
MethodComment$ = Trim(StringField( StringField(MethodLine$, 2, "("), 2, ";"))
; now write the procedure line
If Len(MethodParameter$) > 1
; there are parameter
WriteStringN(#File_Out, "Procedure " + MethodClassName$ + "_" + MethodName$ + "(*THIS." + MethodClassName$ + ", " + MethodParameter$ + " ;" + MethodComment$)
Else
; no parameter
WriteStringN(#File_Out, "Procedure " + MethodClassName$ + "_" + MethodName$ + "(*THIS." + MethodClassName$ + MethodParameter$ + " ;" + MethodComment$)
EndIf
; Debug MethodName$
Else
; this is not a method, but a simple procedure - write it straight into the new file
WriteStringN(#File_Out, RawLine$)
EndIf
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Else
; no CLASS, NEWOBJECT or METHOD found, just copy this line to the new file...
WriteStringN(#File_Out, RawLine$)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EndIf
; goto next line of input file
Until Eof(#File_In)
; end of input file
; now close the files
CloseFile(#File_In)
CloseFile(#File_Out)
End
; this is the end my friend...
Please keep the code simple.
Feedback welcome.

EDIT: Code above updated (examples and parser).
Uses Double Colon for the Method now.
THIS is a keyword.
THIS as the first method (procedure) parameter is not needed anymore.
(see examples)
EDIT: Code above updated (parser).
Fixed bug with comments on the NewObject line.
Comments on the parsed line should not criple the actual code.
EDIT: Code above updated (examples and parser).
NewObject now needs to be defined as Global, because of PureBasic compatibility (like Lists or Arrays).
Also a new Keyword is introduced: NewArray (as macro)
I have it since the first V4 beta. IMHO NewArray fits better with NewList, NewObject etc.
EDIT: Code above updated (parser).
Fixed bug when a Class name contained the name of another Class.
Also forgot to mention that the UBound Macro is needed too.
(it's in the parser code)
Got Multiple Inheritance to work
