Parser für Terme

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

coolo

Betreff: Parser für Terme

BeitragDi, Jun 24, 2008 17:47
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Jun 24, 2008 17:49
Antworten mit Zitat
Benutzer-Profile anzeigen
2. topic von oben im codearchiv...

https://www.blitzforum.de/foru...hp?t=27748
Gewinner der 6. und der 68. BlitzCodeCompo

coolo

BeitragDi, Jun 24, 2008 17:58
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Jun 24, 2008 19:45
Antworten mit Zitat
Benutzer-Profile anzeigen
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

aMul

Sieger des Minimalist Compo 01/13

BeitragDi, Jun 24, 2008 20:10
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Jun 24, 2008 20:14
Antworten mit Zitat
Benutzer-Profile anzeigen
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

aMul

Sieger des Minimalist Compo 01/13

BeitragDi, Jun 24, 2008 20:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Falls du dir selbst was ausdenken willst, hier aufhören zu lesen. Wink

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 Very Happy
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

BeitragDi, Jun 24, 2008 21:10
Antworten mit Zitat
Benutzer-Profile anzeigen
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

aMul

Sieger des Minimalist Compo 01/13

BeitragDi, Jun 24, 2008 21:15
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Jun 24, 2008 22:14
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragFr, Jun 27, 2008 7:19
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, Jun 28, 2008 16:44
Antworten mit Zitat
Benutzer-Profile anzeigen
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.

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group