Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PyParsing improvements #119

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
- name: "Install Imaginary and dependencies"
run: |
pip install --upgrade pip setuptools coverage
pip install .
pip install .[test]

- name: "Dump Environment Info"
uses: "twisted/[email protected]"
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
],
extras_require={
"doc": ["sphinx>=1.2.2"],
"test": ["hypothesis"],
},
package_data={
"imaginary": ["resources/*", "resources/help/*"],
Expand Down
138 changes: 61 additions & 77 deletions src/imaginary/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
_quoteRemovingQuotedString.setParseAction(pyparsing.removeQuotes)

class UnicodeWord(pyparsing.Token):
"""
Match any consecutive sequence of any unicode non-whitespace.
"""
def parseImpl(self, instring, loc, doActions=True):
maxLoc = len(instring)
while loc < maxLoc and instring[loc].isspace():
Expand All @@ -44,6 +47,31 @@ def parseImpl(self, instring, loc, doActions=True):



class White(pyparsing.Token):
"""
Match any consecutive sequence of any unicode whitespace.
"""
def __init__(self, *args, **kwargs):
super(White, self).__init__(*args, **kwargs)
self.leaveWhitespace()


def parseImpl(self, instring, loc, doActions=True):
maxLoc = len(instring)
start = loc
while loc < maxLoc and instring[loc].isspace():
loc += 1
end = loc
return loc, instring[start:end]



restOfLine = (
pyparsing.Optional(White().suppress()) +
pyparsing.restOfLine
)


orLiterals = lambda xs: pyparsing.Or(map(pyparsing.Literal, xs))


Expand Down Expand Up @@ -344,10 +372,8 @@ def do(self, player, line):
class LookAt(TargetAction):
actionName = "look"
expr = (pyparsing.Literal("look") +
pyparsing.Optional(pyparsing.White() +
pyparsing.Literal("at")) +
pyparsing.White() +
pyparsing.restOfLine.setResultsName("target"))
pyparsing.Optional(pyparsing.Literal("at")) +
restOfLine.setResultsName("target"))

targetInterface = iimaginary.IVisible

Expand Down Expand Up @@ -416,7 +442,6 @@ class Illuminate(Action):
actorInterface = iimaginary.IManipulator

expr = (pyparsing.Literal("illuminate") +
pyparsing.White() +
pyparsing.Word("0123456789").setResultsName("candelas"))


Expand Down Expand Up @@ -461,10 +486,8 @@ def do(self, player, line, candelas):

class Describe(TargetAction):
expr = (pyparsing.Literal("describe") +
pyparsing.White() +
targetString("target") +
pyparsing.White() +
pyparsing.restOfLine.setResultsName("description"))
restOfLine.setResultsName("description"))

def targetRadius(self, player):
return 3
Expand All @@ -480,10 +503,8 @@ def do(self, player, line, target, description):

class Name(TargetAction):
expr = (pyparsing.Literal("name") +
pyparsing.White() +
targetString("target") +
pyparsing.White() +
pyparsing.restOfLine.setResultsName("name"))
restOfLine.setResultsName("name"))

def targetRadius(self, player):
return 3
Expand All @@ -500,7 +521,6 @@ def do(self, player, line, target, name):

class Open(TargetAction):
expr = (pyparsing.Literal("open") +
pyparsing.White() +
targetString("target"))

targetInterface = iimaginary.IContainer
Expand All @@ -526,7 +546,6 @@ def do(self, player, line, target):

class Close(TargetAction):
expr = (pyparsing.Literal("close") +
pyparsing.White() +
targetString("target"))

targetInterface = iimaginary.IContainer
Expand Down Expand Up @@ -580,7 +599,6 @@ def targetTaken(player, target, container=None):

class Remove(TargetAction):
expr = (orLiterals(["remove", "take off"]) +
pyparsing.White() +
targetString("target"))

targetInterface = iimaginary.IClothing
Expand Down Expand Up @@ -645,31 +663,6 @@ def do(self, player, line):



