ID:864445
 
Code:
/*AbyssDragon.Parser (v1.4)
written by AbyssDragon (abyssdragon@molotov.nu)
http://www.molotov.nu

Feel free to modify/improve/destroy/steal/use any of this code however you see fit.
A thanks or mention in your project would be nice, but neither are required.

AbyssDragon.Parser is an extremely flexible parser for BYOND, where creating
new commands is as easy as defining new datums. View the accompanying readme.txt
for a complete description of its capabilities. AbyssDragon.ParserDemo will
also provide several useful demonstrations of much of its power, and
AbyssDragon.ChatSystem will show you an actual system that makes use of the parser.

As always, report any bugs encountered while using this library.

Funny story: This is actually the second version of this library. The first
one I accidently overwrote and couldn't replace, so I had to completely start
over.
*/


var/Parser/parser = new()

client/Command(T) {
if(usr.Admin == 1)
parser.Parse(T, mob)
src.updatePrompt()
else
usr.Command++
if(usr.Command => 50)
mb_msgout("{YYou have been disconnected for spamming!{x")
usr.Logout()
if(usr.Unconcious == 1)
mb_msgout("You can't do anything you're unconscious!")
src.updatePrompt()
return
if(usr.loggedIn)
parser.Parse(T, mob)
src.updatePrompt()
}

client
proc
updatePrompt()
command_prompt=mb_msgout("<[usr.CheckColorEnergy()][jru_Commafy(usr.Energy)]%[usr.Reset]> / <[usr.ClassColor][jru_Commafy(usr.PowerLevel)][usr.Reset]/[usr.ClassColor][jru_Commafy(usr.MaxPowerLevel)][usr.Reset]>[usr.CheckBattle()]")

Parser
var
//Public Variables
Allowed = /Command //What type(s) of Command objects to allow to be parsed

//Private Variables
Commands[] = list() //List of Command instances Parser has created

New() //Prepares Command objects for matching
if(ispath(Allowed)) Allowed = list(Allowed)
for(var/P in Allowed)
for(var/T in typesof(P)-/Command)
var/Command/C = new T
if(Commands.len)
for(var/x in 1 to Commands.len)
var/Command/K = Commands[x]
if(C.priority >= K.priority)
Commands = Commands.Copy(1,x) + C + Commands.Copy(x)
break
else
Commands += C

proc
Parse(string, mob/user = usr) //Checks all Commands for a match
var/Temp_Parser/temp = new(user)
var/tokens[] = Tokenize(string)
for(var/Command/C in Commands)
temp.New(user)
if(C.Match(tokens, temp))
var/X = Process(user, C, temp.matches)
del temp
return X
Error(user, string, tokens)
del temp
return 0

Process(mob/user, Command/C, list/matches)
C.Process(arglist(list(user) + matches))
return 1

Tokenize(string)
var/tokens[] = list(), current, quotes = 0
while(length(string))
var/char = copytext(string, 1, 2)
if(char == "\"")
current += char
quotes = !quotes
else if(char != " " || quotes) current += char
else
tokens += current
current = ""
string = copytext(string, 2)
return tokens + current

Error(mob/user, string, list/tokens)


Command
var
//Public Variables
format = ""
usage = ""
allow_types[] = list("datum"=/datum, "atom"=/atom, "area"=/area, "turf"=/turf, "movable"=/atom/movable, "mob"=/mob, "obj"=/obj)
priority = 1

