Essay - Free Blitz2D
Übersicht

Gehe zu Seite Zurück 1, 2, 3, 4 Weiter
![]() |
Arrangemonk |
![]() Antworten mit Zitat ![]() |
---|---|---|
gibts alles schon!
http://de.wikipedia.org/wiki/FreeBASIC |
||
ingeneur |
E. Urbachehemals "Basicprogger" |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
@ArrangeMonk:
Ich bin lieber von GCC und Visual C++ Compiler abhängig als einem mir unbekannten FreeBasic-Compiler. Außerdem kann ich dort die Syntax nicht verändern und ebenso kann ich nicht von den hochgelobten Optimierungen der C++ Compiler profitieren. Des Weiteren ist meine gesamte Standard-Lib in C++ geschrieben und nein, man kann sie aufgrund Templates und massivem 1-Zeilen-Inlining nicht direkt per DLL einbinden. @TheShadow: Der Parser ist im Moment noch die am wenigsten ausgebaute Komponente. Ich sagte bereits, dass er noch lange nicht fertig ist, aber ich kann an einem Beispiel zeigen, wie er vorgeht: Code: [AUSKLAPPEN] Return a*b+7
Der Parser ist im Moment auf BPC (Blitz Max) beschränkt, weshalb ich jetzt nur die Vorgehensweise bei BPC erkläre. BMax ist zeilen-basiert - ob man will oder nicht. Es gibt zwar das .. am Ende einer Zeile, aber dieses kann der vorherigen Zeile direkt übergeben werden, so dass man immer eine Anweisung pro Zeile hat, so ähnlich ist es beim Semikolon in BMax und mein Code Stats Programm nutzt dieselbe Technik. Nun gibt es in BMax im Gegensatz zu C++ nur 2 Anweisungstypen: 1.) Zuweisung 2.) Befehl Jetzt muss der Parser noch wissen, wie diese aufgebaut sind: 1.) Zuweisung: Variable/L-Wert + Gleichheitszeichen + Ausdruck/R-Wert 2.) Befehl: Funktion/Keyword + Parameter Mit diesen 2 Dingen kann man nun die Zeilen sortieren: Zuweisungen und Befehle. Beispiele für Zuweisungen: Code: [AUSKLAPPEN] x = 5
vector.x = 3 obj.life = 100 Beispiele für Befehle: Code: [AUSKLAPPEN] Print a
If x=1 Then Return True EndIf Nun geht man Zeichen für Zeichen durch und prüft mit IsVarChar(char a), ob es sich (immer noch) um ein Zeichen handelt, welches in Variablen vorkommen darf. Es wird btw noch nicht geprüft, ob das erste Zeichen eine Zahl ist, aber das ist im Moment unwichtig. Wenn nun bspw. ein Leerzeichen gefunden wird, Code: [AUSKLAPPEN] Return a*b+7
dann vergleicht er den ersten String, also Return, mit allen Keywords in der Datenbank. Wurde eins gefunden, dann steht fest: Es handelt sich um die Return-Anweisung. Wenn eine Funktion gefunden wurde, wird eben ein call-Knoten in den Tree eingefügt. Nachdem im XML-Tree nun ein <return></return> steht, muss man nun weiter rekursiv aufteilen: Code: [AUSKLAPPEN] node->AddNode(GetExpr(parameters));
Nun wird erkannt, dass a*b+7 ein Ausdruck ist, der keine weiteren Funktionen enthält. Mathematische Ausdrücke/Terme werden nicht in XML umgewandelt, das wäre zuviel des Guten, deshalb kann der Parser einen einfachen Text-Knoten erstellen: Code: [AUSKLAPPEN] return CreateXMLTextNode("a*b+7");
durch das vorherige AddNode wird es zum return-Knoten hinzugefügt: Code: [AUSKLAPPEN] <return>
a * b + 7 </return> Wären noch einige zusätzliche Funktionen vorhanden, dann würde es bspw. so aussehen: Code: [AUSKLAPPEN] <return>
<call function="Sin"> <parameter> a * b </parameter> </call> + 7 </return> Falls es noch irgendwen interessiert, ich habe mal die ersten Seiten abgetippt: Download PDF |
||
The box said, "Requires Windows XP or better", so I installed Ubuntu | Linux is NOT Windows
Flua :: Profiler für BB und BMax :: Partikel-Engine für BMax :: Lyphia-Projekt Quellcode (BMax) :: Automatische Parallelisierung :: Meine Musik |
![]() |
Arrangemonk |
![]() Antworten mit Zitat ![]() |
---|---|---|
@Basicprogger
ich mein nicht dich, sondern vertex, dass der das nehmen soll aber die erschaffung eines neuen basic dialektes mit eigenem compiler und allem drum und dran is meines erachtens doof, da man sich mit headerfiles das ding includebar einfach im vc++ reinladne kann und dann mit nem {} klammer pseudo basic rumschreiben kann |
||
ingeneur |
Florian |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Hallo
Nur eine Idee: Man könnte doch einen Quelltext in XML umwandeln. Das XML-Ausgabe-Format könnte man so gestalten, das es Programmiersprachen unabhängig ist. ... Hier ist ein Lexer der Basic Quelltext in Token umwandelt. Code: [AUSKLAPPEN] %FALSE=0 %TRUE =1 %NUL =0 %DEBUG = %TRUE %SYM_NUL = 0 %SYM_EOL = 1 %SYM_EOS = 2 %SYM_LPARA = 3 %SYM_RPARA = 4 %SYM_LEPARA = 5 %SYM_REPARA = 6 %SYM_KOMMA = 7 %SYM_NUM = 8 %SYM_NUM_CONST = 9 %SYM_META = 10 %SYM_STRING = 12 %SYM_STRING_CONST = 13 %SYM_STRING_VAL = 14 %SYM_EQ = 15 %SYM_NE = 16 %SYM_LE = 17 %SYM_LT = 18 %SYM_GE = 19 %SYM_GT = 20 %SYM_ID = 21 %SYM_OP_ADD = 22 %SYM_OP_SUB = 23 %SYM_OP_MUL = 24 %SYM_OP_DIV = 25 FUNCTION COMPILER(FILENAME AS STRING) AS DWORD IF LOADFILE(FILENAME) =%FALSE THEN FUNCTION=%FALSE EXIT FUNCTION END IF InitParser OUTNR=FREEFILE OPEN "Test.asm" FOR OUTPUT AS OUTNR PRINT#OUTNR,"%include ""win32n.inc""" runParser CLOSE #OUTNR SHELL "nasm.exe "+"Test.asm"+" -fobj" SHELL "ALINK.EXE -c -oPE -subsys gui Test" END FUNCTION SUB InitParser GetChar SkipWhite END SUB SUB runParser DIM TXT AS STRING DIM X AS INTEGER DIM zeile AS STRING getsym DO UNTIL %SYM_EOS=SYM_TYPE SELECT CASE SYM_TYPE CASE %SYM_ID SELECT CASE SYM_TEXT CASE "sub" XSUB CASE "function" XFUNCTION CASE "for" XFOR CASE "if" XIF CASE "select" XSELECT CASE "do" XDO CASE "table" XTABLE CASE "type" XTYPE CASE "asm" XASM END SELECT CASE %SYM_STRING_CONST STRING_CONST END SELECT getsym LOOP CLOSE#1 END SUB SUB SkipWhite IF(EOS) THEN EXIT SUB END IF WHILE IsWhite(Look) OR Look=ASC($VT) OR Look=ASC($CR) OR Look=ASC($LF) GetChar WEND END SUB SUB MathSkipWhite WHILE IsWhite(Look) GetChar WEND END SUB FUNCTION IsAlpha(T AS DWORD) AS DWORD IF T>=ASC("a") AND T<=ASC("z") THEN FUNCTION =%TRUE EXIT FUNCTION ELSEIF T>=ASC("A") AND T<=ASC("Z") THEN FUNCTION =%TRUE EXIT FUNCTION ELSE FUNCTION =%FALSE EXIT FUNCTION END IF END FUNCTION FUNCTION IsAlpha2(T AS DWORD) AS DWORD IF T>=ASC("a") AND T<=ASC("z") THEN FUNCTION =%TRUE EXIT FUNCTION ELSEIF T>=ASC("A") AND T<=ASC("Z") THEN FUNCTION =%TRUE EXIT FUNCTION ELSEIF T=ASC("_") THEN FUNCTION =%TRUE EXIT FUNCTION ELSE FUNCTION =%FALSE EXIT FUNCTION END IF END FUNCTION FUNCTION ishex(T AS DWORD) AS DWORD IF T>=ASC("0") AND T<=ASC("9") THEN FUNCTION =%TRUE EXIT FUNCTION ELSEIF T>=ASC("a") AND T<=ASC("f") THEN FUNCTION =%TRUE EXIT FUNCTION ELSEIF T>=ASC("A") AND T<=ASC("F") THEN FUNCTION =%TRUE EXIT FUNCTION ELSE FUNCTION =%FALSE EXIT FUNCTION END IF END FUNCTION FUNCTION h2d(T AS DWORD) AS DWORD IF T>=ASC("0") AND T<=ASC("9") THEN FUNCTION=T-ASC("0") EXIT FUNCTION ELSEIF T>=ASC("a") AND T<=ASC("f") THEN FUNCTION= T-ASC("a")+10 EXIT FUNCTION ELSEIF T>=ASC("A") AND T<=ASC("F") THEN FUNCTION=T-ASC("A")+10 EXIT FUNCTION ELSE ERR_OUT "Bad numeric format, nor hex neither decimal" END IF END FUNCTION FUNCTION IsAlnum(T AS DWORD) AS DWORD IF IsAlpha(T) OR IsDigit(T) THEN FUNCTION =%TRUE EXIT FUNCTION ELSE FUNCTION =%FALSE EXIT FUNCTION END IF END FUNCTION FUNCTION IsDigit(T AS DWORD) AS DWORD IF T=>ASC("0") AND T=<ASC("9") THEN FUNCTION =%TRUE EXIT FUNCTION ELSE FUNCTION =%FALSE EXIT FUNCTION END IF END FUNCTION SUB GetSym SELECT CASE AS LONG LOOK CASE ASC("'") CASE ASC("+") SYM_TYPE=%SYM_OP_ADD #IF %DEBUG = %TRUE SYM_TEXT = "+" #ENDIF Match ASC("+") EXIT SUB CASE ASC("-") SYM_TYPE=%SYM_OP_SUB #IF %DEBUG = %TRUE SYM_TEXT = "-" #ENDIF Match ASC("-") EXIT SUB CASE ASC("*") SYM_TYPE=%SYM_OP_MUL #IF %DEBUG = %TRUE SYM_TEXT = "*" #ENDIF Match ASC("*") EXIT SUB CASE ASC("@") Match ASC("@") CASE ASC("/") SYM_TYPE=%SYM_OP_DIV #IF %DEBUG = %TRUE SYM_TEXT = "/" #ENDIF Match ASC("/") EXIT SUB CASE ASC("<") Match ASC("<") CASE ASC(">") Match ASC(">") SELECT CASE AS LONG LOOK CASE ASC("=") SYM_TYPE=%SYM_GE #IF %DEBUG = %TRUE SYM_TEXT = ">=" #ENDIF Match ASC("=") EXIT SUB CASE ASC("<") SYM_TYPE=%SYM_NE #IF %DEBUG = %TRUE SYM_TEXT = "><" #ENDIF Match ASC("<") EXIT SUB CASE ELSE SYM_TYPE=%SYM_GE #IF %DEBUG = %TRUE SYM_TEXT = "=" #ENDIF EXIT SUB END SELECT CASE ASC("=") Match ASC("=") SELECT CASE AS LONG LOOK CASE ASC("<") SYM_TYPE=%SYM_LE #IF %DEBUG = %TRUE SYM_TEXT = "=<" #ENDIF Match ASC("<") EXIT SUB CASE ASC(">") SYM_TYPE=%SYM_GE #IF %DEBUG = %TRUE SYM_TEXT = "=>" #ENDIF Match ASC(">") EXIT SUB CASE ELSE SYM_TYPE=%SYM_EQ #IF %DEBUG = %TRUE SYM_TEXT = "=" #ENDIF EXIT SUB END SELECT CASE ASC("%") getchar IF (ASC("a")=<LOOK AND ASC("z")=>LOOK) OR (ASC("A")=>LOOK AND ASC("Z")=<LOOK) THEN SYM_TEXT="" DO SYM_TEXT = SYM_TEXT+LCASE$(CHR$(LOOK)) GetChar LOOP WHILE (LOOK>=ASC("a") AND LOOK<=ASC("z")) OR (LOOK>=ASC("A") AND LOOK<=ASC("Z")) OR (LOOK>=ASC("0") AND LOOK<=ASC("9")) OR LOOK>=ASC("_") SYM_TYPE=%SYM_META MathSkipWhite EXIT SUB ELSE END IF CASE ASC("#") getchar IF (ASC("a")=<LOOK AND ASC("z")=>LOOK) OR (ASC("A")=>LOOK AND ASC("Z")=<LOOK) THEN SYM_TEXT="" DO SYM_TEXT = SYM_TEXT+LCASE$(CHR$(LOOK)) GetChar LOOP WHILE (LOOK>=ASC("a") AND LOOK<=ASC("z")) OR (LOOK>=ASC("A") AND LOOK<=ASC("Z")) OR (LOOK>=ASC("0") AND LOOK<=ASC("9")) OR LOOK>=ASC("_") SYM_TYPE=%SYM_META MathSkipWhite EXIT SUB ELSE SYM_TEXT="#" MathSkipWhite END IF CASE ASC("$") getchar IF (ASC("a")=<LOOK AND ASC("z")=>LOOK) OR (ASC("A")=>LOOK AND ASC("Z")=<LOOK) THEN SYM_TEXT="" DO SYM_TEXT = SYM_TEXT+LCASE$(CHR$(LOOK)) GetChar LOOP WHILE (LOOK>=ASC("a") AND LOOK<=ASC("z")) OR (LOOK>=ASC("A") AND LOOK<=ASC("Z")) OR (LOOK>=ASC("0") AND LOOK<=ASC("9")) OR LOOK>=ASC("_") SYM_TYPE=%SYM_STRING_CONST MathSkipWhite EXIT SUB ELSE SYM_TEXT="$" Match ASC("$") END IF CASE ASC("""") SYM_TEXT="" GetChar DO WHILE (LOOK<>ASC("""") AND ASC($CR)<>LOOK AND ASC($LF)<>LOOK) SYM_TEXT = SYM_TEXT+CHR$(LOOK) GetChar LOOP SYM_TYPE=%SYM_STRING_VAL IF ASC("""")=LOOK THEN Match ASC("""") MathSkipWhite ELSE MathSkipWhite END IF CASE ASC("(") SYM_TYPE=%SYM_LPARA #IF %DEBUG = %TRUE SYM_TEXT="(" #ENDIF Match ASC("(") EXIT SUB CASE ASC(")") SYM_TYPE=%SYM_RPARA #IF %DEBUG = %TRUE SYM_TEXT=")" #ENDIF Match ASC(")") EXIT SUB CASE ASC(",") SYM_TYPE=%SYM_KOMMA #IF %DEBUG = %TRUE SYM_TEXT="," #ENDIF Match ASC(",") EXIT SUB CASE ASC("[") #IF %DEBUG = %TRUE SYM_TEXT="[" #ENDIF SYM_TYPE=%SYM_LEPARA Match ASC("[") EXIT SUB CASE ASC("]") #IF %DEBUG = %TRUE SYM_TEXT="]" #ENDIF SYM_TYPE=%SYM_REPARA Match ASC("]") EXIT SUB CASE ASC("0") TO ASC("9") SYM_TEXT="" DO SYM_TEXT = SYM_TEXT+CHR$(LOOK) GetChar LOOP WHILE (LOOK>=ASC("0") AND LOOK<=ASC("9")) SYM_TYPE=%SYM_NUM MathSkipWhite EXIT SUB CASE ASC("a") TO ASC("z"),ASC("A") TO ASC("Z") SYM_TEXT="" DO SYM_TEXT = SYM_TEXT+LCASE$(CHR$(LOOK)) GetChar LOOP WHILE (LOOK>=ASC("a") AND LOOK<=ASC("z")) OR (LOOK>=ASC("A") AND LOOK<=ASC("Z")) OR (LOOK>=ASC("0") AND LOOK<=ASC("9")) OR LOOK>=ASC("_") SYM_TYPE=%SYM_ID MathSkipWhite EXIT SUB CASE ASC($CR),ASC($LF) SYM_TYPE=%SYM_EOL SYM_TEXT ="" SkipWhite EXIT SUB CASE %NUL SYM_TYPE=%SYM_EOS SYM_TEXT ="" CASE ELSE MSGBOX CHR$(LOOK) SYM_TYPE=%SYM_NUL SYM_TEXT ="" EXIT SUB END SELECT END SUB FUNCTION LOADFILE(FILENAME AS STRING) AS DWORD DIM FILENR AS DWORD DIM FILELOF AS DWORD DIM PUFFER AS STRING DIM MEM AS DWORD FILENR=FREEFILE OPEN FILENAME FOR BINARY AS FILENR FILELOF=LOF(FILENR) GET$ FILENR,FILELOF,PUFFER CLOSE#FILENR MEM=GetAsciiz(PUFFER) IF MEM = %FALSE THEN FUNCTION = %FALSE EXIT FUNCTION END IF INCR CURFILE FILE(CURFILE).FILE=GetAsciiz(FILENAME) FILE(CURFILE).LINENR = 1 FILE(CURFILE).MEM = MEM FILE(CURFILE).MEMPTR = MEM FUNCTION = %TRUE END FUNCTION |
||
E. Urbachehemals "Basicprogger" |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
@ArrangeMonk:
Sorry, hab ja vorher was gepostet, dachte das wär auf mich bezogen. Aber habe ich dich richtig verstanden mit dem Pseudo-Basic? Code: [AUSKLAPPEN] #define If if(
#define Then ) { #define Else } else { #define EndIf } Das ist aber eine seeehr schlechte Methode, nicht nur weil man #define besser meiden sollte, sondern weil man damit schnell auf Beschränkungen stößt. Außerdem hast du glaube ich das mit dem "Compiler" missverstanden, es geht nicht um die Übersetzung in Assembler/EXEs, sondern um die Übersetzung in C++ Code und das automatische Linken, so dass sich der User nicht damit auskennen muss. Na ja, wenn du's richtig verstanden hast, entschuldige bitte ![]() Zitat: Man könnte doch einen Quelltext in XML umwandeln. Das XML-Ausgabe-Format könnte man so gestalten, das es Programmiersprachen unabhängig ist. ...
Ist es zurzeit auch ![]() |
||
The box said, "Requires Windows XP or better", so I installed Ubuntu | Linux is NOT Windows
Flua :: Profiler für BB und BMax :: Partikel-Engine für BMax :: Lyphia-Projekt Quellcode (BMax) :: Automatische Parallelisierung :: Meine Musik |
![]() |
TheShadowModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
hm... Basicprogger
Du machst es dir ganz schön LEICHT - da du deine Token nicht weiter in Tree aufteilst... Dir ist dann doch schon klar, dass du dann so einen Code nicht einfach wahlweise nach C++ oder JS umwandeln kannst... damit meine ich sowas wie: <return> a * b + 7 </return> Korrekt müsste man Code: [AUSKLAPPEN] RETURN{KEYWORD:RETURN}
| +{SYMBOL:PLUS} / \ *{SYMBOL:MULT} 7{NUMBER:INT} / \ a{VARIABLE:INT} b{VARIABLE:FLOAT} in etwa so aufteilen - das ist jetzt vereinfacht - in wirklichkeit muß noch für a und b eine Tabelle existieren. Sind a und/oder b nicht in Tabelle - dann gibts Error. Die Typen von a und b werden aus Tabelle geholt. was du dann machst, weiß ich nicht da ich in C++ und nicht nach XML umwandeln würde, würde ich dann aus so einem Tree wieder einen C++ Code generieren... wobei einzelne Zweige wieder aufgelöst und dabei konvertiert werden müssen: Man löst das dann in etwa so auf: a ist INT und b ist FLOAT - Ergebis von * ist dann FLOAT * ist FLOAT und 7 ist INT - Ergebnis von + ist dann FLOAT RETURN liefert FLOAT zurück - ist der Rückgabetyp anders wie definiert, dann muss es wieder gewandelt werden - etwa nach INT. Ist Konvertierung nicht möglich, dann kommt Error. So wie ich sehe prüfst du das Ergebnis NICHT - wird bei RETURN ein Objekttyp oder Pointer erwartet - dann gibt es schon Probleme - meinst du nicht? Da JS z.B. gar keine Pointer hat - muss deine Sprache insgesamt auf Pointer verzichten. Du verstehst dann dass die Sprache limitiert wäre? D.h. du kannst später nicht C++ nach XML wandeln, da du überhaupt keien Pointer nutzen kannst - weswegen du dann auf Basic festsitzen würdest... Ich habe mir schon große gedanken gemacht und je mehr ich nachdachte, desto mehr habe ich begriffen, dass dieses Thema hochkomplex ist. Das was oben beschrieben ist - is z.B. nur ein Bruchteil - es wird komplex wenn man noch module, classen, methoden, vererbung, pointer usw. macht... ein Code wie !ptr = blub.slup() * 7 muß dann immer noch gut konvertiert werden können in C würde so ein Code am Ende etwa so aussehen: *ptr = blub->slup() * 7; Wobei ! nicht einfach durck * und . nicht einfach durch -> ersetzt werden, sondern aus dem TREE nach bestimmten Regeln konvertiert werden müssen. FÜr jede Art der Konvertierung aus dem Tree muß eine bestimmte Regel existieren. Genau wie für Typumwandlungen. Denn einige Typen können konvertiert werden BYTE->INT - andere dagegen müssen entw. explizit umgewandelt werden INT->BYTE - andernfalls gib es error. Ich persönlich wollte gerne einen "Compiler" coden, der alle Fehler abfangen würde - einzig Linkfehler von ld.exe (mingw) kann es dann nicht mehr abfangen... |
||
E. Urbachehemals "Basicprogger" |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
@TheShadow: Lass mich raten, du hast dir nicht den Speichermanagement-Teil in der PDF-Datei durchgelesen?
Ich versuch es nochmal konkreter zu beschreiben, meine vorherige Beschreibung war ja etwas abstrakt: Fangen wir ganz bei 0 an. Es gibt Types. Und es gibt Structs. Types sind Structs, aber sie werden dynamisch initialisiert. In BPC gibt es nur Types, sonst wäre es - wie du schon gesagt hast - nicht möglich, solche Dinge zu portieren. Es werden somit alle Variablen, die der User definiert, dynamisch angelegt. Jetzt zum GC von Java und der Sache mit JavaScript: Zitat: Da JS z.B. gar keine Pointer hat - muss deine Sprache insgesamt auf Pointer verzichten.
Sie verzichtet auf C-Pointer - aber nicht auf SharedPtr. Ich versuch es mal in Code auszudrücken: Code: [AUSKLAPPEN] Local window:Window = New Window("Hello", -1, -1, 640, 480)
Local button:Button = New Button("Test") window.Add(button) button.SetPosition(5, 5) button.SetSize(96, 24) button.OnClick(ShowMsg, "Hello World") Nun sieht der Code in C++ so aus: Code: [AUSKLAPPEN] Window window = new Window("Hello", -1, -1, 640, 480);
Button button = new Button("Test"); window->Add(button); button->SetPosition(5, 5); button->SetSize(96, 24); button->OnClick(ShowMsg, "Hello World"); window und button sind hier SharedPtr, keine Stack-Objekte. In Java sieht er fast genauso aus und bei JS ist es auch nur eine Frage der Syntax. Man kann es sogar sehr gut mit Java vergleichen: Ints, Floats, etc. werden per call by value übergeben, die Type-Instanzen per call by reference. Zitat: Man löst das dann in etwa so auf:
a ist INT und b ist FLOAT - Ergebis von * ist dann FLOAT * ist FLOAT und 7 ist INT - Ergebnis von + ist dann FLOAT RETURN liefert FLOAT zurück - ist der Rückgabetyp anders wie definiert, dann muss es wieder gewandelt werden - etwa nach INT. Ist Konvertierung nicht möglich, dann kommt Error. Ich hätt's nicht besser beschreiben können ![]() Zitat: Ich habe mir schon große gedanken gemacht und je mehr ich nachdachte, desto mehr habe ich begriffen, dass dieses Thema hochkomplex ist.
Ist dir aber früh aufgefallen ![]() Zitat: Du machst es dir ganz schön LEICHT - da du deine Token nicht weiter in Tree aufteilst...
Ja, ich weiß, erinnerst du dich noch an die Frage in meinem "Konzept-Thread"? Ich war mir nicht sicher, dann ist mir aber aufgefallen, dass man bei solchen Ausdrücken eigentlich nur ein simples String-Replace machen muss, um sie in andere Sprachen umzuwandeln. Ich beschäftige mich gerade mit den anderen Teilen des Parsers, um genau zu sein mit den Befehlen und der Operatoren-Priorität. Möglicherweise werde ich heute noch eine feinere Strukturierung mit typensicheren Ausdrücken implementieren. Ich habe dir ja gesagt, dass der Parser noch nicht fertig ist, lass mir noch ein wenig Zeit, dann kannst du mich zu Tode kritisieren ![]() |
||
The box said, "Requires Windows XP or better", so I installed Ubuntu | Linux is NOT Windows
Flua :: Profiler für BB und BMax :: Partikel-Engine für BMax :: Lyphia-Projekt Quellcode (BMax) :: Automatische Parallelisierung :: Meine Musik |
![]() |
TheShadowModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
aber ich verstehe nicht dein oberer Code (basic-like) sieht genau aus wie c++
da werden echt nur paar paar wörter getauscht... hm... Zitat: Ich war mir nicht sicher, dann ist mir aber aufgefallen, dass man bei solchen Ausdrücken eigentlich nur ein simples String-Replace machen muss, um sie in andere Sprachen umzuwandeln.
Das ist dir dirty-methode - wenn es geht, dann ok - die types MÜSSEN jedoch geprüft werden - andernfalls überlässt du es dem c++ compiler - der dann fehler ausspucken wird. Du wärst dann auch nicht in der Lage sein notwenige Konvertierungen durchzuführen... wie gesagt normal müssen die Tokens bis ins letzte Detail in tree abgebildet werden... |
||
AMD64 3500+ | GeForce6600GT 128MB | 1GB DDR | WinXPsp2 |
![]() |
Vertex |
![]() Antworten mit Zitat ![]() |
---|---|---|
Zitat: @Basicprogger
ich mein nicht dich, sondern vertex, dass der das nehmen soll aber die erschaffung eines neuen basic dialektes mit eigenem compiler und allem drum und dran is meines erachtens doof, da man sich mit headerfiles das ding includebar einfach im vc++ reinladne kann und dann mit nem {} klammer pseudo basic rumschreiben kann a) geht es hier darum, einen open source Compiler für Blitz2d und nicht für QBASIC zu schaffen und b) ist diese Test-Sprache nur dazu da, um zu sehen, wie kompliziert so etwas ist. Wie gesagt, ich habe eine kleine Test-Grammatik entwickelt, um zu sehen, ob das Projekt überhaupt ohne weiteres möglich ist. Erste Ergebnisse: MiniBasic (den Namen wird es sicher schon ein paar hundert mal geben, aber das ist ja wie gesagt nur ein Test) Beispiel Code: [AUSKLAPPEN] Const NUMBER : Int = 10
Var I : Int For I = 1 To NUMBER Print("Hallo Welt " + I) Next Der Scanner scheint einwandfrei zu funktionieren und der Parser meldet mir schon Syntaxfehler. Vorbereitungen für den AST sind getroffen. Ich muss nur die Rückgabe-Werte der ParseXYZ Methoden von True/False auf Null/Instanz umstellen. Bspw.: Code: [AUSKLAPPEN] Method ParseWhileLoop:TWhileLoop(Match:Int)
Rem WhileLoop = 'While' Expression {Statement} 'Wend'; End Rem Local WhileLoop : TWhileLoop Self.PushToken() ' 'While' If Not Self.MatchId(TOKEN_KW_WHILE, Match) Then Self.PopToken() Return Null EndIf Self.NextToken() WhileLoop = New TWhileLoop ' Expression WhileLoop.Condition = Self.ParseExpression(True) If Not WhileLoop.Condition Then Self.PopToken() Return Null EndIf ' {Statement} While WhileLoop.AddBody(Self.ParseStatement(False)) Wend ' 'Wend' If Not Self.MatchId(TOKEN_KW_WEND, True) Then Self.PopToken() Return Null EndIf Self.NextToken() Self.PopToken(True) Return WhileLoop End Method Basicprogger: Viel wichtiger wäre eine Beschreibung deiner XML "Sprache". Also welche Tags es gibt bzw. wenn es OpenSource ist, wo man den Source findet. mfg olli |
||
vertex.dreamfall.at | GitHub |
![]() |
TheShadowModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ha Vertex - ich dachte du hast die Sprachregeln aufgestellt und einen Parser geschrieben der nach den Regeln arbeitet - du hast es aber doch nativ eingecodet... ![]() So wie ich verstehe, dann fügst du alle token innerhalb von while zu einem while-object - und arbeitest den rest ebenfalls rekursiv ab... das ist auch eine interessante Lösung - die aber schon viel Speicher brauchen wird... hast du noch sowas wie ENDOFLINE-Token? ich hätte das z.B. anders gemacht... ich hätte alles zeilenweise gescant... ich weiß nicht ob es nun besser wäre... z.B. kommt LOOP - dann wird zu einer tabelle Loop-Signatur angefügt. Kommt dann FOR, dann wird For-Signatur zu Tabelle hinzugefügt. Kommt END, dann wird ein Eintrag aus Tabelle gelöscht usw... Ist etwas nicht möglich - z.B. FOR innerhalb von CLASS, dann kommt error. Dadurch wäre der Scanner "flach" - während dein jetziger scanner die Token mehrmals in "BLÖCKE" umpackt und so nur zeit verliert Man denke an CLASS>METHODE>WHILE>FOR>IF Für die CLASS müsstest du dann ersmal das ende von class suchen - und das liegt irgendwo 4x weiter - dann musst du für METHODE das Ende suchen usw... zuvor müsstest du noch den gesamten Code in Token aufteilen und im Speicher halten... Hm... |
||
AMD64 3500+ | GeForce6600GT 128MB | 1GB DDR | WinXPsp2 |
E. Urbachehemals "Basicprogger" |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Zitat: Basicprogger: Viel wichtiger wäre eine Beschreibung deiner XML "Sprache". Also welche Tags es gibt bzw. wenn es OpenSource ist, wo man den Source findet.
Projektseite Code Alle "Branches" Bug Reports Feature Requests Fragen Überarbeitete Dokumentation Kompilierte 64-Bit-Binary für Linux Alte Projektseite Wenn es dir nicht reicht, sag bescheid, dann kann ich weitere Informationen hinzufügen. @TheShadow: Ich habe die XML-Zwischenstufe entfernt ![]() In irgendeinem Format muss ich die Daten sowieso im Speicher halten, sonst kann ich keine Fehler abfangen. XML ist dazu bestens geeignet und hat einen sehr geringen Overhead. Das Interface habe ich jetzt ebenfalls verbessert. Es ist jetzt noch abstrakter als vorhin und prüft bereits, ob bestimmte Keywords in Klassen, Funktionen, etc. enthalten sein dürfen. Trotzdem bin ich noch weit vom Ziel entfernt - nämlich 95 % aller Fehler abzufangen (Linker-Fehler natürlich nicht, wie auch?). Das Parsen von mathematischen Ausdrücken werde ich ebenfalls implementieren, ich habe schon einen guten Ansatz, der nicht viel Zeit benötigt, er basiert auf der Operatorenpriorität, aber auf Details möchte ich hier nicht eingehen. Aktuelle Version ist zurzeit 0.1.4. Bei 0.5 werde ich die Beta auch für Windows kompilieren, dann kann sie jeder ausgiebig testen. |
||
The box said, "Requires Windows XP or better", so I installed Ubuntu | Linux is NOT Windows
Flua :: Profiler für BB und BMax :: Partikel-Engine für BMax :: Lyphia-Projekt Quellcode (BMax) :: Automatische Parallelisierung :: Meine Musik |
- Zuletzt bearbeitet von E. Urbach am Sa, Nov 03, 2007 14:21, insgesamt einmal bearbeitet
![]() |
Vertex |
![]() Antworten mit Zitat ![]() |
---|---|---|
TheShadow, jup aber ich habe da ein interessantes Tool gefunden:
Jaccie - ein Compiler-Compiler Also das Parser-Tool habe ich noch nicht zum laufen gebracht, aber selbst der Scanner ist nützlich. Der erzeugte Compiler ist allerdings Java-Code. minibasic.zip Aus dem Beispiel Code: [AUSKLAPPEN] Const NUMBER : Int = 10
Var I : Int For I = 1 To NUMBER Print("Hallo Welt " + I) Next Wird nun folgender AST generiert: Code: [AUSKLAPPEN] <?xml version="1.0"?>
<ast> <program> <constantDecleration> <constant> <decleration name="NUMBER" valueType="Integer" /> <expression> <simpleExpression> <term> <factor> <integer>10</integer> </factor> </term> </simpleExpression> </expression> </constant> </constantDecleration> <variableDecleration> <variable> <decleration name="I" valueType="Integer" /> </variable> </variableDecleration> <forLoop> <assignment> <identifier>I</identifier> <expression> <simpleExpression> <term> <factor> <integer>1</integer> </factor> </term> </simpleExpression> </expression> </assignment> <to> <expression> <simpleExpression> <term> <factor> <identifier>NUMBER</identifier> </factor> </term> </simpleExpression> </expression> </to> <functionCall> <identifier>Print</identifier> <expression> <simpleExpression> <term> <factor> <string>Hallo Welt </string> </factor> </term> <plus /> <simpleExpression> <term> <factor> <identifier>I</identifier> </factor> </term> </simpleExpression> </simpleExpression> </expression> </functionCall> </forLoop> </program> </ast> Man möge mir mal hier die grauenhafte Programmierung verzeihen. Das XML Modul habe ich jetzt nur auf die Schnelle hinein gequetscht, um überhaupt ein Ergebnis zu sehen. Basicprogger, sorry, kam jetzt den ganzen Tag nicht an den Code von dir ran. Gerade wo ich hier schreibe geht es nun auf einmal. Werde mich also später nochmal dazu äußern. mfg olli Edit: Ich hoffe, das ist die korrekte EBNF von BlitzBasic. Hat mich jetzt viel Nerven gekostet ![]() Code: [AUSKLAPPEN] (* Parser *)
Program = {ConstantDeclaration | Statement}; IncludeDirective = 'Include' StringLiteral; ConstantDeclaration = 'Const' Constant {',' Constant}; Constant = Identifier ['%' | '#' | '$'] '=' Expression; ArrayDeclaration = 'Dim' Identifier ['%' | '#' | '$' | '.' Identifier] '(' Expression {',' Expression} ')'; LocalDeclaration = 'Local' Variable {',' Variable}; GlobalDeclaration = 'Global' Variable {',' Variable}; Variable = Identifier ['%' | '#' | '$' | '.' Identifier] ['=' Expression]; DataDefinition = 'Data' Expression {',' Expression}; RestoreStatement = 'Restore' [Identifier]; ReadStatement = 'Read' Name {',' Name}; GotoStatement = 'Goto' Identifier; GosubStatement = 'Gosub' Identifier; IfStatement = ('If' Expression ['Then'] Statement) | ('If' Expression ['Then'] {Statement} {('ElseIf' | 'Else If') Expression ['Then'] {Statement}} ['Else' {Statement}] ('EndIf' | 'End If')); SelectStatement = 'Select' Expression {'Case' Expression {Statement}} ['Default' {Statement}] 'End Select'; ExitStatement = 'Exit'; ReturnStatement = 'Return'; RepeatStatement = 'Repeat' {Statement} ('Until' Expression | 'Forever'); WhileStatement = 'While' Expression {Statement} 'Wend'; ForStatement = 'For' Assignment 'To' Expression ['Step' Expression] {Statement} 'Next'; EachStatement = 'For' Name '=' 'Each' Identifier {Statement} 'Next'; AssignStatement = Name '=' ( | 'New' Identifier | BeforeExpression | AfterExpression | Expression); Name = Identifier ['.' Identifier] ['(' [Expression {',' Expression}] ')'] [{'\' Identifier}+ ['%' | '#' | '$']] | Identifier ['%' | '#' | '$' | '.' Identifier]; CallStatement = Identifier ('(' [Expression {',' Expression}] ')') | Identifier [Expression {',' Expression}]; InsertStatement = 'Insert' Name (BeforeExpression | AfterExpression); DeleteStatement = 'Delete' ('(' Name ')' | Name)); BeforeExpression = 'Before' ('(' Name ')' | Name)); AfterExpression = 'After' ('(' Name ')' | Name)); InsertStatement = 'Insert' Name ('Before' | 'After'); Statement = IncludeDirective | ArrayDeclaration | LocalDeclaration | GlobalDeclaration | RestoreStatement | ReadStatement | GotoStatement | GosubStatement | ExitStatement | ReturnStatement | IfStatement | SelectStatement | RepeatStatement | WhileStatement | ForStatement | EachStatement | AssignStatement | CallStatement Function = 'Function' Identifier ['%' | '#' | '$' | '.' Identifier] '(' [Variable {',' Variable}] ')' {('Return' ('(' Expression ')' | Expression)) | Statement} 'End Function'; TypeDeclaration = 'Type' Identifier {'Field' Identifier ['%' | '#' | '$' | '.' Identifier]} 'End Type'; Expression = ['Not'] BitExpression {'Not' BitExpression}; BitExpression = Relation {('And' | 'Or' | 'Xor') Relation}; Relation = AddExpression {RelationOperator AddExpression}; RelationOperator = '=' | '<>' | '><' | '<' | '<=' | '=<' | '>' | '>=' | '=>'; AddExpression = Shift {('+' | '-') Shift}; Shift = Term {('Shl' | 'Shr' |'Sar') Term}; Term = Power {('*' | '/' | 'Mod') Power}; Power = Unary {'^' Unary}; Unary = ['~'] Factor {'~' Factor}; Factor = IntegerLiteral | FloatLiteral | StringLiteral | '(' Expression ')' | TypeCast | Name; TypeCast = 'Int' '(' Expression ')' | 'Float' '(' Expression ')' | 'Str' '(' Expression ')'; (* Lexer *) Comment = ';' {CHARACTERS-?EOL?}; Digit = '0' | '1' | '2' | ... | '9'; BinaryDigit = '0' | '1'; HexDigit = Digit | 'A' | 'B' | 'C' | ... | 'F' | 'a' | 'b' | 'c' | ... | 'f'; Letter = 'A' | 'B' | 'C' | ... | 'Z' | 'a' | 'b' | 'c' | ... | 'z'; FloatLiteral = {Digit} '.' {Digit}; DecimalNumber = Digit {Digit}; BinaryNumber = '%' BinaryDigit {BinaryDigit}; HexNumber = '$' HexDigit {HexDigit}; IntegerLiteral = DecimalNumber | BinaryNumber | HexNumber; StringLiteral = '"' {CHARACTERS-('"' | ?EOL?)} '"'; Identifier = Letter {'_' | Letter | Digit}; Label = '.' Identifier; |
||
vertex.dreamfall.at | GitHub |
![]() |
TheShadowModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
hm vertex und blitzprogger - ich stelle fest ihr verfolgt fast das gleiche Ziel ![]() mittlerweile habe ich selbst wieder lust bekommen einen neuanfang zu wagen... ![]() Allerdings würde ich es wieder in C machen - und ohne XML, Compiler-Compiler und Co. |
||
AMD64 3500+ | GeForce6600GT 128MB | 1GB DDR | WinXPsp2 |
E. Urbachehemals "Basicprogger" |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
3 Personen an 3 Projekten mit 1 Ziel...wenn das mal gut geht...
Btw, der Parser für mathematische Ausdrücke ist jetzt fertig. Ein Code wie dieser Code: [AUSKLAPPEN] Local a:Int = 3
Local b:Int = 4 Local c:Int = 5 Local isPythagoreanTriple:Bool = (a^2 + b^2 = c^2) wird jetzt korrekt und bis ins Detail in einen AST umgewandelt: Code: [AUSKLAPPEN] <?xml version="1.0"?>
<module> <header> </header> <code> <local> <var name="a"> <type> Int </type> <value> 3 </value> </var> </local> <local> <var name="b"> <type> Int </type> <value> 4 </value> </var> </local> <local> <var name="c"> <type> Int </type> <value> 5 </value> </var> </local> <local> <var name="isPythagoreanTriple"> <type> Bool </type> <value> <compare> <term> <add> <term> <pow> <term> a </term> <term> 2 </term> </pow> </term> <term> <pow> <term> b </term> <term> 2 </term> </pow> </term> </add> </term> <term> <pow> <term> c </term> <term> 2 </term> </pow> </term> </compare> </value> </var> </local> </code> </module> Habe den neuen Code bereits hochgeladen, ist im Versionskontrollsystem zu finden. Edit: Wenn's irgendwen interessiert: Bin vom kommenden Montag bis Freitag nicht mehr erreichbar weil ich nach Berlin fahre, kann also auch keine Fragen zum Code oder anderen Sachen beantworten... |
||
The box said, "Requires Windows XP or better", so I installed Ubuntu | Linux is NOT Windows
Flua :: Profiler für BB und BMax :: Partikel-Engine für BMax :: Lyphia-Projekt Quellcode (BMax) :: Automatische Parallelisierung :: Meine Musik |
![]() |
Vertex |
![]() Antworten mit Zitat ![]() |
---|---|---|
Zum Thema mathematische Ausdrücke hier einen simplen Parser:
Code: [AUSKLAPPEN] SuperStrict
Framework BRL.Blitz Global In : String, .. Position : Int, .. Token : Byte ' Test In = "10<3^2+~~9/8*(20>2)" ' 10 Shl 3^2 + ~9/8*(20 Shr 2) Try Parse() Catch Exception:Object WriteStdout(Exception.ToString()) End Try End Function Parse:Int() Local Result:Int GetToken() Result = Expression() WriteStdout("Result: " + Result) End Function Function GetToken() If Position > In.Length - 1 Then Token = Asc("~n") Else Token = In[Position] EndIf Position :+ 1 End Function Function Match(Char:Byte) If Token = Char Then GetToken() Else Throw("Expected '" + Chr(Char) + "'") EndIf End Function Function Expression:Int() Local Result:Int Result = Shift() While Token = Asc("+") Or Token = Asc("-") If Token = Asc("+") GetToken() Result = Result + Shift() Else GetToken() Result = Result - Shift() EndIf Wend Return Result End Function Function Shift:Int() Local Result:Int Result = Term() While Token = Asc(">") Or Token = Asc("<") If Token = Asc(">") Then GetToken() Result = Result Shr Term() Else GetToken() Result = Result Shl Term() EndIf Wend Return Result End Function Function Term:Int() Local Result:Int Result = Power() While Token = Asc("*") Or Token = Asc("/") If Token = Asc("*") Then GetToken() Result = Result*Power() Else GetToken() Result = Result/Power() EndIf Wend Return Result End Function Function Power:Int() Local Result:Int Result = Unary() While Token = Asc("^") GetToken() Result = Result^Unary() Wend Return Result End Function Function Unary:Int() Local Result:Int If Token = Asc("~~") Then GetToken() Result = ~Factor() Else Result = Factor() EndIf Return Result End Function Function Factor:Int() Local Result:Int If Token = Asc("(") Then Match(Asc("(")) Result = Expression() Match(Asc(")")) Else Result = Number() EndIf Return Result End Function Function Number:Int() Local Result:Int While Token => Asc("0") And Token <= Asc("9") Result = Result*10 + Digit() Wend Return Result End Function Function Digit:Int() Local Result:Int If Token => Asc("0") And Token <= Asc("9") Then Result = Token - Asc("0") Match(Token) Else Throw("Expected Digit") EndIf Return Result End Function Vgl. zu Blitz: Code: [AUSKLAPPEN] Print 10 Shl 3^2 + ~9/8*(20 Shr 2)
Beide liefern 5115 als Ergebnis. Ansonsten bin ich gerade am Ball den FreeBlitz Scanner zu schreiben aber hierzu werde ich nun C# benutzen. Wäre zwar cool, das Projekt in BlitzMax zu entwickeln, bloß ist das Debugging bei BMax mir zu bescheiden. mfg olli |
||
vertex.dreamfall.at | GitHub |
![]() |
Vertex |
![]() Antworten mit Zitat ![]() |
---|---|---|
Joar, der FreeBlitz Scanner ist soweit fertig. Man kann in C# dann so etwas machen:
Code: [AUSKLAPPEN] scanner = new Scanner(@"C:\Test.bb");
// scanner = new Scanner(textCode.Text); token = scanner.NextToken(); while(token.Id != TokenId.EndOfFile) { switch(token.Id) { case TokenId.IntegerLiteral: // token.value break; case TokenId.StringLiteral: // token.value break; // ... case TokenId.EndFunction // ... } token = scanner.NextToken(); } Das ganze habe ich mal in 3 Minuten in eine Form gepappt und es funktioniert alles einwandfrei bis jetzt: ![]() Mal schauen, ob ich wirklich noch dazu einen Parser entwickle ![]() mfg olli Achja: Damit muss nicht erst der ganze Quellcode gescannt werden. Es reicht praktisch ein Parser mit 2 Pässen aus. Der erste, der benötigte Tokens analysiert und der zweite, der die semantische Analyse durchführt. |
||
vertex.dreamfall.at | GitHub |
lettorTrepuS |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
-aus Sicherheitsgründen gelöscht- Diese Information ist mit Ihrer Sicherheitsfreigabe leider nicht erhältlich, Bürger. | ||
porcus |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Wäre es nicht einfacher das ganze in BlitzMax zu machen ? | ||
*Account deaktiviert* |
Sebe |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Dann wäre das ganze ja durch BlitzMax limitiert.
Viel interessanter fände ich sowas für .Net/Mono. |
||
![]() |
mahe |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wenn es nicht richtig kompiliert wird kann man es gleich vergessen.
Diese ganzen virtuellen Maschinen mit ihrem seltsamen Byte-Code usw. sind für Spiele ziemlich ungeeignet (zumindest wenn es über Handy-Games hinausgehen soll). Das ist immer langsam, vorher muss der ganze Unsinn erst einmal installiert werden und überhaupt ist das irgendwie nervig und unnötig. Derzeit gibt es drei wichtige Plattformen (Win, Lin und Mac) und für die drei zu kompilieren ist doch nicht so ein Aufwand (siehe BMax). Für alle drei eine neue virtuelle Maschine zu erstellen wäre also unsinnig. Wenn das ganze aber nach C(++) konvertiert wird und ordentlich kompiliert wird, kann ich mir vorstellen, dass das was wird! |
||
ʇɹǝıdɯnɹɹoʞ ɹnʇɐuƃıs - ǝpoɥʇǝɯ-ɹoɹɹıɯ ɹǝp uı ,ɹoɹɹǝ, |
Gehe zu Seite Zurück 1, 2, 3, 4 Weiter
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group