Code archives/Miscellaneous/PsychoScript v0.5
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| So this is the first simple stages of my scripting language. I'm releasing this to GPU cause it's a bit sloppy. But yeah, you can add to it. Just make sure I get a bit of credit please! :) It has the feature of creating classes with functions and variables. Variables can hold integers floats and characters. You can also conform it to your app by creating custom functions, call-backs, and classes/objects. So that means it can be highly modifiable. I will release some classes and function modules later if this gets popular. !!!!!!!!!!!!!!!TEST SCRIPT! SAVE THIS AS "SIMPLEAPP.PS"!!!!! //THIS SIMPLE SCRIPT ASKS FOR THE USERS NAME AND GREETS THEM //========================================================== //Create new object from the stdio class. obj std = new stdio //Calls the custom module STD for an input function. //std.input saves data to std.buffer std.input("Whats your name? ") print("Hello there "+std.buffer+"! Welcome to the party!") std.input("Whats your age? ") var age%=std.buffer if age>=18 print("Wow! Your an adult!") else print("Cool! Still young!") endif !!!!!!!!!!!!!!!!!!!!!!TEST APPLICATION!!!!!!!!!!!!!!!!!!!!! Graphics 640,480,16,2 AppTitle "Simple Scripting Application" Include "ScriptEngine2.bb" Initialize(True) If Not LoadScript("SimpleApp") Then PromptError() ExecuteScript("SimpleApp") If CheckErrors() Then PromptError() Destroy() Print "<END OF SCRIPT>" WaitKey() End Function CallFunction(name$,param$) Select name$ Case "stdio::input" param$ = TrimEnds(param$) SetClassVariable(obj\name$,"buffer",dqt$+Input(param$)+dqt$) Default AddError("The requested function does not exist!","CallFunction") End Select End Function Function ClassConstructor.class(className$,objectName$) Select className$ Case "stdio" temp.class = New class temp\className$="stdio" temp\name$=objectName$ SetClassVariable(objectName$,"buffer","","$") Return temp Default AddError("The requested class does not exist!","ClassConstructor") End Select End Function | |||||
;Globals and other variables.
;============================
Global debug_mode=True,debug_file
Global last_error$,isError=False
Global last_tokcnt%
Global el$ = Chr$(10) + Chr$(13)
Global tb$ = Chr$(9)
Global dqt$ = Chr$(34)
Global inIf,isTrue=False,wasFalse=False
Global inFunction,runStart%,runFinish%,runTime%
Global temp1$,temp2$,temp3$,temp4$
Type error
Field msg$,caller$
End Type
Global er.error
Type token
Field value$,id%
End Type
Global tk.token,tk2.token
;===VARIABLE TYPE===
Type variable
Field name$,kind%,parent$
Field vStr$,vFlt#,vInt%,vFnc$ ;STRING$, FLOAT#, INTEGER%, FUNCTION-POINTER&
End Type
Global var.variable
;===COMPLEX CLASSES===
Type class
Field name$,className$
End Type
Global obj.class
Type scrLine
Field value$,parent$
End Type
Type fncLine
Field value$,parent$
End Type
Type script
Field name$,ln.scrLine
End Type
Global scr2.script
Type func
Field name$,params$,fln.fncLine
End Type
Global fnc.func,fncE.func
;Initializing and routine functions
;==================================
Function AddError(msg$,caller$)
er.error=New error
er\msg$=msg$
er\caller$=caller$
last_error$ = "["+caller$+"]: "+msg$
DebugOut("! ERROR: "+last_error$)
End Function
Function PrintErrors()
For er.error = Each error
Print "["+er\caller$+"]: "+er\msg$
Next
End Function
Function ClearErrors()
For er.error = Each error
Delete er
Next
last_error$=""
isError=False
End Function
Function CheckErrors(caller$="")
For er.error = Each error
If caller$=""
If er\msg$<>"" Then Return True
Else
If caller$=er\caller$ And er\msg$<>"" Then Return True
EndIf
Next
End Function
Function PromptError() ;Formats a runtimerror message for you! No using variables now!
msg$ = "AN ERROR HAS ACCURED:"+el$
msg$ = msg$ + tb$ +last_error$+el$
msg$ = msg$ + tb$ +"You can review the debug.log file for more information,"+el$
msg$ = msg$ + tb$ +"there could also be more errors found there."+el$
RuntimeError(msg$)
End Function
Function Initialize%(dbg%=False)
debug_mode = dbg%
If dbg%
debug_file=WriteFile("Debug.log") ;Just clear and write
If Not debug_file
AddError("Could not write debug log file!","Initialize")
Return False
EndIf
DebugOut("DEBUG LOG STARTED!")
DebugOut("DATE: "+CurrentDate$())
DebugOut("TIME: "+CurrentTime$())
DebugOut("==================")
EndIf
End Function
Function Destroy()
If debug_mode
CloseFile(debug_file)
EndIf
End Function
Function DebugOut(msg$)
If debug_mode=True
If debug_file<>0
WriteLine(debug_file,msg$)
Else
AddError("Debug file could not be writen to!","DebugOut")
EndIf
EndIf
End Function
Function PrintDebug%()
Local dfile = ReadFile("debug.log")
If Not dfile
AddError("Could not load debug log file!","PrintDebug")
Return False
EndIf
While Not Eof(dfile)
Print ReadLine(dfile)
Wend
CloseFile(dfile)
Return True
End Function
;PARSING AND TOKENIZER FUNCTIONS
;===============================
Function SimpleTokenize(inp$,sep$,prsvQt=True) ;This tokenizes by given character.
;Always sets ID To -1 for seperation. prsvQt option is for excluding sep$ charecters in quotes.
Local temp$,char$,stk.token,qt=False
For i = 1 To Len(inp$)
char$ = Mid(inp$,i,1)
If char$=sep$
If qt=False And prsvQt=True
stk.token = New token
stk\id% = -1
stk\value$ = temp$
temp$=""
EndIf
Else
If char$=dqt$
qt=Not qt
Else
temp$=temp$+char$
EndIf
EndIf
Next
If Len(temp$)>0
stk.token = New token
stk\id% = -1
stk\value$ = temp$
temp$=""
EndIf
End Function
Function AdvancedTokenize(inp$,id%=0,smb%=0) ;This tokenizes by symbols and characters! Spiffy huh?
;Allows for stack ordering with the id% parameter
;smb% is to start tokenizing by symbols first.
Local temp$,mode%=smb
Local char$,kind%,qt=False,par=False
For i = 1 To Len(inp$)
char$ = Mid(inp$,i,1)
;Check type of character symbol or character!
kind%=1
If Asc(char$)>=48 And Asc(char$)<=57;Number, counts as character
kind%=0
Else If Asc(Lower(char$))>=97 And Asc(Lower(char$))<=122;letter
kind%=0
Else If Asc(char$)=34 ;Quotes count too! SET QUOTE MODE
kind%=0
qt = Not qt
Else If Asc(char$)<>32 ;don't count spaces, symbol!
kind%=1
EndIf
;Check last type with mode and add to temp
If Not mode% ;characters
If Not kind% ;If character
temp$=temp$+char$
Else ;Broke loop add token and switch
If qt=False
If Trim(temp$)<>"" Then PushToken(temp$,id%)
If Trim(char$)<>"" Then PushToken(char$,id%)
mode%=1
Else
temp$=temp$+char$
EndIf
EndIf
Else ;Symbols
If kind%
If Trim(char$)<>"" Then PushToken(char$,id%)
Else ;Broke loop add token and switch back
temp$=char$;Right(temp$,Len(temp$)-1)
mode%=0
EndIf
EndIf
Next
If temp$<>""
PushToken(temp$,id%)
EndIf
End Function
Function PushToken(inp$,id%) ;Pushes a token to stack. Dunno why.
tk.token = New token
tk\value$ = inp$
tk\id% = id%
last_tokcnt% = last_tokcnt% + 1
End Function
Function PullToken$(id%=-1,del=True) ;Pull first token of matching ID, deletes after if del=True
Local rtn$
For tk.token = Each token
If tk\id%=id% Or id%=-1
rtn$=tk\value$
If del=True
Delete tk
EndIf
Exit
EndIf
Next
Return rtn$
End Function
Function GetToken$(pos%,id%=-1) ;Will retrieve token #
Local num%
For tk.token = Each token
If tk\id%=id% Or id%=-1
num%=num%+1
If num%=pos%
Return tk\value$
EndIf
EndIf
Next
AddError("Token number does not exist! Check ID# or Position#","GetToken()")
Return ""
End Function
Function GotoToken%(pos%)
Local cnt%
For tk.token = Each token
cnt%=cnt%+1
If cnt%=pos%
Return True
EndIf
Next
AddError("Token number does not exist! Check ID# or Position#","GotoToken()")
Return False
End Function
Function GetNextToken$(id%=0)
If id%=0
tk = After tk
Return tk\value$
Else
Repeat
tk = After tk
Until tk\id% = id%
Return tk\value$
EndIf
End Function
Function ClearTokens(id%=-1)
For tk.token = Each token
If tk\id%=id% Or id%=-1
Delete tk
EndIf
Next
last_tokcnt%=0
End Function
Function DebugTokens(id%=-1)
Local temp$
For tk.token = Each token
If tk\id%=id% Or id%=-1
temp$=temp$+"'"+tk\value$+"' "
EndIf
Next
DebugOut("~ TOKENS: "+temp$)
End Function
Function ContainsChar(inp$) ;Checks only for letters
If Asc(Lower(inp$))>=97 And Asc(Lower(inp$))<=122
Return True
EndIf
Return False
End Function
Function TrimEnds$(inp$,amnt=1) ;Trims off the ends
Return Mid(inp$,1+amnt,Len(inp$)-(1+amnt))
End Function
;DATA EDITING
;============
Function SetClassVariable(clName$,varName$,varValue$,varType$="$")
;Formats a variable to this...
; var [ClassName]_[VarName] = [VALUE] parent to cl_[ClassName]
SetVariable(clName$+"_"+varName$,varValue$,varType$,"cl_"+clName$)
End Function
Function GetClassVariable$(objName$,varName$) ;Returns the value from a obj.var run
Return FillVariable(objName$+"_"+varName$,True)
End Function
Function SetVariable(vname$,vvalue$,vtype$="$",parent$="",noChange=False)
Local found=False
For var.variable = Each variable
If var\name$=vname$ And var\parent$=parent$;Change value
If noChange=True
Return False
EndIf
Select var\kind%
Case 1 ;String
vvalue$ = Mid(vvalue$,2,Len(vvalue$)-2) ;Strip quotes
var\vStr$=vvalue$
Case 2 ;Float
var\vFlt#=Float(vvalue$)
Case 3 ;Integer
var\vInt%=Int(vvalue$)
Case 4 ;Function Pointer
vvalue$ = Mid(vvalue$,2,Len(vvalue$)-2) ;Strip quotes
var\vFnc$=vvalue$
Default
AddError("Memory Access Violation, variable type incorrect!","SetVariable")
End Select
EndIf
Next
If Not found
var.variable = New variable
var\name$ = vname$
var\parent$ = parent$
Select vtype$
Case "$"
var\kind%=1
vvalue$ = Mid(vvalue$,2,Len(vvalue$)-2) ;Strip quotes
var\vStr$=vvalue$
Case "#"
var\kind%=2
var\vFlt#=Float(vvalue$)
Case "%"
var\kind%=3
var\vInt%=Int(vvalue$)
Case "&"
var\kind%=4
vvalue$ = Mid(vvalue$,2,Len(vvalue$)-2) ;Strip quotes
var\vFnc$=vvalue$
Default
AddError("Memory Access Violation, variable type incorrect!","SetVariable")
End Select
EndIf
End Function
Function FillVariable$(inp$,clr=True) ;Returns variable value as string
;CLR is whether to return empty "" if not found, else return original input
For var.variable = Each variable
If var\name$ = inp$
Select var\kind%
Case 1 ;String
Return var\vStr$
Case 2 ;Float
Return Str(var\vFlt#)
Case 3 ;Integer
Return Str(var\vInt%)
Case 4 ;Function Pointer
Return var\vFnc$
Default
AddError("Memory Access Violation, variable type incorrect!","FillVariable")
End Select
EndIf
Next
Return inp$
End Function
;SCRIPTING FUNCTIONS
;===================
Function CreateNewScript%(name$) ;Pretty easy huh? Works off the global variable scr2.script to add to
;Search if name is taken
For scr2.script = Each script
If scr2\name$ = name$
AddError("A script with that name already exists!","CreateNewScript")
Return False
EndIf
Next
scr2.script = New script
scr2\name$ = name$
DebugOut("- INFO: Created new script named '"+name$+"'")
Return True
End Function
Function AddLineToScript%(inp$,name$) ;Add line of inp$ to script named name$
If Trim(inp$)="" Then Return True
If Left(inp$,2)="//" Then Return True
For scr2.script = Each script
If scr2\name$ = name$
;!!! Parse inputting line!
inp$ = Replace(inp$,Chr$(9),"")
ClearTokens()
AdvancedTokenize(inp$)
tk.token = First token
Select Lower(Trim(tk\value$))
Case "function"
If inFunction=True
AddError("Can not declare function inside of another!","AddLineToScript")
Return False
EndIf
temp1$ = GetNextToken$()
temp2$ = ""
temp3$ = ""
If GetNextToken$()="(" ;Just make sure
For i=1 To last_tokcnt%-3
temp$ = GetNextToken$()
If temp$=")" ;Ship out parameters
Exit
Else
If temp$="," ;Register variable
SetVariable(Left(temp3$,Len(temp3$)-1),"",Right(temp3$,1),temp1$,True)
temp3$ = temp3$ + temp$
temp2$ = temp2$ + temp3$
temp3$ = ""
Else
temp3$ = temp3$ + temp$
EndIf
EndIf
Next
If Len(temp3$)<>0
SetVariable(Left(temp3$,Len(temp3$)-1),"",Right(temp3$,1),temp1$,True)
temp3$ = temp3$ + temp$
temp2$ = temp2$ + temp3$
temp3$ = ""
EndIf
;!!! NOW SAVE FUNCTION AND SET TO READ MODE!
fnc.func = New func
fnc\name$ = temp1$
fnc\params$ = temp2$
inFunction = True
Else
AddError("Incorrect format for function!","AddLineToScript")
EndIf
Case "endfunction" ;Now end it!
If Not inFunction
AddError("Function must first be initialized before ended!","AddLineToScript")
Return False
EndIf
inFunction = False
Default ;Just add the line to the script
If Not inFunction
scr2\ln.scrLine = New scrLine
scr2\ln\parent$ = name$
scr2\ln\value$ = inp$
Else
fnc\fln.fncLine = New fncLine
fnc\fln\parent$ = fnc\name$
fnc\fln\value$ = inp$
EndIf
End Select
Return True
EndIf
Next
AddError("Could not add line to script named '"+name$+"'!","AddLineToScript")
Return False
End Function
Function LoadScript%(name$) ;Loads a script named 'Scripts\'+name$+'.ps'
For scr2.script = Each script
If scr2\name$ = name$
AddError("A script with that name already exists!","LoadScript")
Return False
EndIf
Next
file = ReadFile("Scripts\"+name$+".ps")
If Not file
AddError("Could not find file named Scripts\"+name$+".ps!","LoadScript")
Return False
EndIf
scr2.script=New script
scr2\name$=name$
While Not Eof(file)
AddLineToScript(ReadLine(file),name$)
Wend
CloseFile(file)
DebugOut("- INFO: Loaded script with name '"+name$+"'")
Return True
End Function
Function ExportScript(name$) ;Exports the script, results is after pre-parseing.
;Only useful if saving programaticly generated scripts. Its de-commented and de-blank-lined
For scr2.script = Each script
If scr2\name$ = name$
Local temp = WriteFile("Scripts\"+name$+"_exp.ps")
For scr2\ln.scrLine = Each scrLine
If scr2\ln\parent$ = name$
WriteLine(temp,scr2\ln\value$)
EndIf
Next
CloseFile(temp)
EndIf
Next
End Function
Function ExecuteScript(name$)
runStart% = MilliSecs()
Local found=False
For scr2.script = Each script
If scr2\name$ = name$
found = True
Exit
EndIf
Next
If Not found Then AddError("No script found with the name '"+name$+"'","ExecuteScript")
;Now we can start execution. We don't bother with ; characters. each line is a single call.
For scr2\ln.scrLine = Each scrLine
If scr2\ln\parent$ = name$
ClearTokens()
AdvancedTokenize(scr2\ln\value$) ;BUILD TOKEN BANK
DebugTokens() ;PRINT OUT THE TOKENS
ParseTokens() ;ILLETERATE AND PARSE (NO IDEA ABOUT ID NUMS)
EndIf
Next
runFinish% = MilliSecs()
runTime% = runFinish%-runStart%
DebugOut("- INFO: Time to execute = "+runTime%+"/ms")
End Function
Function ExecuteFunction() ;Works off global variable fncE.func for function to be executed
For fncE\fln.fncLine = Each fncLine
If fncE\fln\parent$ = fncE\name$
ClearTokens()
AdvancedTokenize(fncE\fln\value$)
DebugTokens()
ParseTokens()
EndIf
Next
End Function
Function ParseTokens() ;Parsing! Check the first, then start formatting!
tk.token = First token ;Some other functions set this to the end
Select Lower(Trim(tk\value$)) ;Only need to check the first one
Case "var" ;Settting variable!
If inIf=False Or ifTrue=True
temp1$=GetNextToken$() ;Name
temp2$=GetNextToken$() ;Type
If GetNextToken$()="=" ;Set initial value
temp3$ = GetNextToken$()
If last_tokcnt%>5 ;THERES MORE!?!?
For i=1 To last_tokcnt%-5
temp3$=temp3$+GetNextToken$()
Next
temp3$ = ParseVariables(temp3$)
EndIf
Else ;Set empty
If temp2$="$"
temp3$=""
Else
temp3$="0"
EndIf
EndIf
SetVariable(temp1$,temp3$,temp2$)
DebugOut("- INFO: Variable '"+temp1$+"' was assigned '"+temp3$+"'!")
EndIf
Case "obj" ;Object handle
If inIf=False Or ifTrue=True ;If statements... take up space but oh well
temp1$=GetNextToken$() ;Object name
If GetNextToken$()="=" ;As it should be
temp2$=GetNextToken$() ;Operator, just use new
Select temp2$
Case "new"
temp3$=GetNextToken$() ;Class name!
obj = ClassConstructor(temp3$,temp1$)
Default
AddError("Unknown creation operator!","ExecuteScript")
End Select
Else
AddError("Expected = operator at object creation!","ExecuteScript")
EndIf
EndIf
Case "if"
isTrue=False
If inIf=False
inIf=True
If (last_tokcnt%-1)>4 ;Muliple statements
For i=1 To (last_tokcnt%-1)/4
Next
Else ;Just a single statement
temp1$=GetNextToken$() ;value 1
temp2$=GetNextToken$() ;operator
temp3$=GetNextToken$() ;operator
temp4$=GetNextToken$() ;value 2
temp1$=ParseVariables(temp1$)
temp4$=ParseVariables(temp4$)
If ContainsChar(temp1$)=False And ContainsChar(temp4$)=False
var1#=Float(temp1$)
var2#=Float(temp2$)
EndIf
DebugOut(temp1$+" "+temp2$+temp3$+" "+temp4$)
If temp2$="=" And temp3$="=" ;EQUAL
If temp1$=temp4$ Then isTrue=True
Else If temp2$=">" And temp3$="=" ;LESS THEN EQUAL
If temp1$>=temp4$ Then isTrue=True
Else If temp2$="<" And temp3$="=" ;GREATER THEN EQUAL
If temp1$<=temp4$ Then isTrue=True
Else If temp2$=">" And temp3$=">" ;GREATER THEN
If temp1$>temp4$ Then isTrue=True
Else If temp2$="<" And temp3$="<" ;LESS THEN
If temp1$<temp4$ Then isTrue=True
Else If temp2$="<" And temp3$=">" ;NOT EQUAL
If temp1$<>temp4$ Then isTrue=True
Else If temp2$="!" And temp3$="=" ;NOT EQUAL
If temp1$<>temp4$ Then isTrue=True
Else
AddError("ParseTokens::If - Invalid operator!","ExecuteScript")
EndIf
EndIf
If isTrue=False
wasFalse=True
Else
wasFalse=False
DebugOut("False")
EndIf
Else
AddError("ParseTokens::If - IF can only appear once in this statement!","ExecuteScript")
EndIf
Case "elseif"
isTrue=False
If inIf=True
If wasFalse=True
If (last_tokcnt%-1)>4 ;Muliple statements
For i=1 To (last_tokcnt%-1)/4
Next
Else ;Just a single statement
temp1$=GetNextToken$() ;value 1
temp2$=GetNextToken$() ;operator
temp3$=GetNextToken$() ;operator
temp4$=GetNextToken$() ;value 2
temp1$=ParseVariables(temp1$)
temp4$=ParseVariables(temp4$)
If ContainsChar(temp1$)=False And ContainsChar(temp4$)=False
var1#=Float(temp1$)
var2#=Float(temp2$)
EndIf
DebugOut(temp1$+" "+temp2$+temp3$+" "+temp4$)
isTrue=False
If temp2$="=" And temp3$="=" ;EQUAL
If temp1$=temp4$ Then isTrue=True
Else If temp2$=">" And temp3$="=" ;LESS THEN EQUAL
If temp1$>=temp4$ Then isTrue=True
Else If temp2$="<" And temp3$="=" ;GREATER THEN EQUAL
If temp1$<=temp4$ Then isTrue=True
Else If temp2$=">" And temp3$=">" ;GREATER THEN
If temp1$>temp4$ Then isTrue=True
Else If temp2$="<" And temp3$="<" ;LESS THEN
If temp1$<temp4$ Then isTrue=True
Else If temp2$="<" And temp3$=">" ;NOT EQUAL
If temp1$<>temp4$ Then isTrue=True
Else If temp2$="!" And temp3$="=" ;NOT EQUAL
If temp1$<>temp4$ Then isTrue=True
Else
AddError("ParseTokens::If - Invalid operator!","ExecuteScript")
EndIf
EndIf
If isTrue=False
wasFalse=True
Else
wasFalse=False
DebugOut("False")
EndIf
EndIf
Else
AddError("ParseTokens::ElseIf - Requires an IF statement first!","ExecuteScript")
EndIf
Case "else"
isTrue=False
If inIf=True
If wasFalse=True ;No true statements yet
isTrue = True ;This one is true, execute script
EndIf
Else
AddError("ParseTokens::Else - Requires an IF statement first!","ExecuteScript")
EndIf
Case "endif"
If inIf=True
inIf=False
Else
AddError("ParseTokens::EndIf - Requires an IF statement first!","ExecuteScript")
EndIf
Default ;Function!
If inIf=False Or isTrue=True
temp1$ = tk\value$ ;Function, or variable/object to change
temp2$ = GetNextToken$() ;If ( then parse for function, else if = then variable
temp3$ = ""
If temp2$ = "(" ;Dealing with Function
For i=1 To last_tokcnt%-2
temp$ = GetNextToken$()
If temp$=")" ;Ship out parameters
Exit
Else
temp3$ = temp3$ + temp$
EndIf
Next
RunFunction(temp1$,temp3$)
Else If temp2$ = "=" ;Re-assigning variable
temp3$ = GetNextToken$()
If last_tokcnt%>3 ;THERES MORE!?!?
For i=1 To last_tokcnt%-3
temp3$=temp3$+GetNextToken$()
Next
temp3$ = ParseVariables(temp3$)
EndIf
SetVariable(temp1$,temp3$)
Else If temp2$ = "." ;Object operation
temp2$ = GetNextToken$() ;Var Name, or function name
temp4$ = GetNextToken$()
If temp4$ = "=" ;Setting variable
temp3$ = GetNextToken$()
If last_tokcnt%>5 ;THERES MORE!?!?
For i=1 To last_tokcnt%-5
temp3$=temp3$+GetNextToken$()
Next
temp3$ = ParseVariables(temp3$)
EndIf
SetClassVariable(temp1$,temp2$,temp3$)
DebugOut("SETTING TO var "+temp1$+"."+temp2$+"="+temp3$)
Else temp4$ = "("
For i=1 To last_tokcnt%-4
temp$ = GetNextToken$()
If temp$=")" ;Ship out parameters
Exit
Else
temp3$ = temp3$ + temp$
EndIf
Next
For obj.class = Each class
If obj\name$ = temp1$ ;Getting className$
temp2$=obj\className$+"::"+temp2$ ;Compile the function for calling
Exit
EndIf
Next
CallFunction(temp2$,temp3$)
EndIf
Else ;Show error
AddError("ParseTokens::Default - Unknown command, or incorrect format!","ExecuteScript")
EndIf
EndIf
End Select
End Function
Function ParseVariables$(inp$) ;Fills variables AND Formats string concenations
Local temp$,temp2$,found,mode%
ClearTokens()
AdvancedTokenize(inp$)
For tk.token = Each token
found=False
For tmp.class = Each class
If tk\value$=tmp\name$ ;Heres a class!
If GetNextToken$()="."
tname$=GetNextToken$()
temp2$=FillVariable(tmp\name$+"_"+tname$,True)
temp2$=Replace(temp2$,dqt$,"") ;Remove quotes
temp$ = temp$ + temp2$
DebugOut("- INFO: Filled class variable "+tmp\name$+"."+tname$+" with "+temp2$)
found=True
Exit
Else
AddError("A period after the object name is required!","ParseVariable")
EndIf
EndIf
Next
If found=False
temp2$ = FillVariable(tk\value$,False) ;Fill all variables
temp2$=Replace(temp2$,dqt$,"") ;Remove quotes
temp$ = temp$ + temp2$
EndIf
Next
If ContainsChar(temp$) ;Concenation
temp$ = Replace(temp$,"+","") ;This should do it. No advanced parsing
Else
temp$ = MathToString$(temp$)
EndIf
Return temp$
End Function
Function ParseParameters(fname$,params$) ;Fills function variables with params
Local toknum%=0,varnum%,found
ClearTokens()
SimpleTokenize(params$,",")
For tk2.token = Each token
If tk2\id%=-1 ;This is our simple tokens, each one is conveniently our parameter
toknum%=toknum%+1
varnum%=0:found=False
For var.variable = Each variable
If var\parent$ = fname$
varnum% = varnum% + 1
If varnum% = toknum% ;Alignment is crucial
found=True
Select var\kind%
Case 1
var\vStr$ = tk2\value$
Case 2
var\vFlt# = Float(tk2\value$)
Case 3
var\vInt% = Int(tk2\value$)
Case 4
var\vFnc$ = tk2\value$
End Select
EndIf
EndIf
Next
If Not found
AddError("To many parameters!","ParseParameters")
EndIf
EndIf
Next
End Function
Function RunFunction(fname$,fparam$) ;Function name, and compiled parameters.
fparam$ = ParseVariables$(fparam$) ; Fill variables now
DebugOut("- INFO: Function '"+fname$+"' called with parameter(s) '"+fparam$+"'")
;ORDER ENABLES OVER-RIDING! BEWARE!
For fnc.func = Each func
If fnc\name$=fname$
fncE = fnc
ParseParameters(fname$,fparam$)
ExecuteFunction()
Return True
EndIf
Next
Select Lower(fname$) ;Pick function, will parse parameters per function
Case "print" ;OUR FIRST FUNCTION!
Print ">"+fparam$ ;Simple huh. Doesn't parse number or params or anything
Default
CallFunction(Lower(fname$),fparam$)
End Select
End Function
;THIRD PARTY FUNCTIONS (I DIDN'T WRITE THESE BUT THEY ARE GNU)
;=============================================================
Function MathToString$(TheMath$, unit = 0, divnow = 0)
Local MyParam$ = "*/^+-=<>&|%@", MyNumbs$ = "0123456789.", MyDivParam$ = "*/^"
Local Ziffer$, ScanPos, MathAnswer#, MathArt$, MathPower#, OldMathPower#
Local Scan, ScanNumber$, OldScanNumber$, MathScan$, MyScanText$
Local bscan, bscannow, bscanhave, ScanPosA, ScanPosB
Local deScan, deMathScan$, deMath
Local debsScan
TheMath$ = Lower(TheMath$)
TheMath$ = Replace(TheMath$, "and", "&")
TheMath$ = Replace(TheMath$, "xor", "@")
TheMath$ = Replace(TheMath$, "or", "|")
TheMath$ = Replace(TheMath$, "mod", "%")
MathScan$ = Replace(TheMath$, " ", "") : debsScan = 1
While bscan < Len(MathScan$)
bscan = bscan + 1
If Mid$(MathScan$, bscan, 1) = "(" Then
ScanPosA = bscan : bscannow = 1
While bscannow
If Mid$(MathScan$, bscan, 1) = "(" Then bscanhave = bscanhave + 1
If Mid$(MathScan$, bscan, 1) = ")" Then bscanhave = bscanhave - 1
If bscanhave = 0 Then bscannow = 0
bscan = bscan + 1
If KeyDown(1) Then End
Wend
ScanPosB = bscan
MyScanText$ = Mid$(MathScan$, ScanPosA+1, ScanPosB - ScanPosA - 2)
MyScanText$ = MathToString$(MyScanText$, unit + 1)
MathScan$ = Replace(MathScan$, Mid$(MathScan$, ScanPosA, ScanPosB - ScanPosA), MyScanText$)
bscan = 0
End If
If KeyDown(1) Then End
Wend
.NewMathScan
deMathScan$ = MathScan$
Scan = InMid$(MathScan$, MyParam$)
If Scan Then
ScanNumber$ = Mid$(MathScan$, 1, Scan-1)
MathScan$ = Mid$(MathScan$, Scan)
MathAnswer = val2(ScanNumber$)
Else
Return MathScan$
End If
deScan = 1
While Not MathScan$ = ""
uu$ = MathScan$
MathArt$ = Mid$(MathScan$, 1, 1)
MathScan$ = Mid$(MathScan$, 2)
If Mid$(MathScan$,1,1) = "-" Then
MathPower# = -1
MathScan$ = Mid$(MathScan$, 2)
Else
MathPower# = 1
End If
Scan = InMid$(MathScan$, MyParam$)
OldScanNumber$ = ScanNumber$
OldMathPower# = MathPower#
ScanNumber$ = Mid$(MathScan$, 1, Scan-1)
MathScan$ = Mid$(MathScan$, Len(ScanNumber$)+1)
If MathArt$ = "+" Then
MathAnswer# = MathAnswer# + (val2(ScanNumber$)*MathPower#)
ElseIf MathArt$ = "-" Then
MathAnswer# = MathAnswer# - (val2(ScanNumber$)*MathPower#)
ElseIf MathArt$ = "*" Then
MathAnswer# = (val2(OldScanNumber$)*OldMathPower#) * (val2(ScanNumber$)*MathPower#)
If MathPower# = -1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "*-" + ScanNumber$, "-" + Str$(MathAnswer))
ElseIf MathPower# = 1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "*" + ScanNumber$, Str$(MathAnswer))
End If
Goto NewMathScan
ElseIf MathArt$ = "/" Then
MathAnswer# = (val2(OldScanNumber$)*OldMathPower#) / (val2(ScanNumber$)*MathPower#)
If MathPower# = -1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "/-" + ScanNumber$, "-" + Str$(MathAnswer))
ElseIf MathPower# = 1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "/" + ScanNumber$, Str$(MathAnswer))
End If
Goto NewMathScan
ElseIf MathArt$ = "^" Then
MathAnswer# = (val2(OldScanNumber$)*OldMathPower#) ^ (val2(ScanNumber$)*MathPower#)
If MathPower# = -1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "^-" + ScanNumber$, "-" + Str$(MathAnswer))
ElseIf MathPower# = 1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "^" + ScanNumber$, Str$(MathAnswer))
End If
Goto NewMathScan
ElseIf MathArt$ = "=" Then
MathAnswer# = (val2(OldScanNumber$)*OldMathPower#) = (val2(ScanNumber$)*MathPower#)
If MathPower# = -1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "=-" + ScanNumber$, "-" + Str$(MathAnswer))
ElseIf MathPower# = 1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "=" + ScanNumber$, Str$(MathAnswer))
End If
Goto NewMathScan
ElseIf MathArt$ = "<" Then
MathAnswer# = (val2(OldScanNumber$)*OldMathPower#) < (val2(ScanNumber$)*MathPower#)
If MathPower# = -1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "<-" + ScanNumber$, "-" + Str$(MathAnswer))
ElseIf MathPower# = 1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "<" + ScanNumber$, Str$(MathAnswer))
End If
Goto NewMathScan
ElseIf MathArt$ = ">" Then
MathAnswer# = (val2(OldScanNumber$)*OldMathPower#) > (val2(ScanNumber$)*MathPower#)
If MathPower# = -1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + ">-" + ScanNumber$, "-" + Str$(MathAnswer))
ElseIf MathPower# = 1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + ">" + ScanNumber$, Str$(MathAnswer))
End If
Goto NewMathScan
ElseIf MathArt$ = "&" Then
MathAnswer# = (val2(OldScanNumber$)*OldMathPower#) And (val2(ScanNumber$)*MathPower#)
If MathPower# = -1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "&-" + ScanNumber$, "-" + Str$(MathAnswer))
ElseIf MathPower# = 1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "&" + ScanNumber$, Str$(MathAnswer))
End If
Goto NewMathScan
ElseIf MathArt$ = "|" Then
MathAnswer# = (val2(OldScanNumber$)*OldMathPower#) Or (val2(ScanNumber$)*MathPower#)
If MathPower# = -1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "|-" + ScanNumber$, "-" + Str$(MathAnswer))
ElseIf MathPower# = 1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "|" + ScanNumber$, Str$(MathAnswer))
End If
Goto NewMathScan
ElseIf MathArt$ = "%" Then
MathAnswer# = (val2(OldScanNumber$)*OldMathPower#) Mod (val2(ScanNumber$)*MathPower#)
If MathPower# = -1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "%-" + ScanNumber$, "-" + Str$(MathAnswer))
ElseIf MathPower# = 1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "%" + ScanNumber$, Str$(MathAnswer))
End If
Goto NewMathScan
ElseIf MathArt$ = "@" Then
MathAnswer# = (val2(OldScanNumber$)*OldMathPower#) Xor (val2(ScanNumber$)*MathPower#)
If MathPower# = -1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "@-" + ScanNumber$, "-" + Str$(MathAnswer))
ElseIf MathPower# = 1 Then
MathScan$ = Replace(deMathScan$, OldScanNumber$ + "@" + ScanNumber$, Str$(MathAnswer))
End If
Goto NewMathScan
Else
Return "SYNTAX ERROR"
End If
Wend
Return Str(MathAnswer)
End Function
Function InMid$(A$, B$) ; in benutzung
Local C, Q, W
C = 0
For Q = 1 To Len(A$)
For W = 1 To Len(B$)
If (Mid$(A$, Q, 1) = Mid$(B$, W, 1)) And C = 0 Then C = Q : Exit
Next
If C>0 Then Exit
Next
Return C
End Function
Function val2#(sstring$)
Local temp#=0
Local decimal=0
Local sign=1
Local a
Local b
Local c
Local base=10
a=Instr(sstring$,"-",1)
If a Then negative=-1
b=Instr(sstring$,"&",a+1)
If b Then
Select Mid$(sstring$,a+1,1)
Case "B", "b"
base=2
a=b+1
Case "O", "o"
base=8
a=b+1
Case "H", "h"
base=16
a=b+1
Default
base=10
End Select
End If
decimal=0
For b=a+1 To Len(sstring$)
c=Asc(Mid(sstring$,b,1))
Select c
Case 44 ;","
Goto skip
Case 45 ;"-"
sign=-sign
Case 46 ;"."
decimal=1
Case 48,49,50,51,52,53,54,55,56,57 ;"0" To "9"
temp#=temp*base+c-48
If decimal Then decimal=decimal*base
Case 65,66,67,68,69,60 ;"A" to "F"
If base=16 Then
temp#=temp#*base+c-55
If decimal Then decimal=decimal*base
Else
Goto fini
EndIf
Case 97,98,99,100,101,102 ;"a" to "f"
If base=16 Then
temp#=temp#*base+c-87
If decimal Then decimal=decimal*base
Else
Goto fini
EndIf
Default
Goto fini
End Select
.skip
Next
.fini
If decimal Then temp#=temp#/decimal
If negative = -1 Then
Return -(temp#*sign)
Else
Return temp#*sign
End If
End Function |
Comments
None.
Code Archives Forum