//Private Variables
ProcessMatcher/Matcher
New()
format += "&" //Attach end of string character
var/ProcessMatcher/currentMatcher = new(src)
Matcher = currentMatcher
var/temp_format = format
var/current
var/mode = "normal"
var/seperators = list("|","=","*", "(", ")", ",", ";", "'","!", "?","&","~","$","+")
while(temp_format)
var/char = copytext(temp_format, 1, 2)
if(char in seperators)
switch(mode)
if("normal")
if(current == "text") currentMatcher.allow_text = 1
else if(current == "num") currentMatcher.allow_num = 1
else if(current == "link") currentMatcher.allow_link = 1
else if(current == "anything") currentMatcher.wildcard = 1
else
if(allow_types[current]) currentMatcher.allow_types += allow_types[current]
if("list")
currentMatcher.List = current
if("center")
currentMatcher.Center = current
if("range")
currentMatcher.Range = text2num(current)
if("variable")
currentMatcher.variables = current
if("multiply")
var/number = text2num(current)-1
if(number > 1)
while(number)
number--
currentMatcher.Next = currentMatcher.Copy()
currentMatcher = currentMatcher.Next
switch(char)
if("?") currentMatcher.optional = 1
if("!") currentMatcher.force = 1
if("~") currentMatcher.multi = 1
if("$") currentMatcher.ignorecase = 1
if("+") currentMatcher.unique = 1
if("=") mode = "variable"
if("*") mode = "multiply"
if("(") mode = "list"
if(",")
if(mode == "list") mode = "center"
else if(mode == "center") mode = "range"
if(")") mode = "normal"
if(";")
currentMatcher.Next = new/ProcessMatcher(src)
currentMatcher = currentMatcher.Next
mode ="normal"
if("'")
if(mode=="literal")
currentMatcher.literals += current
mode="normal"
else mode = "literal"
if("=") mode = "variable"
current = ""
else
if(char != " ") current += char
temp_format = copytext(temp_format, 2)
if(!currentMatcher.allow_text && !currentMatcher.allow_num && !currentMatcher.allow_link && !currentMatcher.wildcard && !currentMatcher.allow_types.len && !currentMatcher.literals.len)
del currentMatcher
proc/Match(list/tokens, Temp_Parser/temp)
if(Matcher)
return Matcher.Match(tokens, temp)
else return 0
proc/Set_List(List, Range, atom/temp_center)
var/temp_list[]
switch(List)
if("view") temp_list = view(Range, temp_center)
if("oview") temp_list = oview(Range, temp_center)
if("range") temp_list = range(Range, temp_center)
if("orange") temp_list = orange(Range, temp_center)
if("world") temp_list = world.contents
if("contents") temp_list = temp_center.contents
if("hearers") temp_list = hearers(Range, temp_center)
if("ohearers") temp_list = ohearers(Range, temp_center)
if("viewers") temp_list = viewers(Range, temp_center)
if("oviewers") temp_list = oviewers(Range, temp_center)
if("worldmobs") return worldmobs
else temp_list = temp_center.vars[List]
return temp_list
proc/Process(mob/user, list/tokens)
return 1

Temp_Parser //Temporary object created to hold Parser lists
var
matches[] = list()
variables[] = list()
New(user)
matches = list()
variables = list("user" = user, "usr" = usr)


ProcessMatcher //Objects created to hold matching information for commands
var
Command/Parent
ProcessMatcher/Next
literals[] = list()
allow_types[] = list()
allow_text
allow_num
allow_link
wildcard
optional
force
multi
ignorecase
unique

