0

Certain tools that we all use often allow strings to be parsed as optional commands. For example, with most IRC tools one can write something like /msg <nick> hi there!, resulting in the string being parsed and executing a command.

I was thinking about this on the weekend, and realised that I have absolutely no idea how I could implement this functionality robustly. My birds-eye view understanding of it is that every input will need to be parsed, a potential match found for issuing a command, and that command will need to be executed with proper validation in place.

I wrote a quick proof of concept for this in Python:

class InputParser:

    def __init__(self):
        self.command_character = '!!'
        self.message = None
        self.command = None
        self.method = None

    def process_message(self, message):
        # every input into the system is sent through here.  If the 
        # start of the string matches the command_character, try and 
        # find the command, otherwise return back the initial
        # message.
        self.message = message

        if self.message.startswith(self.command_character):
            self.command = self.message.split(' ')[0]
            self.method = self.command.replace(self.command_character, '')
            try:
                return self.__class__.__dict__['_%s' % self.method]()
            except KeyError:
                # no matching command found, return the input message 
                return self.message
        return self.message

    def _yell(self):
        # returns an uppercase string
        return self.message.upper().replace(self.command, '')

    def _me(self):
        # returns a string wrapped by * characters
        return ('*%s*' % self.message).replace(self.command, '')

Example usage:

!!yell hello friend > HELLO FRIEND

Question: Can someone provide me a link to an existing project, an existing library or give me a conceptual overview on an effective way to robustly change the manner in which a string is interpreted by a program, leading to different behaviour by the application?

Jamie S
  • 760
  • 3
  • 9
  • 19
  • It sounds like you need a lexer / string tokenizer. Try http://stackoverflow.com/q/36953/1141876 – fiat Oct 26 '16 at 05:24

1 Answers1

0

Rather than hacking away at the class internals, you would be better off using a dictionary to map the command strings to a function that performs the command. Set up the dictionary at the class level, or in the __init__() if it might vary between instances.

This way the dictionary serves two purposes: one to provide the valid command tokens and the other to map the command token to an action.

mhawke
  • 84,695
  • 9
  • 117
  • 138
  • Thats essentially what I've done. Each of the `commands` maps exactly to a method on the class, so `!!yell` maps to `def _yell`. I'm accessing these properties through the class dict. – Jamie S Sep 26 '16 at 02:43