Parser für Terme
Übersicht

![]() |
cooloBetreff: Parser für Terme |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo erstmal,
Nach langem eröffne ich nun wieder einen Theard: Ich mache im Moment meine 4. Scriptsprache. Und da bruche ich nun eine Stringrechen Funktion. Früher habe ich die calc Funktion von hier verwendet, aber die ist eindeutig zu langsam. Jetzt frage ich mich, wie stellt man sowas an? Hab schon oft was von Token und zerlegen gehört, aber mir fällt nichts ein... hoffe auf eure Hilfe |
||
http://programming-with-design.at/ <-- Der Preis ist heiß!
That's no bug, that's my project! "Eigenzitate sind nur was für Deppen" -Eigenzitat |
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
2. topic von oben im codearchiv...
https://www.blitzforum.de/foru...hp?t=27748 |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
![]() |
coolo |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ja eben, aber wie berechnet man das vor? | ||
http://programming-with-design.at/ <-- Der Preis ist heiß!
That's no bug, that's my project! "Eigenzitate sind nur was für Deppen" -Eigenzitat |
![]() |
Triton |
![]() Antworten mit Zitat ![]() |
---|---|---|
Damit keine Missverständnisse entstehen: es hat sich eher durchgesetzt Funktionen die einen Term zerlegen und ausrechnen können (z.B 2x²+x³(4/3x - 3)) als Parser zu bezeichnen und Funktionen die als Zahlenformat Strings nutzen und damit weiterrechnen als Stringrechenfunktionen.
Ich habe den Titel mal entsprechend geändert. |
||
Coding: silizium-net.de | Portfolio: Triton.ch.vu |
![]() |
aMulSieger des Minimalist Compo 01/13 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Du musst eine Funktion über den String laufen lassen, welche dann die Logik dahinter, also was in welcher Reihenfolge gemacht werden soll irgendwo speichert(ich denke, hier bieten sich Banks an).
Dann kannst du einfach immer durch diese Bank "durchrauschen" und hast die benötigten Sachen gleich in richtiger Reihenfolge drinstehen. Im Prinzip musst den String also in eine schneller lesbare Sprache übersetzen(=compilen). Das kann man übrigens auch gleich mit der ganzen Scriptsprache machen. Das zu programmieren ist natürlich nicht einfach, aber dafür ist das eigentlich Ausführen der Scripte dann wesentlich schneller. |
||
Panic Pong - ultimate action mashup of Pong and Breakout <= aktives Spiele-Projekt, Downloads mit vielen bunten Farben!
advASCIIdraw - the advanced ASCII art program <= aktives nicht-Spiele-Projekt, must-have für ASCII/roguelike/dungeon-crawler fans! Alter BB-Kram: ThroughTheAsteroidBelt - mit Quelltext! | RGB-Palette in 32²-Textur / Farbige Beleuchtung mit Dot3 | Stereoskopie in Blitz3D | Teleport-Animation Screensaver |
![]() |
coolo |
![]() Antworten mit Zitat ![]() |
---|---|---|
aMul, dieses Prinzip verwende ich auch in meiner scriptsprache (Der Worklog zu Tehadon hat mich dazu angeregt), aber ich komme nicht dazu, diese zu zerlegen, werde wohl grübeln müssen...
Bis dann |
||
http://programming-with-design.at/ <-- Der Preis ist heiß!
That's no bug, that's my project! "Eigenzitate sind nur was für Deppen" -Eigenzitat |
![]() |
aMulSieger des Minimalist Compo 01/13 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Falls du dir selbst was ausdenken willst, hier aufhören zu lesen. ![]() Ich denke, man könnte die interne Sprache am einfachsten als eine Folge von Anweisungen nach folgendem Schema umsetzen: Code: [AUSKLAPPEN] "y = x + (z * 2) + (a * 3)"
1. reserviere Speicher für zwei Werte 2. multipliziere z mit 2 und speichere das Ergebnis an Position 1 3. multipliziere a mit 3 und speichere das Ergebnis an Position 2 4. addiere den Wert aus Position 1 mit x und speichere das Ergebnis in Position 1 5. addiere den Wert aus Position 1 mit dem Wert aus Position 2 und speichere das Ergebnis in Position 1 6. weise y den Wert aus Position 1 zu 7. fertig Das übersetzen in diese Sprache wäre natürlich nicht ganz einfach, wenn man das Speicher optimiert nutzen möchte(obwohl man auch mein Beispiel noch optimieren könnte) und gleichzeitig doppelt vorkommende Teil-Terme nur einmal berechnen möchte um Geschwindigkeit zu sparen. Aber so lange man auf eines dieser Features verzichten kann, sollte das kein allzu großes Problem werden, denke ich. Das einzig komplizierte wäre, wenn man Variablen aus BB in der Scriptsprache benutzen wollte. Für sowas wären Pointer hervorragend geeignet, aber da hat BB ja gewisse Defizite. EDIT: Man könnte jeder Variable auf die die Scriptsprache zugreifen darf einen Wert zuweisen, der dann intern für den Namen verwendet wird. Dann bräuchte man allerdings zwei riesige Select-Case-Anweisungen zum umwandeln, ich weiß nicht wie viel Geschwindigkeit das ziehen würde, aber es sollte sich nicht so enorm auswirken. Man könnte es auch so machen, dass alle Variablen die geteilt werden gar keine Variablen sind, sondern alle in einer riesen Bank oder einem Array liegen. Dann würde das von Nummer zu Name übersetzen entfallen, da die Nummer gleich dem Index im Array wäre. Anderes Problem: Wenn man ausgiebigen Gebrauch von Scriptsprache macht, dann müssen die Dateien natürlich auch untereinander aufeinander zugreifen können (zum Teil). Das heißt man müsste eine Liste aller global verwendbaren Werte haben und das Programm müsste zwischen lokalem und globalem Speicher unterscheiden. Ich glaube ich habe gerade herausgefunden, warum ich sowas bisher noch nicht programmiert habe: Das ist verdammt kompliziert ![]() |
||
Panic Pong - ultimate action mashup of Pong and Breakout <= aktives Spiele-Projekt, Downloads mit vielen bunten Farben!
advASCIIdraw - the advanced ASCII art program <= aktives nicht-Spiele-Projekt, must-have für ASCII/roguelike/dungeon-crawler fans! Alter BB-Kram: ThroughTheAsteroidBelt - mit Quelltext! | RGB-Palette in 32²-Textur / Farbige Beleuchtung mit Dot3 | Stereoskopie in Blitz3D | Teleport-Animation Screensaver |
- Zuletzt bearbeitet von aMul am Di, Jun 24, 2008 21:10, insgesamt einmal bearbeitet
![]() |
coolo |
![]() Antworten mit Zitat ![]() |
---|---|---|
Für dieses Variablen Problem habe ich mich für eine Mischung aus TYpes und Arrays entschieden.
Da ich mich mit Banks nicht auskenne, werde ich diese Zwischenschritte einmal in eine Datei speichern und diese dann parsen. Jetzt werde ichs umsetzen |
||
http://programming-with-design.at/ <-- Der Preis ist heiß!
That's no bug, that's my project! "Eigenzitate sind nur was für Deppen" -Eigenzitat |
![]() |
aMulSieger des Minimalist Compo 01/13 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wenn du Types benutzen würdest hättest du das Problem tatsächlich gelöst, allerdings kann ich dir davon nur abraten, da Types im Verhältnis wirklich langsam sind.
Würde da lieber auf das von mir vorgeschlagene Select-Case-System zurückgreifen. Und wenn du dich mit Banks nicht auskennst, dann empfehle ich dir, das unbedingt nachzuholen. Ich bin mir sicher, du verstehst dass recht schnell(so schwer ist es nicht) und man kann mit Banks wirklich sehr viel machen. |
||
Panic Pong - ultimate action mashup of Pong and Breakout <= aktives Spiele-Projekt, Downloads mit vielen bunten Farben!
advASCIIdraw - the advanced ASCII art program <= aktives nicht-Spiele-Projekt, must-have für ASCII/roguelike/dungeon-crawler fans! Alter BB-Kram: ThroughTheAsteroidBelt - mit Quelltext! | RGB-Palette in 32²-Textur / Farbige Beleuchtung mit Dot3 | Stereoskopie in Blitz3D | Teleport-Animation Screensaver |
Matthias |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Hay.
@aMul. Deine vorgehensweise erinnert mich irgendwie an Asammbler. Das ist auch eine Geniale Idee. Ich wolte nur sagen das Banks immernoch langsammer sind als Dims. Allerdings ist der unterschied gering in gegensatz zu Types. Ich bin gespannt wie es weiter geht, und wie schnell es ist im Vergleich zur Blitz eigenden Berechnungsmethode. Naja mal sehen. Werde auch mal mein Glück versuchen. |
||
![]() |
coolo |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich gebs auf...
Hab jetzt lange probiert etwas anständiges zu machen, aber die Funktion ist einfach zu langsam... sie hat nur pnkt vor Strich und braucht 10ms um es auszurechnen... Code: [AUSKLAPPEN] z=MilliSecs()
Print rechnen("1+1*2+1") Print MilliSecs()-z WaitKey End Function rechnen(s$) s$=Replace(s$," ","") s$=Replace(s$,"--","+") s$=Replace(s$,"++","+") s$=Replace(s$,"---","-") s$=Replace(s$,"+-","-") s$=Replace(s$,"-+","+") Repeat If Instr(s$,"*") Then;Mal rechnen pos=Instr(s$,"*") zahl1=zahl1_herausfinden(pos,s$) zahl2=zahl2_herausfinden(pos,s$) zahl=zahl1*zahl2 s$=Replace(s$,zahl1+"*"+zahl2,zahl) Else Exit EndIf Forever Repeat If Instr(s$,"/") Then;Durch rechnen pos=Instr(s$,"/") zahl1=zahl1_herausfinden(pos,s$) zahl2=zahl2_herausfinden(pos,s$) zahl=zahl1/zahl2 s$=Replace(s$,zahl1+"/"+zahl2,zahl) Else Exit EndIf Forever Repeat If Instr(s$,"+") Then;Plus rechnen pos=Instr(s$,"+") zahl1=zahl1_herausfinden(pos,s$) zahl2=zahl2_herausfinden(pos,s$) zahl=zahl1+zahl2 s$=Replace(s$,zahl1+"+"+zahl2,zahl) Else Exit EndIf Forever Repeat If Instr(s$,"-") Then;Minus rechnen pos=Instr(s$,"-") zahl1=zahl1_herausfinden(pos,s$) zahl2=zahl2_herausfinden(pos,s$) WaitKey zahl=zahl1-zahl2 s$=Replace(s$,zahl1+"-"+zahl2,zahl) Else Exit EndIf Forever Return s End Function Function zahl2_herausfinden(pos,s$) v=pos b=pos+1 Repeat v=v+1 b=b+1 z=Mid(s$,v,b-v) If z=0 Then Exit Select z Case "+" Exit Case "-" Exit Case "*" Exit Case "/" Exit Case "^" Exit Case "(" Exit Case ")" Exit End Select Forever v=v-1 b=b-1 zahl1#=Float(Mid(s$,v,b-v)) Return zahl1# End Function Function zahl1_herausfinden(pos,s$) v=pos b=pos-1 Repeat v=v-1 b=b-1 If b=-1 Or v=0 Then Exit z=Mid(s$,v,b-v) Select z Case "+" Exit Case "-" Exit Case "*" Exit Case "/" Exit Case "^" Exit Case "(" Exit Case ")" Exit End Select Forever If v=0 Then v=v+1 b=b+1 EndIf zahl2#=Float(Mid(s$,v,b-v)) Return zahl2# End Function Ich weiß, der code ist katastrophal... und wenn man jetzt noch klammern dzu nimmt, wird es sicher 3mal langsamer... |
||
http://programming-with-design.at/ <-- Der Preis ist heiß!
That's no bug, that's my project! "Eigenzitate sind nur was für Deppen" -Eigenzitat |
Matthias |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Hay.
@Coolo. Nur Mut. Habe jetzt auch mal mein möglichstes versucht. Das es so kompliziert ist und so viel Zeit verschlingt hätte ich nicht gedacht. Nach 5 Versuchen habe ich jetzt wenigstens schonmal einen Ansatz zu stande gebracht. Ich glaube Ansatz ist schon zu viel. Aber drozdem will ich den Code Posten, um zu zeigen das ich mich damit befasse. Mit Zahlen selbst kann mann noch nicht rechnen, nur mit Variablen. Auch gibs noch keine Vorzeichen erkennung und nur *,/,- und Plus. Aber der Code ist Ausbaufähing und Optiemierbar. Code: [AUSKLAPPEN] Graphics 800,600,32,2 Dim Memory(5000) Dim OpName$(100) Dim VarName$(5000),VarWert(5000) OpName(1)="*" OpName(2)="/" OpName(3)="+" OpName(4)="-" Wert1=3 Wert2=4 Wert3=100 Wert4=2 Wert5=7 Wert6=8 Wert7=9 SetVar("Wert1",Wert1) SetVar("Wert2",Wert2) SetVar("Wert3",Wert3) SetVar("Wert4",Wert4) SetVar("Wert5",Wert5) SetVar("Wert6",Wert6) SetVar("Wert7",Wert7) SetVar("Ergebnis",1) Compelieren("Ergebnis=Wert1+Wert2+(Wert3+Wert6)*Wert4+Wert5") Wert=(Wert1+Wert2+(Wert3+Wert6)*Wert4+Wert5) PrgTimer=CreateTimer(60) SetBuffer BackBuffer() ;Standartberechnung ZeitA=MilliSecs() For I=0 To 50000 Wert=Wert1+Wert2+(Wert3+Wert6)*Wert4+Wert5 Next:ZeitA=MilliSecs()-ZeitA Delay 100 ;Meine berechnung ZeitB=MilliSecs() For I=0 To 50000:Rechnen():Next ZeitB=MilliSecs()-ZeitB AppTitle ZeitA+" "+ZeitB Erg=VarWert(FindVar("Ergebnis")) Repeat Wert5=Wert5+1 SetVar("Wert5",Wert5) Cls Rechnen() Text 10,250,Wert Text 10,300,VarWert(FindVar("Ergebnis")) Flip 0:WaitTimer(PrgTimer) Until KeyDown(1)=1 End Function Rechnen() Local VarMemory[20000],Mem=4 While Memory(Mem)<>0 ZErg=Memory(Mem+0) AddA=Memory(Mem+1) AddB=Memory(Mem+3) If AddA>9999 WertA=VarMemory[AddA] If AddA<10000 WertA=VarWert(AddA) If AddB>9999 WertB=VarMemory[AddB] If AddB<10000 WertB=VarWert(AddB) Select Memory(Mem+2) Case 42 VarMemory[ZErg]=WertA*WertB Case 47 VarMemory[ZErg]=WertA/WertB Case 43 VarMemory[ZErg]=WertA+WertB Case 45 VarMemory[ZErg]=WertA-WertB End Select:Mem=Mem+4 Wend:VarWert(Memory(0))=VarMemory[ZErg] End Function Function VarErsetzen$(Term$) L=Len(Term) For I=0 To L:St$=Mid(Term,I+1,1) Select St:Case ")" Kl$=Kl$+St Case "(" NTerm$=NTerm+ST:P=P+1 Case "=","+","-","*","/"," " V$=Replace(Mid(Term,P+1,I-P),")"," ") NTerm=NTerm+Right("00000"+FindVar(V),5) NTerm=NTerm+Kl+St:Kl="":If St<>")" P=I+1 End Select Next:Return NTerm End Function Function Compelieren(Term$) Local NAdd=10001,Mem=4 Term=Replace(Term,"=","=(")+") " Term=VarErsetzen(Term):Memory(0)=Left(Term,5) Repeat:P=0 Repeat:P=I:I=Instr(Term,"(",I+1):Until I=0 If P=0 Then Return Term OTTerm$=Mid(Term,P+1,Instr(Term,")",P)-P-1) TTerm$=OTTerm:OpZa=1 Repeat OpN$=OpName(OpZa) If OpN$="" Then Exit P=Instr(TTerm,OpN):If P=0 Then OpZa=OpZa+1 If P<>0 Then WertA$=Mid(TTerm,P-5,5):WertB$=Mid(TTerm,P+1,5) Memory(Mem)=NAdd:Memory(Mem+1)=Int(WertA) Memory(Mem+2)=Asc(OpN$):Memory(Mem+3)=Int(WertB) ATerm$=Right("00000"+NAdd,5):Mem=Mem+4:NAdd=NAdd+1 TTerm=Replace(TTerm,WertA+OpN$+WertB,ATerm) End If Forever Term=Replace(Term,"("+OTTerm+")",TTerm) Forever Return Term End Function Function FindVar(Name$) Name$=Trim(Name) While VarName(Add+1)<>"":Add=Add+1 If Name=VarName(Add) Return Add Wend End Function Function SetVar(Name$,Wert) While VarName(Add+1)<>"" If Name=VarName(Add+1) VarWert(Add+1)=Wert:Return Add=Add+1:Wend VarName(Add+1)=Name VarWert(Add+1)=Wert End Function Werde in den nästen Tagen den Code immer weiter ausbauen. Ziel ist eine Skriptsprache die Rechnen kann, und besonders schnell ist. |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group