Evennia script parsing mk alpha
I asked for some advice on the Evennia discord and got some useful directions, which got me started enough that I've put together a rough framework for the parser.
It still needs all the object-handling code that Evennia uses - mostly searching stuff to get the dbrefs for the relevant objects involved - but I think I've nailed the logic flow. It's really, really simplified, on purpose. The final player scripts should look something like this:
if v is !object:
run -o !object exec_a
run -t v exec_a
else:
if v not @player:
run -o !object exec_b
I want to make it so that I can do an else if condition:
line but I have to do a special handler on the else
line for that and I just haven't gotten to it yet. More importantly than that, I also want to set up the option to test the outcome of running a subroutine within an "if" statement, which I also haven't gotten to yet.
Here's all the framework I have so far:
def parse_eq(a,b):
if a == b:
return True
if a.startswith("@"):
# search players
elif a.startswith("!"):
# search objects
elif a == "v":
# use caller - have to add caller as param to all these
if b.startswith("@"):
# search players
elif b.startswith("!"):
# search objects
elif b == "v":
# use caller - have to add caller as param to all these
return a == b
def parse_ineq(a,b):
if a == b:
return False
if a.startswith("@"):
# search players
elif a.startswith("!"):
# search objects
elif a == "v":
# use caller - have to add caller as param to all these
if b.startswith("@"):
# search players
elif b.startswith("!"):
# search objects
elif b == "v":
# use caller - have to add caller as param to all these
return a != b
def parse_ifthen(lines):
# validate structure
line = lines[0].lower().strip()
if line.startswith("if") and line.endswith(":"):
# basic syntax check passed
# find first else block
elsepos = 1
while not lines[elsepos].lower().strip() == "else" and elsepos < len(lines):
elsepos = elsepos + 1
ents = line.split()
i = 1
# evaluate "if" condition
while i < len(ents):
a = ents[i]
b = ents[i+2]
eq = ents[i+1]
if eq == "is":
# equality check
elif eq = "not":
# inequality check
else:
# not *quality check
return "ERROR: invalid condition"
# parse out and/or connectors
if len(ents) > i+3:
andor = ents[i+3]
if andor != "and" and andor != "or":
# not an and/or statement, invalid script
return "ERROR: invalid logic operator"
if andor == "and" and comp == False:
# "and" condition fails
break
elif andor == "or" and comp == True:
# "or" condition succeeds
break
else:
i = i+4
if comp:
# evaluate "then" result
i = 1
while i < elsepos:
line = lines[i].lower().strip()
# is it another "if"?
if line.startswith("if"):
# RECURSION TIME
err = parse_ifthen(lines[i:elsepos])
if err:
return err
break
# otherwise parse each line as a command
elif line.startswith("run "):
# do the stuff
else:
return "ERROR: invalid command"
i = i+1
elif elsepos < len(lines):
# evaluate "else" result
i = elsepos + 1
while i < len(lines):
line = lines[i].lower().strip()
# is it another "if"?
if line.startswith("if"):
# RECURSION TIME
err = parse_ifthen(lines[i:])
if err:
return err
break
# otherwise parse each line as a command
elif line.startswith("run "):
# do the stuff
else:
return "ERROR: invalid command"
i = i+1
return False # return value is error so False means no error
def pc_script(text):
lines = text.splitlines()
err = parse_ifthen(lines)
if err:
#handle error