class TakeFrom(ToolAction):
actionName = "take"

expr = (orLiterals(["get", "take"]) +
pyparsing.White() +
targetString("target") +
pyparsing.Optional(pyparsing.White() +
pyparsing.Literal("from")) +
pyparsing.White() +
targetString("tool"))

def cantFind_target(self, player, targetName):
return "Nothing like that around here."
cantFind_tool = cantFind_target

def do(self, player, line, target, tool):
# XXX Make sure target is in tool
targetTaken(player.thing, target, tool).broadcast()
try:
target.moveTo(player.thing)
except eimaginary.DoesntFit:
raise tooHeavy(player.thing, target)



class PutIn(ToolAction):

toolInterface = iimaginary.IThing
Expand All @@ -679,11 +672,8 @@ def cantFind_target(self, player, targetName):
return "That doesn't work."

expr = (pyparsing.Literal("put") +
pyparsing.White() +
targetString("tool") +
pyparsing.Optional(pyparsing.White() +
pyparsing.Literal("in")) +
pyparsing.White() +
pyparsing.Optional(pyparsing.Literal("in")) +
targetString("target"))

def do(self, player, line, tool, target):
Expand Down Expand Up @@ -732,24 +722,30 @@ def do(self, player, line, tool, target):



class Take(TargetAction):
expr = ((pyparsing.Literal("get") ^ pyparsing.Literal("take")) +
pyparsing.White() +
targetString("target"))
class Take(ToolAction):
expr = (
orLiterals(["get", "take"]) +
targetString("target") +
pyparsing.Optional(
pyparsing.Literal("from") +
targetString("tool")
)
)

def cantFind_target(self, player, targetName):
return u"Nothing like that around here."
cantFind_tool = cantFind_target

def targetRadius(self, player):
return 1

def do(self, player, line, target):
def do(self, player, line, target, tool=None):
if target in (player.thing, player.thing.location) or target.location is player.thing:
raise eimaginary.ActionFailure(events.ThatDoesntMakeSense(
actor=player.thing,
actorMessage=("You cannot take ", target, ".")))

targetTaken(player.thing, target).broadcast()
targetTaken(player.thing, target, tool).broadcast()
try:
target.moveTo(player.thing)
except eimaginary.DoesntFit:
Expand Down Expand Up @@ -792,9 +788,7 @@ def insufficientSpace(player):


class Drop(TargetAction):
expr = (pyparsing.Literal("drop") +
pyparsing.White() +
targetString("target"))
expr = pyparsing.Literal("drop") + targetString("target")

def cantFind_target(self, player, targetName):
return "Nothing like that around here."
Expand Down Expand Up @@ -845,10 +839,8 @@ def expandDirection(direction):

class Dig(Action):
expr = (pyparsing.Literal("dig") +
pyparsing.White() +
DIRECTION_LITERAL +
pyparsing.White() +
pyparsing.restOfLine.setResultsName("name"))
restOfLine.setResultsName("name"))

def do(self, player, line, direction, name):
direction = expandDirection(direction)
Expand All @@ -875,7 +867,6 @@ def do(self, player, line, direction, name):

class Bury(Action):
expr = (pyparsing.Literal("bury") +
pyparsing.White() +
DIRECTION_LITERAL)

def do(self, player, line, direction):
Expand Down Expand Up @@ -907,7 +898,7 @@ def do(self, player, line, direction):

class Go(Action):
_goVerbs = orLiterals(["go", "enter", "exit"])
_goForm = _goVerbs + pyparsing.White() + targetString("direction")
_goForm = _goVerbs + targetString("direction")
expr = _goForm | DIRECTION_LITERAL

actorInterface = iimaginary.IThing
Expand Down Expand Up @@ -966,8 +957,7 @@ def do(self, player, line, direction):

class Restore(TargetAction):
expr = (pyparsing.Literal("restore") +
pyparsing.White() +
pyparsing.restOfLine.setResultsName("target"))
restOfLine.setResultsName("target"))

