ID:151830
 
Here is the parser I made for my MUD. I realize AbyssDragon already has a nice parser, but it's got too many features I don't need and it doesn't handle certain things like I need them to be handled, so I made my own.

Does it look decent? I've never really made a command parser.

var/Parser/parser = new

mob
var/list/inventory = list()

client/Command(cmd)
parser.parse(mob, cmd)

obj/really_big_candy

Command // TEST COMMANDS
say
format = "(say);txt"
function(mob/user, txt)
world << "[user.name]: [txt]"

tell
format = "(tell whisper);mob:view,1,usr txt"
function(mob/user, mob/mob, txt)
if(mob)
if(txt)
if(mob != user)
mob << "[user] tells you, \"[txt]\""
user << "You tell [mob], \"[txt]\""

else user << "You tell yourself, \"[txt]\""
else user << "Tell what?"
else user << "Tell who?"

get
format = "(get grab);obj:view,1,usr"
function(mob/user, obj/obj)
if(obj)
user << "You get [obj]."
user.inventory += obj
obj.Move(user)

else user << "Get what?"

drop
format = "(drop);obj:view,1,usr"
function(mob/user, obj/obj)
if(obj)
if(obj in user.inventory)
user << "You drop [obj]."

obj.Move(user.loc)
user.inventory -= obj

else user << "Drop what?"

walk
format = "(walk step);txt"
function(mob/user, txt)
switch(txt)
if("north", "n") step(user, NORTH)
if("south", "s") step(user, SOUTH)
if("east", "e") step(user, EAST)
if("west", "w") step(user, WEST)

give
format = "(give);mob:view,1,usr obj:.inventory"
function(mob/user, mob/mob, mob/obj)
if(mob)
if(obj)
user << "You give [mob] [obj]."
mob << "[user] gives you [obj]."

obj.Move(mob)
user.inventory -= obj
mob.inventory += obj

else user << "Give what?"
else user << "Give who?"

proc
stringSplit(string, delimiter = " ")
if(string)
. = list()

var/pos = findtext(string, delimiter)

while(pos)
. += copytext(string, 1, pos)
string = copytext(string, pos + length(delimiter))

pos = findtext(string, delimiter)

if(string)
. += string

else return

list2text(list/l, delimiter = " ")
. = ""

for(var/i = 1, i <= length(l), i ++)
. += l[i]

if(i < length(l))
. += delimiter

tokenize(string)
var
list/tokens = list()
current
quotes = FALSE
char = ""

while(length(string))
char = copytext(string, 1, 2)

if(char == "\"" || char == "'") quotes = !quotes
else if(char != " " || quotes) current += char
else
tokens += current
current = ""

string = copytext(string, 2)

return tokens + current

text2atom(mob/user, name, token, type)
var/location

if(findtext(token, ":"))
var
ltag = copytext(token, findtext(token, ":") + 1)
list/argl = stringSplit(ltag, ",")

if(findtext(argl[1], ".")) location = user.vars[copytext(argl[1], findtext(argl[1], ".") + 1)]
else
switch(argl[1])
if("world") location = world
if("view") location = parseFind(user, "view", argl[2], argl[3])
if("oview") location = parseFind(user, "oview", argl[2], argl[3])
if("range") location = parseFind(user, "range", argl[2], argl[3])
if("orange") location = parseFind(user, "orange", argl[2], argl[3])

else location = world

for(var/atom/a in location)
if(istype(a, type))
if(a.name == name) return a
if(ckey(a.name) == name) return a
if(findtext(a.name, name)) return a
if(findtext(ckey(a.name), ckey(name))) return a

parseFind(mob/user, p, dist, center)
dist = text2num(dist)
center = parseCenter(user, center)

switch(p)
if("view") return view(dist, center)
if("oview") return oview(dist, center)
if("range") return range(dist, center)
if("orange") return orange(dist, center)

parseCenter(mob/user, tag)
if(findtext(tag, "."))
return user.vars[copytext(tag, findtext(tag, ".") + 1)]

else
switch(tag)
if("usr") return user
else return user

Command
var
format = ""
list/arguments = null
list/alias = null

New()
alias = getAlias()
arguments = tokenize(format)

proc
getAlias()
var
start = findtext(format, "(") + 1
end = findtext(format, ");")

aliasTxt = lowertext(copytext(format, start, end))

format = copytext(format, end + 2)

return stringSplit(aliasTxt, " ")

process(mob/user, list/tokens)
tokens.Cut(1, 2)

var/argsend[length(arguments)]

for(var/a = 1, a <= length(arguments), a ++)
var
arga = arguments[a]
argt = tokens[a]

switch(copytext(arga, 1, 4))
if("txt")
tokens.Cut(a - 1, a)
argsend[a] = list2text(tokens, " ")

if("mob") argsend[a] = text2atom(user, argt, arga, /mob)
if("obj") argsend[a] = text2atom(user, argt, arga, /obj)
if("num") argsend[a] = text2num(argt)

argsend.Insert(1, user)
function(arglist(argsend))

function(mob/user)
match(list/tokens) if(length(tokens) >= length(arguments)) if(ckey(tokens[1]) in alias) return TRUE

Parser
var
list/commands

New()
commands = list()

for(var/cmd in typesof(/Command) - /Command)
var/Command/command = new cmd
commands += command

proc
parse(mob/user, string)
if(string)
var/list/tokens = tokenize(string)
for(var/Command/c in commands)
if(c.match(tokens))
c.process(user, tokens)

break
Does it work decent? That's all I care about. You might pass this on to some of the people trying to make telnet MUDs.