variables
List = "world"
Center = "user"
Range
New(parent)
Parent = parent
Range = world.view
return ..()
proc/Copy()
var/ProcessMatcher/Copy = new()
Copy.literals = literals.Copy()
Copy.allow_types = allow_types.Copy()
Copy.allow_text = allow_text
Copy.allow_num = allow_num
Copy.allow_link = allow_link
Copy.wildcard = wildcard
Copy.optional = optional
Copy.force = force
Copy.multi = multi
Copy.ignorecase = ignorecase
Copy.List = List
Copy.Center = Center
Copy.Range = Range
return Copy
proc/Match(list/tokens, Temp_Parser/temp)
var/literal_match
if(!length(tokens))
if(optional) return 1
return 0
var/cont
var/token = tokens[1]
var/match
var/mob/temp_center = temp.variables[Center]
var/temp_list[] = Parent.Set_List(List, Range, temp_center)
if(literals.len)
for(var/x in literals)
if(TextMatch(x, token, multi, ignorecase))
literal_match = !force
match = token
cont = 1
goto end
if(allow_text)
match = copytext(token,2, findtext(token,"\"",3))
if(copytext(token, 1, 2) == "\"")
if(List == "world") cont = 1
else
for(var/x in temp_list)
cont = TextMatch(x, match, multi, ignorecase)
if(cont) goto end
if(allow_num)
match = text2num(token)
if(match)
cont = (!temp_list || temp_list.Find(match) || List == "world")
//cont = (!temp_list || temp_list.Find(match)) //bug
if(cont) goto end
if(allow_link)
match = "<A HREF='[token]'>[token]</A>"
if(copytext(token, 1, 8) == "http://")
if(List == "world") cont = 1
else
for(var/x in temp_list)
cont = TextMatch(x, match, multi, ignorecase)
if(cont) goto end
if(length(allow_types))
if(copytext(token,1,2)=="\"") token = copytext(token,2,findtext(token,"\"",2))
var/number = 0
var/temp_match
var/temp_unique = unique
if(isnum(text2num(copytext(token, 1, 2))))
var/stop = findtext(token,".",2)
if(stop)
number = text2num(copytext(token,1,stop)) - 1
token = copytext(token,stop+1)
temp_unique = 0
for(var/O in temp_list)
for(var/t in allow_types)
if(istype(O, t))
match = O
if(istype(O, /atom))
cont = O:ParseMatch(token, multi, ignorecase)
else
cont = TextMatch("[O]", token, multi, ignorecase)
if(cont)
if(number > 0) number--
else
if(temp_unique)
if(temp_match)
cont = 0
goto end
else temp_match = match
else goto end
if(temp_match)
cont = 1
match = temp_match
goto end
if(wildcard)
match = token
if(copytext(match,1,2)=="\"") match = copytext(match,2,findtext(match,"\"",2))
if(!Next)
for(var/j in 2 to tokens.len) match += " [tokens[j]]"
if(List == "world") cont = 1
else
for(var/x in temp_list)
cont = TextMatch(x, match, multi, ignorecase)
if(cont) goto end
end
if(variables && cont) temp.variables[variables] = match
if(optional && !force)
if(cont)
if(Next)return Next.Match(tokens.Copy(2), temp)
else return 1
else
if(Next)return Next.Match(tokens, temp)
else return 1
else if(cont)
if(!literal_match)temp.matches += match
if(Next) return Next.Match(tokens.Copy(2), temp)
else return 1
return 0

atom/proc/ParseMatch(Name, multi, ignorecase)
var/match = name
if(ignorecase)
Name = lowertext(Name)
match = lowertext(name)
if(multi) return (Name == match || copytext(match,1,length(Name)+1)==Name)
else return Name == match

proc/TextMatch(Text, Name, multi, ignorecase)
if(ignorecase)
Name = lowertext(Name)
Text = lowertext(Text)
if(multi) return (Name == Text || copytext(Text,1,length(Name)+1)==Name)
else return Text == Name


Problem description:

When i use the number format..it makes my cpu spike to 25% i'm not sure why anyone with more knowledge please scan this code and see why.. i would greatly appreciate the help D:
Can you give us an example of a command that causes the CPU spike?
    move
format = "'move'; num*3"
Process(mob/user, X, Y, Z)
user.loc = locate(X, Y, Z)


the error after using the command like that

runtime error: Cannot execute null.Set List().
proc name: Match (/ProcessMatcher/proc/Match)
source file: Parser.dm,259
usr: the thunderz (/mob/Player)
src: /ProcessMatcher (/ProcessMatcher)
call stack:
/ProcessMatcher (/ProcessMatcher): Match(/list (/list), /Temp_Parser (/Temp_Parser))
/ProcessMatcher (/ProcessMatcher): Match(/list (/list), /Temp_Parser (/Temp_Parser))
/ProcessMatcher (/ProcessMatcher): Match(/list (/list), /Temp_Parser (/Temp_Parser))
/Command/gotoz (/Command/gotoz): Match(/list (/list), /Temp_Parser (/Temp_Parser))
/Parser (/Parser): Parse("goto 1 2 3", the thunderz (/mob/Player))
Telnet @127.000.000.001 (/client): Command("goto 1 2 3")


straight from abyssdragon's parser demo even this lags and actually is broken it doesnt even work when calling 3 numbers or anything but it does work with single numbers.

it will really do it with any command
Okay so instead of wasting my time with that i just used the anything format and detected if it was a number and used text2num to convert for whenever i needed..

issue resolved.