targetInterface = iimaginary.IActor

Expand Down Expand Up @@ -1009,8 +999,7 @@ def do(self, player, line, target):

class Hit(TargetAction):
expr = (orLiterals(["hit", "attack", "kill"]) +
pyparsing.White() +
pyparsing.restOfLine.setResultsName("target"))
restOfLine.setResultsName("target"))

targetInterface = iimaginary.IActor

Expand Down Expand Up @@ -1053,9 +1042,8 @@ def do(self, player, line, target):


class Say(Action):
expr = (((pyparsing.Literal("say") + pyparsing.White()) ^
pyparsing.Literal("'")) +
pyparsing.restOfLine.setResultsName("text"))
expr = (orLiterals(["say", "'"]) +
restOfLine.setResultsName("text"))

def do(self, player, line, text):
evt = events.SpeechEvent(speaker=player.thing, text=text)
Expand All @@ -1064,9 +1052,8 @@ def do(self, player, line, text):


class Emote(Action):
expr = (((pyparsing.Literal("emote") + pyparsing.White()) ^
pyparsing.Literal(":")) +
pyparsing.restOfLine.setResultsName("text"))
expr = (orLiterals(["emote", ":"]) +
restOfLine.setResultsName("text"))

def do(self, player, line, text):
evt = events.Success(actor=player.thing,
Expand Down Expand Up @@ -1147,9 +1134,7 @@ class Scrutinize(TargetAction):
"""
Show detailed information about the model structure of a game object.
"""
expr = (pyparsing.Literal("scrutinize") +
pyparsing.White() +
targetString("target"))
expr = pyparsing.Literal("scrutinize") + targetString("target")

def targetRadius(self, player):
return 3
Expand Down Expand Up @@ -1201,11 +1186,11 @@ class Set(TargetAction):
Direct model-level state manipulation command.
"""
expr = (
pyparsing.Literal("set") + pyparsing.White() +
targetString("attribute") + pyparsing.White() +
pyparsing.Literal("of") + pyparsing.White() +
targetString("target") + pyparsing.White() +
pyparsing.Literal("to") + pyparsing.White() +
pyparsing.Literal("set") +
targetString("attribute") +
pyparsing.Literal("of") +
targetString("target") +
pyparsing.Literal("to") +
targetString("value"))

def do(self, player, line, attribute, target, value):
Expand Down Expand Up @@ -1305,8 +1290,7 @@ class Help(Action):
@type helpContentPath: L{filepath.FilePath}
"""
expr = (pyparsing.Literal("help") +
pyparsing.White() +
pyparsing.restOfLine.setResultsName("topic"))
restOfLine.setResultsName("topic"))

helpContentPath = filepath.FilePath(imaginary.__file__).sibling(
"resources").child("help")
Expand Down
20 changes: 11 additions & 9 deletions src/imaginary/creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@
from imaginary.iimaginary import IThingType
from imaginary.eimaginary import ActionFailure, DoesntFit

from imaginary.action import Action, insufficientSpace
from imaginary.action import (
Action,
restOfLine,
orLiterals,
insufficientSpace,
)
from imaginary.action import targetString

from imaginary.pyparsing import Literal, White, Optional, restOfLine
from imaginary.pyparsing import Literal, Optional


def getPlugins(iface, package):
Expand Down Expand Up @@ -115,16 +120,13 @@ class Create(Action):
registry.
"""
expr = (Literal("create") +
Optional(White() +
(Literal("an") | Literal("a") | Literal("the")).setResultsName("article")) +
White() +
Optional(
orLiterals(["a", "an", "the"])
).setResultsName("article") +
targetString("typeName") +
White() +
Literal("named") +
White() +
targetString("name") +
Optional(White() +
restOfLine.setResultsName("description")))
Optional(restOfLine.setResultsName("description")))

def do(self, player, line, typeName, name, description=None, article=None):
"""
Expand Down
Loading